ESXi kickstart with Python

I recently spent some time building kickstart files. Something I hadn’t done much since 2008. The most noticeable change in the process is I’m older and fatter. I re/learnt a few things, and did my first ever python script.

First up, William Lam has plenty of articles on the topic, and the official vSphere installation doco is pretty good too.
While testing, it’s much easier to link to a kickstart file or scripts from a webserver than directly embedded on the boot CD. For a lightweight webserver on Windows, I’ve used mongoose-free-6.4 available at
If you need to customise the installation process further, you can use Ash shell commands, or python 2.7 by using the switch –interpreter=busybox | python.

To see which python modules are available, view /lib/python2.7 on your ESXi host.

Mixing busybox and python.

I found it easier to start off with busybox, then call the python script.

%firstboot –interpreter=busybox

# For troubleshooting only
vim-cmd hostsvc/enable_esx_shell
vim-cmd hostsvc/start_esx_shell

wget -O http://webserver/

chmod u+x

When testing the whole kickstart file, put sleep 600; in %pre, %post or %firstboot sections, and jump to the console (Alt-F1) to test commands. You can also watch detailed messages using Alt-F12.
Keep in mind you may not be in a full blown ESXi environment, depending on if you’re in pre/post/firstboot.
%pre – Runs BEFORE the installation
%post – Runs AFTER installation. No hostd services are running. There is NO root password set and commands like esxcli won’t be available. You’ll need to use localcli instead.

%firstboot script is running now.

%firstboot – Runs at the very end of the first boot after installation. All services should be available. It’s the last thing that runs before the console shows the ESXi host name, IP. Look for “Running 001.firstboot_001”.

Deploy multiple ESXi hosts using kickstart and embedded CSV.

In a home lab or remote environment there may not be DHCP/PXE services, or justification for Auto Deploy. For that use case I created a boot CD that would install ESXi and set the hostname and IP based on matching the host’s MAC address with a CSV file included on the CDROM. Perfect for where there is no DHCP. If you have DHCP and a webserver available, you can host the CSV there so it can be easily updated.

First, customise an ESXi boot CD from William Lam.

Create the CSV file (HOSTS.CSV) in the format Hostname,MAC,IP,Subnet Mask,Gateway.


Create the python script (SETNET.PY) to check the CSV for the matching MAC address:

 2import os, commands, csv, subprocess
 4MAC=subprocess.check_output("esxcli network ip interface list |grep MAC",shell=True)
 6MACADDR = MAC.split()
 8with open(/vmfs/volumes/datastore1/HOSTS.CSV, rb) as f:
 9        reader = csv.reader(f)
10        for row in reader:
11                if MACADDR[2] == row[1]:
12                        os.system("esxcli system hostname set –fqdn=" + row[0])
13                        os.system("esxcli network ip interface ipv4 set –interface-name=vmk0 –ipv4=" + row[2] + " –netmask=" + row[3] + " –type=static")
14print "End of loop"

[This was my first time to use python, so i chose a range of functions that worked at the time. Be wary of python’s strict indentation requirements.]
Copy HOSTS.CSV and SETNET.PY to the custom ESXi boot CD just before the mkisofs step in Williams post.
The hard part was getting the files from the CD, to a location available during firstboot. If you’re installing to an ESXi disk bigger than 6GB, a VMFS datastore will be created and we can use that for persistent storage.

Include the following in your ks.cfg:

 1%post --interpreter=busybox
 3cp /vmfs/volumes/CDROM/BUILD/HOSTS.CSV /vmfs/volumes/datastore1
 4cp /vmfs/volumes/CDROM/BUILD/SETNET.PY /vmfs/volumes/datastore1
 6%firstboot --interpreter=busybox
 8sleep 30;
10chmod u+x /vmfs/volumes/datastore1/SETNET.PY
11/bin/python /vmfs/volumes/datastore1/SETNET.PY

This gets the ESXi host configured with a hostname and IP where you can join it to vCenter and do the remaining configuration or apply Host Profiles.