A better placement strategy for vCAC with Custom Properties
As an update to the previous post on doing a manual placement of VMs I would like to present a approach for a placement strategy in vCAC that is a […]
Audit and Consulting of Information Systems and Business Processes
As an update to the previous post on doing a manual placement of VMs I would like to present a approach for a placement strategy in vCAC that is a […]
As an update to the previous post on doing a manual placement of VMs I would like to present a approach for a placement strategy in vCAC that is a little bit more flexible than just relying on the location field and a reservation policy. The idea is to have custom properties on various reservations that will be checked before placement. If and only if all custom properties match the input pattern that reservation should be selected for provisioning. As an example see the following figure where five custom properties have been defined on the reservation ‘GOLD02’:
So for your workflow to check on these properties you define them in a hashtable and pass them on to the placement script:
PS > $Policies.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Hashtable System.Object PS > $Policies Name Value ---- ----- biz.dfch.Machine.NetZoneGroup Internal biz.dfch.Machine.ISO27001 1 biz.dfch.Level Gold biz.dfch.Machine.StageValue Prod biz.dfch.Machine.Location PremierSite
You would then use this ‘Policies’ object to pass it on to the placement script to determine possible resources (reservation and storagepath). Resources are taken on a first match policy which you could easily change to something more sophisticated.
PS > $m.GetType().FullName DynamicOps.ManagementModel.ManagementModelEntities PS > $Machine.GetType().FullName DynamicOps.ManagementModel.VirtualMachine # Required storage for this machine $StorageRequired = [math]::Ceiling($Machine.VMUsedStorageGB) -as [int64]; Write-Host ("{0}: StorageRequired/Machine.VMUsedStorageGB: [{1}]." -f $Machine.VirtualMachineID, $StorageRequired); # ResourcePlacementParameters holds parameters for actual placement $ResourcePlacementParameters = @{}; # holds possible HostReservations to use $hrCandidates = @{} foreach($hr in $m.HostReservations) { $fReturn = $true; # Check if enabled if($fReturn -And !$hr.Enabled) { $fReturn = $false; } # Check hr against given Policies hash table to match - if no policy is defined this reservation is skipped $ahrProp = @{}; $m.LoadProperty($hr, 'HostReservationProperties') | Select-Object PropertyName, PropertyValue |% { $ahrProp.Add($_.PropertyName, $_.PropertyValue); }; foreach($p in $Policies.GetEnumerator()) { if($fReturn -And (!$ahrProp.ContainsKey($p.Name) -Or ($p.Value -ne $ahrProp.($p.Name))) { Write-Host ("{0}: HostReservation '{1}' does not match '{2}'. Skipping ..." -f $Machine.VirtualMachineID, $hr.HostReservationName, $p.Name); $fReturn = $false; break; } # if } # foreach # Check if enough storage on reservation $StorageFree = ($hr.ReservationStorageSizeGB - $hr.HostReservationStats.StorageAllocated); if($StorageFree -lt $StorageRequired) { Write-Host ("{0}: HostReservation '{1}' does not have enough free space '{2}'. Skipping ..." -f $Machine.VirtualMachineID, $hr.HostReservationName, $StorageFree); $fReturn = $false; } # if # Check if another reservation policy with the same priority already exists if($hrCandidates.ContainsKey($hr.ReservationPriority)) { Write-Host ("{0}: Processing hr '{1}' [{2}]. Other ReservationPriority '{3}' already exists. Skipping ..." -f $Machine.VirtualMachineID, $hr.HostReservationName, $hr.HostReservationID, $hr.ReservationPriority); continue; } # if Write-Host ('ahrProp: {0}' -f ($ahrProp | Out-String)); $null = $hrCandidates.Add($hr.ReservationPriority, $hr.HostReservationName); } # foreach # Get the first reservation policy with lowest numerical priority $hrKey = $hrCandidates.Keys | Sort | Select-Object -First 1; if(!$hrKey) { Write-Error ("{0}: No HostReservation found." -f $Machine.VirtualMachineID); throw($gotoFailure); } # if $ResourcePlacementParameters.HostReservation = $hrCandidates.$hrKey; if(!$fReturn) { $msg = "{0}: No HostReservation meets requirement. Aborting ... " -f $Machine.VirtualMachineID; Log-Critical $fn $msg; $null = New-VcacUserLog -Message $msg -Username $Machine.Owner.UserName; $e = New-CustomErrorRecord -msg $msg -cat ObjectNotFound -o $Machine; throw($gotoError); } # if Write-Info ("{0}: HostReservation '{1}' meets requirements." -f $Machine.VirtualMachineID, $hr.HostReservationName); $htsCandidates = @{} $h = $hr.Host; $ahts = $m.LoadProperty($h, 'HostToStorages'); foreach($hrts in $hr.HostReservationToStorages) { Write-Host ("{0}: Processing hrts '{1}' with Priority '{2}' and MaxCapacity '{3}' ..." -f $Machine.VirtualMachineID, $hrts.HostReservationToStorageID, $hrts.ReservationPriority, $hrts.MaxCapacity); if(!$hrts.Enabled) { Write-Warning ("{0}: Processing hrts '{1}'. HostReservationToStrage is disabled. Skipping ..." -f $Machine.VirtualMachineID, $hrts.HostReservationToStorageID); continue; } # if if($hrts.MaxCapacity -le $StorageRequired) { Write-Warning ("{0}: Processing hrts '{1}'. MaxCapacity [{2}] is less than StorageRequired [{3}] ..." -f $Machine.VirtualMachineID, $hrts.HostReservationToStorageID, $hrts.MaxCapacity, $StorageRequired); continue; } # if $hrhts = $m.LoadProperty($hrts, 'HostToStorage'); $hts = $ahts |? HostToStorageID -eq $hrhts.HostToStorageID; if($htsCandidates.ContainsKey($hrts.ReservationPriority)) { Write-Host ("{0}: Processing hrts '{1}'. Other HostReservationToStrage priority '{2}' already exists. Skipping ..." -f $Machine.VirtualMachineID, $hrts.HostReservationToStorageID, $hrts.ReservationPriority); continue; } # if $null = $m.LoadProperty($hts, 'Storage'); Write-Host ("{0}: Checking hts[{1}].Storage.StorageFreeCapacityGB against StorageRequired [{2}] ..." -f $Machine.VirtualMachineID, $hts.StoragePath, $StorageRequired); if($hts.Storage.StorageFreeCapacityGB -le $StorageRequired) { Write-Warning ("{0}: Checking hts[{1}].Storage.StorageFreeCapacityGB against StorageRequired [{2}] FAILED: [{3}]." -f $Machine.VirtualMachineID, $hts.StoragePath, $StorageRequired, $hts.Storage.StorageFreeCapacityGB); continue; } # if Write-Info ("{0}: Checking hts[{1}].Storage.StorageFreeCapacityGB against StorageRequired [{2}] SUCCEEDED: [{3}]." -f $Machine.VirtualMachineID, $hts.StoragePath, $StorageRequired, $hts.Storage.StorageFreeCapacityGB); $null = $htsCandidates.Add($hrts.ReservationPriority, $hts.StoragePath); } # foreach # Get the first storage path with lowest numerical priority $htsKey = $htsCandidates.Keys | Sort | Select-Object -First 1; if(!$htsKey) { Write-Error ("{0}: No HostReservationToStorages/HostToStorages found." -f $Machine.VirtualMachineID); throw($gotoFailure); } # if $ResourcePlacementParameters.StoragePath = $htsCandidates.$htsKey;
After running the code against the match script you might get back a result like the following which you can then use to place the machine on actual resources:
PS > $$ResourcePlacementParameters Name Value ---- ----- HostReservation GOLD02 StoragePath vCenterResources2-storage-pool-3
As usual error handling, logging and resource cleanup has been removed from this sample code.