Automatic Virtual Machine Creation from command line in VMware's ESXi

This post is 4 years old. (Or older!) Code samples may not work, screenshots may be missing and links could be broken. Although some of the content may be relevant please take it with a pinch of salt.

In my current job I work a lot with Virtual Machines - mainly with VMWare's ESXi - and I'm sure all of you already know that it's basically a bare metal embedded hypervisior. (A hypervisior is just a piece of software that creates and runs virtual machines). Virtualisation is great. In fact it's awesome. Who doesn't like to have a server which can be crashed, and simply restored from a snapshot? I believe that it gives developers and system administrators great flexibility not only to develop something new but also to freely test updates. Anyway, let's be serious for a moment.

Currently I look after about 30 virtual machines and the biggest issue I faced was back in the day when I had to set them up, and of course some of them failed for various reasons and I had to recreate the machines from scratch. The fact that I had to setup 10s of virtual machines a day wasn't appealing especially because and it is a rather cumbersome exercise to open the vSphere client, create a new virtual machine, configure the machine - add RAM, HDD, CPU, ISO image - and start it up. Then onto the next one, and the next, and the next ... So you can all see why I came up with a script that automates all of this. All I have to do now is copy my script onto the ESXi itself - most probably via 'scp' and add the right parameters and hit enter - the virtual machine gets created in about 5 seconds, now that's what I call time-saving! Let's go through this script now.

As always, the bash script is available on Github. The first thing to note is that the first line is not /bin/bash but:

#!/bin/sh

The reason for this is that ESXi is running a very bare-bone version of Linux and on top of that they utilise 'BusyBox' which is a single piece of binary code that provides a number of basic services/commands and due to these 'limitations' shall we say, /bin/bash doesn't exist.

My script accepts the following parameters:

- n: Name of the Virtual Machine (this parameter is required)
- c: Number of virtual CPUs (has to be an integer and between 1 and 32
- i: Location of an ISO image (has to have an .iso extension)
- r: RAM size in MB (needs to be integer and greater than 1MB)
- s: Disk size in GB (needs to be an integer and greater than 1GB)

As you can see the only required parameter is the name of the machine, the rest is optional, and other than the location of the ISO image, all the other parameters have defaults: CPU: 2, RAM: 4096MB and HDD-SIZE: 20GB.

This is the big while loop that takes care of pretty much everything:

while getopts n:c:i:r:s: option
do
case $option in
n)
NAME=${OPTARG};
FLAG=false;
if [ -z $NAME ]; then
ERR=true
MSG="$MSG | Please make sure to enter a VM name."
fi
;;
c)
CPU=${OPTARG}
if [ `echo "$CPU" | egrep "^-?[0-9]+$"` ]; then
if [ "$CPU" -le "0" ] || [ "$CPU" -ge "32" ]; then
ERR=true
MSG="$MSG | The number of cores has to be between 1 and 32."
fi
else
ERR=true
MSG="$MSG | The CPU core number has to be an integer."
fi
;;
i)
ISO=${OPTARG}
if [ ! `echo "$ISO" | egrep "^.*\.(iso)$"` ]; then
ERR=true
MSG="$MSG | The extension should be .iso"
fi
;;
r)
RAM=${OPTARG}
if [ `echo "$RAM" | egrep "^-?[0-9]+$"` ]; then
if [ "$RAM" -le "0" ]; then
ERR=true
MSG="$MSG | Please assign more than 1MB memory to the VM."
fi
else
ERR=true
MSG="$MSG | The RAM size has to be an integer."
fi
;;
s)
SIZE=${OPTARG}
if [ `echo "$SIZE" | egrep "^-?[0-9]+$"` ]; then
if [ "$SIZE" -le "0" ]; then
ERR=true
MSG="$MSG | Please assign more than 1GB for the HDD size."
fi
else
ERR=true
MSG="$MSG | The HDD size has to be an integer."
fi
;;
\?) echo "Unknown option: -$OPTARG" >&2; phelp; exit 1;;
:) echo "Missing option argument for -$OPTARG" >&2; phelp; exit 1;;
*) echo "Unimplimented option: -$OPTARG" >&2; phelp; exit 1;;
esac
done

I'm using these values to first create the folder for the Virtual Machine, then to assign the right values for the right configuration files, then I add the virtual machine to the ESXi's registry and finally I start it up:

mkdir ${NAME}

#Creating the actual Virtual Disk file (the HDD) with vmkfstools
vmkfstools -c "${SIZE}"G -a lsilogic $NAME/$NAME.vmdk

#Creating the config file
touch $NAME/$NAME.vmx

#writing information into the configuration file
cat << EOF > $NAME/$NAME.vmx
#adding variables -- note code has been trimmed:
numvcpus = "${CPU}"
scsi0.present = "TRUE"
scsi0.sharedBus = "none"
scsi0.virtualDev = "lsilogic"
memsize = "${RAM}"

EOF


#Adding Virtual Machine to VM register - modify your path accordingly!!
MYVM=`vim-cmd solo/registervm /vmfs/volumes/datastore1/${NAME}/${NAME}.vmx`
#Powering up virtual machine:
vim-cmd vmsvc/power.on $MYVM

Et voilà - we have a running virtual machine! Don't forget to check out the whole source code on Github.

For further configuration options for the .vmx files, please have a look at this site.