November 25, 2009

Notes on How to perform a scripted install of VMware ESX 4.0

Filed under: vmware — Tags: , , , , , , , — Tim Lefler @ 5:32 pm

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:

  1. Installation is done totally from media so network not required during the scripted installation
  2. One configuration script for any ESX host being installed that prompts for dynamic elements.
  3. A post installation download of an additional script that can be easily updated without changing the installation media.
  4. The downloaded script can configure anything that can be configured on a running ESX host.
  5. 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”.

Select

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.

5 Comments »

  1. 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

  2. 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

  3. 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

  4. 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

  5. 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

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress