PowerCLI Script – Deploy VMs and Configure the Guest OS

 

 

Last week I had the distinct pleasure of getting to speak at the VMUG UserCon events in both Seattle and South Florida. My goal in both of these speaking slots was not to do the typical vendor sales pitch, but provide some good solid information to the community that could be taken back to attendees’ locations and be put to good use. The topic I chose is a popular one in the industry right now. I wanted to talk about automation, with one PowerCLI Script I put together in mind.

The Story

In a previous job, I was in charge of managing a fairly large vSphere implementation that housed the hosted-private-cloud practice of a managed services provider and hoster. This environment, while it ran good, always challenged me to find ways to further optimize deployment processes. Each on-boarded customer had a couple of things in common. They all wanted AD, and they all needed file hosting. I wanted to incorporate those needs into the VM deployment process to ultimately save on time. Sadly, time was in short supply to come up with a script at the time. Now that I work for Altaro, and one of my primary duties is coming up with community focused content, I finally had the chance to come back to this issue, and tackle it. My goal was to solve this issue, and share the solution with the community.

Technical Goals of the Script

  1. Must be FULLY automated from the moment you hit the enter key to start the script.
  2. Must provide verbose information for the administrators viewing if desired.
  3. Must Deploy 2 VMs from pre-existing templates and customization specs.
  4. Must customize each virtual machine according to the specified customization spec.
  5. Must be able to define static IP addresses.
  6. Must configure AD on one of the new VMs and provision a new AD Forest.
  7. Must create a new custom administrative account within the domain.
  8. 2nd VM must be automatically joined to the newly defined domain.
  9. File Services must be installed on the second VM
  10. A new SMB share must be defined on the file server VM, once the file services role is present.

This is certainly a lot to get done with a single press of the enter key, but it is doable. Also, this is likely just the beginnings of a new environment, but the script could very easily be modified to deploy more than just the two VMs.

Community Goals of the Script

I’ve always enjoyed giving back to the IT community that has helped me so much throughout my career, and I really wanted to that with this script. My goal from a teaching aspect with this script was to be the follow:

  1. Well Documented and Heavily Commented
  2. VERY sequential ordering of the commands, as to be easy to follow for beginners
  3. Best Practices definition of variables at the top of the script.
  4. Well segmented so that certain sections can be copied and duplicated if desired.

While the script was very well received at the VMUG events, I was asked by some of the more tenured PowerShell folks as to why I didn’t use any functions or more advanced formatting. The main reason was number 2 above. I’ve found that IT Pros have a very sequential line of thinking when it comes to completing tasks. I wanted to script to be done in a very….  step 1…. then step 2….  then step 3, type of fashion. This way it’s easier for a PowerShell beginner to see how the script works, and take the bits and pieces that they need for their own scripts. Functions and some of the more advanced techniques can be more difficult to follow if you’re not used to PowerShell.

The Secret Sauce

The first half of the script simply consists of setting variables to be used later in the script’s execution. Once the actual task completing commands start being called, there are a number of basic cmdlets being called to complete most of the functions. If I had to pick some of the most important cmdlets for this script they would be the 3 below

Wait-Tools: While nothing really special, this is an immensely helpful cmdlet. I call this cmdlet several times throughout the script. What Wait-Tools does, is it targets a VM, and waits until VMware Tools within that Guest VM is in a responsive state. This is especially useful for reboots, where you don’t want to script to continue until VMware Tools within the guest is working. In most cases all other services in the VM will be up and running once tools is functioning, however there were a couple of times in the script where I had to follow this up with a Start-Sleep cmdlet to give the OS just a little extra time to come online before continuing.

Get-VIEvent: Like the above, Get-VIEvent is not overly special by itself. However, When paired with other commands and some filtering options, it can become quite powerful. I used this cmdlet in a loop fashion in the script to scan the vCenter logs to look for various VM customization events. This logic allows the script to wait until the guest customization of the first VM is completed, prior to trying to make any changes to the OS contained within the VM.

