Simple PowerCLi script for batch virtual machine deployment

<Update – August 25th, 2014>
Hello! If you are reading this you might be also interested in an updated version of this script, that I posted here.
It includes background jobs, asynchronous tasks and displays colorful messages too!

First of all – I’d like to introduce myself as this is the first blog post I ever wrote in my life

My name is Sebastian Baryło and Artur was brave enough to invite me to contribute to his blog every now and then.

I am that kind of lazy person who prefers to spend two days on writing and testing a script rather than spend half a day on manual iterations of tedious tasks, so most of my posts here would be in “PowerCLI scripts” category, but I will try to share my knowledge on anything interesting that I experienced during my daily struggle of being system engineer.

What I would like to share today is “yet another vm deployment script” that might come handy when you want to automate deployment of  a batch of virtual machines (in my case they were windows desktops)

Of course having a proper template and OS Customization Specification are pre-requisites, once you have them you need to prepare (or better yet – request from your customer) input for the script in the form of .csv file (let’s call it vms2deploy.csv) that should look like this.

I hope it is pretty self-explanatory what does each of the fields mean, please note that I’m using datastore clusters here, but it is very easy to replace them with single datastores (get-datastorecluster cmdlet in the script just needs to be replaced with get-datastore)

Now that we know what to deploy, it is time to introduce the script.

It is pretty lenghty – I know, but I blame it on the comments 🙂

Not really rocket science with deployment part – it is just feeding new-vm cmdlet with what we read from .csv, you can easily extend functionality here with customizing things like number of cpus or amount of memory per vm, the more interesting part for me is how we configure IP settings during deployment.

At first I experimented with set-vmguestnetworkinterface and invoke-vmscript cmdlets, but I wasn’t very successful as above cmdlets have very specific requirements that you can find described in excellent post of LucD here.

Finally I decided to use OS Customization Specification to configure IP settings for deployed vm, the script first creates a “temporary clone” of “master” OS customization provided in .csv file, modifies it to include IP settings specified, deploys and powers-on the vm and cleans up by deleting “temporary clone” of OS customization.

Please note that to run “oscustomizationspec related” cmdlets you need to use 32-bit version of PowerCLi.

You may wonder about the sequence of three “until-loops” that I used to control whether deployment is successful, I know it is not very elegant (proper way would probably be to query vCenter for events like “CustomizationStarted” etc) but it just does the job.

First loop waits until vmware tools are running for freshly deployed vm (so the intial power-on is successful),
the second waits for a reboot initiated by OS Customization (at least in case of deploying Windows XP) and the final is running in circles until vmware tools are available again (customization successful).

You can probably remove third loop (and proceed with deployment not waiting for completion of OS customization – which is usually the longest part).

As you can see there is also some timeout control introduced, vmware tools are checked every 3 seconds, so $timeout value of 1800 gives us not more than 90 minutes of waiting for deployment of single vm (it is very long – I know, but the way I was using this script is to fire it at the end of business day and check the results next morning).

What can be improved?

You might want to run many “new-vm” tasks simultaneously (with start-job cmdlet for example), this should be possible since each vm deployed is using its own copy of OS customization.
And yeah – sanitizing input (checking for empty fields in .csv file) could have probably be done in one line, but I’m a bit “old-school” when it comes to scripting and I like to be able to see what is going on there 😉

I hope you find this script useful, any comments are welcome!

Sebastian Baryło

Successfully jumping to conclusions since 2001.

  • Chris

    Hi there – great script…even without powershell-jobs and with until-loops 😉

    How did you manage to get the OS Customizations working for Windows Server 2012 (and 2012R2)?

    • sbarylo

      Hi Chris, thanks for positive feedback!
      I’m actually working on re-writing this script to use “jobs” and make it deploy (at least a few) vms in parallel (cause this is the “demand” from my colleagues that are using it everyday 😉 ), so stay tuned for updates ;).
      As for Win2k12… I honestly haven’t tried to script-deploy this OS (yet) :o, so… I don’t even know if it works, sorry.
      Do you have any experience? Anyone? Beuller? 😉

      • Chris

        Hi, thanks for your super-fast reply…in my experience, guest customizations don’t work at all on 2012… 🙁

        Regarding your script: I’ll try to deploy ’bout 150 2012R2 VMs with a minimally altered version of it today…will tell you if I have success 🙂

        • sbarylo

          WoW! 150 VMs! That will take a while!
          You might want to have more than one instance of (any) “deployment script” running for that (divide your batch of vms accordingly of course 😉 )

  • venkatesh

    hi i tried this script it works for me but i am getting error for this oscustomizationspec can you please tell what is this and how to create . and the ipaddress are not assigning to the vm .

  • Pingback: Return of the Automated Linked Clones -

  • Daniel Hill

    If you copy the script from the website, make sure you check for non printable characters. I found a bunch around the match commands.