First a little backgroud and a few links. You will find all kinds of information on automated installation on the VMWare User Group community. VMWare also has some paltry level of documentation on the subject. This best beginning source of information for me was this blog….. and it is from here that the following excerpt was taken to help remind me of the basiss behinfd the ESX scripted installation:
“The vSphere ESX 4 install process uses an updated linux boot release commonly referred to as Syslinux. This Syslinux release version 3.63 supports a variety of popular protocols to facilitate a remote central install repository. FTP, HTTP, NFS and gPXE are all available options for provisioning network attachment to a remote install repository.
From the Syslinux boot process vSphere launches it’s initrd.img kernel instance which is a custom VMware/Linux kernel containing a multitude of VMware ESX 4 drivers and components. The custom drivers allow for a more closely integrated VMware ESX 4 install process that targets an improved ESX 4 server configuration result.
The custom VMware kernel incorporates Linux kickstart scripting functionality to invoke automated installations. The script location is defined as part of the Syslinux functionality and is available as a menu at boot time. A control file located on the boot media provides these variable control elements. Depending on the media type Syslinux uses a respective cfg file to implement this function. The various available Syslinux boot methods that I am aware of are USB, CD, DVD, PXE and gPXE. In this blog I will demonstrate an ISO CDROM method to perform the automated boot cycle. Any of the boot methods mentioned will all work and have varying levels of complexity to achieve.
The ISO CD and DVD based Syslinux configuration uses a config file named isolinux.cfg, USB boot images would use isolinux.cfg as well as gPXE based boot services can use either depending on the final gPXE target image.“
This is a great source of reference, although it did not meet all my needs because it is a network based installation.
So what exactly am I trying to do? I want to use the built in kickstart scripting mechanism to consistently install or reinstall ESX Hosts in our VMWare vSphere 4.0 environment. I want the installation script to prompt for things that change from ESX host to ESX host like: Service console IP information, iSCSI IP information, and the FQDN. I also want the installation script to download an additional configuration script from a centralized repository after the installation is complete and execute it.
This is probably complicated a little in our environment because all of the network connections to our ESX hosts are 802.1Q VLAN trunks to give us the greatest flexibility in production. Unfortunately, the ESX kickstart/syslinux kernel used for the ESX 4.0 installation does not support VLAN trunking, so no networking is available unless we switch the port before and after the installation. I don’t want to do that……
So what are the advantages to how I approached this automated installation problem:
- Installation is done totally from media so network not required during the scripted installation
- One configuration script for any ESX host being installed that prompts for dynamic elements.
- A post installation download of an additional script that can be easily updated without changing the installation media.
- The downloaded script can configure anything that can be configured on a running ESX host.
- Complete install/reinstall of ESX environment in 25 minutes.
We used to do all this with ESX 3.5. By omitting the “network” section in the kickstart “ks.cfg” the installation would prompt us, allowing us to setup the dynamic elements. Unfortunately, I had to build my own prompting mechanism into my ESX4 kickstart script and it was a little tricky.
I’ve found the most straight forward approach is to simply use the same old boring default DVD iso downloaded from VMWare. Download it, burn it to a DVD and we are 25% of the way there already. The default installtion DVD, contains a non default option to do a “ESX Scripted Install using USB ks.cfg”.
ESX Scripted Install using USB ks.cfg
So now, all I need to do is place my modified kickstart “ks.cfg” file on a USB memory stick and it will install from the CD but because I’ve modified the %pre and %post sections of the “ks.cfg” in the manner I’m about to describe, the ks.cfg will prompt me for the dynamic networking components. If you don’t want to use a USB drive then you can see my other post that talks about a complicated method of burning your custom ks.cfg on to the DVD media.
So now lets look at my customized kickstart “ks.cfg”
We start with some of the basics……
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | accepteula keyboard us # Read network information from a file we are going to populate in the %pre section # of this kixstart script. %include /tmp/networkconfig auth --enablemd5 --enableshadow install cdrom rootpw --iscrypted $1$M7fvhjkgghkyguysdfjhgjoqg. timezone --utc 'US/Eastern' # Read partition information from a file we are going to populate in the %pre section # This allows me to create local vmfs with "hostname:storage1" and I've adjusted the sizes # on my service console partitions. %include /tmp/partconfig %pre --interpreter=bash |
Now the “%pre” section is where it begins to get interesting. We need to collect information for three things:
- Service Console IP
- iSCSI Service Console IP
- iSCSI Kernel IP
I have my script fill in all the other stuff, like subnet, gateway, VLAN excetera because we set up all of our hosts consistently and that stuff doesn’t change. You could easily expand on this part to prompt for other items. I’ve XX’d out my specific settings you will need to plug in your own if you model after this script.
So here is my “%pre” section…..
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | ################################# ### Get network information ### ################################# # Clear screen prior to prompting for input and change to virtual terminal 1 # vSphere will only work on tty1 to read input exec </dev/tty1 >/dev/tty1 chvt 1 header () { clear echo echo "################################################################" echo "### VMWare ESX 4.0 Scripted Install ###" echo "################################################################" echo } # Get user input while [ "$fqdn" == "" ] ;do header echo -n "Please Enter FQDN for ESX Host: " read fqdn done while [ "$ipnew" == "" ] ;do header echo "Important note: This scripted install assumes vmnic0 is a VLAN " echo "trunk and that the service console will be on VLAN XX" echo "" echo -n "Please Enter Main Service Console IP Address (ie. 10.XX.XX.XX): " read ipnew done while [ "$iscsi_kernel" == "" ] ;do header echo "Important note: This scripted install assumes vmnic1 is a VLAN " echo "trunk and that the iSCSI kernel will be on VLAN XX" echo "" echo -n "Please Enter iSCSI Kernel IP Address (ie. 10.XX.XX.XX): " read iscsi_kernel done while [ "$iscsi_srv" == "" ] ;do header echo "Important note: This scripted install assumes vmnic1 is a VLAN " echo "trunk and that the iSCSI service console will be on VLAN XX" echo "" echo -n "Please Enter iSCSI Service Console IP Address (ie. 10.XX.XX.XX): " read iscsi_srv done # To make these variables in the %pre section available in the %post section we have to do # a few tricks because the %post section is chrooted. # First save off the variables to the ram disk the %pre section is running in... cat <<EOF> /tmp/iscsiconfig iscsi_srv=$iscsi_srv iscsi_kernel=$iscsi_kernel EOF # Change back to tty 6 to watch progress on packages chvt 6 # Let's cut the fqdn suffix off the hostname so we can name the vmfs partition # named something like this: "hostname:storage1" temp_host=`echo $fqdn | cut -f1 -d"."` # Now we are going to save of partition information using the new vmfs volume name # so that it can be used by Weasel install cat <<EOF> /tmp/partconfig # Use first detected disk: clearpart --firstdisk --overwritevmfs part '/boot' --fstype=ext3 --size=1100 --onfirstdisk part 'none' --fstype=vmkcore --size=110 --onfirstdisk part $temp_host:storage1 --fstype=vmfs3 --size=90000 --grow --onfirstdisk virtualdisk 'esxconsole' --size=13804 --onvmfs=$temp_host:storage1 part 'swap' --fstype=swap --size=800 --onvirtualdisk='esxconsole' part '/var/log' --fstype=ext3 --size=3000 --maxsize=3000 --onvirtualdisk='esxconsole' part '/' --fstype=ext3 --size=10000 --maxsize=10000 --onvirtualdisk='esxconsole' EOF # Write the networkconfig file to be used by the Weasel install # Using the "--addvmportgroup=0" option because another script will define my specific port groups cat <<EOF> /tmp/networkconfig network --device=vmnic0 --bootproto=static --ip=$ipnew --netmask=255.255.255.0 --gateway=10.XX.XX.1 --nameserver=10.XX.XX.XX --hostname=$fqdn --addvmportgroup=0 --vlanid=XX EOF |
So now the Weasel installer can import from the Ram disk /tmp directory the Service console IP information and the partition information using directives like “%include /tmp/networkconfig” from above.
The %post section is a little more complicated because it is chrooted and therefore does not have access to the installation/Weasel /tmp location.
I get around this by have 2 %post directives…… the first one copies these previously configured /tmp configuration files to the chrooted source directory so that it will be available to the second %post section.
113 114 115 116 117 | # Need an extra post section that is not chrooted to save my variables from PRE %post --nochroot # Copy from ram disk to chrooted env used for POST cp /tmp/iscsiconfig /mnt/sysimage/tmp |
Finally my final post section does the following:
- Sucks in the %pre variables so that they can be used.
- Creates a startup script that will be executed during the first reboot.
- The startup script will download a further configuration script and execute it.
Here is the rest of my %post section:
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | %post --interpreter=bash # Now we need to suck in variables from PRE section . /tmp/iscsiconfig cat > /root/esxcfg.sh << EOF1 #!/bin/sh # # MAIN PROGRAM - ENTER HERE... # echo "# ESX Post Install Script" echo "# Opening Firewall ports..." /usr/sbin/esxcfg-firewall --allowOutgoing # Save off iSCSI info enter just incase cat <<EOF> /root/iscsiconfig iscsi_srv=$iscsi_srv iscsi_kernel=$iscsi_kernel EOF echo "# Transferring POST install files." cat > /tmp/ftpcmds << EOF2 open 10.XX.XX.XX user anonymous postinstall lcd /root cd esx bin get postinstall.tgz quit EOF2 ftp -in < /tmp/ftpcmds if [ ! -f /root/postinstall.tgz ] then echo "# ERROR.. unable to transfer postinstall.tgz ...exiting" exit 9 fi echo "# Transferred." echo "# Extracting files." cd /root tar -xzvpf /root/postinstall.tgz if [ ! -d /root/postinstall ] then echo "# ERROR.. postinstall.tgz not extracted ...exiting" exit 9 fi echo "# Extracted files." chmod 700 /root/postinstall/postinstall.sh echo "# Executing /root/postinstall/postinstall.sh" /root/postinstall/postinstall.sh echo "# Postinstall.sh - ended" echo “Removing automated post script.” rm /etc/rc3.d/S99postconf EOF1 cp /root/esxcfg.sh /etc/rc3.d/S99postconf chmod 770 /etc/rc3.d/S99postconf |
So that is about it. You can download my complete ks.cfg here. Good luck and shoot me a comment if you have a question.
Thanks for a great example! I’m stuck at one part though – I’ve set mine up to save a variable to /tmp/varfile in the %pre section (like you did) and then copy it from /tmp to /mnt/sysimage/tmp in the %post –nochroot section. Finally I source it (.) in the %post section (which is actually output to S99postconf). Doesn’t appear the file is actually getting copied to /mnt/sysimage/tmp since (I assume) it should STILL be in /tmp after the build is complete.
Any suggestions?
Comment by John Champion — December 31, 2009 @ 2:50 pm
Not sure what exactly is happening for your installation, but I wouldn’t count on anything in the /tmp location remaining across reboots of the system. I had similar problems and that is why I dump stuff to a file in the %post section to ease in diagnosing the problem. Maybe you could try something like this to help troubleshoot further:
%post –nochroot
cp /tmp/varfile /mnt/root/varfile # This way you can examine the contents
%post
. /root/varfile
Comment by Tim Lefler% — January 4, 2010 @ 4:27 pm
Can you help me remove the iscsi from the script. We don,t use ISCSI AT THE present time.
Comment by Sam — January 20, 2010 @ 6:06 pm
The First Post
Tim I am Getting an Error writing to ks.cfg
Writing to ks.cfg failed with Track Back
systeminstall.py
Have you seen this in the 4.0.1 Builds
I will try to get you a creen shot of the Error
Comment by Sam — January 21, 2010 @ 1:22 am
Sam,
As far as iSCSI is concerned the script above will work without modification. I collect the information during the install portion but don’t put it to use until my postinstall.sh script is executed. I setup stuff unique to my environment using this script and did not post the contents since it is customized heavily for my particular environment. If you don’t have a postinstall.sh or use one that doesn’t reference the environment variables for iSCSI then the information collected will just be ignored.
I have not tried this process with 4.0 update 1 as of yet so I’m not sure why it would be writing to “ks.cfg”. Have you tried it with ks.cfg on a USB device instead of burned to the CD?
Comment by Tim Lefler — January 25, 2010 @ 1:02 pm