Invoke-VMScript: If you can only take away one useful command from this post, choose this one. This cmdlet, in a word, is awesome. This single cmdlet allows your script to reach into the guest operating system, and execute a block of code. This is how all of the OS level changes are done throughout the script. It takes care of things like the installation of AD, and the configuration of the new file share on the file server. It completes this task by pushing the codeblock to the VM via VMware Tools. So the only thing that is needed for this is for tools to be in a running state inside of the target VM.

See it in Action

I’ve annotated the below video to show the script in action. Be advised, that the script actually takes 20 to 30 minutes to run in the below state. This video has had quite a bit of the wait periods removed so you can see the script function in it’s entirety.

 

 

 

 

The Script

So here is the part you’ve been waiting for. Below is the script. Take it! Use it. Learn from it. This is simply one of my humble contributions back to the IT community.

Again the script is heavily self-documented and commented, so you should be able to read through it and set the needed variables as needed. Note, all of the user-definable variables are at the top of the script.

# DISCLAIMER: There are no warranties or support provided for this script. Use at you're own discretion. Andy Syrewicze and/or Altaro Software are not liable for any
# damage or problems that misuse of this script may cause.

# Script is Written by Andy Syrewicze - Tech. Evangelist with Altaro Software and is free to use as needed within your organization.

# This Script is Primarily a Deployment Script. It will first deploy a template from your vSphere environment, apply a customization specification, and then install and configure Active
# Directory Domain Services on one VM, and the File Services on another. Additionally the file server will be a member of the newly deployed VM, a new administrative user account will
# be created and a file share will be provisioned on the new file server. 

# Script was designed for PowerShell/PowerCLI Beginners who have not yet begun to work with functions and more advanced PowerShell features. 
# The below script first lists all user definable varibles and then executes the script's actions in an easy to follow sequential order. 

# Assumptions
# - You Have vCenter inside your environment
# - You have pre-configured templates and customization specifications inside of vCenter
# - Your PowerShell execution policy allows the execution of this script

# ------vCenter Targeting Varibles and Connection Commands Below------
# This section insures that the PowerCLI PowerShell Modules are currently active. The pipe to Out-Null can be removed if you desire additional
# Console output.
Get-Module -ListAvailable VMware* | Import-Module | Out-Null

# ------vSphere Targeting Variables tracked below------
$vCenterInstance = "VCENTER FQDN HERE"
$vCenterUser = "VCENTER USER ACCOUNT HERE"
$vCenterPass = "VCENTER PASSWORD HERE"

# This section logs on to the defined vCenter instance above
Connect-VIServer $vCenterInstance -User $vCenterUser -Password $vCenterPass -WarningAction SilentlyContinue 


######################################################-User-Definable Variables-In-This-Section-##########################################################################################


# ------Virtual Machine Targeting Variables tracked below------

# The Below Variables define the names of the virtual machines upon deployment, the target cluster, and the source template and customization specification inside of vCenter to use during
# the deployment of the VMs.
$DomainControllerVMName = "DESIRED DC NAME HERE"
$FSVMName = "DESIRED FS NAME HERE"
$TargetCluster = Get-Cluster -Name "TARGET CLUSTER IN VCENTER"
$SourceVMTemplate = Get-Template -Name "SOURCE TEMPLATE IN VCENTER"
$SourceCustomSpec = Get-OSCustomizationSpec -Name "SOURCE CUSTOMIZATION SPEC IN VCENTER"



# ------This section contains the commands for defining the IP and networking settings for the new virtual machines------
# NOTE: The below IPs and Interface Names need to be updated for your environment. 

# Domain Controller VM IPs Below
# NOTE: Insert IP info in IP SubnetMask Gateway Order
# NOTE: For the purposes of this script we do not define static DNS settings for this single DC VM as it will point to itself for DNS after provisioning of the new domain.
# You could add an additional netsh line below to assign static DNS settings in the event you need to do so. See the File Server Section below for further details. 
$DCNetworkSettings = 'netsh interface ip set address "Ethernet0" static x.x.x.x 255.255.255.0 x.x.x.x'

