Follow @chaderoth

Friday, December 29, 2017

How To Deploy Multiple VMs Using PowerCLI (Part 2) - Dynamic Parameters

In my previous post, "How To Deploy Multiple VMs Using PowerCLI" I showed how to script creating multiple VMs using PowerCLI and a Hash Table to track the build status. In that post I mentioned it was my first attempt at such an approach. Though this script had the potential to save someone quite a bit of time, it is actually a pretty tedious task to answer all of the questions the script prompts the user for and requires the user manually input the values needed for things like which ESXi host, Datastore, etc. to use for the VM build process.

This would likely result in an added step of the user needing to look up this information and could result in user error while mistyping information into the prompt.

While contemplating how to solve this problem I was recently introduced to parameters and using them in PowerShell to collect information from the command line and store their values into variables as part of another project I'm working on.

Have I mentioned that I'm pretty new to; well, I'm not actually sure how to term it. I guess since PowerShell is described as a scripting language I'd have to say, scripting, but it wouldn't be accurate for me to say that I'm new to scripting. It's just that PowerShell is so much more powerful than say, Batch scripting. Up until I started teaching myself PowerShell, I've always written simple, focused, one-task oriented scripts. With PowerShell, it's easy to build on past scripts with new methods you learn along the way and new ideas have a way of continuing to spawn new ideas. Anyway, I digress.

I have also been starting to work a bit with functions in PowerShell and thought that cleaning up this script would be a great opportunity to combine these newly acquired skills.

I had originally planned on manually entering all the parameters and their value sets in the script so the user of the script could tab-complete through them and wouldn't need to type them manually. This, however; would require a lot of script maintenance should these values change due to changes in the environment.

If only I could populate these parameter values dynamically. Is there such a thing? A dynamic parameter? I figured there must be or at least something that would get the job done since we see this functionality native in some PowerShell cmdlets.

This led me here, Dynamic ValidateSet in a Dynamic Parameter by Martin Schvartzman.

Let's take this function and tweak it to work for our purposes.

Creating The Basic Function and Static Parameter

We will start by creating our function and our static parameter of "VMNames" as the user will be entering the name(s) of the VMs in a comma separated list.

Creating The Dynamic Parameter Library

To create the dynamic parameters using Martin's example we need to create the dynamic parameter block under the parameter block as well as adding CmdletBinding, Set the dynamic parameters' name, Create the parameter dictionary, Create the collection of attributes, Create and set the parameters' attributes, Add the attributes to the attributes collection, Generate and set the ValidateSet, Add the ValidateSet to the attributes collection, Create the dynamic parameter, and Return the parameter dictionary. Note that we are replacing Martin's "ArrSet" variable of "Get-ChildItem" with our PowerCLI cmdlet of "Get-VMHost" so we can populate this variable with our ESXI host names. We have also modified the "Set the dynamic parameters' name, Create the dynamic parameter, and Store parameter as a nice variable" areas of the script to match our "Set the dynamic parameters' name". You will see the reason for this in a minute. Lastly, we are "Binding the parameter to a friendly variable" which we match to the parameter name we used under "Set the dynamic parameters' name".

Creating The Dynamic Parameters

Because Martin is only creating one dynamic parameter in his example "Path" he is "Creating the parameter dictionary" and "Returning the completed dynamic parameter dictionary" all in one area of the script. Because we would like to add additional parameters to our function we only need to create the dictionary at the beginning and continue to add our attributes to the dictionary, only returning our parameter dictionary once we are through. This is also the reason for modifying the "Set the dynamic parameters' name, Create the dynamic parameter, and Store parameter as a nice variable" areas to match the values we would like to pull from vCenter using the appropriate PowerCLI cmdlets for the corresponding "ArrSet" variable. Note that we are using "Get-VMHost, Get-Template, Get-Folder, and Get-Datastore". Here is our completed dictionary.

Putting It All Together

Now all that is left is to grab the code from our original build script and use it in the "Process" code block while remembering to update the variables used in our foreach loop and "New-VM" PowerCLI cmdlet to match the new dynamic parameter variables created from our dictionary.


I believe I have reached some of the goals I have set for this next version of the script and for myself. The requirement for manual input from a user has been greatly reduced; however, this function now requires the user to add the script to their profile to load when PowerCLI loads or to dot-source the script before use. It also requires connecting to vCenter before calling the function as the dynamic parameter library is built using information gathered from vCenter by way of the PowerCLI cmdlets. I plan on continuing research to see if there is a way to make this process more fluid.

Thanks again for reading and please let me know if you have any comments or advice.

No comments:

Post a Comment