VMware – PowerCLI | Deploy Ubuntu/Debian VM from template and set basic parameters

Today it’s a common task of an operator to create a new virtual machine quickly for a customer or for testing purposes. Scripting the setup and the basic customization can provide a good basis for automation, mass deployment or integration with self-service portals as well.

The following example intends to give hints on basic usage of PowerCLI and a simple checklist: which basic parameters should be customized for a newly deployed VM.


  • installed Ubuntu/Debian system with LVM and VMware-tools
  • known root password 🙂 (if not known, reset it)
  • vCenter server with the Ubuntu template in it’s inventory
  • PowerCLI installed on a Windows machine that is capable of connecting to the vCenter server


Each of these steps may be executed manually or using the corresponding piece of code below

  1. Connect to vCenter server
  2. Create VM from template
  3. Set RAM, Memory and Disk size
  4. Boot the VM
  5. Configure the network
  6. Update the OS
  7. Extend the root partition
  8. Set the hostname

The non-manual way


First we’ll ask the user for the parameters of the VM. They could also be acquired as input parameters, or read from a csv file as imput.

param (
[Parameter(Mandatory=$true, HelpMessage=”Template Name”)] [ValidateNotNull()] [string] $Template,
[Parameter(Mandatory=$true, HelpMessage=”Template’s original root password”)] [ValidateNotNull()] [string] $VMOrigRootPwd,
[Parameter(Mandatory=$true, HelpMessage=”VM Name”)] [ValidateNotNull()] [string] $VMName,
[Parameter(Mandatory=$true, HelpMessage=”Memory [MB]”)] [ValidateNotNull()] [int] $VMMemory,
[Parameter(Mandatory=$true, HelpMessage=”vCPU”)] [ValidateNotNull()] [int] $VMCPU,
[Parameter(Mandatory=$true, HelpMessage=”Disk [GB]”)] [ValidateNotNull()] [int] $VMDiskSize,
[Parameter(Mandatory=$true, HelpMessage=”IP Address network-part”)] [ValidateNotNull()] [int] $VMIPN,
[Parameter(Mandatory=$true, HelpMessage=”IP Address last octet”)] [ValidateNotNull()] [int] $VMIPL,
[Parameter(Mandatory=$true, HelpMessage=”Hostname”)] [ValidateNotNull()] [string] $VMHostName,
[Parameter(Mandatory=$true, HelpMessage=”ESXi host”)] [ValidateNotNull()] [string] $ESXiHost,
[Parameter(Mandatory=$true, HelpMessage=”Datastore”)] [ValidateNotNull()] [string] $Datastore

 Connect to vCenter server

The name of the vCenter server is fixed here. It may also be a parameter.

$VCSCred = $Host.UI.PromptForCredential(“Please enter credentials”, “Enter Guest credentials for vcs”, “root”, “”)
Connect-VIServer vcs -Credential $VCSCred -SaveCredentials

Create the VM from template

new-vm -Name $VMName -template template-$Template -VMHost (get-vmhost $ESXiHost* |Select -first 1) -Datastore $Datastore

Set resources

Set-VM $VMName -MemoryMB $VMMemory -NumCpu $VMCPU -Confirm:$false
Get-HardDisk -VM $VMName|Set-HardDisk -CapacityGB $VMDiskSize -Confirm:$false

boot the VM

Start-VM $VMName

and wait till it’s VMware-tools starts – if you fail to have VMware-tools in the template – well – you’ll spend ~infinite time here 😛

write-host “Waiting for VM Tools to Start”
do {
$toolsStatus = (Get-VM $VMName).extensiondata.Guest.ToolsStatus
write-host $toolsStatus
sleep 3
} until ( ($toolsStatus -eq ‘toolsOk’) -or ($toolsStatus -eq ‘toolsOld’)   )

Configure network

Assuming /24 network, 254 as the gateway and using Google’s DNS servers. Obviously You could also use an extra parameter for these.

$VMNetwork=”auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
address $VMIPN.$VMIPL
network $VMIPN.0
broadcast $VMIPN.255
gateway $VMIPN.254

$configNetwork=”echo `”$VMNetwork`” > /etc/network/interfaces.bak;sed `’s/; /\n/g`’ /etc/network/interfaces.bak > /etc/network/interfaces; rm /etc/network/interfaces.bak;service networking restart”
Invoke-VMScript -ScriptType bash -VM $VMName -ScriptText $configNetwork -GuestUser root -GuestPassword $VMOrigRootPwd

Update the OS

$updateOS=”apt-get update;apt-get -y dist-upgrade”
Invoke-VMScript -ScriptType bash -VM $VMName -ScriptText $updateOS -GuestUser root -GuestPassword $VMOrigRootPwd

Extend the root partition (lv)

We’re using a scripts.iso with extendLVMfirst.sh script on it. This method could be used for the other steps too. EG passing the IP as a parameter to a script that modifies a prepared template.

extendLVMfirst.sh – not a masterpiece for sure 🙂


apt-get -y install parted bc

end=`parted /dev/sda unit cyl p free|tail -2|head -1|awk -F ‘ ‘ ‘{print $2}’|awk -F ‘cyl’ ‘{print $1}’`;end=`echo $end-1|bc`
lvbegin=`parted /dev/sda unit cyl p free|tail -2|head -1|awk -F ‘ ‘ ‘{print $1}’|awk -F ‘cyl’ ‘{print $1}’`;end=`echo $end-1|bc`
begin=`parted /dev/sda unit cyl p free|grep lvm|awk -F ‘ ‘ ‘{print $2}’|awk -F ‘cyl’ ‘{print $1}’`

parted /dev/sda unit cyl resize 2 $begin $end -s
parted /dev/sda unit cyl mkpart logical $lvbegin $end -s

pvcreate /dev/sda6
vgname=`vgdisplay |grep “VG Name”|awk -F ‘ ‘ ‘{print $3}’`
vgextend $vgname /dev/sda6
lvextend /dev/$vgname/root -l +100%FREE
resize2fs /dev/$vgname/root

apt-get -y remove –purge parted bc

commands to extend the patrition with PowerCLI

assuming the name of the datastore containing scripts.iso is datastore1

$ISOPath=”[datastore1] iso\scripts.iso”
get-cddrive -VM $VMName | set-cddrive -IsoPath $ISOPath -Connected $true -Confirm:$false

$extendPartition=”mount /dev/cdrom /media/cdrom/; sed $’s/\r//’ /media/cdrom/extendLVMfirst.sh > doit;sh doit;rm -f doit;umount /media/cdrom”
Invoke-VMScript -ScriptType bash -VM $VMName -ScriptText $extendPartition -GuestUser root -GuestPassword $VMOrigRootPwd

get-cddrive -VM $VMName | set-cddrive -NoMedia -Confirm:$false

Set the hostname

$hostsFile=”       localhost

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters”

$setHostName=”echo `”$VMHostName`” > /etc/hostname; echo `”$hostsFile`” > /etc/hosts.bak; sed `’s/; /\n/g`’ /etc/hosts.bak > /etc/hosts; rm /etc/hosts.bak”
Invoke-VMScript -ScriptType bash -VM $VMName -ScriptText $setHostName -GuestUser root -GuestPassword $VMOrigRootPwd

and finally reboot to the newly deployed VM with basic customization

Restart-VMGuest -VM $VMName -Confirm:$false

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s