# FS VM IPs Below
# NOTE: Insert IP info in IP SubnetMask Gateway Order
$FSNetworkSettings = 'netsh interface ip set address "Ethernet0" static x.x.x.x 255.255.255.0 x.x.x.x'
# NOTE: DNS Server IP below should be the same IP as given to the domain controller in the $DCNetworkSettings Variable
$FSDNSSettings = 'netsh interface ip set dnsservers name="Ethernet0" static x.x.x.x primary'



# ------This Section Sets the Credentials to be used to connect to Guest VMs that are NOT part of a Domain------

# NOTE - Make sure you input the local credentials for your domain controller virtual machines below. This is used for logins prior to them being promoted to DCs.
# This should be the same local credentials as defined within the template that you are using for the domain controller VM. 
$DCLocalUser = "$DomainControllerVMName\DC LOCAL USER NAME HERE"
$DCLocalPWord = ConvertTo-SecureString -String "DC LOCAL PASSWORD HERE*" -AsPlainText -Force
$DCLocalCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $DCLocalUser, $DCLocalPWord

# Below Credentials are used by the File Server VM for first login to be able to add the machine to the new Domain.
# This should be the same local credentials as defined within the template that you are using for the file server VM. 
$FSLocalUser = "$FSVMName\FS LOCAL USER NAME HERE"
$FSLocalPWord = ConvertTo-SecureString -String "FS LOCAL PASSWORD HERE" -AsPlainText -Force
$FSLocalCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $FSLocalUser, $FSLocalPWord

# The below credentials are used by operations below once the domain controller virtual machines and the new domain are in place. These credentials should match the credentials
# used during the provisioning of the new domain. 
$DomainUser = "TESTDOMAIN\administrator"
$DomainPWord = ConvertTo-SecureString -String "Password01" -AsPlainText -Force
$DomainCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $DomainUser, $DomainPWord 



# ------This Section Contains the Scripts to be executed against new VMs Regardless of Role

# This Scriptblock is used to add new VMs to the newly created domain by first defining the domain creds on the machine and then using Add-Computer
$JoinNewDomain = '$DomainUser = "TESTDOMAIN\Administrator";
                  $DomainPWord = ConvertTo-SecureString -String "Password01" -AsPlainText -Force;
                  $DomainCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $DomainUser, $DomainPWord;
                  Add-Computer -DomainName TestDomain.lcl -Credential $DomainCredential;
                  Start-Sleep -Seconds 20;
                  Shutdown /r /t 0'



# ------This Section Contains the Scripts to be executed against New Domain Controller VMs------

# This Command will Install the AD Role on the target virtual machine. 
$InstallADRole = 'Install-WindowsFeature -Name "AD-Domain-Services" -Restart'

# This Scriptblock will define settings for a new AD Forest and then provision it with said settings. 
# NOTE - Make sure to define the DSRM Password below in the line below that defines the $DSRMPWord Variable!!!!
$ConfigureNewDomain = 'Write-Verbose -Message "Configuring Active Directory" -Verbose;
                       $DomainMode = "Win2012R2";
                       $ForestMode = "Win2012R2";
                       $DomainName = "TestDomain.lcl";
                       $DSRMPWord = ConvertTo-SecureString -String "Password01" -AsPlainText -Force;
                       Install-ADDSForest -ForestMode $ForestMode -DomainMode $DomainMode -DomainName $DomainName -InstallDns -SafeModeAdministratorPassword $DSRMPWord -Force'

# This scriptblock creates a new administrative user account inside of the new domain
# NOTE - Be Sure to set the password using the $AdminUserPWord Below!
$NewAdminUser = '$AdminUserPWord = ConvertTo-SecureString -String "Password01" -AsPlainText -Force;
                 New-ADUser -Name "TestAdmin" -AccountPassword $AdminUserPWord;
                 Add-ADGroupMember -Identity "Domain Admins" -Members "TestAdmin";
                 Enable-ADAccount -Identity "TestAdmin"'



