Disk name changed after reboot

We are using Alma Linux 9.3 as our base system. when we reboot the system, we found that the disk name changed, for example : SDB → SDC.

Then we changed the kernel parameter “sd_mod.probe=sync”. It is working well on Vmware and AWS cloud, but not working on Azure cloud.

Anyone has suggestions?

Those names are not predictable. Probably never were.

Where do you need those names?

Our system is a legacy system, upgraded from CentOS to Alma linux.
It depends on the disk name.
we know it’s better to use UUID to identify the disk, but that requires big working effort.

CentOS 7 did use UUID, rather than sda-style references. CentOS 6 did use UUID. How ancient legacy do you have?

“It” does not exactly tell where in the config do those names appear.

But when done it will be done. How big is “big”? How many places in the config? How many systems?

My experience with CentOS 7 is that the the SDA style naming is stable and consisted.
While on Alma it can change on a reboot.
Solution is to use UUID as others already suggested.

Maybe off topic:
One of the problems is the kickstart script uses SDA naming style a I had to make a small script to generate the partition information to make installs consistent.

I have used kickstart to set up numerous systems with AlmaLinux 8 and 9. I have created a script that runs as a pre-install that determines the disk layout predictably on whatever the hardware happens to be. The script also sets up the network IP from the MAC address, as we use static IP for our systems. I raided the arp cache on a few of the current machines to get a mapping of MAC to IP and MAC to hostname, which I have left a sample of in the Kickstart to make the format make sense. I set this up as we were implementing IdM on this domain, and have it installed as part of the kickstart.
The key to the partitioning is the names that exist in /dev/disk. There are 6 sub-directories that map the disks with symbolic links to the /dev names for the devices. The ones that I use are the by-label and by-id to find the installation source, and then to filter out USB devices and other smaller devices from consideration for the install. I then set the swap partition size, and then start the setup of partitions, writing the info out to a file in /tmp. This file is then read by Anaconda and the disks are then set up on the fly. I am attaching a sanitized version of the kickstart that yo are free to use if you like.
Enjoy.

#version=RHEL8
# vi:set ts=4 et:
#
eula --agreed
# Use graphical install
graphical 
# Network information
%include /tmp/net.cfg
#
#network  --bootproto=dhcp --device=link --ipv6=auto --activate
#network  --bootproto=dhcp --hostname=alma.ipa.localdomain
#
%include /tmp/parts.cfg
#  Installation sources -- Moved to pre script include
harddrive  --partition=LABEL=ALMALINUX-8 --dir=
repo --name="AppStream" --baseurl=file:///run/install/repo/AppStream
#
# Keyboard layouts
keyboard --xlayouts='us'
# System language
lang en_US.UTF-8
module --name idm --stream DL1  # idm servers,client
%packages
@^graphical-server-environment
@development 
@graphical-admin-tools
@network-file-system-client
@system-tools
@idm:DL1/client
#@idm:DL1/server
#@idm:DL1/dns
kexec-tools
gnome-tweaks
python3-pip
vim-X11
-insights-client
-cockpit
%end


# Run the Setup Agent on first boot
firstboot --disable

# System timezone
timezone America/Chicago --isUtc --ntpservers=2.cloudlinux.pool.ntp.org,2.cloudlinux.pool.ntp.org,2.cloudlinux.pool.ntp.org,2.cloudlinux.pool.ntp.org,time.google.com,time.google.com,time.google.com,time.google.com

# Root password
rootpw --iscrypted <removed encrypted password>

reboot

%addon com_redhat_kdump --enable --reserve-mb='auto'

%end

