The ultimate VM batch deployment script.

In my first blog post ever, almost three months ago I shared my good ol’ script for batch deployment of virtual machines.
That script served me well for quite a few years already, but it was somewhat on the crude side of scripting.
It was using new-vm cmdlet sequentially for each line of .csv input and the method of controlling the deployment progress was just a sequence of while loops that tested the status of VMTools in freshly deployed VM.
Not very elegant, but this wasn’t a big issue for me, neither was the sluggishness of synchronous deployment.
I simply used to run this script overnight and if I had any concerns the batch would not complete before I come back to work in the morning, I would just split it into separate .csv-s and start multiple instances of PowerCLI for that.

Once that simple script “went public” I made a commitment to “some people” that I will re-write it to use async tasks (so deploy multiple VMs simultaneously) and I promised to finish that before my summer holiday this year ;).

This was also great opportunity for me to learn more on how to control background jobs, so here we go.

The new script still takes input (VMs to be deployed) from a CSV file which should be saved in script’s working directory, under “hard coded”  name of vms2deploy.csv.

Just to remind you, the CSV file should look somewhat like this:

Fields are still pretty self-explanatory I believe, but I introduced first improvement here already – as you can see for deploying a Linux VM you can (in fact you should) put “none” as value of “dns1” field.
This is because it is impossible to set DNS servers configuration via OS Customization Specification for Linux VMs (there is a check in the script that handles this value properly).
Not much else to comment on here, except maybe “datastorecluster” field – If you’re still not using Datastore Clusters in your environment, you should modify this script to use get-cluster cmdlet instead of get-datastorecluster where necessary (it is only used twice, so this shouldn’t be a big problem 😉 ).
If you do use Datastore Clusters however, remember to turn Storage DRS (SDRS) on.
This is required for initial placement of new VMs on the datastores just like DRS is required for initial placement of new VMs on hosts. If SDRS is not enabled the script will fail miserably (and silently 😉 ).
Many thanks to @KrazieEyes for finding this out and letting me know via Twitter!

Because of this KB script requires PowerCLI 5.5 R1 and because I manipulate OS Customization Specifications during deployment, it needs to be started from 32-bit PowerCLI window…
Well, not anymore – as pointed-out by Shawn Masterson below, VMware did a great job recently and complied 64-bit versions of “OS Customization related” cmdlets, that’s why the condition in Line 371 is fixed to $true now 😉 .

The general workflow for the script is as follows. In step one input is sanitized (empty fields and duplicate VM names are eliminated from CSV file), then script groups VMs to be deployed per host cluster and starts a separate background job (so separate PowerShell process) for each cluster.
I still tend to think in host clusters categories, if you also group your hosts in logical folders (which is actually VMware’s recommendation), I encourage you to modify this script to use -Location instead of -Cluster where necessary.
After dispatching background jobs the only responsibility of “main” script is to pool these jobs every 20 seconds and display overall progress, as usual quite detailed logging is done both for main script and for each background deployment job.

This is how the code looks:

WoW! That was long! A new record of 486 lines!

But seriously – control part of the script is contained between Line 325 and Line 486, this is where input is sanitized and background jobs are dispatched.

From Line 413 to the very end the script is only pooling these jobs for progress and displaying information about it.

All the “deployment magic” happens in a humongous script-block defined between Line 97 and Line 320, so lets focus on that first.

Because this script-block is started as separate PowerShell (not PowerCLI!) process we first have to (and this time I mean it) load the PowerCLI snapin, then connect to our vCenter Server (because background job doesn’t inherit this connection).
As you can see vCenter address and log-on credentials (gathered from user upon script start-up) are passed to script-block as parameters. The three remaining parameters are array of VMs to be deployed in given cluster and locations of log and progress tracking files. The helper object to track job progress is defined between Line 100 and Line 110

Now, I was trying to “think big” when writing this script, but I’m also a bit of a “control freak”, so I decided against just firing all the VMs we want to deploy at once. You can of course start 100 or more new-vm tasks asynchronously and let vCenter sort the load out, but well… I prefer to do it in smaller chunks, with cluster capacity in mind if possible. That’s why I’ve defined two while loops that make sure each available host in cluster is deploying at most one VM at any given moment this script-block is running. The loops continue until we run out of VMs from input. You can say this slows the whole process down, but in my opinion it is better to be safe than sorry.
When your cluster runs out of capacity for example (because you requested too many VMs to be deployed) and DRS is not able to power on any VMs more (I actually created such condition for testing purposes, you can see that in screenshots below), the deployment will just stop in a controlled way, without overloading vCenter or anything, this approach also makes control of deployment and OS Customization faster and less resource greedy.
Last but not least – it is really easy to change this code to start more than one VM deployment per host ;).