# ------This Section Contains the Scripts to be executed against file server VMs------
$InstallFSRole = 'Install-WindowsFeature -Name "FS-FileServer"'

# The below block of code first creates a new folder and then creates a new SMB Share with rights given to the defined user or group.
$NewFileShare = '$ShareLocation = "C:\ShareTest";
                 $FolderName = "Public";
                 New-Item -Path $ShareLocation -Name $FolderName -ItemType "Directory";
                 New-SmbShare -Name "Public" -Path "$ShareLocation\$FolderName" -FullAccess "TestDomain\TestAdmin"'


#########################################################################################################################################################################################



# Script Execution Occurs from this point down

# ------This Section Deploys the new VM(s) using a pre-built template and then applies a customization specification to it. It then waits for Provisioning To Finish------

Write-Verbose -Message "Deploying Virtual Machine with Name: [$DomainControllerVMName] using Template: [$SourceVMTemplate] and Customization Specification: [$SourceCustomSpec] on Cluster: [$TargetCluster] and waiting for completion" -Verbose
 
New-VM -Name $DomainControllerVMName -Template $SourceVMTemplate -ResourcePool $TargetCluster -OSCustomizationSpec $SourceCustomSpec

Write-Verbose -Message "Virtual Machine $DomainControllerVMName Deployed. Powering On" -Verbose

Start-VM -VM $DomainControllerVMName

Write-Verbose -Message "Deploying Virtual Machine with Name: [$FSVMName] using Template: [$SourceVMTemplate] and Customization Specification: [$SourceCustomSpec] on Cluster: [$TargetCluster] and waiting for completion" -Verbose

New-VM -Name $FSVMName -Template $SourceVMTemplate -ResourcePool $TargetCluster -OSCustomizationSpec $SourceCustomSpec

Write-Verbose -Message "Virtual Machine $FSVMName Deployed. Powering On" -Verbose

Start-VM -VM $FSVMName


# ------This Section Targets and Executes the Scripts on the New Domain Controller Guest VM------

# We first verify that the guest customization has finished on on the new DC VM by using the below loops to look for the relevant events within vCenter. 

Write-Verbose -Message "Verifying that Customization for VM $DomainControllerVMName has started ..." -Verbose
	while($True)
	{
		$DCvmEvents = Get-VIEvent -Entity $DomainControllerVMName 
		$DCstartedEvent = $DCvmEvents | Where { $_.GetType().Name -eq "CustomizationStartedEvent" }
 
		if ($DCstartedEvent)
		{
			break	
		}

		else 	
		{
			Start-Sleep -Seconds 5
		}
	}

Write-Verbose -Message "Customization of VM $DomainControllerVMName has started. Checking for Completed Status......." -Verbose
	while($True)
	{
		$DCvmEvents = Get-VIEvent -Entity $DomainControllerVMName 
		$DCSucceededEvent = $DCvmEvents | Where { $_.GetType().Name -eq "CustomizationSucceeded" }
        $DCFailureEvent = $DCvmEvents | Where { $_.GetType().Name -eq "CustomizationFailed" }
 
		if ($DCFailureEvent)
		{
			Write-Warning -Message "Customization of VM $DomainControllerVMName failed" -Verbose
            return $False	
		}

		if ($DCSucceededEvent) 	
		{
            break
		}
        Start-Sleep -Seconds 5
	}
Write-Verbose -Message "Customization of VM $DomainControllerVMName Completed Successfully!" -Verbose

# NOTE - The below Sleep command is to help prevent situations where the post customization reboot is delayed slightly causing
# the Wait-Tools command to think everything is fine and carrying on with the script before all services are ready. Value can be adjusted for your environment. 
Start-Sleep -Seconds 30

Write-Verbose -Message "Waiting for VM $DomainControllerVMName to complete post-customization reboot." -Verbose

Wait-Tools -VM $DomainControllerVMName -TimeoutSeconds 300

