Migration/vSphere/vSphereUtil.psm1
using module './RiverMeadow.VSphereVMTag' Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath Common ` | Join-Path -ChildPath Wrappers | Join-Path -ChildPath Wrappers) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath Util ` | Join-Path -ChildPath Util) function Get-RMVSphereTagCategory { param( [System.Object] $TargetInventory ) $TagCategories = @() $TagCategoryAsHashtable = @{} foreach ($TagCategory in $TargetInventory.attributes.vsphere.tag_categories) { $RMTagCategory = [RMVSphereTagCategory]::new($TagCategory.name, $TagCategory.identifier) foreach ($Tag in $TagCategory.tags) { $RMTag = $RMTagCategory.AddTag($Tag.name, $Tag.identifier) if ($TagCategoryAsHashtable.ContainsKey($TagCategory.name)) { $TagCategoryAsHashtable[$TagCategory.name] += $RMTag } else { $TagCategoryAsHashtable.Add($TagCategory.name, @($RMTag)) } } $TagCategories += $RMTagCategory } return $TagCategories, $TagCategoryAsHashtable } function Get-RMTagOption { param( [RMVSphereTagCategory[]] $TagCategory ) $TagOptions = @() foreach ($Category in $TagCategory) { foreach ($Tag in $Category.Tags) { $TagOption = $Tag.Name + "[" + $Category.Name + "]" $TagOptions += $TagOption } } return $TagOptions } function Get-RMVMTag { param( [System.Object] $TargetInventory ) $TagCategories, $TagCategoryAsHashtable = Get-RMVSphereTagCategory -TargetInventory $TargetInventory $TagOptions = Get-RMTagOption -TagCategory $TagCategories while ($true) { $VMTags = Read-RMToken -UserMessage "Enter one or more VM tags separated by commas" -Options $TagOptions ` -DefaultValue "None" -ParameterName "VM tags" -Separator "," if ([string]::IsNullOrWhiteSpace($VMTags)) { return @{} } $CompareResults = Compare-Object -ReferenceObject $TagOptions -DifferenceObject $VMTags -IncludeEqual $InputObjects = Get-RMInputObjectBySideIndicator -CompareResult $CompareResults -SideIndicator "==" if ($InputObjects.Count -ne $VMTags.Count) { Write-RMError -Message "One or more VM tags does not belong to the given list of VM tags, please try again." } else { return (Get-RMSelectedVMTag -VMTag $VMTags -TagCategory $TagCategoryAsHashtable) } } } function Get-RMSelectedVMTag { param( [string[]] $VMTag, [hashtable] $TagCategory ) $SelectedVMTag = @{} foreach ($Tag in $VMTag) { $TagName = $Tag.Substring(0, $Tag.LastIndexOf("[")) $CategoryName = $Tag.Substring($Tag.LastIndexOf("[") + 1, $Tag.LastIndexOf("]") - ($Tag.LastIndexOf("[") + 1)) $RMTags = $TagCategory[$CategoryName] foreach ($RMTag in $RMTags) { if ($RMTag.name -ine $TagName) { continue } if ($SelectedVMTag.ContainsKey($CategoryName)) { $SelectedVMTag[$CategoryName] += $RMTag } else { $Tags = @($RMTag) $SelectedVMTag.Add($CategoryName, $Tags) } } } return $SelectedVMTag } function Get-RMSelectedVMTagByRMVSphereTag { param( [RMVSphereTag[]] $InputTag, [System.Object] $TargetInventory ) $SelectedVMTag = @{} $TagCategories, $TagCategoryAsHashtable = Get-RMVSphereTagCategory -TargetInventory $TargetInventory foreach ($RMVSphereTag in $InputTag) { $CategoryName = $RMVSphereTag.RMVSphereTagCategory.GetCategoryName() $RMTags = $TagCategoryAsHashtable[$CategoryName] foreach ($RMTag in $RMTags) { if ($RMTag.GetTagName() -ne $RMVSphereTag.GetTagName()) { continue } if ($SelectedVMTag.ContainsKey($CategoryName)) { $SelectedVMTag[$CategoryName] += $RMTag } else { $SelectedVMTag.Add($CategoryName, @($RMTag)) } } } return $SelectedVMTag } function Get-RMStoragePolicy { param( [System.Object] $TargetInventory, [System.Object] $Source, [string[]] $SelectedDiskIndex, [bool] $IsInteractive ) $DiskCnt = 0 $SelectedStorageProfileIds = @{} $SelectedStorageProfileNames = @{} $StoragePolicyOptions = Get-RMStoragePolicyOption -TargetInventory $TargetInventory foreach ($DiskIndex in $SelectedDiskIndex) { if ($IsInteractive) { $Disk = $Source.attributes.storage.vm_disks[$DiskIndex] $Size = $Disk.size_kb/(1024*1024) $Size = [math]::round($Size, 2) $StoragePolicyName = Read-RMString -UserMessage "Enter storage policy name for disk of size $Size GiB" ` -Options $StoragePolicyOptions.keys -DefaultValue "None" -ParameterName "Storage policy name" -IsRequired $false if (![string]::IsNullOrWhiteSpace($StoragePolicyName)) { $SelectedStorageProfileIds.Add($Disk.label, $StoragePolicyOptions[$StoragePolicyName]) $SelectedStorageProfileNames.Add($Disk.label, $StoragePolicyName) } } else { #TODO: Add non-interactive case functionality } $DiskCnt ++ } return $SelectedStorageProfileIds, $SelectedStorageProfileNames } function Get-RMStoragePolicyOption { param( [System.Object] $TargetInventory ) $StoragePolicyOptions = @{} # Storage profiles are not datacenter specific and live at the vCenter level and applies to # all the datacenters; though ME's target inventory puts it under the datacenter JSON block, # so if a vCenter has multiple datacenters then the storage profiles under each datacenter # will be the same, hence we are just picking up the storage profiles from the first datacenter. foreach ($StorageProfile in $TargetInventory.attributes.vsphere.datacenters[0].storage_profiles) { # User will be providing the storage profile name and hence using it as the key # so that we can send both the UUID and the name to FE. # Storage profile names are unique in given vCenter $StoragePolicyOptions.Add($StorageProfile.name, $StorageProfile.uuid) } return $StoragePolicyOptions } function Get-RMStorageProfileIdByStoragePolicyName { param ( [hashtable] $StoragePolicyNamePerDiskLabel, [System.Object] $TargetInventory ) $ProfileId = @{} if ($null -eq $StoragePolicyNamePerDiskLabel -or $StoragePolicyNamePerDiskLabel.Keys.Count -eq 0) { return $ProfileId } $PolicyNameToUUIDMapping = Get-RMStoragePolicyOption -TargetInventory $TargetInventory foreach ($DiskLabel in $StoragePolicyNamePerDiskLabel.Keys) { $StoragePolicyName = $StoragePolicyNamePerDiskLabel[$DiskLabel].Trim() if ($PolicyNameToUUIDMapping.ContainsKey($StoragePolicyName)) { $ProfileId.Add($DiskLabel, $PolicyNameToUUIDMapping[$StoragePolicyName]) } } return $ProfileId } function Get-RMDiskProvisioningTypeForVMBasedSource { param( [System.Object] $Source, [string[]] $DiskProvisioningType, [string[]] $SelectedDiskIndex, [hashtable] $SelectedStorageProfileName, [bool] $IsInteractive ) if ($Source.collection_type -ine "vm") { throw "Get-RMDiskProvisioningTypeForVMBasedSource is supported for VM based sources only" } $ProvisioningTypes = "thick-lazy-zeroed", "thick-eager-zeroed", "thin" $DiskWithProvisioningTypeCnt = 0 $ResultProvisioningTypes = @() for ($Index = 0; $Index -lt $Source.attributes.storage.vm_disks.Count; $Index++) { if ($SelectedDiskIndex -notcontains $Index) { $ResultProvisioningTypes += $null continue } $Disk = $Source.attributes.storage.vm_disks[$Index] if ($null -ne $SelectedStorageProfileName -and $SelectedStorageProfileName.ContainsKey($Disk.label)) { $ResultProvisioningTypes += "" continue } if ($IsInteractive) { $Size = $Disk.size_kb/(1024*1024) $Size = [math]::round($Size, 2) $ResultProvisioningTypes += Read-RMString -UserMessage "Enter disk provisioning type for disk of size $Size GiB" ` -Options $ProvisioningTypes -DefaultValue "thin" -ParameterName "Disk provisioning type" -IsRequired $false } else { if ($null -ne $DiskProvisioningType -and $DiskWithProvisioningTypeCnt -lt $DiskProvisioningType.Count) { $ResultProvisioningTypes += $DiskProvisioningType[$DiskWithProvisioningTypeCnt].Trim() $DiskWithProvisioningTypeCnt ++ } else { $ResultProvisioningTypes += "thin" } } } return $ResultProvisioningTypes } function Get-RMDatastoreByVMBasedSource { param( [System.Object] $Source, [string[]] $TargetDatastores, [string[]] $SelectedDiskIndex, [bool] $IsInteractive ) if (!$IsInteractive) { Throw "The function Get-RMDatastoreBySource does not support non-interactive case" } if ($TargetDatastores.Count -eq 0) { Throw "No datastores were found, migration cannot be started." } if ($Source.collection_type -ine "vm") { Throw "Get-RMDatastoreByVMBasedSource is supported for VM based sources only" } $Datastores = @() for ($Index = 0; $Index -lt $Source.attributes.storage.vm_disks.Count; $Index++) { if ($SelectedDiskIndex -contains $Index) { $Disk = $Source.attributes.storage.vm_disks[$Index] $Size = $Disk.size_kb/(1024*1024) $Size = [math]::round($Size, 2) $Datastores += Read-RMString -UserMessage "Enter the datastore name for disk of size $Size GiB" ` -Options $TargetDatastores -DefaultValue $TargetDatastores[0] -ParameterName "Datastore name" -IsRequired $false } else { $Datastores += "" } } return $Datastores } function Get-RMVMBasedSourceDiskLabel { param( [System.Object] $Source ) $DiskLabels = @() foreach ($Disk in $Source.attributes.storage.vm_disks) { $DiskLabels += $Disk.label } return $DiskLabels } function Get-RMStoragePolicyNameByTargetInventory { param( [System.Object] $TargetInventory ) $StoragePolicyNames = @() # Read the comment above for loop in method Get-RMStoragePolicyOption as to why first datacenter # is being used foreach ($StorageProfile in $TargetInventory.attributes.vsphere.datacenters[0].storage_profiles) { $StoragePolicyNames += $StorageProfile.name } return $StoragePolicyNames } function Remove-RMDefaultStoragePolicy { param( [hashtable] $StoragePolicyNamePerDiskLabel, [hashtable] $UserParameter ) if ($null -eq $StoragePolicyNamePerDiskLabel) { return $null, $UserParameter } $UpdatedPolicyAndDiskMapping = @{} foreach ($DiskLabel in $StoragePolicyNamePerDiskLabel.Keys) { if ($StoragePolicyNamePerDiskLabel[$DiskLabel] -notmatch "\s*datastore\s+default\s*") { $UpdatedPolicyAndDiskMapping.Add($DiskLabel, $StoragePolicyNamePerDiskLabel[$DiskLabel]) } } $UserParameter["StoragePolicyNamePerDiskLabel"] = $UpdatedPolicyAndDiskMapping return $UpdatedPolicyAndDiskMapping, $UserParameter } |