As for deployment control – I use classic method described by Luc Dekens (who else? 😉 ) ages ago. Between Line 150 and Line 202 a “chunk” of new-vm tasks is started asynchronously, information about these tasks is saved into a hash table, using task id as hash and name of deployed VM as value.
Further on (between Line 205 and Line 225) list of recent tasks is retrieved from vCenter and matched against our saved ids. If there is a match and the task was successful we power on the machine (to let OS Customization process begin) and remove this task from our table (removing is also done for all failed tasks).
This part loops until we run out of deployment tasks, then new “chunk” is started.

Only after we deploy (and hopefully power on) all requested VMs, we switch to track the progress of OS Customization inside the guests. If your batch is on the larger side, there is a good chance that some of the OS Customizations will complete before we even check ;). This part of script is “inspired” (OK, I almost copy-pasted it completely 😉 ) by excellent post of VMware’s Vitali Baruh. Although it looks somewhat complicated (defining a script-block inside script-block to control main loop…) the idea is not that difficult to perceive.
Basically for each VM that powered-on successfully (we don’t care about failed ones anymore) we search vCenter events for “CustomizationStarted”, “CustomizationSucceeded” and “CustomizationFailure” events. The loop repeats every 10 seconds (like all loops in this script-block) until we are out of VMs or time-out (fixed to 7200 seconds or two hours) elapses.
I would like to stress-out that this time-out is only for OS Customizations part (we all know how many things can go wrong there, right?), by no means will it disrupt “deploy and power on” part of the script-block.

And that’s basically it for the “worker horse” of this script.

I have to admit I cheated a little in the main loop that displays script progress…
As you can see every major loop inside the script-blog dumps current progress indexes (I define 6 of them between Line 100 and Line 110) to a .csv file inside the script log directory.
The control loop in main script section picks-up these indexes for all dispatched background jobs and estimates overall progress (or at least tries to do so 😉 ).
You’re free to say it is neither most elegant nor the fastest way to track progress of background jobs, but it just does the trick and I’m not too worried that short write sequence every ten seconds will kill your storage subsystem ;).
In the first stage of workflow the progress is calculated as proportion of sum of VMs that powered on successfully (or failed across all background tasks) against the grand total of VM deployment requests (from CSV file), so your PowerCLI window might look like that:

ultimate1

Then, if script detects that OS Customization has started inside any of the background jobs (CUSTSTART index greater than 0), it switches to displaying progress as sum of successful and failed customizations compared to total of successfully powered on VMs.
You can see that “current activity” field displayed by write-progress cmdlet changes from “VM deployment in progress” to “VM OS Customization in progress”.

ultimate2

This might have funny effects, in situations where you, for example, deploy one “monster VM” in (say) “server cluster” and a bunch of small VMs in (say) “vdi cluster”.
Probably many of the small VMs will power on before “the monster”, so your indicated progress will be soaring, then once “monster VM” starts OS Customization, the progress will suddenly drop to zero…
To my defense: this approach always shows “worst case” scenario, so you will never see progress bar stuck at 100% for hours and such unexpected behavior can be somewhat amusing while you wait for jobs to complete ;).

I call this script “ultimate” for two reasons. First of all – as a joke of course :D.
Secondly – I really have no idea how to make it more complex… ah wait… I could introduce additional safety checks (like free diskspace in datastores, or load on host clusters) or I could introduce customization of vCPU and vRAM assignments (so that VMs could be deployed with resources different from the ones fixed in template)…
Sky is (almost) the limit and maybe I should come back to this script once again in the future .
(Read: after I’m back from holiday 😉 ).

That’s it for now. I hope you will find this script useful, feel free to share or provide your feedback!

<Update, August 29th, 2014>
I just noticed that (by mistake) I posted “very early” version of this script…
While I create a “very advanced hash-table” in Line 395  I do not make any use of it (at least not in the version originally posted) 🙁
Instead I just did a rudimentary query (Line 402 of “early script”) for all background jobs that are running (which in some cases – like “orphaned” background jobs – can lead to unexpected results).
This was legacy from the time I struggled a bit with controlling these jobs, so I corrected it and now you see a really “elegant” way of querying only the jobs we started between Line 409 and Line 421.
Enjoy!
</Update>

Sebastian Baryło