# NOTE - Another short sleep here to make sure that other services have time to come up after VMware Tools are ready. 
Start-Sleep -Seconds 30

# After Customization Verification is done we change the IP of the VM to the value defined near the top of the script
Write-Verbose -Message "Getting ready to change IP Settings on VM $DomainControllerVMName." -Verbose
Invoke-VMScript -ScriptText $DCNetworkSettings -VM $DomainControllerVMName -GuestCredential $DCLocalCredential

# NOTE - The Below Sleep Command is due to it taking a few seconds for VMware Tools to read the IP Change so that we can return the below output. 
# This is strctly informational and can be commented out if needed, but it's helpful when you want to verify that the settings defined above have been 
# applied successfully within the VM. We use the Get-VM command to return the reported IP information from Tools at the Hypervisor Layer. 
Start-Sleep 30
$DCEffectiveAddress = (Get-VM $DomainControllerVMName).guest.ipaddress[0]
Write-Verbose -Message "Assigned IP for VM [$DomainControllerVMName] is [$DCEffectiveAddress]" -Verbose

# Then we Actually install the AD Role and configure the new domain
Write-Verbose -Message "Getting Ready to Install Active Directory Services on $DomainControllerVMName" -Verbose

Invoke-VMScript -ScriptText $InstallADRole -VM $DomainControllerVMName -GuestCredential $DCLocalCredential

Write-Verbose -Message "Configuring New AD Forest on $DomainControllerVMName" -Verbose

Invoke-VMScript -ScriptText $ConfigureNewDomain -VM $DomainControllerVMName -GuestCredential $DCLocalCredential

# Script Block for configuration of AD automatically reboots the machine after provisioning
Write-Verbose -Message "Rebooting $DomainControllerVMName to Complete Forest Provisioning" -Verbose

# Below sleep command is in place as the reboot needed from the above command doesn't always happen before the wait-tools command is run
Start-Sleep -Seconds 60

Wait-Tools -VM $DomainControllerVMName -TimeoutSeconds 300

Write-Verbose -Message "Installation of Domain Services and Forest Provisioning on $DomainControllerVMName Complete" -Verbose

Write-Verbose -Message "Adding new administative user account to domain" -Verbose

Invoke-VMScript -ScriptText $NewAdminUser -VM $DomainControllerVMName -GuestCredential $DomainCredential


# ------This Section Targets and Executes the Scripts on the New FS VM.

# Just like the DC VM, we have to first modify the IP Settings of the VM
Write-Verbose -Message "Getting ready to change IP Settings on VM $FSVMName." -Verbose
Invoke-VMScript -ScriptText $FSNetworkSettings -VM $FSVMName -GuestCredential $FSLocalCredential
Invoke-VMScript -ScriptText $FSDNSSettings -VM $FSVMName -GuestCredential $FSLocalCredential

# NOTE - The Below Sleep Command is due to it taking a few seconds for VMware Tools to read the IP Change so that we can return the below output. 
# This is strctly informational and can be commented out if needed, but it's helpful when you want to verify that the settings defined above have been 
# applied successfully within the VM. We use the Get-VM command to return the reported IP information from Tools at the Hypervisor Layer.
Start-Sleep 30
$FSEffectiveAddress = (Get-VM $FSVMName).guest.ipaddress[0]
Write-Verbose -Message "Assigned IP for VM [$FSVMName] is [$FSEffectiveAddress]" -Verbose 

# The Below Cmdlets actually add the VM to the newly deployed domain. 
Invoke-VMScript -ScriptText $JoinNewDomain -VM $FSVMName -GuestCredential $FSLocalCredential

# Below sleep command is in place as the reboot needed from the above command doesn't always happen before the wait-tools command is run
Start-Sleep -Seconds 60

Wait-Tools -VM $FSVMName -TimeoutSeconds 300

Write-Verbose -Message "VM $FSVMName Added to Domain and Successfully Rebooted." -Verbose

Write-Verbose -Message "Installing File Server Role and Creating File Share on $FSVMName." -Verbose

