When you want to install linux on a large number of servers kickstart approach is a very good one. But what about hostname?! You have many choices:
- A kickstart file for each server, but come on... what kind the choice is this?!
- A kickstart file for all servers and set hostname after installation (manually on every single server, or using a script)
Fortunately for you there is a third option: Automatically set the hostname during Kickstart Installation. I wish to take credit for this, but this will be so unfair for the guy which wrote an article about this.
I won't get to long with the story so... let's get started.
The trick is to pass the kernel a parameter and use it in our kickstart file. What if you were to pass a parameter that it doesn't recognize? In most cases, it will probably ignore it, but it will still in the kernel list. We can check kernel parameters by issuing the following command:
[codesyntax lang="bash"]
cat /proc/cmdline
[/codesyntax]
So what if we can pass a parameter with desired hostname to the kernel? With a very simple script we can parse the output of the above command and look for our parameter.
[codesyntax lang="bash"]
#!/bin/sh echo "network --device eth0 --bootproto dhcp --hostname localhost.localdomain" > /tmp/network.ks for x in `cat /proc/cmdline`; do case $x in SERVERNAME*) eval $x echo "network --device eth0 --bootproto dhcp --hostname ${SERVERNAME}" > /tmp/network.ks ;; esac; done
[/codesyntax]
Here we are looking for SERVERNAME end evaluates that value into a variable. We will then echo the network setup with the variable (which we will use as part of the hostname setup) and redirect into the file under /tmp. Then we will include that file in our installation section.
You may ask yourself what is all about this line:
[codesyntax lang="bash"]
echo "network --device eth0 --bootproto dhcp --hostname localhost.localdomain" > /tmp/network.ks
[/codesyntax]
in the script above?! Well, if you don't pass the SERVERNAME to the kernel, then /tmp/network.ks will not be created and your installation will fail.
So this is my kickstart file for a minimal CentOS 6.3 installation:
install
firewall --disabled
url --url="ftp://ftp.ines.lug.ro/centos/6.3/os/i386"
network --bootproto=dhcp --device=eth0
rootpw --iscrypted YOUR_ENCRYPTED_PASSWORD
text
%include /tmp/network.ks
keyboard us
lang en_US
selinux --disabled
skipx
logging --level=info
reboot
timezone --utc Europe/Bucharest
bootloader --location=mbr --driveorder=sda,sdb --append="console=tty0 console=ttyS0,115200N1"
zerombr
clearpart --all --initlabel
part / --fstype="ext4" --size=10000
part swap --fstype="swap" --size=8000
part pv.01 --fstype="ext4" --grow --size=1
volgroup vg0 pv.01
logvol /data --vgname=vg0 --percent=90 --name=lv0 --fsoptions=noatime --fstype=ext4 --size=1 --grow
%packages
@core
sed
perl
less
dmidecode
bzip2
iproute
iputils
sysfsutils
rsync
nano
mdadm
setserial
man-pages.noarch
findutils
tar
net-tools
tmpwatch
lsof
python
screen
lvm2
curl
ypbind
yp-tools
smartmontools
openssh-clients
acpid
irqbalance
which
bind-utils
ntsysv
ntp
man
mysql
postfix
chkconfig
gzip
%end
%pre
#!/bin/sh
echo "network --device eth0 --bootproto dhcp --hostname localhost.localdomain" > /tmp/network.ks
for x in `cat /proc/cmdline`; do
case $x in SERVERNAME*)
eval $x
echo "network --device eth0 --bootproto dhcp --hostname ${SERVERNAME}" > /tmp/network.ks
;;
esac;
done
%end
%post
cat > /etc/cron.d/ntpdate < /dev/null 2>&1
EOF
chkconfig ntpd on
chkconfig sshd on
chkconfig ypbind on
chkconfig iptables off
chkconfig ip6tables off
chkconfig yum-updatesd off
chkconfig haldaemon off
chkconfig mcstrans off
chkconfig sysstat off
cat > /etc/motd <> /etc/motd
echo >> /etc/motd
%end
Hi - I stumbled on this page while searching on Google. Please help me a bit more. Where does the SERVERNAME value come from?
Hello Kevin - The value of SERVERNAME is the hostname of the machine you want to install. You have to add SERVERNAME=hostname as kernel parameter before booting from network (in the PXE boot menu).
Hey, thanks for the tips. Unfortunately, I couldn't get your approach to work, but did realise that you can set a hostname attribute in your boot command.
So, instead of "SERVERNAME=host", I just added hostname=host as a kernel parameter and skipped everything else. It's worked a charm!
I don't know why my approach didn't work for you. I used this for a lot of servers. But, if it helped you I am really happy.
Thanks for the feedback.
Thank you! Awesome tip!
You can also add a command to your (non-chrooted) pre-script: dhclient.
That command WILL set the hostname, where the other DHCP requests done by the kickstart won't.
Of course your DHCP server will have to send the hostname ('option host-name ""' per client or just 'use-host-decl-names on;').
Thank you Elmar for your comment. One of my teachers had a saying: "If there are more than one solutions, the student will choose the most complicated one". He was right. My approach is different and more complicated than yours. I will test it with the first opportunity.
Thanks, that's a really simple fix to the problem.
how easy would it to be to modify the case $x to also grab ip, netmask, gateway? Thanks,
Well, the network configuration is pushed by dhcp server. Why would you need to grab those settings?
Using RHEL6.5 I am unable to see the kernel parameter when I press TAB key on an item. All I see is vmlinuz and it dosn't seem to accept the servername flag. Is there a workaround?
I just tested this on RHEL 7.2 and it still works!
if i want to parse in static ip instead of dhcp will it be possible to be to modify the case $x to also grab ip, netmask, gateway? meaning in the pxe boot when i press tab i add in these additional fields
the following should work for fedora, centos and rhel
# Mainsection
# Keyboard layouts
keyboard 'de'
# Desktop Environment
xconfig --defaultdesktop=GNOME --startxonboot
# Other stuff ...
# Network information (see the pre% section below for generating /tmp/network.ks)
%include /tmp/network.ks
# Other stuff ...
# pre% section
%pre
# Define clients ("mac-address" "ipv4-address" "hostname")
clients=("00:00:00:00:A0:01" "10.0.0.201" "client-01")
clients+=("00:00:00:00:B0:02" "10.0.0.202" "client-02")
clients+=("00:00:00:00:C0:03" "10.0.0.203" "client-03")
clients+=("00:00:00:00:D0:04" "10.0.0.204" "client-04")
clients+=("00:00:00:00:E0:05" "10.0.0.205" "client-05") # etc. ...
# Grep the ethernet adapter name usually the first in /sys/class/net
ethernet="$(ls /sys/class/net | head -n1 | cut -d " " -f1)"
# Grep ethernet adapters mac address TO UPPERCASE
mac="$(cat /sys/class/net/"$ethernet"/address | tr a-z A-Z)"
# Define domainname (if needed)
domain="your.domain.com"
# Define default gateway
gateway="10.0.0.1"
# Define subnetmask
netmask="255.255.255.0"
# Define dns servers
dns1="10.0.0.2"
dns2="10.0.0.3"
# Define search domains (if needed)
search="your.domain.com other.domain.com another.domain.com"
# iterate trough the clients
for (( i=0; i /tmp/network.ks
# setup static ipv4 configuration
nmcli con mod "$ethernet" connection.autoconnect yes
nmcli con mod "$ethernet" ipv4.addresses "${clients[i+1]}/24"
nmcli con mod "$ethernet" ipv4.gateway "$gateway"
nmcli con mod "$ethernet" ipv4.dns "$dns1,$dns2"
nmcli con mod "$ethernet" ipv4.dns-search "$search"
nmcli con mod "$ethernet" ipv4.method manual
nmcli con down "$ethernet"; nmcli con up "$ethernet"
fi
done
%end
Sorry the website does not accept the code completely
Ok, I'll try the for loop at the end again.
# iterate trough the clients
for (( i=0; i /tmp/network.ks
# setup static ipv4 configuration
nmcli con mod "$ethernet" connection.autoconnect yes
nmcli con mod "$ethernet" ipv4.addresses "${clients[i+1]}/24"
nmcli con mod "$ethernet" ipv4.gateway "$gateway"
nmcli con mod "$ethernet" ipv4.dns "$dns1,$dns2"
nmcli con mod "$ethernet" ipv4.dns-search "$search"
nmcli con mod "$ethernet" ipv4.method manual
nmcli con down "$ethernet"; nmcli con up "$ethernet"
fi
done
Nope, this website does not accept this code, sorry . . .