%anaconda
pwpolicy root --minlen=9 --minquality=30 --strict --nochanges --notempty
pwpolicy user --minlen=9 --minquality=30 --strict --changesok --notempty
pwpolicy luks --minlen=9 --minquality=30 --strict --nochanges --notempty
%end
##
%pre --interpreter=/usr/libexec/platform-python
#
import subprocess 
cache='''
00:21:9f:73:f9:83 10.0.0.162
7c:5c:f8:ff:3f:20 10.0.0.219
00:1b:21:bb:ff:94 10.0.0.100
'''
lines = cache.splitlines()
mac_ip = {}
for l in lines:
    ll = l.split()
    mac_ip[ll[0]] = ll[1]

names='''
00:21:9b:73:f9:83 test1.ipa.localdomain
7c:5c:f8:f0:3f:20 test2.ipa.localdomain
00:1b:21:bb:71:94 test3.ipa.localdomain
'''
lines = names.splitlines()
mac_name = {}
for l in lines:
    ll = l.split()
    mac_name[ll[0]] = ll[1]
#
#
# get mac address using ip

args=['ip','-br','link','show']
#addresses = Sub.CompletedProcess()
addresses = subprocess.run(args, stdout=subprocess.PIPE)
lines=str(addresses.stdout,encoding='utf-8').splitlines()
interfaces =dict()  # dictionary of interfaces indexed by MAC
for l in lines:
    ll = l.split()
    if ll[0] not in ['lo','virbr0']:  # only interested in hardware
        interfaces[ll[2]] = ll[0]
systems = {}
ip = None
sysname = None
for (k,v) in interfaces.items():
    if k in mac_ip:
        mac=k
        ip = mac_ip.get(k)
        sysname = mac_name.get(k)
        break
dev=interfaces.pop(k)
import socket
# for gateway and nameservers, get ip masked for gateway, and
# key off of 1st quad for nameserver string
nip = socket.inet_aton(ip)
adr = [c for c in nip]
nip = socket.inet_aton('255.255.255.0')
mask= [c for c in nip]
gate = []
for i in range(4):
    gate.append(adr[i] & mask[i])
gate[3] += 1
gateway = "%d.%d.%d.%d"%tuple(gate)
if gate[0] < 11:
    nservers = '75.75.75.75,75.75.76.76'
else:
    nservers = 'xxx.xxx.xxx.xxx'
import sys
fd = sys.stdout
# print to log
if ip:
    print('network --bootproto=static --ip=%(ip)s --netmask=255.255.255.0 --hostname=%(sysname)s --device=%(mac)s --bindto=mac --activate --gateway=%(gate)s --nameserver=%(dns)s --onboot=True'
       %{'ip':ip,'sysname':sysname,'mac':mac,'gate':gateway,'dns':nservers},file=fd)
for (k,v) in interfaces.items():
    print('network --bootproto=dhcp --device=%s --bindto=mac --onboot=False --nodefroute --notksdevice'%(k,),file=fd)
with open('/tmp/net.cfg','w') as fd:
    if ip:
        print('network --bootproto=static --ip=%(ip)s --netmask=255.255.255.0 --hostname=%(sysname)s --device=%(mac)s --bindto=mac --activate --gateway=%(gate)s --nameserver=%(dns)s --onboot=True'
                %{'ip':ip,'sysname':sysname,'mac':mac,'gate':gateway,'dns':nservers},file=fd)
    for (k,v) in interfaces.items():
        print('network --bootproto=dhcp --device=%s --bindto=mac --onboot=False --nodefroute --notksdevice'%(k,),file=fd)
#
#  Autopartition Script
#
from pathlib import Path
import parted as Part
import os.path as Ospath
DEBUG=False
DEBUG=True

def SizeGB(dev):
    s = dev.as_posix()
    with open(s+'/size') as fd:
        sz=int(fd.read())//2**21
    return(sz)
if DEBUG:
    print('\n\n*************************************************************\n')
paths =  Path('/sys/block').glob('*')
lines = list(paths)
lines.sort()  # this will prioritze NVME #sort in place
sizes = {}
for l in lines:
    n=l.name
    sizes[n] = SizeGB(l)
if DEBUG:
    print(sizes)
    print('\n\n*************************************************************\n')