# The below commands actually execute the script blocks defined above to install the file server role and then configure the new file share. 
Invoke-VMScript -ScriptText $InstallFSRole -VM $FSVMName -GuestCredential $DomainCredential

Invoke-VMScript -ScriptText $NewFileShare -VM $FSVMName -GuestCredential $DomainCredential

Write-Verbose -Message "Environment Setup Complete" -Verbose

# End of Script

Summary

There you have it! It is my hope that this will be of some use to you, whether that be helping you get a task done at your job, or helping you learn how to use PowerShell and automate.

If you have questions, feel free to use the comment form below, and I’m looking forward to seeing if this script was useful to you.

Enjoy!

 

Share this post

Not a DOJO Member yet?

Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!

90 thoughts on "PowerCLI Script – Deploy VMs and Configure the Guest OS"

  • Iain Anderson says:

    Amazing script!
    Looking through it are you missing a semi-colon on line 126?

    • Andy Syrewicze says:

      Glad you like it! Good Catch on that Semi-Colon as well! It’s been put back in place!

      Thanks!

      • Derek Grant says:

        Hi Andy

        Good morning to you

        I have read your blog in to creating VM’s a power shell to deploy VM’s it will take a template and create a standard windows 2016 server? I am using VMware 6.7

        I cant seem to get it to work, if I called up lines of commands they work but when I run the script it does not like I see lots of red!!

        Thanks for your help

        Derek Grant

  • kabir hussein says:

    Brilliant piece of codes and also thanks for the presentation, really useful

  • Daisy Malone says:

    Thank you for the script it is amazing. I am a beginner and this script has helped me tremendously.

  • sam williams says:

    Awsome knowledge sharing . Really good scripting

  • Elton says:

    Brilliant!

    Saved my life!

    Thank you

  • Hanson says:

    Awesome! I just started to build something similar to Deploy VMs and Configure the Guest OS. Your post saves me lots of time.

    Thank you!

  • Andrii says:

    Invoke-VMScript with ADD-Computer command doesnt work with windows 8.1. Is says Access Denied, because invoke-VMScript should run scripts with elevation.

    • Andy Syrewicze says:

      Hi Andrii!

      What line of the script are you talking about specifically?

      Have you verified that credentials you setup in the credential variables near the top of the script have administrative rights inside of the Windows 8.1 VM?

  • senob796 says:

    Why does the script stop at Customization of VM testdc01 has started. Checking for Completed Status….
    Can you post the example unattend file too? I know I missed something easy..

    • Andy Syrewicze says:

      Hi there!

      The script takes some time during that particular time window for the VM customization to complete. In my own tests, I’ve seen it take as long as 10 minutes. The VM should reboot a few times during this process.

      This script uses VMware customization specifications and VMware quickprep, instead of Windows Sysprep, so no answer file is needed. All of that information is contained in the VMware customization specification that you define at the beginning of the script.

  • Jamal says:

    This is a great script, saved me a lot of time in automation.
    I am doing this in Jenkins and it works great.
    One question though:
    I am trying to pass the Domain Name as a local Variable on Line 108 e.g $DomainName = $Env:DomainName and this is where it fails for $Domain Name “Null”
    I tried Parameters but still having an issue.
    any suggestions on how to do that?
    Thanks

    • Andy Syrewicze says:

      Hi Jamal!

      Glad to hear it’s working well with Jenkins!

      As for the local variable…. I’m not really tracking why you’re attempting to pass it as a local variable. The script is designed to allow you to just place in the domain name string on line 108 and that’s what the domain FQDN will be upon deployment.

      Written as you have in your comment, it’s likely working as written, it’s just $env:DomainName is empty, thus the $DomainName Variable is showing up as Null. The environment variable has to be populated prior to using it in this context based on how you’ve written it.

      Is there anymore info you can provide as to why you’re attempting to do it this way?

  • Nikhil Sabhani says:

    What would be the code for specifying CPU , RAM , and SCSI controller in this script ?

    Am totally new on vmware and powershell …….

    • Andy Syrewicze says:

      Hi Nikhil!

      If you want to specify the amount of resources at the time of VM creation (Or with Set-VM later on) you can use the -MemoryGB parameter for RAM, the -NumCPU parameter for number of vCPUs, and as for SCSI controller take a look at the New-SCSIController/Set-SCSIController cmdlets.

      Also, for detailed usage instructions make sure to first use Update-Help, then you can use “Get-Help COMMAND-HERE -Full” to get full detailed help and usage information for that command and it’s parameters.

      Hope that Helps!

  • Ronan says:

    Good man yourself Andy. Dipping my toe into automation and so glad to have found this. Thank you.

    • Andy Syrewicze says:

      Hi Ronan!

      Automation will certainly make your day-to-day IT stuff much easier! =)

      Glad to be of help!

  • Richie says:

    Hey buddy, very amazing script!
    Just one question, will it work for win 2k8 r2?
    I tried on 2k8r2 but the customizepsc not working.

    • Andy Syrewicze says:

      Hi Richie!

      The script was designed for 2012 R2 and newer. It may work for 2008 R2, but some of the PowerShell commands were different at times. I would make sure that your 2008 R2 image is running the latest version of PowerShell, and you may have to go through each command that is executed against the guest OS and verify that it exists in that version of PowerShell.

      As for the PC customization not working, can you provide more details? is it the VMware customization not working or does the script just sit and wait for customization forever and never advances?

  • Ragnar says:

    What a script! I am totally grateful to Andy, wish I could buy you a beer or 20!!

  • Richard says:

    Hi Andy, Great script, thank you for sharing… what is the requirement for the customisation spec on line 43 as all the naming etc is done by the script?

    Thanks again
    Richard

    • Andy Syrewicze (Chief Editor) says:

      The customization spec should be created manually beforehand and then you simply adjust the line near the top where the $SourceCustomSpec variable is defined. Simply input your customization name at the end of that line, and you should be good to go!

  • Matthew Tandy says:

    Great post and some useful bits I have taken away from this post

  • Abdul Khader Mohideen says:

    How to download the script into my laptop?

  • Bent G. says:

    Sorry, I’m pretty new to scripting and am trying to write a simple deployment script and came across your blog while researching. I have not tried to run this script yet. One question I have is how do you get around not defining the target “-VM” parameter when using the Invoke-VMScript command? When I looked up that command it states that that parameter is required.

    • Andy Syrewicze (Chief Editor) says:

      Hello!

      I am using the -VM parameter for Invoke-VMScript, I’m simply storing the name of the VM in a variable. For example in the below line:

      Invoke-VMScript -ScriptText $DCNetworkSettings -VM $DomainControllerVMName -GuestCredential $DCLocalCredential

      $DomainControllerVMName is a variable defined earlier in the script using syntax like, $DomainControllerVMName = NAME. PowerCLI knows to look at what the value stored in the variable is, and use it inline with the command.

      Make sense?

  • Stefan says:

    Thanks for sharing this.
    Is there a possibility to add settings like : vcpu, vram, target storage, dvpg…?

    I will also look myself for those parameters, but i can imagine you want to add those settings in the automatic roll out as well. Not every VM will use the same settings.

    Thanks!

  • s31064 says:

    While I get the idea of sequential coding for PS newbies, I would have loved to see this (or something similar) written for those of us that are more familiar with PS and functions, but are VMware newbies. For instance, in a few places, you use the netsh command instead of the Set-IPAddress cmdlet. Do you have a more PS advanced deploy script available anywhere that we can edit?

    • Hi. There’s a blog coming out soon about a simplified VM deployment script with a Powershell form GUI.
      In the meantime, there’s a github repo with the ps1 you might want to check out.
      PSGUI is the simplified script and GUIDeploy2 is the more interesting one.
      It has functions and uses customization specs. Hope you enjoy 😉

Leave a comment

Your email address will not be published. Required fields are marked *