Problem statement:
We are in the process of converting our provisioning code from utilizing conventional Templates stored in specific datastores to leveraging a Content Library per datacenter to allow templates to be used across a larger surface area. Reading through the documentation for PowerCLI New-VM doesn't support the -OSCustomizationSpec when the VM is being created from a Content Library.
Question:
Is there a way via powershell and powercli (or other means) to set the OS Customization Spec after a vm has been created via New-VM? If so, what am I missing?
Notes:
Current snippet is as follows.
# Workaround for misplaced Templates in various datacenters $templateName = Get-MyTemplateName -Site $decodedname.Site -OS $server.OperatingSystem -Version $server.OperatingSystemVersion -Server $vcenter -Credential $Credential # -DataCenter $datacenter $datacentername = Get-MyDataCenterName -Server $vcenter -Site $decodedname.Site -Zone $decodedname.Zone -Credential $Credential $clustername = Get-MyClusterName -Server $vcenter -Site $decodedname.Site -Zone $decodedname.Zone -Category $server.Category -Credential $Credential #-ComputerName $server.ComputerName $foldername = Get-MyFolderName -Server $vcenter -Type VM -ApplicationCode $decodedname.App -Datacenter $datacentername -Credential $Credential #-ComputerName $server.ComputerName # Build the hashtable which will be used to splat params to the call to New-VM $params = @{} $params.'Name' = $server.ComputerName.ToUpper() $params.'Datastore' = try { $datastoreclustername = Get-MyDataStoreClusterName -Server $vcenter -Category $server.Category -Credential $Credential Get-DatastoreCluster -Name $datastoreclustername -Server $vcenter -ErrorAction Stop } catch { $datastorename = Get-MyDataStoreName -Server $vcenter -ComputerName $server.ComputerName -Credential $Credential Get-Datastore -Name $datastorename -Server $vcenter } $params.'ResourcePool' = try { Get-Cluster -Name $clustername -Server $vcenter -ErrorAction Stop } catch { Get-VMHost -Name $clustername -Server $vcenter } $params.'ContentLibraryItem' = Get-ContentLibraryItem -Name $templateName.Name -Server $vcenter | Where-Object{$_.ContentLibrary.Name -eq ($templateName.ContentLibrary).Name} $params.'Location' = Get-Folder -Name $foldername -Server $vcenter -Location $datacentername $params.'Server' = $vcenter $params.'OSCustomizationSpec' = try { $customizationParams = @{} $customizationParams.'Name' = $server.ComputerName $customizationParams.'IPAddress' = $ipaddress $customizationParams.'SubnetMask' = Get-MySubnetMaskFromCIDR -CIDR $server.CIDRAddress.Split('/')[1] $customizationParams.'DefaultGateway' = Get-MyDefaultGatewayFromIPAddress -IPAddress $customizationParams.IPAddress $customizationParams.'Dns' = Get-MyDNSServerIPAddress -Site $decodedname.Site -Zone $decodedname.Zone $customizationParams.'Server' = $vcenter $customizationParams.'Specification' = ('OSC_{0}_{1}' -f $server.OperatingSystem,$server.Domain).ToUpper() $customizationParams.'Credential' = $Credential New-EzVmOSCustomizationSpec @customizationParams } catch { $customizationspec = Get-OSCustomizationSpec -Name ('temp_{0}' -f $params.Name) -ErrorAction SilentlyContinue if ($customizationspec -ne $null) { Remove-OSCustomizationSpec -OSCustomizationSpec $customizationspec -Confirm:$false -ErrorAction Stop } Write-Error ('Could not create OSCustomization Spec for {0}. Error details: {1}' -f $server.ComputerName,$Error[0].Exception) } Write-Verbose ('Creating virtual machine {0} using parameters:' -f $server.ComputerName) # Create the new VM try { $vm = New-VM @params -ErrorAction Stop # Doesn't work currently with OS Customization Specifications due to implementation of Content Library for storage of templates.
# How could we apply the OS Customization Specification after the New-VM command?
} catch { Write-Error ('Could not create VM {0}. Error details: {1}' -f $server.ComputerName,$Error[0].Exception) continue } finally { Remove-OSCustomizationSpec -OSCustomizationSpec $params.OSCustomizationSpec -Confirm:$false -ErrorAction Stop }
# Workaround for misplaced Templates in various datacenters
$templateName = Get-F5VMWareTemplateName -Site $decodedname.Site -OS $server.OperatingSystem -Version $server.OperatingSystemVersion -Server $vcenter -Credential $Credential # -DataCenter $datacenter
$datacentername = Get-F5VmWareDataCenterName -Server $vcenter -Site $decodedname.Site -Zone $decodedname.Zone -Credential $Credential
$clustername = Get-F5VmWareClusterName -Server $vcenter -Site $decodedname.Site -Zone $decodedname.Zone -Category $server.Category -Credential $Credential #-ComputerName $server.ComputerName
$foldername = Get-F5VmWareFolderName -Server $vcenter -Type VM -ApplicationCode $decodedname.App -Datacenter $datacentername -Credential $Credential #-ComputerName $server.ComputerName
# Build the hashtable which will be used to splat params to the call to New-VM
$params = @{}
$params.'Name' = $server.ComputerName.ToUpper()
$params.'Datastore' =
try
{
$datastoreclustername = Get-F5VmWareDataStoreClusterName -Server $vcenter -Category $server.Category -Credential $Credential
Get-DatastoreCluster -Name $datastoreclustername -Server $vcenter -ErrorAction Stop
}
catch
{
$datastorename = Get-F5VMWareDataStoreName -Server $vcenter -ComputerName $server.ComputerName -Credential $Credential
Get-Datastore -Name $datastorename -Server $vcenter
}
$params.'ResourcePool' =
try
{
Get-Cluster -Name $clustername -Server $vcenter -ErrorAction Stop
}
catch
{
Get-VMHost -Name $clustername -Server $vcenter
}
$params.'ContentLibraryItem' = Get-ContentLibraryItem -Name $templateName.Name -Server $vcenter | Where-Object{$_.ContentLibrary.Name -eq ($templateName.ContentLibrary).Name}
$params.'Location' = Get-Folder -Name $foldername -Server $vcenter -Location $datacentername
$params.'Server' = $vcenter
$params.'OSCustomizationSpec' =
try
{
$customizationParams = @{}
$customizationParams.'Name' = $server.ComputerName
$customizationParams.'IPAddress' = $ipaddress
$customizationParams.'SubnetMask' = Get-F5SubnetMaskFromCIDR -CIDR $server.CIDRAddress.Split('/')[1]
$customizationParams.'DefaultGateway' = Get-F5DefaultGatewayFromIPAddress -IPAddress $customizationParams.IPAddress
$customizationParams.'Dns' = Get-F5DNSServerIPAddress -Site $decodedname.Site -Zone $decodedname.Zone
$customizationParams.'Server' = $vcenter
$customizationParams.'Specification' = ('OSC_{0}_{1}' -f $server.OperatingSystem,$server.Domain).ToUpper()
$customizationParams.'Credential' = $Credential
New-EzVmOSCustomizationSpec @customizationParams
}
catch
{
$customizationspec = Get-OSCustomizationSpec -Name ('temp_{0}' -f $params.Name) -ErrorAction SilentlyContinue
if ($customizationspec -ne $null) {
Remove-OSCustomizationSpec -OSCustomizationSpec $customizationspec -Confirm:$false -ErrorAction Stop
}
Write-Error ('Could not create OSCustomization Spec for {0}. Error details: {1}' -f $server.ComputerName,$Error[0].Exception)
}
Write-Verbose ('Creating virtual machine {0} using parameters:' -f $server.ComputerName)
# Create the new VM
try
{
$vm = New-VM @params -ErrorAction Stop # Doesn't work currently with OS Customization Specifications due to implementation of Content Library for storage of templates.
}
catch
{
Write-Error ('Could not create VM {0}. Error details: {1}' -f $server.ComputerName,$Error[0].Exception)
continue
}
finally
{
Remove-OSCustomizationSpec -OSCustomizationSpec $params.OSCustomizationSpec -Confirm:$false -ErrorAction Stop
}