devs = {}
#print(lines)
paths= Path('/dev/disk/by-label').glob('*')
lines = list(paths)
for l in lines:
    s=l.as_posix()
    if s.startswith('/dev/disk/by-label/ALMALINUX'):
        Source = l
        source = l.resolve().as_posix()  # partition of source
        d,s = Ospath.split(source)
        sourceDevice = source.rstrip('0123456789')  # will be something like sde
#for d,s in devs.items():
#    print(d,s)
if DEBUG:
    print(sourceDevice)
# only look at targets that are not usb
targets = {}
ipaths = list(Path('/dev/disk/by-id').glob('*'))
#print(ipaths)
for i in range(len(ipaths)):
    p = ipaths[i]
    l=p.as_posix()
    rp = p.resolve()
    if not(l.endswith(('-part','-par'),-7,-2)):
        print(l,' >> ',str(rp))
        if 'usb-' in l:
            continue
        if sizes[rp.name] < 200:
            continue
        targets[rp.name] = rp
if DEBUG:
    print('\n-------------------------------------------------------------\n')
    print(targets)        


#
# now have a small bios level set of devices to install to.
# I have deliberatly removed usb devices, as they
# cannot be depended on to remain with the system.  
# They are at least 200GiB in size.
#
# choose the smallest. or the first in line if al equal, for root/boot
size = 1e12
mxsz =0
homedev=None
dest = None
count =0
for d in targets.keys():
    if sizes[d] < size:
        size = sizes[d]
        dest = targets[d]
        dindex = d
    if sizes[d] >= mxsz:
        mxsz = sizes[d]
        homedev = targets[d]
        count +=1
# determine swap size
with open('/proc/meminfo') as fd:
    l=fd.readline()
ll = l.split()
sz=int(ll[1])//1e6  # GB ram, 
# allocate min 4GB for swap, to a max of 24GB mem+swap
# with swap no larger than 2x memory
# this limits swap to 16Gb at 8Gb ram
# minimal swap in low disk size limit
# if disk space is not an issue, limit at mem/2
swap = min(max(4,(24-sz)),2*sz)   # in Gb
maxopt=''
if(homedev != dest):
    maxopt = '--maxsize=131072 '
