Applies to VMware, PowerCLI, Virtual Machines
Modules needed: vmware.powercli
As someone who works in a VMware environment, and likes the command line, PowerCLI is a lifesaver. Are you mad about the phasing-out of vSphere, forcing everyone to use the web-based vCenter manager? PowerCLI is the best way to get around it. I’ve been doing my research making sure I can do everything in PowerShell that I can in vSphere/vCenter. One of the most common tasks being creating virtual machines.
Before we get started, there are a few things you are going to need. First of all, you need a vCenter host. Got it? Great. Next, you need the module PowerCLI. This can be easily installed by typing install-module vmware.powercli.
In my current environment, we are utilizing Templates, Customization Specifications, and Tags.
- Templates are pretty simple to make, since you can just convert a running VM to one. This is a good place to start.
- In a future post, I’ll explain how to create Customization Specs using PowerCLI as well. Currently, I’m using OS Customization specs to set the network adapters, and join the machine to the domain.
- Lastly, we use Tags to set when the VM will be backed up using Veeam.
Since there’s a good amount of code going into this, I’ve commented through the script to show you what’s happening. It goes like this:
# Static settings, based on your environment. # DEFINE THESE VARIABLES BEFORE RUNNING THE SCRIPT $server = # The name of the vCenter Server you are connected to. $KnownGoodSpec = # This variable asks for an OS Customization, created in vCenter. Use get-oscustomizationspec to see what you have available. $SubnetMask = # Subnet, DNS, and Gateway are assumed to be static, if you are using this script on the same network every time. $dnsServers = $DefaultGateway = $Template = # This variable asks for a template, created in vCenter. Use get-template to see what you have available. # Begin Clear-Host Write-Host "Create a VM" -ForegroundColor Yellow Write-Host Write-Host # Gets the new VM name. In my OSCustomization, this also gets set to the hostname of the machine. $vmname = Read-Host "VM Name" # Displays available Hosts, in order of least utilized to most. $gvmh = Get-VMHost | Sort-Object -Property CpuUsageMhz | Format-Table -AutoSize | Out-String Write-Host $gvmh $vmhost = Read-Host "Host" # Displays available Datastores, in order of most free space to least. $lds = Get-Datastore | Sort-Object -Property FreeSpaceGB -Descending | Out-String Write-Host $lds $datastore = Read-Host "Datastore" # The "Backup Scheme" section is based on VM Tags, which correlate to Backup Schedules in Veeam # If you don't utilize this in your environment, you may want to remove the next block of code, and the "Get-VM -Name $vmname | New-TagAssignment -Tag $tag" at the end of the script. $gtag = Get-Tag | Where-Object -Property Category -Like "Backup Scheme" | Format-Table -AutoSize | Out-String Write-Host $gtag $backupTag = Read-Host "Tag Name" $backupCat = Read-Host "Tag Category" $tag = Get-Tag -Name $backupTag -Category $backupCat # Displays all Folders. $gf = Get-Folder | Format-Table -Property Id,Name,parent -AutoSize | Out-String Write-Host $gf $folderID = Read-Host "Folder Id" $folder = Get-Folder -Id $FolderID Write-Host Write-Host Write-Host Write-Host Write-Host # Collects VM Specs. $spec1 = Write-Host "VM Specs:" -ForegroundColor Yellow $spec2 = Write-Host "---------------" $cpu = Read-Host "Number of CPUs" $core = Read-Host "Cores per CPU" $ram = Read-Host "Memory (GB)" # The IP address is added to the OSCustomizationspec, using the OSCusomtizationNicMapping cmdlet. $ip = Read-Host "IP Address" # Gets additional Disks, and stores them in an array, such that the size and format correlate when being added to the VM. $disk = @() do { [int]$count = 0 while ($count -lt 1) { Write-Host Write-Host Write-Host "Would you like to attach additional disks?" Write-Host Write-Host "1) Yes" Write-Host "2) No" Write-Host $selection = Read-Host "Select" $hdisks = New-Object system.object switch ($selection) { '1' { Write-Host Write-Host $hdsize = Read-Host "Hard disk size (GB)" $hdisks | Add-Member -Type NoteProperty -Name Size -Value $hdsize $disk += $hdisks Write-Host Write-Host "Storage Format" Write-Host Write-Host "1) Thin Provisioned" Write-Host "2) Thick Provisioned" Write-Host $hdprovswitch = Read-Host "Select" switch ($hdprovswitch) { '1' { $hdprov = "Thin" $hdisks | Add-Member -Type NoteProperty -Name Provision -Value $hdprov } '2' { $hdprov = "Thick" $hdisks | Add-Member -Type NoteProperty -Name Provision -Value $hdprov } } Write-Host "Disk added." -ForegroundColor Green } '2' { $count = 1 } } } } until ($count -gt 0) Clear-Host Write-Host Write-Host Write-Host Write-Host Write-Host Write-Host Write-Host # Displays Confirmation Sheet. $conf0 = Write-Host "----------------------------------------" $conf1 = Write-Host "Confirmation:" -ForegroundColor Yellow $conf2 = Write-Host "---------------------------------------- VM Name: $vmname Host: $vmhost Datastore: $datastore Backup Scheme: $backup Location: $Folder Number of CPUs: $cpu Cores per CPU: $core Memory (GB): $ram IP Address: $ip " # If you did not add additional disks, "None" is shown. if ($disk.count -eq 0) { Write-Host "Additional Disks: None" } # Otherwise, it will list the disks added, their size, and Storage Format. else { Write-Host "Additional Disks:" } $n = 1 foreach ($d in $disk) { Write-Host Write-Host "Disk $n" Write-Host "---------" Write-Host "Size:" $d.Size "GB" Write-Host $d.Provision "Provisioned" $n = $n + 1 } Write-Host "---------------------------------------- " # Script pauses before executing anything for the VM. This is where you would Cancel if changes need to be made. Pause Write-Host Write-Host "Creating VM..." -ForegroundColor green # Script grabs the OSCustomizationSpec defined at the beginning of the script, and makes a temporary copy of it with the VM in the name. $oscust = New-OSCustomizationSpec -OSCustomizationSpec $KnownGoodSpec -Name "Temp-$vmname" # Script then gets the Nic settings of the copy, and replaces them with the info you supplied at the beginning of the script. Get-OSCustomizationSpec $oscust | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $ip -SubnetMask $SubnetMask -Dns $dnsServers -DefaultGateway $DefaultGateway -Position 1 # Saves all changes to the variable that gets used. $useCust = Get-OSCustomizationSpec -Name "Temp-$vmname" # Creates the VM, Sets the specifications entered, starts the VM, and opens a remote console Window. New-VM -Template $Template -Name $vmname -Server $server -VmHost $vmhost -Datastore $datastore -Location $folder -OSCustomizationSpec $useCust | Set-VM -NumCpu $cpu -CoresPerSocket $core -MemoryGB $ram -Confirm:$false | Start-VM | Open-VMConsoleWindow # Adds the additional disks. foreach ($d in $disk) { New-HardDisk -VM $vmname -CapacityGB $d.Size -StorageFormat $d.Provision } # Sets the tag assignment for Backup Scheduling. Remove the following line if you are not utilizing tags for Backup Scheduling. Get-VM -Name $vmname | New-TagAssignment -Tag $tag # Removes the temporary OSCustomizationspec created earlier. Remove-OSCustomizationSpec -OSCustomizationSpec "Temp-$vmname" -Confirm:$false -ErrorAction Ignore
There you have it. When all the information is entered, you should get a confirmation sheet that looks like this:
Of course, creating VM’s in vSphere doesn’t take all that much time. But when you start adding the Customization Specs, Additional Disks, Tags- there’s a good chunk of your life spent clicking.