Successfully jumping to conclusions since 2001.

  • smasterson

    Excellent script! One note – moving to PowerCLI 5.5 R2 would alleviate the need to use a 32bit PowerShell console.

    • sbarylo

      Hi Shawn! Thanks for the positive feedback! And thanks for the hint 😉
      I guess I saw your script of this kind among pingbacks under Luc’s post about async tasks. I was impressed and I was wondering how did you make it work without 32bit, so R2 is the answer! 🙂

  • kevon27

    Hi.. How would someone run this script especially if they are a beginner at scripting..

    • sbarylo

      Hi. Well, you need the basic knowledge on how to use (start) PowerCLI console (I assume you do have it installed).
      The script has short “help” section that you can read from the script directly or use get-help ultimate_deploy.ps1 (assuming you copied the script and saved it under “ultimate_deploy.ps1” name in your working directory).
      The only prerequisite is to have a properly formatted CSV file (see example above) saved under “vms2deploy.csv” name in the same folder as script.

  • Todd Russell

    I am trying to use this for mass builds but it keeps using the same host names and not all of them. I use names sequentially and it picks only a few repeatedly and skips the others entirely. For example, guests named ABCDCTX101 – ABCDCTX160 would be in the CSV and it will choose 108, 109, and 122 and start them off. It will try the same three names every time and all of them fail. If I use less machine than the number of the hosts in a cluster I get a divide by 0 error. Any help would be great.
    Thanks.

    • sbarylo

      Hi Todd! Looks like some scenario I didn’t think of during the testing, can you share (contact me privately via Linkedin or Twitter) the .csv you’re using together with your host/cluster layout?

    • sbarylo

      The division by zero error is really strange anyways – the only division operations in this script are inside arguments for “write-progress” cmdlet and they only use VM related counters, I can’t really help you without looking into your .csv (and some basic knowledge about your host / cluster layout)

    • sbarylo

      One thing that came to my mind (after 2nd and 3rd thought 😉 ). Do you have datastore clusters implemented or still using “standard” datastores? If the latter is the case this script requires small modification (as mentioned in the post itself).

    • sbarylo

      And if you do have Datastore Clusters – make sure SDRS is enabled, otherwise initial placement of VMs will fail (as just pointed out by @KrazieEyes ).

  • JuanJose Vidañez

    Hey,
    Looks really good I’m going to try it with powercli 5.8 R1.
    Did you think to introduce also the portgroup configuration?

    • sbarylo

      This is actually good idea to introduce portgroup configuration (if different than inherited from template). It should be really easy (using -NetworkName parameter of New-VM cmdlet) for single vNIC virtual machines (and I encourage you to modify this script yourself! 😉 ).
      On the other hand – if I wanted to “go big” and try to recognize between single and multi homed VMs, the script would grow well above 500 lines and well…
      I think it is hardly readable already ;).
      Maybe it’s easier to write a separate, much shorter script that would take care of network reconfiguration of newly deployed VMs (taking “progress indicators” of this script as input for example).

      • Reza Ambler

        The only problem here is that -Template and -NetworkName / -PortGroup are in different parameter sets of New-VM

  • Rehman Memon

    Hi!

    Thanks for the script, would appreciate some help, I have gone through your instruction but all I am seeing is :

    [2014-10-21 18:05:04] :Info: Out of total 4 VM deploy requests there are 0 VMs successfully powered on, 0 failed.

    [2014-10-21 18:05:04] :Info: Out of total 0 successfully powered on VMs OS Customization has started for 0 VMs, succeeded for 0 VMs, failed for 0.

    The script has been running for over an hour! Anything I should be looking at? The input CSV has the esx hostname and the folder name is where I want the VM’s to land in vcenter server. Any pointers will be greatly appreciated.

    • sbarylo

      Not sure if I understand you correctly about esx hostname in the CSV file but the script expects DRS cluster name as one of the inputs.
      It will not work with single host (unless you modify it – which I encourage you to do) but then why would you need async deployment if you know which host you want to deploy to 😉
      Hope you’d understand I don’t really had time and resources to test this script in-and-out like a commercial product (which this script is not), it worked in scenarios I was able to think of but for sure there are many scenarios that I simply didn’t cover 😉
      And here is a field for your invention to introduce own modifications 🙂
      The script also writes a pretty detailed log per every background job, so check the logs for what is failing exactly.

  • Hi,

    It must be a little problem for customization on linux systems.

    The script poweron the VM but never customatize it and keep on a infinite loop on messages:

    [2014-10-28 10:51:00] :Info: Out of total 2 VM deploy requests there are 2 VMs successfully powered on, 0 failed.

    [2014-10-28 10:51:00] :Info: Out of total 2 successfully powered on VMs OS Customization has started for 0 VMs, succeeded for 0 VMs, failed for 0.

    Any idea?

    • sbarylo

      Yeah 🙁
      OS Customization is “delicate” topic (I mention it in the post that many things can go wrong during this process) and there is many official VMware KBs on why it can fail and how to deal with it.
      Do the OS Customization work when you deploy VMs manually?.
      If you don’t see “customization started” events in the vCenter logs for that deployed VM(s) then indeed you have some issue with this.
      The root cause of this issue is however outside of the script who is just using plain “new-vm” cmdlet, which depends on vCenter to start customization, no special tricks here.
      Even in case the customization doesn’t even start, the loop should not be infinite, there is “timeout” variable defined in line 138 and set to 7200 seconds (or 2hrs), so the script should not run for more than two hours (provided my code is correct, cause honestly I didn’t have patience to test that scenario 😉 ).
      You can try to decrease the value of this variable to finish the script earlier (shorten the timeout) or modify the script (two lines where “new-vm” is invoked) to not use OS Customizations.
      Then again – the reason why customization does not work in your environment is outside the script, I encourage you to search KBs and communities to troubleshoot it.
      Good luck!

      • I found the issue, it’s because in the OScustomizationSpec that you had to have already created before run the script, the option to set the hostname must be set to “Use virtual Machine name”. This would be good to be explain on the script explanation.

        Just a thought, about customization would be good to create it with -nonpersistent option and you dont need to delete…

        Thanks!!

        • sbarylo

          Hi!
          Thanks for the feedback!
          Indeed the script expects OS customizations to be ready before deployment is started and does not create them “on-the-fly” (this is what I always do, so this approach was “natural” to me but when I think about it now it can be root-cause for issues of Rehman and Todd below, so thanks for pointing this out!)
          And I didn’t even know about -nonpersistent option for “customization related” cmdlets, so I will use them for sure (to make script shorter and more readable).
          Many thanks!

  • bburt

    Hi!

    First of all great script! I’m running into an issue where it keeps saying X# of VMs have failed while the vmware files are being copied.

    [2014-11-05 10:52:33] :Error: Out of total 2 VM deploy requests there are 0 VMs successfully powered on, 2 failed.

    After they finish copying and start up it still says X# have failed but the same number successfully powered on:

    [2014-11-05 10:59:35] :Error: Out of total 2 VM deploy requests there are 2 VMs successfully powered on, 2 failed.

    then never continues from there and gives an error:
    ——-
    Write-Progress : Cannot validate argument on parameter ‘PercentComplete’. The 200 argument is greater than the maximum allowed range of 100. Supply an argument that is less than or equal to 100 and then try the command again.
    At C:Usersbenjamin.burtDocumentsScriptsMTServerDeploy.ps1:361 char:185
    + … ercentComplete (($processed_vms / $total_vms) * 100) -CurrentOperation “VM deplo …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Write-Progress], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.WriteProgressCommand

    ———

    Any ideas whats going on here?

    Thanks,
    Ben

    • sbarylo

      Hmm… I mentioned in the post that I’m “cheating a little” with these counters 😉
      But this is 2nd time somebody mentions errors coming from “write-progress”.
      Have you checked all the issues with the script listed in comments here? (like proper Customization Specs, working Datastore Cluster and all things I assumed “default” ?)
      Do VMs deploy and power-on properly?
      If so can you show an example of your .csv and share some information about your environment?
      Also – any specific errors/warnings in the vCenter log?

  • Cory S

    Everytime I try to run it I just get the following

    Attempted to divide by zero.

    At U:scriptsdeployvms.ps1:361 char:31

    + “{0:N2}” -f (($processed_vms / <<<< $total_v

    + CategoryInfo : NotSpecified: (:)

    + FullyQualifiedErrorId : RuntimeException

    Attempted to divide by zero.

    At U:scriptsdeployvms.ps1:361 char:203

    + write-progress -Activ

    ployment jobs in progress" -Status "Percent com

    _vms / $total_vms) * 100))%" -PercentComplete (

    ms) * 100) -CurrentOperation "VM deployment in

    + CategoryInfo : NotSpecified: (:)

    + FullyQualifiedErrorId : RuntimeException

    • Kyle Burk

      I solved this by changing line
      $total_vms = $vms2deploy.count
      to
      $total_vms = $vms2deploy.name.count

  • Cory S

    I got this working, looks like when you install PowerCLI you really do need to reboot 😛 One question. is there away to assign multiple IPs to a new VM? I am deploying 300 web servers with 6 IPs each atm. Currently, I am using a fairly simple script on the C drive which asks you to manually input the last octet of the IP. It is a time saver, but a fully automated method would be more more preferable.

    • sbarylo

      Hi Cory!
      Glad to hear you made it work 😉
      Anyways – there has been too many “reports” of division by zero errors with this script, looks like my “cheating” with displaying progress just bitten me back and I really have to review this part of script (and update the post of course 😉 )
      As for your question – honestly I wanted to avoid “multihomed vms” topic when writing this script. Input for this script is (very simple) CSV file, when you allow more than one NIC (say two) the question opens “Why not three”? 😉 And providing “variable lenght” input with CSV is… at least very difficult (if not impossible 😉 )
      If these servers Web servers are Windows I would probably create a second “post-deployment” PS script which would configure remaining 5 IPs after VM is deployed, that doesn’t seem difficult. Things get a bit more tricky if these are Linux… I’d probably still deploy with single IP (for nic1 only) and introduce some BASH / Perl / Python scripting as “post-install” script to connect (say) NFS share and then read & configure IP settings per each VM.
      In theory you can always try PowerCLI cmdlets that configure IPs via VMware Tools but… I honestly never managed to get them working… (in my older post with “simple” version of this script you can find a link to excellent post of LucD where he explains all the official and un-official requirements needed to successfully run these cmdlets)

      • Cory S

        Hey thanks for the reply. They actually only have one NIC, and are running 2008 R2, they just have multiple IPs assigned to the NIC. The main issue I have with scripting it in after the fact is it is difficult to script in assigned IPs to a machine that was deployed from a template made before the IPs were assigned.

      • Cory S

        Hey sbarylo, did you ever figure out a solution for the divide by zero issues? I am having trouble again on another management server.

  • Moe

    Hi Sebastian,

    First, great script but we are missing something.

    As you suggested, we modified the script as we do not run datastore cluster, so we changed two locations to get-cluster.

    After initiating the script, we are prompted to connect to the server, that succeeds.

    And then we get the following

    [2015-02-04 02:57:27] :Info: vCenter v1173vmvc01 successfully connected

    [2015-02-04 02:57:27] :Info: Dispatching background deployment job for cluster

    1173-Cluster

    [2015-02-04 02:57:48] :Warning: Pooling background deployment jobs

    [2015-02-04 02:57:48] :Info: Out of total 2 VM deploy requests there are 0 VMs

    successfully powered on, 0 failed.

    [2015-02-04 02:57:48] :Info: Out of total 0 successfully powered on VMs OS Cust

    omization has started for 0 VMs, succeeded for 0 VMs, failed for 0.

    [2015-02-04 02:58:08] :Warning: Pooling background deployment jobs

    [2015-02-04 02:58:08] :Info: Out of total 2 VM deploy requests there are 0 VMs

    successfully powered on, 0 failed.

    [2015-02-04 02:58:08] :Info: Out of total 0 successfully powered on VMs OS Cust

    omization has started for 0 VMs, succeeded for 0 VMs, failed for 0.

    [2015-02-04 02:58:08] :Info: Out of total 2 VM deploy requests 0 VMs were succe

    ssfully powered on, 0 failed, 2 duplicate VM names were detected (not deployed)

    .

    [2015-02-04 02:58:08] :Info: Out of total 0 successfully powered on VMs OS Cust

    omization has been successful for 0 VMs, failed for 0.

    [2015-02-04 02:58:08] :Info: background deployment jobs completed in 40.55s, 0

    ERRORs reported, exiting.

    We have attempted this on two different hosts with the same results. The host are configured the same at each site. Not sure what it is referring to when it reports duplicate VM names were detected. We have verified no duplicates exist and we have used new names just to make sure.

    Our CSV file only has two entries and the vm names are different.

    Wondering if you have any idea that we can try?

    thanks
    Moe

    • RyanGarvelink

      I’m having the exact same issue. Any ideas?

      • Oliver Rester

        me too …

    • Oliver Rester

      thats the magic we have to looking for/inside:

      if (!(get-vm $vms[($batch + $index)].name -erroraction 0)){ #check if vm name is already taken

  • Moe

    Sebastian,

    I also neglected to say our CSV contains the following

    name,template,oscust,cluster,folder,datastore,ip,mask,gw,dns1,dns2

    wanted to make sure that was correct since we modified the datastorecluster to datastore

    thanks for any help you can provide
    moe

  • Moe

    Also just noticed the DeployJob.log has the following

    [2015-02-04 03:56:11] :Info: vCenter vmvc01 successfully connected

    [2015-02-04 03:56:12] :Info: Cloning OS customization for vmtest1

    [2015-02-04 03:56:14] :Info: Starting async deployment for vmtest1

    Cannot bind parameter ‘Datastore’. Cannot convert the “” value of type “System.
    Management.Automation.PSCustomObject” to type “VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.StorageResource”.

  • avnish choudhary

    First of all thanks for the Script but I am having some trouble deploying VMs from this script. I am using vpshere5.1U2 and power cli as 5.5r2patch1. when i am running script it clones customization and after that does nothing. I checked logs and this is what I see in the logs. Can you please help me with this.

    “Cannot convert ‘System.Object[]’ to the type ‘VMware.VimAutomation.ViCore.Types.V1.Inventory.Template’ required by parameter ‘Template’. Specified method is not supported.”

  • Matthias Kainz

    Hi, first of all thanks for the script, but I am also having some trouble deploying VMs. I am using PowerCLI Version 5.8 R1. The script is trying to start the deployment, but is exiting after a few seconds (without showing any errors).

    Messages like “[2015-03-05 12:53:38] :Info: vCenter 192.168.154.7 successfully connected

    [2015-03-05 12:53:45] :Info: Cloning OS customization for TST-V-154-008-U

    [2015-03-05 12:53:46] :Info: Starting async deployment for TST-V-154-008-U

    Cannot validate argument on parameter ‘Datastore’. The argument is null or

    empty. Provide an argument that is not null or empty, and then try the command

    again.

    [2015-03-05 12:53:47] :Info: Cloning OS customization for TST-V-154-008-W

    [2015-03-05 12:53:47] :Info: Starting async deployment for TST-V-154-008-W

    Cannot validate argument on parameter ‘Template’. The argument is null.

    Provide a valid value for the argument, and then try running the command again.

    [2015-03-05 12:53:47] :Info: Cloning OS customization for TST-V-154-221-U

    [2015-03-05 12:53:47] :Info: Starting async deployment for TST-V-154-221-U

    Cannot validate argument on parameter ‘Datastore’. The argument is null or

    empty. Provide an argument that is not null or empty, and then try the command

    again.” are written to the log files. We are using datastore clusters, SDRS is enabled. Can you please help me with this?

  • Matt Wale

    To fix “Cannot validate argument on parameter ‘Datastore'” errors, when not using datastore-clusters…Sebastian said to change two lines from “get-datastorecluster” to “get-cluster”, I found that it needs to be “get-datastore” instead, probably just mistyped the instructions.

    After you change that on two lines, the vms will deploy to the datastore in the csv. Leave the csv field as datastorecluster, that is just a label referenced by the script.

  • Dave Mahoney

    I have been toying with this on and off today. Using the get-datastorecluster commands do not appear to work at all. Yes I have SDRS enabled clusters. Job fails with the following :
    Required property datastore is missing from data object of type
    VirtualMachineRelocateSpecDiskLocator

    Using the get-datastore command seems to work better but erroneous errors are thrown even though the job is working fine:
    [2015-04-10 13:23:55] :Error: Out of total 2 VM deploy requests there are 2 VMs
    successfully powered on, 2 failed.

    Also the timestamps reported in the logs are not consistently formatted:

    [2015-04-10 13:05:16] :Info: Starting async deployment for DeployTestVM1
    4/10/2015 1:05:19 PM New-VM
    Required property datastore is missing from data object of type
    VirtualMachineRelocateSpecDiskLocator

    [2015-04-10 13:18:06] :Info: Starting async deployment for DeployTestVM7
    4/10/2015 1:18:05 PM Get-VM VM with name ‘DeployTestVM7’ was not
    found using the specified filter(s).

    And that error about not validating the PercentComplete – It doesn’t feel right to have a perfectly good deployment running while the screen is covered in brilliant red error text.

    Also – are there any requirements or limitations in terms of having spaces in the names of your datastores (since datastore clusters don’t work with the published code), templates, cluster names etc…

    • Oliver Rester

      Hi Dave,

      just remove -DiskstorageFormat thin in ps scrip (if your using DataStoreClusters). It´s a known bug of the cmdlet.

      BR
      Oliver

  • Dan Lee (Dan B. Lee)

    Thanks for putting this together. I’m running powercli version 5.8. I made the cluster change in the notes below. PowerCLI is crashing when I run the script:

    Problem signature:
    Problem Event Name: APPCRASH
    Application Name: powershell.exe
    Application Version: 6.1.7600.16385
    Application Timestamp: 4a5bc7f3
    Fault Module Name: KERNELBASE.dll
    Fault Module Version: 6.1.7601.18409
    Fault Module Timestamp: 5315a05a
    Exception Code: e053534f
    Exception Offset: 000000000000940d
    OS Version: 6.1.7601.2.1.0.272.7
    Locale ID: 1033

    The internet doesn’t really have a desciption for this error. Any ideas?

  • Mark Constant

    Everytime I try to run this script it says that the VM names are duplicate so they won’t deploy. Each time for testing I change the name and when I test deploying by just doing a new-vm from the command line outside of your script it does not fail at all. Any help would be appreciated.

  • Adrian

    Brilliant script
    I have an issue that it thinks the new vms already exist any ideas ?
    [2015-08-27 10:31:27] :Info: vCenter ch-vcntr5-2k8 successfully connected
    [2015-08-27 10:31:27] :Info: Dispatching background deployment job for cluster
    Cluster1
    [2015-08-27 10:31:50] :Warning: Pooling background deployment jobs
    [2015-08-27 10:31:50] :Info: Out of total 2 VM deploy requests there are 0 VMs
    successfully powered on, 0 failed.
    [2015-08-27 10:31:50] :Info: Out of total 0 successfully powered on VMs OS Cust
    omization has started for 0 VMs, succeeded for 0 VMs, failed for 0.
    [2015-08-27 10:32:10] :Warning: Pooling background deployment jobs
    [2015-08-27 10:32:10] :Info: Out of total 2 VM deploy requests there are 0 VMs
    successfully powered on, 0 failed.
    [2015-08-27 10:32:10] :Info: Out of total 0 successfully powered on VMs OS Cust
    omization has started for 0 VMs, succeeded for 0 VMs, failed for 0.
    [2015-08-27 10:32:10] :Info: Out of total 2 VM deploy requests 0 VMs were succe
    ssfully powered on, 0 failed, 2 duplicate VM names were detected (not deployed)
    .
    [2015-08-27 10:32:10] :Info: Out of total 0 successfully powered on VMs OS Cust
    omization has been successful for 0 VMs, failed for 0.
    [2015-08-27 10:32:10] :Info: background deployment jobs completed in 43.91s, 0
    ERRORs reported, exiting.
    PS C:VM ScriptsBulk create servers>

    • gothicreader

      Make sure you changed the get-cluster to get-datastore, and other minor changes noted in the comment section.

  • gothicreader

    Nice script, Sebastian.
    I’m having an issue when deploying multiple VMs concurrently.
    So that only one VM is cloned from the template and until that VM is completed to include power on – then it moves to the next VM. However, at some point its stops deploying VMs. I noticed that vCenter is showing an error from the template:
    error caused by /vmfs/volumes/GUID/<>/<>
    Not sure what’s going on there.

    Secondly the next error I see in the powershell:
    “attempted to divide by zero”
    it doesn’t like “{0:N2}” -f (($processed_vms / ((( $total_vms> * 100)

    Which others have commented.
    Has there been a fix or suggestion to change the script?

    Thanks!

  • Etan Reisner

    Found this from your post on LucD’s original post. I’m having the client task/server task issue you mentioned there (not using this script using something I’m writing myself).

    Can you explain what you did to work around the problem you originally had and how this script avoids that issue?

    Because I don’t see it and I’m very puzzled.

  • gothicreader

    I got it to work to deploy concurrently the VMs. I went ahead and created a shell VM and pointed an existing vmdk (the old template).
    Once this was done things started to go as it should, with the exception of the “Attempted to divide by zero” error.

  • Bradley Sessions

    when I run it I get the following error

    [2015-11-18 15:24:07] :Info: PowerCLI VimAutomation.Core Snap-in was successfully enabled.

    [2015-11-18 15:24:07] :Error: This script requires PowerCLI 5.5 or greater to run properly

    and then it quits, i have powershell 4.0 and PowerCLI 6.0 installed.

    • shockwavecs

      I got the same thing and after trying a few weird things like launch VMware powerCLI in 32-bit and 64-bit mode and then launch the Windows powershell…it seemed to work. Although the script runs the commands without a new window, just play around with launching the tools in random order

  • shockwavecs

    I am having an issue where no errors come up and I don’t know what parameters to correctly type into the CSV. I am only adding in a single host during testing for now.

    I am trying:

    Notes on fields:

    “cluster”
    “hqvcenter1 – Cluster” is the name of my 3 node cluster

    “datastorecluster”
    – I don’t have a datastore cluster. The RAID10-Slow-VM2 is the name of a datastore that is available to the entire 3 node cluster.
    – I have already changed the powershell script to say “get-datastore” instead of “get-datastorecluster” in the 2 locations.

    “folder”
    – hqvcenter1 is the name of the “Folder” where the VM will end up. I do not actually want it to go into any of the other folders I have manually created. Just the default top level one

    Output from the powershell (updated and powercli 6 installed)

    • shockwavecs

      weird. I attempted it on a different vcenter server and it failed to complete. Attempted it back on the original server and it completes. Not sure if it caches anything? Now I am just getting false errors saying it could not deploy 2 of 2 VMs. But both VMs are deployed and running just fine.

  • Sonny Vang

    I was wondering if you can help with the following error. I am trying to add just two VMs for testing and I don’t know what I’m doing wrong here.

    “409 char:23 $jobs_tab +=$cluster.cluster” A null key is not allowed in a hash literal.
    “426 char:13 if ($jobs_tab.Get_Item($cluster.cluster>>.state -eq “running” You cannot call a meth on a null-valued express
    “447 char:115 Attempted to divide by zero.

    Log files

    [2016-02-22 16:05:22] :Info: vCenter uwhc-vc02 successfully connected
    [2016-02-22 16:05:41] :Info: Cleaning-up cloned OS customizations

    [2016-02-22 16:05:14] :Info: Dispatching background deployment job for cluster
    [2016-02-22 16:05:34] :Info: Out of total 0 VM deploy requests there are 0 VMs successfully powered on, 0 failed.
    [2016-02-22 16:05:34] :Info: Out of total 0 successfully powered on VMs OS Customization has started for 0 VMs, succeeded for 0 VMs, failed for 0.
    [2016-02-22 16:05:34] :Info: Out of total 0 VM deploy requests 0 VMs were successfully powered on, 0 failed, 0 duplicate VM names were detected (not deployed).
    [2016-02-22 16:05:34] :Info: Out of total 0 successfully powered on VMs OS Customization has been successful for 0 VMs, failed for 0.
    [2016-02-22 16:05:34] :Info: background deployment jobs completed in 20.18s, 0 ERRORs reported, exiting.

  • infinit_e

    I’m curious, has anyone reading been able to modify this script to deploy to a specific host instead of to a cluster? My environment has 2 unclustered hosts at a remote datacenter that we use as a lab environment. It would be great to use this script for creating a bunch of test systems. I’m a still quite the novice when it comes to PowerShell.

  • Adam I

    If you are still having the Divide by Zero issue…. Follow what Cory said….. Just add more than 1 test VM in your .CSV file and that will work… Also, if you are not using Datastore Clusters…. replace in the source code where ever there is ‘Get-DatastoreCluster’ to -> ‘Get-Datastore’ and leave the CSV header the same… Thanks Matt & Cory for the advice.

  • Jawed Abbasi

    So far I have been very unlucky to use this. I am powercli 5.5 R2 on windows2008 R2 system; connecting to a VC

    with DRS enabled on storage and cluster nodes with following vms2deploy.vcs

    vm1-jaw,Template_Win2012-R2-Std-CL02,Server 2012 R2 Std (Enterprise License),DHESXCL02,Infrastructure,DH-XIOCL02,10.55.4.45,255.255.255.0,10.25.4.1,10.55.4.38,10.55.4.102
    vm2-jaw,Template_Win2012-R2-Std-CL02,Server 2012 R2 Std (Enterprise License),DHESXCL02,Infrastructure,DH-XIOCL02,10.55.4.46,255.255.255.0,10.25.4.1,10.55.4.38,10.55.4.102

    I keep getting these errors and nothing happens; scritp does not log why its failling

    .Vm-batchdeployment.ps1

    cmdlet Vm-batchdeployment.ps1 at command pipeline position 1
    Supply values for the following parameters:
    vCenterServer: 10.55.90.220
    [2016-05-06 11:10:35] :Info: PowerCLI VimAutomation.Core Snap-in is already enabled
    WARNING: There were one or more problems with the server certificate for the server 10.55.90.220:443:

    * The X509 chain could not be built up to the root certificate.

    * The certificate’s CN name does not match the passed value.

    Certificate: [Subject]
    E=support@vmware.com, CN=VMware default certificate, OU=”VMware, Inc.”, O=”VMware, Inc.”

    [Issuer]
    O=VMware Installer

    [Serial Number]
    2C88E1FA

    [Not Before]
    7/22/2011 4:04:17 PM

    [Not After]
    7/19/2021 4:04:17 PM

    [Thumbprint]
    99BD73273C96083FC99F4DDDA990F7F58184B8BE

    The server certificate is not valid.

    WARNING: THE DEFAULT BEHAVIOR UPON INVALID SERVER CERTIFICATE WILL CHANGE IN A FUTURE RELEASE. To ensure scripts are not affected by the change, use Set-PowerCLIConfiguration to set a value for
    InvalidCertificateAction option.

    [2016-05-06 11:11:26] :Info: vCenter 10.55.90.220 successfully connected
    [2016-05-06 11:11:26] :Info: Dispatching background deployment job for cluster
    A null key is not allowed in a hash literal.
    At C:UserstestDocumentsvm2deployVm-batchdeployment.ps1:409 char:23
    + $jobs_tab += @{ $cluster.cluster = start-job -name $cluster.cluster -scrip …
    + ~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (System.Collections.Hashtable:Hashtable) [], RuntimeException
    + FullyQualifiedErrorId : InvalidNullKey

    [2016-05-06 11:11:48] :Warning: Pooling background deployment jobs
    You cannot call a method on a null-valued expression.
    At C:UserstestDocumentsvm2deployVm-batchdeployment.ps1:426 char:13
    + if ($($jobs_tab.Get_Item($cluster.cluster)).state -eq “running”) {
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Attempted to divide by zero.
    At C:UserstestDocumentsvm2deployVm-batchdeployment.ps1:447 char:115
    + … ent complete $(“{0:N2}” -f (($processed_vms / $total_vms) * 100))%” -PercentComp …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

    Attempted to divide by zero.
    At C:UserstestDocumentsvm2deployVm-batchdeployment.ps1:447 char:115
    + … ent complete $(“{0:N2}” -f (($processed_vms / $total_vms) * 100))%” -PercentComp …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

    [2016-05-06 11:11:48] :Info: Out of total 0 VM deploy requests there are 0 VMs successfully powered on, 0 failed.
    [2016-05-06 11:11:48] :Info: Out of total 0 successfully powered on VMs OS Customization has started for 0 VMs, succeeded for 0 VMs, failed for 0.
    [2016-05-06 11:11:48] :Info: Out of total 0 VM deploy requests 0 VMs were successfully powered on, 0 failed, 0 duplicate VM names were detected (not deployed).
    [2016-05-06 11:11:48] :Info: Out of total 0 successfully powered on VMs OS Customization has been successful for 0 VMs, failed for 0.
    [2016-05-06 11:11:48] :Info: background deployment jobs completed in 21.81s, 0 ERRORs reported, exiting.
    PowerCLI C:UserstestDocumentsvm2deploy>

  • JD Freeman

    I too am getting the “duplicate VM names were detected (not deployed).” message.

  • Rob Freeman

    Can the script be edited to allow configuration of a second vNIC?

  • Gitesh Sharma

    Thanks for amazing script, kindly advise what modification i need to do if i am using this script for one cluster. Please advise.