if (mxsz >400) or (homedev != dest):
    swap = max(swap,sz//2)
  
if DEBUG:
    print('destination disk',dest,' size:',sizes[dindex],'GiB')
    print('home: ',homedev,' swap: ',swap)
diskmb = sizes[dindex]*2**10 # disk size in MiB
# sizes in MB
'''
biosboot=2
#swap calc'd above, max 32GiB
boot=2 000  # 2GB
bootefi=400
root=48 000   153 600
usr=48 000  200 000
var=32 000  150 000
log=48 000
vartmp=20 000
audit=20 000
tmp=20 000
opt=32 000 150 000 
home=10 000 remander
'''
#
##
fd = sys.stdout
print('ignoredisk --drives=%s'%(sourceDevice),file=fd)
print('bootloader --location=mbr   --drive=%s'%(dest),file=fd)
if homedev != dest:
    print('clearpart --all --initlabel --disklabel=gpt --drives=%s,%s'%(dest,homedev),file=fd)
else:    
    print('clearpart --all --initlabel --disklabel=gpt --drives=%s'%(dest),file=fd)
# Disk partitioning information
print('part biosboot --fstype="biosboot" --size=2 --ondisk=%s'%(dest),file=fd)
print('part /boot/efi --fstype="efi" --size=512 --ondisk=%s'%(dest),file=fd)
print('part swap  --fstype="swap" --hibernation --maxsize=%d  --ondisk=%s'%(swap,dest),file=fd)
print('part /boot --fstype="xfs" --label=BOOT --size=2048   --ondisk=%s'%(dest),file=fd)
print('part /     --fstype="xfs" --label=ROOT --size=24568 --maxsize=131072 --grow --ondisk=%s'%(dest),file=fd)
print('part /usr  --fstype="xfs" --label=USR  --size=49152 --maxsize=226815 --grow --ondisk=%s'%(dest),file=fd)
print('part /var  --fstype="xfs" --label=VAR  --size=20480 --maxsize=163840 --grow --ondisk=%s'%(dest),file=fd)
print('part /var/log  --fstype="xfs" --label=VAR  --size=20480 --maxsize=40960 --grow --ondisk=%s'%(dest),file=fd)
print('part /tmp  --fstype="xfs" --label=TMP  --size=10240 --maxsize=32768 --grow --ondisk=%s'%(dest),file=fd)
print('part /var/tmp  --fstype="xfs" --label=VARTMP  --size=10240 --maxsize=32768 --grow --ondisk=%s'%(dest),file=fd)
print('part /var/log/audit  --fstype="xfs" --label=AUDIT  --size=10240 --maxsize=20480 --grow --ondisk=%s'%(dest),file=fd)
print('part /opt  --fstype="xfs" --label=OPT  --size=10240 %s--grow --ondisk=%s'%(maxopt,dest),file=fd) # dump rest of disk in /opt if home on separte device
print('part /home --fstype="xfs" --label=HOME --size=10240 --grow --ondisk=%s'%(homedev),file=fd)
#
fd = open('/tmp/parts.cfg',mode='w')
print('ignoredisk --drives=%s'%(sourceDevice),file=fd)
print('bootloader --location=mbr   --drive=%s'%(dest),file=fd)
if homedev != dest:
    print('clearpart --all --initlabel --disklabel=gpt --drives=%s,%s'%(dest,homedev),file=fd)
else:    
    print('clearpart --all --initlabel --disklabel=gpt --drives=%s'%(dest),file=fd)
# Disk partitioning information
print('part biosboot --fstype="biosboot" --size=2 --ondisk=%s'%(dest),file=fd)
print('part /boot/efi --fstype="efi" --size=512 --ondisk=%s'%(dest),file=fd)
print('part swap  --fstype="swap" --hibernation --maxsize=%d  --ondisk=%s'%(swap,dest),file=fd)
print('part /boot --fstype="xfs" --label=BOOT --size=2048   --ondisk=%s'%(dest),file=fd)
print('part /     --fstype="xfs" --label=ROOT --size=24568 --maxsize=131072 --grow --ondisk=%s'%(dest),file=fd)
print('part /usr  --fstype="xfs" --label=USR  --size=49152 --maxsize=226815 --grow --ondisk=%s'%(dest),file=fd)
print('part /var  --fstype="xfs" --label=VAR  --size=20480 --maxsize=163840 --grow --ondisk=%s'%(dest),file=fd)
print('part /var/log  --fstype="xfs" --label=VAR  --size=20480 --maxsize=40960 --grow --ondisk=%s'%(dest),file=fd)
print('part /tmp  --fstype="xfs" --label=TMP  --size=10240 --maxsize=32768 --grow --ondisk=%s'%(dest),file=fd)
print('part /var/tmp  --fstype="xfs" --label=VARTMP  --size=10240 --maxsize=32768 --grow --ondisk=%s'%(dest),file=fd)
print('part /var/log/audit  --fstype="xfs" --label=AUDIT  --size=10240 --maxsize=20480 --grow --ondisk=%s'%(dest),file=fd)
print('part /opt  --fstype="xfs" --label=OPT  --size=10240 %s--grow --ondisk=%s'%(maxopt,dest),file=fd) # dump rest of disk in /opt if home on separte device
print('part /home --fstype="xfs" --label=HOME --size=10240 --grow --ondisk=%s'%(homedev),file=fd)
fd.close()
%end
1 Like

Thanks for your information and help!
I’ll try it.

Yes, In CentOS 7 ,it is stable and consisted.

Now we are trying to use UUID in Alma linux .