Migration/vSphere/vSphere.psm1
using module '../../Common/Result' using module './RiverMeadow.VSphereNetworkConfiguration' using module './RiverMeadow.VSphereVMTag' Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath MigrationProfile | Join-Path -ChildPath VSphereMigrationProfile) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath DifferentialProfile | Join-Path -ChildPath DifferentialProfile) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath Preflight | Join-Path -ChildPath Preflight) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath Util | Join-Path -ChildPath Util) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath Util | Join-Path -ChildPath MigrationUtil) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath CloudAccount | Join-Path -ChildPath CloudAccount) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath RiverMeadow.Source | Join-Path -ChildPath SourceUtil | Join-Path -ChildPath SourceUtil) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath Validate | Join-Path -ChildPath Validate) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath Common | Join-Path -ChildPath Common) 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 vSphereUtil) function Start-RMNonInteractiveVsphereOsBasedMigration { param ( [string] $TargetCloud, [string] $SourceIP, [string] $ScheduledAt, [string] $TargetVMName, [string[]] $MountPoints, [string[]] $ResizeMountPoints, [string] $TransferMethod, [int] $TargetVMVCPUCount, [string] $CoresPerSocket, [int] $TargetVMMemorySize, [string] $DatacenterName, [bool] $EnableDestinationNetworkIsolation, [RMVSphereMigrationNetworkConfiguration] $MigrationNetworkConfig, [RMVSphereIsolatedNetworkConfiguration] $IsolatedNetworkConfig, [RMVSphereDestinationNetworkConfiguration[]] $DestinationNICConfig, [bool] $DisableAutomaticDNSRegistrationOnTheTarget, [string] $ClusterName, [string] $ResourcePoolName, [string] $FolderName, [string] $DatastoreClusterName, [string[]] $DatastoreNames, [string[]] $DiskProvisioningTypes, [int] $HardwareVersion, [bool] $ShutdownSource, [bool] $ShutdownTarget, [bool] $RemoveRMSAgentFromSource, [bool] $RemoveRMSAgentFromTarget, [string[]] $MigrationInstructions, [string] $UpgradeOSVersion, [bool] $IgnoreValidationErrors, [bool] $OverrideExistingMigration ) $Errors, $Warnings, $IsSourceAndTargetCloudPresent, $IsRequiredParametersPresentAndValid = Confirm-RMvSphereFullMigrationParameter $PSBoundParameters $CloudAccount = $null $Source = $null try { if (![string]::IsNullOrEmpty($TargetCloud)) { $CloudAccount, $ErrorString = Get-RMCloudAccountByName -CloudAccountName $TargetCloud -AccountType "rivermeadow_standalone" if (![string]::IsNullOrEmpty($ErrorString)) { $Errors += $ErrorString $IsSourceAndTargetCloudPresent = $false } else { Get-RMTargetInventory -CloudAccount $CloudAccount | Out-Null } } } catch [System.Management.Automation.RuntimeException] { $Errors += $PSItem.Exception.Message $IsSourceAndTargetCloudPresent = $false } $ShouldExit = $false try { if (![string]::IsNullOrEmpty($SourceIP)) { $Source = Get-RMSourceByIP -IPAddress $SourceIP } } catch [System.Management.Automation.RuntimeException] { $Errors += $PSItem.Exception.Message $IsSourceAndTargetCloudPresent = $false } [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() if (!$IsSourceAndTargetCloudPresent) { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } try { $Source, $ShouldExit, $OverrideExistingMigrationWarning, $OverrideExistingMigrationError = ` Get-RMSourceWithAttribute -Source $Source -CloudAccount $CloudAccount ` -IgnoreValidationErrors $IgnoreValidationErrors -AccountType "rivermeadow_standalone" ` -RMMigrationReturn $RMMigrationReturn if (!$IgnoreValidationErrors -and $OverrideExistingMigrationError -and !$OverrideExistingMigration) { $Errors += "Please set 'OverrideExistingMigration' to true and try again." } } catch [System.Management.Automation.RuntimeException] { $Errors += $PSItem.Exception.Message } if ($null -ne $Source) { $SourceErrors, $RequiredParameterState = Confirm-RMvSphereFullMigrationParameterWithSource ` -UserParameter $PSBoundParameters -Source $Source if ($IsRequiredParametersPresentAndValid) { $IsRequiredParametersPresentAndValid = $RequiredParameterState } $Errors += $SourceErrors } $UserInput = @{} $Entitlement = Get-RMEntitlement $UserInput.Add("CloudAccount", $CloudAccount) $UserInput.Add("Entitlement", $Entitlement) $UserInput.Add("Source", $Source) if ([string]::IsNullOrEmpty($TargetVMName)) { $TargetVMName = $Source.hostname } $UserInput.Add("TargetVMName", $TargetVMName) $SelectedMountPoints = $null $SourceMountPoints = Get-MountPoint -Source $Source if ($MountPoints.Count -gt 0) { $SelectedMountPoints = Get-RMSelectedMount -MountPoints $SourceMountPoints -DifferenceList $MountPoints -IncludeEqual $true } else { # If no mount points are given then take all mount points on the source as the selected mount points $SelectedMountPoints = $SourceMountPoints } $UserInput.Add("SelectedMounts", $SelectedMountPoints) $MountsResize = @{} if ($null -ne $ResizeMountPoints -and $ResizeMountPoints -gt 0) { $MountsResize, $MountsResizeErrors = Get-RMResizeMountsPoint -ResizeMountPoints $ResizeMountPoints -SelectedMountPoints $SelectedMountPoints -Source $Source if($null -eq $MountsResize) { $Errors += $MountsResizeErrors } if ("" -ne $TransferMethod -and "block-based" -eq $TransferMethod ) { $Errors += "TransferMethod needs to be 'file-based' if you want to resize the mount points." } $TransferMethod = "file-based" } else { $TransferMethod, $ErrorString = Get-RMTransferMethod -Source $Source -SelectedMountPoints $SelectedMountPoints ` -TransferMethod $TransferMethod if (![string]::IsNullOrEmpty($ErrorString)) { $Errors += $ErrorString } } $UserInput.Add("ResizeMountPoints", $MountsResize) $UserInput.Add("TransferType", $TransferMethod) if(0 -eq $TargetVMVCPUCount) { $TargetVMVCPUCount = $Source.attributes.cpu.processors.Count } $UserInput.Add("TargetVMVCPUCount", $TargetVMVCPUCount) if ("" -eq $CoresPerSocket) { $CoresPerSocket = 1 } else { $CoresPerSockets = Get-RMCoresPerSocket -TargetVMVCPUCount $TargetVMVCPUCount if(!($CoresPerSocket -in $CoresPerSockets)) { $CoresPerSocketsAsString = $CoresPerSockets -join ", " $Errors += "Invalid CoresPerSocket '$CoresPerSocket', valid cores per socket are: '$CoresPerSocketsAsString'" } } $UserInput.Add("CoresPerSocket", $CoresPerSocket) $UserInput.Add("TargetVMMemorySize", $TargetVMMemorySize) if ($Source.os_type -eq "windows") { $UserInput.Add("DisableAutomaticDNSRegistrationOnTheTarget", $DisableAutomaticDNSRegistrationOnTheTarget) } else { $UserInput.Add("DisableAutomaticDNSRegistrationOnTheTarget", $false) } $UserInput.Add("DatacenterName", $DatacenterName) $UserInput.Add("EnableDestinationNetworkIsolation", $EnableDestinationNetworkIsolation) $UserInput.Add("MigrationNetworkConfig", $MigrationNetworkConfig) $UserInput.Add("IsolatedNetworkConfig", $IsolatedNetworkConfig) $UserInput.Add("DestinationNICConfig", $DestinationNICConfig) $UserInput.Add("ClusterName", $ClusterName) $UserInput.Add("ResourcePoolName", $ResourcePoolName) $UserInput.Add("FolderName", $FolderName) $UserInput.Add("DatastoreClusterName", $DatastoreClusterName) $DiskProvisioningTypes = Get-DiskProvisioningTypeBySource -Source $Source -DiskProvisioningTypes $DiskProvisioningTypes -IsInteractive $false $UserInput.Add("DatastoreLocations", $DatastoreNames) $UserInput.Add("DisksProvisioningType", $DiskProvisioningTypes) $HardwareVersions, $DefaultHardwareVersion, $ToolsPackage = Get-RMHardwareVersionsAndToolsVersion -CloudAccount $CloudAccount if (0 -eq $HardwareVersion) { $HardwareVersion = $DefaultHardwareVersion } else { if ($HardwareVersions -notcontains $HardwareVersion) { $HardwareVersionsAsString = $HardwareVersions -join ", " $Errors += "Invalid HardwareVersion '$HardwareVersion', valid hardware versions are: '$HardwareVersionsAsString'" } } $UserInput.Add("HardwareVersion", $HardwareVersion) $UserInput.Add("ToolsPackage", $ToolsPackage) $MigrationInstructionsAsHashTable = $null try { if (($IgnoreValidationErrors -and $OverrideExistingMigration) -or (!$IgnoreValidationErrors -and $OverrideExistingMigration) -or $OverrideExistingMigrationWarning) { $MigrationInstructions += "override_source_migration=true" } $MigrationInstructionsAsHashTable = Get-RMStringArrayAsHashtable -InputItems $MigrationInstructions -ParameterName "MigrationInstructions" } catch { $Errors += $PSItem.Exception.Message } $UserInput.Add("MigrationInstructions", $MigrationInstructionsAsHashTable) $UserInput.Add("ShutdownSource", $ShutdownSource) $UserInput.Add("ShutdownTarget", $ShutdownTarget) $UserInput.Add("RemoveRMSAgentFromSource", $RemoveRMSAgentFromSource) $UserInput.Add("RemoveRMSAgentFromTarget", $RemoveRMSAgentFromTarget) Add-RMOSUpgrade -UserParameter $PSBoundParameters -UpdatedParameter $UserInput -Source $Source $ValidationErrors = $null if ($IsRequiredParametersPresentAndValid) { $ValidationErrors = Confirm-RMVSphereValidateOSBasedMigrationProfile @UserInput } if ($null -ne $ValidationErrors) { # validation errors have already been printed, so add after the below call Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings $Errors += $ValidationErrors Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } else { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings if ($Errors.Count -gt 0 -or $ShouldExit) { return $RMMigrationReturn } } if ([string]::IsNullOrEmpty($ScheduledAt)) { $UserInput.Add("ScheduledAt", "") } else { $UserInput.Add("ScheduledAt", (Convert-RMDateTimeToUTC -InputDateTime $ScheduledAt)) } $UserInput["DisksProvisioningType"] = Update-DiskProvisioningTypeForME -DiskProvisioningTypes $UserInput["DisksProvisioningType"] $UserInput.Add("IgnoreValidationErrors", $IgnoreValidationErrors) $Response = New-RMVSphereMigrationProfile @UserInput $ShouldExit = Start-RMMigrationPreflight -MigrationProfileId $Response.id -IgnoreValidationErrors $IgnoreValidationErrors -RMMigrationReturn $RMMigrationReturn if ($ShouldExit) { return $RMMigrationReturn } $IsScheduled = ![string]::IsNullOrEmpty($ScheduledAt) $MigrationResponse = Invoke-RMMigrationPost -MigrationProfileResponse $Response return Update-RMMigrationReturnAsSuccess -MigrationResponse $MigrationResponse ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $IsScheduled ` -ReturnMessage "Migration started successfully, migration ID" } function Start-RMInteractiveVSphereOSBasedMigration { param( ) $Entitlement = Get-RMEntitlement $CloudAccount = Read-RMCloudAccount -AccountType "rivermeadow_standalone" $TargetInventory = Get-RMTargetInventory -CloudAccount $CloudAccount $Source = Read-RMSource -UserMessage "Enter the IP address of the source machine to be migrated" -ParameterName "Source IP address" -IsRequired $true $IgnoreValidationErrors = Read-RMBoolean -UserMessage "Ignore validation errors" -DefaultValue "false" [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() $Source, $ShouldExit, $OverrideExistingMigrationWarning, $OverrideExistingMigrationError = Get-RMSourceWithAttribute -Source $Source -CloudAccount $CloudAccount ` -IgnoreValidationErrors $IgnoreValidationErrors -RMMigrationReturn $RMMigrationReturn -AccountType "rivermeadow_standalone" if ($ShouldExit) { return $RMMigrationReturn } if ($OverrideExistingMigrationError) { $OverrideExistingMigrationError = Read-RMBoolean -UserMessage "Would you like to override the previous migration attempt" -DefaultValue $false if (!$IgnoreValidationErrors -and !$OverrideExistingMigrationError) { return $RMMigrationReturn } } $ScheduledAt = Read-RMMigrationSchedule $TargetVMName = Read-RMString -UserMessage "Enter target VM Name" -DefaultValue $Source.hostname ` -ParameterName "Target VM Name" -IsRequired $false $MountPoints = Get-MountPoint -Source $Source if (0 -eq $MountPoints.count) { throw "Source has no mount points, cannot be migrated" } $MountPointsAsString = $MountPoints.values -join ", " Write-Output "Mount points to be migrated [$MountPointsAsString]" | Out-Host $ExcludedMountPoints = Get-RMExcludedMountPoint -OSType $Source.os_type -MountPoints $MountPoints.Values $SelectedMountPoints = $MountPoints if ("" -ne $ExcludedMountPoints) { $ExcludedList = $ExcludedMountPoints.Split(",").Trim() $SelectedMountPoints = Get-RMSelectedMount -MountPoints $MountPoints -DifferenceList $ExcludedList -IncludeEqual $false } $ReadValue = Read-RMBoolean -UserMessage "Resize mount points" -DefaultValue "false" $MountsResize = @{} $TransferType = "file-based" if ($ReadValue) { $MountsResize = Get-RMInteractiveMountsResize -SelectedMountPoints $SelectedMountPoints -Source $Source } else { $TransferType = (Get-RMTransferMethod -Source $Source -SelectedMountPoints $SelectedMountPoints -IsInteractive $true)[0] } $TargetVMVCPUCount = $Source.attributes.cpu.processors.Count $TargetVMVCPUCount = Read-RMInt -UserMessage "Enter virtual CPU count" -DefaultValue $TargetVMVCPUCount ` -ParameterName "Virtual CPUs count" -IsRequired $false $CoresPerSocket = 1 $CoresPerSockets = Get-RMCoresPerSocket -TargetVMVCPUCount $TargetVMVCPUCount $CoresPerSocket = Read-RMInt -UserMessage "Enter cores per socket" -Options $CoresPerSockets -DefaultValue $CoresPerSocket ` -ParameterName "Cores per socket" -IsRequired $false $SourceMemorySize = [math]::Round($Source.attributes.memory.total_kb/(1024 * 1024),2) $TargetVMMemorySize = Read-RMInt -UserMessage "Enter target VM's memory size in GiB" -DefaultValue $SourceMemorySize ` -ParameterName "Target VM's memory size" -IsRequired $false $DatacenterNames = Get-RMDatacenterName -TargetInventory $TargetInventory $DatacenterName = Read-RMString -UserMessage "Enter datacenter name" -Options $DatacenterNames ` -ParameterName "Datacenter name" -IsRequired $true $NetworkNames = Get-RMNetworkName -TargetInventory $TargetInventory -datacenterName $DatacenterName $EnableDestinationNetworkIsolation = $false [RMVSphereMigrationNetworkConfiguration] $MigrationNetworkConfig = $null [RMVSphereIsolatedNetworkConfiguration] $IsolatedNetworkConfig = $null [RMVSphereDestinationNetworkConfiguration[]] $DestinationNetworkConfigs = $null if ($Source.os_type -eq "windows") { $EnableDestinationNetworkIsolation = Read-RMBoolean -UserMessage "Enable destination network isolation" -DefaultValue "false" if ($EnableDestinationNetworkIsolation) { $MigrationNetworkConfig = Get-RMMigrationNetworkConfig -NetworkName $NetworkNames $IsolatedNetworkConfig = Get-RMIsolatedNetworkConfig -NetworkName $NetworkNames } else { $DestinationNetworkConfigs = Get-RMDestinationNetworkConfig -NetworkName $NetworkNames } } else { $DestinationNetworkConfigs = Get-RMDestinationNetworkConfig -NetworkName $NetworkNames } $DisableAutomaticDNSRegistrationOnTheTarget = $false if ($Source.os_type -eq "windows") { $DisableAutomaticDNSRegistrationOnTheTarget = Read-RMBoolean -UserMessage "Disable automatic DNS registration on the Target" ` -DefaultValue "false" } $Clusters = Get-RMCluster -TargetInventory $TargetInventory -datacenterName $DatacenterName $ClusterName = Read-RMString -UserMessage "Enter cluster name" -Options $Clusters -ParameterName "Cluster name" -IsRequired $true $ResourcePoolName = Read-RMString -UserMessage "Enter resource pool name" -DefaultValue "None" ` -ParameterName "Resource pool name" -IsRequired $false $VMFolders = Get-RMVMFolderName -TargetInventory $TargetInventory -DatacenterName $DatacenterName $FolderName = Read-RMVMFolderString -UserMessage "Enter the VM folder path using '/' as the path separator" -VMFolders $VMFolders -DefaultValue "None" $DatastoreClusters = Get-RMDatastoreCluster -TargetInventory $TargetInventory -datacenterName $DatacenterName $DatastoreClusterName = Read-RMString -UserMessage "Enter datastore cluster name" -Options $DatastoreClusters ` -DefaultValue "None" -ParameterName "Datastore cluster name" -IsRequired $false $Datastores = Get-RMDatastore -TargetInventory $TargetInventory -DatacenterName $DatacenterName -ClusterName $ClusterName $SelectedDatastores = Get-RMDatastoreBySource -Source $Source -TargetDatastores $Datastores -IsInteractive $true $SelectedProvisioningTypes = Get-DiskProvisioningTypeBySource -Source $Source -IsInteractive $true $SelectedProvisioningTypes = Update-DiskProvisioningTypeForME -DiskProvisioningTypes $SelectedProvisioningTypes $HardwareVersions, $DefaultHardwareVersion, $ToolsPackage = Get-RMHardwareVersionsAndToolsVersion -CloudAccount $CloudAccount $HardwareVersion = Read-RMInt -UserMessage "Enter VM hardware version" -Options $HardwareVersions ` -DefaultValue $DefaultHardwareVersion -ParameterName "VM hardware version" -IsRequired $false $OSMUpgradeUserInput = @{} Read-RMOSMUpgradeOption -Source $Source -UpdatedUserInput $OSMUpgradeUserInput $UpgradeOSVersion = $OSMUpgradeUserInput["UpgradeOSVersion"] $InPlaceUpgrade = $OSMUpgradeUserInput["InPlaceUpgrade"] $ShutdownSource = Read-RMBoolean -UserMessage "Shutdown source after data is fully migrated" -DefaultValue "false" $ShutdownTarget = Read-RMBoolean -UserMessage "Shutdown target after data is fully migrated" -DefaultValue "false" $RemoveRMSAgentFromSource = Read-RMBoolean -UserMessage "Remove RMS agent post migration from source" -DefaultValue "false" $RemoveRMSAgentFromTarget = Read-RMBoolean -UserMessage "Remove RMS agent post migration from target" -DefaultValue "false" $ReadValue = Read-RMPair -UserMessage "Enter migration instructions in the format 'key=value' and separated by commas" ` -Separator "=" -DefaultValue "None" if (($IgnoreValidationErrors -and $OverrideExistingMigrationError) -or (!$IgnoreValidationErrors -and $OverrideExistingMigrationError) -or $OverrideExistingMigrationWarning) { if ("" -eq $ReadValue) { $ReadValue = "override_source_migration=true" } else { $ReadValue += ",override_source_migration=true" } } $MigrationInstructions = Get-RMStringAsHashtable -InputString $ReadValue $HashArguments = @{ CloudAccount = $CloudAccount Entitlement = $Entitlement Source = $Source ScheduledAt = $ScheduledAt TargetVMName = $TargetVMName SelectedMounts = $SelectedMountPoints ResizeMountPoints = $MountsResize ShutdownSource = $ShutdownSource ShutdownTarget = $ShutdownTarget RemoveRMSAgentFromSource = $RemoveRMSAgentFromSource RemoveRMSAgentFromTarget = $RemoveRMSAgentFromTarget DatacenterName = $DatacenterName EnableDestinationNetworkIsolation = $EnableDestinationNetworkIsolation MigrationNetworkConfig = $MigrationNetworkConfig IsolatedNetworkConfig = $IsolatedNetworkConfig DestinationNICConfig = $DestinationNetworkConfigs DisableAutomaticDNSRegistrationOnTheTarget = $DisableAutomaticDNSRegistrationOnTheTarget ClusterName = $ClusterName DatastoreClusterName = $DatastoreClusterName DatastoreLocations = $SelectedDatastores FolderName = $FolderName DisksProvisioningType = $SelectedProvisioningTypes TransferType = $TransferType TargetVMVCPUCount = $TargetVMVCPUCount CoresPerSocket = $CoresPerSocket TargetVMMemorySize = $TargetVMMemorySize ResourcePoolName = $ResourcePoolName HardwareVersion = $HardwareVersion ToolsPackage = $ToolsPackage MigrationInstructions = $MigrationInstructions UpgradeOSVersion = $UpgradeOSVersion IgnoreValidationErrors = $IgnoreValidationErrors InPlaceUpgrade = $InPlaceUpgrade } $Response = New-RMVSphereMigrationProfile @HashArguments $ShouldExit = Start-RMMigrationPreflight -MigrationProfileId $Response.id -IgnoreValidationErrors $IgnoreValidationErrors -RMMigrationReturn $RMMigrationReturn if ($ShouldExit) { return $RMMigrationReturn } $IsScheduled = ![string]::IsNullOrEmpty($ScheduledAt) $MigrationResponse = Invoke-RMMigrationPost -MigrationProfileResponse $Response return Update-RMMigrationReturnAsSuccess -MigrationResponse $MigrationResponse ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $IsScheduled ` -ReturnMessage "Migration started successfully, migration ID" } function Start-RMInteractiveVSphereVMBasedMigration { param () $UserInput = @{} $Source = Read-RMVMBasedSource -UserMessage "Enter the VM name of the source machine to be migrated" ` -ParameterName "Source VM name" -IsRequired $true $Entitlement = Get-RMEntitlement $UserInput.Add("Entitlement", $Entitlement) [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() $CloudAccount = Get-RMVMBasedCloudAccountBySource -Source $Source -AccountType "rivermeadow_standalone" if ($null -eq $CloudAccount) { return Update-RMMigrationReturnAsError ` -Message "The migration appliance associated with the given source is not ready for use, cannot start the migration" ` -RMMigrationReturn $RMMigrationReturn } $UserInput.Add("CloudAccount", $CloudAccount) $TargetInventory = Get-RMTargetInventory -CloudAccount $CloudAccount $IgnoreValidationErrors = Read-RMBoolean -UserMessage "Ignore validation errors" -DefaultValue "false" $UserInput.Add("IgnoreValidationErrors", $IgnoreValidationErrors) $SourceAttributeResult = Get-RMSourceWithAttribute -Source $Source -CloudAccount $CloudAccount ` -IgnoreValidationErrors $IgnoreValidationErrors -RMMigrationReturn $RMMigrationReturn ` -AccountType "rivermeadow_standalone" $Source, $ShouldExit, $OverrideExistingMigrationWarning, $OverrideExistingMigrationError = $SourceAttributeResult $UserInput.Add("Source", $Source) if ($ShouldExit) { return $RMMigrationReturn } if ($OverrideExistingMigrationError) { $OverrideExistingMigrationError = Read-RMBoolean -UserMessage "Would you like to override the previous migration attempt" -DefaultValue $false if (!$IgnoreValidationErrors -and !$OverrideExistingMigrationError) { return $RMMigrationReturn } } $ScheduledAt = Read-RMMigrationSchedule $UserInput.Add("ScheduledAt", $ScheduledAt) $TargetVMName = Read-RMString -UserMessage "Enter target VM Name" -DefaultValue $Source.host ` -ParameterName "Target VM Name" -IsRequired $false $UserInput.Add("TargetVMName", $TargetVMName) if (0 -eq $Source.attributes.storage.vm_disks.Count) { return Update-RMMigrationReturnAsError ` -Message "Source has no disks, cannot be migrated" -RMMigrationReturn $RMMigrationReturn } $SourceDisksAsString = "Disks to be migrated [" + ((Get-RMVMDiskProperty -Source $Source) -join ", ") + "]" Write-Output $SourceDisksAsString | Out-Host $SelectedDisks = @() $ReturnedValue = Get-RMSelectedDisk -Source $Source if ($SelectedDisks -is [hashtable]) { $SelectedDisks += $ReturnedValue } else { $SelectedDisks = $ReturnedValue } $UserInput.Add("SelectedDisk", $SelectedDisks) $SelectedDiskIndices = @() foreach ($Item in $SelectedDisks) { $SelectedDiskIndices += $Item.Values } $UserInput.Add("SelectedDiskIndex", $SelectedDiskIndices) $TargetVMVCPUCount = $Source.attributes.cpu.processors.Count $TargetVMVCPUCount = Read-RMInt -UserMessage "Enter virtual CPU count" -DefaultValue $TargetVMVCPUCount ` -ParameterName "Virtual CPUs count" -IsRequired $false $UserInput.Add("TargetVMVCPUCount", $TargetVMVCPUCount) $CoresPerSocket = 1 $CoresPerSockets = Get-RMCoresPerSocket -TargetVMVCPUCount $TargetVMVCPUCount $CoresPerSocket = Read-RMInt -UserMessage "Enter cores per socket" -Options $CoresPerSockets -DefaultValue $CoresPerSocket ` -ParameterName "Cores per socket" -IsRequired $false $UserInput.Add("CoresPerSocket", $CoresPerSocket) $SourceMemorySize = [math]::Round($Source.attributes.memory.total_kb/(1024 * 1024),2) $TargetVMMemorySize = Read-RMInt -UserMessage "Enter target VM's memory size in GiB" -DefaultValue $SourceMemorySize ` -ParameterName "Target VM's memory size" -IsRequired $false $UserInput.Add("TargetVMMemorySize", $TargetVMMemorySize) $DatacenterNames = Get-RMDatacenterName -TargetInventory $TargetInventory $DatacenterName = Read-RMString -UserMessage "Enter datacenter name" -Options $DatacenterNames ` -ParameterName "Datacenter name" -IsRequired $true $UserInput.Add("DatacenterName", $DatacenterName) $NetworkNames = Get-RMNetworkName -TargetInventory $TargetInventory -datacenterName $DatacenterName $PreserveIPAddress = Read-RMBoolean -UserMessage "Do you want to preserve the IP address" -DefaultValue "false" $UserInput.Add("PreserveIPAddress", $PreserveIPAddress) [RMVSphereDestinationNetworkConfiguration[]] $DestinationNetworkConfigs = $null if ($PreserveIPAddress) { $DestinationNetworkName = Read-RMString -UserMessage "Enter destination network name" ` -ParameterName "Destination network name" -Options $NetworkNames -IsRequired $true $DestinationNetworkConfigs += [RMVSphereDestinationNetworkConfiguration]::new(` $DestinationNetworkName, "dhcp") } else { $DestinationNetworkConfigs = Get-RMDestinationNetworkConfig -NetworkName $NetworkNames -Source $Source } $UserInput.Add("DestinationNICConfig", $DestinationNetworkConfigs) $UserInput.Add("PreserveMACAddress", (Read-RMBoolean -UserMessage "Do you want to preserve the MAC address" ` -DefaultValue "false")) $UserInput.Add("VMTag", (Get-RMVMTag -TargetInventory $TargetInventory)) $Clusters = Get-RMCluster -TargetInventory $TargetInventory -datacenterName $DatacenterName $ClusterName = Read-RMString -UserMessage "Enter cluster name" -Options $Clusters ` -ParameterName "Cluster name" -IsRequired $true $UserInput.Add("ClusterName", $ClusterName) $UserInput.Add("ResourcePoolName", (Read-RMString -UserMessage "Enter resource pool name" -DefaultValue "None" ` -ParameterName "Resource pool name" -IsRequired $false)) $UserInput.Add("FolderName", (Read-RMString -UserMessage "Enter VM folder name" -DefaultValue "None" ` -ParameterName "VM folder name" -IsRequired $false)) $DatastoreClusters = Get-RMDatastoreCluster -TargetInventory $TargetInventory -datacenterName $DatacenterName $UserInput.Add("DatastoreClusterName", (Read-RMString -UserMessage "Enter datastore cluster name" -Options $DatastoreClusters ` -DefaultValue "None" -ParameterName "Datastore cluster name" -IsRequired $false)) $Datastores = Get-RMDatastore -TargetInventory $TargetInventory -DatacenterName $DatacenterName -ClusterName $ClusterName $UserInput.Add("DatastoreLocation", (Get-RMDatastoreByVMBasedSource -Source $Source ` -TargetDatastores $Datastores -SelectedDiskIndex $SelectedDiskIndices -IsInteractive $true)) $SelectedStorageProfileIds, $SelectedStorageProfileNames = Get-RMStoragePolicy -TargetInventory $TargetInventory ` -Source $Source -SelectedDiskIndex $SelectedDiskIndices -IsInteractive $true $UserInput.Add("StorageProfileId", $SelectedStorageProfileIds) $UserInput.Add("StorageProfileName", $SelectedStorageProfileNames) $SelectedDiskProvisioningTypes = Get-RMDiskProvisioningTypeForVMBasedSource -Source $Source ` -SelectedStorageProfileName $SelectedStorageProfileNames -SelectedDiskIndex $SelectedDiskIndices -IsInteractive $true $UserInput.Add("DiskProvisioningType", (Update-DiskProvisioningTypeForME -DiskProvisioningTypes $SelectedDiskProvisioningTypes)) $UserInput.Add("UpgradeTool", (Read-RMBoolean -UserMessage "Do you want to upgrade the VM tools on the target VM" -DefaultValue "false")) $HardwareVersions, $DefaultHardwareVersion, $ToolsPackage = Get-RMHardwareVersionsAndToolsVersion -CloudAccount $CloudAccount $UserInput.Add("HardwareVersion", (Read-RMInt -UserMessage "Enter VM hardware version" -Options $HardwareVersions ` -DefaultValue $DefaultHardwareVersion -ParameterName "VM hardware version" -IsRequired $false)) $UserInput.Add("ToolsPackage", $ToolsPackage) $UserInput.Add("ShutdownSource", (Read-RMBoolean -UserMessage "Shutdown source after data is fully migrated" -DefaultValue "false")) $UserInput.Add("ShutdownTarget", (Read-RMBoolean -UserMessage "Shutdown target after data is fully migrated" -DefaultValue "false")) $UserInput.Add("FinalizeMigration", (Read-RMBoolean -UserMessage "Remove snapshot(s) from the Target VM in preparation for a cutover" ` -DefaultValue "false")) $ReadValue = Read-RMPair -UserMessage "Enter migration instructions in the format 'key=value' and separated by commas" ` -Separator "=" -DefaultValue "None" if (($IgnoreValidationErrors -and $OverrideExistingMigrationError) -or (!$IgnoreValidationErrors -and $OverrideExistingMigrationError) -or $OverrideExistingMigrationWarning) { if ("" -eq $ReadValue) { $ReadValue = "override_source_migration=true" } else { $ReadValue += ",override_source_migration=true" } } $MigrationInstructions = Get-RMStringAsHashtable -InputString $ReadValue $UserInput.Add("MigrationInstruction", $MigrationInstructions) $Response = New-RMVSphereVMBasedMigrationProfile @UserInput $ShouldExit = Start-RMMigrationPreflight -MigrationProfileId $Response.id ` -IgnoreValidationErrors $IgnoreValidationErrors -RMMigrationReturn $RMMigrationReturn if ($ShouldExit) { return $RMMigrationReturn } $IsScheduled = ![string]::IsNullOrEmpty($ScheduledAt) $MigrationResponse = Invoke-RMMigrationPost -MigrationProfileResponse $Response return Update-RMMigrationReturnAsSuccess -MigrationResponse $MigrationResponse ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $IsScheduled ` -ReturnMessage "Migration started successfully, migration ID" } function Start-RMNonInteractiveVsphereVMBasedMigration { param( [string] $SourceVMName, [string] $ScheduledAt, [string] $TargetVMName, [string[]] $SelectedDiskLabel, [int] $TargetVMVCPUCount, [string] $CoresPerSocket, [int] $TargetVMMemorySize, [string] $DatacenterName, [bool] $PreserveIPAddress, [RMVSphereDestinationNetworkConfiguration[]] $DestinationNICConfig, [bool] $PreserveMACAddress, [RMVSphereTag[]] $VMTag, [string] $ClusterName, [string] $ResourcePoolName, [string] $FolderName, [string] $DatastoreClusterName, [string[]] $DatastoreName, [hashtable] $StoragePolicyNamePerDiskLabel, [string[]] $DiskProvisioningType, [bool] $UpgradeTools, [int] $HardwareVersion, [bool] $ShutdownSource, [bool] $ShutdownTarget, [bool] $FinalizeMigration, [string[]] $MigrationInstructions, [bool] $IgnoreValidationErrors, [bool] $OverrideExistingMigration ) $Errors, $Warnings, $IsSourceAndTargetCloudPresent, $IsRequiredParametersPresentAndValid = ` Confirm-RMvSphereVMBasedFullMigrationParameter $PSBoundParameters $Source = $null [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() try { if (![string]::IsNullOrEmpty($SourceVMName)) { $Source = Get-RMSourceByIP -IPAddress $SourceVMName if ($Source.collection_type -ine "VM") { $Errors += "Source '$SourceVMName' is not a VM-Based source, to migrate this source, please use the cmdlet 'Start-RMVSphereOSBasedMigration'." Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } } } catch [System.Management.Automation.RuntimeException] { $Errors += $PSItem.Exception.Message $IsSourceAndTargetCloudPresent = $false } $TargetInventory = $null $CloudAccount = $null if ($null -ne $Source) { $CloudAccount = Get-RMVMBasedCloudAccountBySource -Source $Source -AccountType "rivermeadow_standalone" if ($null -eq $CloudAccount) { $Errors += "The migration appliance associated with the given source is not ready for use, cannot start the migration" $IsSourceAndTargetCloudPresent = $false } else { $TargetInventory = Get-RMTargetInventory -CloudAccount $CloudAccount } } if (!$IsSourceAndTargetCloudPresent) { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } $ShouldExit = $false try { $Source, $ShouldExit, $OverrideExistingMigrationWarning, $OverrideExistingMigrationError = ` Get-RMSourceWithAttribute -Source $Source -CloudAccount $CloudAccount ` -IgnoreValidationErrors $IgnoreValidationErrors -RMMigrationReturn $RMMigrationReturn ` -AccountType "rivermeadow_standalone" if (!$IgnoreValidationErrors -and $OverrideExistingMigrationError -and !$OverrideExistingMigration) { $Errors += "Please set 'OverrideExistingMigration' to true and try again." } } catch [System.Management.Automation.RuntimeException] { $Errors += $PSItem.Exception.Message } # removing the "Datastore Default" to facilitate further processing $StoragePolicyNamePerDiskLabel, $PSBoundParameters = Remove-RMDefaultStoragePolicy ` -StoragePolicyNamePerDiskLabel $StoragePolicyNamePerDiskLabel -UserParameter $PSBoundParameters if ($null -ne $Source) { $SourceErrors, $SourceWarnings, $RequiredParameterState = Confirm-RMvSphereVMBasedFullMigrationParameterWithSource ` -UserParameter $PSBoundParameters -Source $Source -TargetInventory $TargetInventory if ($IsRequiredParametersPresentAndValid) { $IsRequiredParametersPresentAndValid = $RequiredParameterState } $Errors += $SourceErrors $Warnings += $SourceWarnings } $UserInput = @{} $Entitlement = Get-RMEntitlement $UserInput.Add("CloudAccount", $CloudAccount) $UserInput.Add("Entitlement", $Entitlement) $UserInput.Add("Source", $Source) if ([string]::IsNullOrEmpty($TargetVMName)) { $TargetVMName = $Source.hostname } $UserInput.Add("TargetVMName", $TargetVMName) $SelectedDisks = Get-RMSelectedDiskByDiskLabel -DiskLabel $SelectedDiskLabel -Source $Source $UserInput.Add("SelectedDiskLabel", $SelectedDiskLabel) $UserInput.Add("SelectedDisk", $SelectedDisks) $SelectedDiskIndices = @() foreach ($Item in $SelectedDisks) { $SelectedDiskIndices += $Item.Values } $UserInput.Add("SelectedDiskIndex", $SelectedDiskIndices) if(0 -eq $TargetVMVCPUCount) { $TargetVMVCPUCount = $Source.attributes.cpu.processors.Count } $UserInput.Add("TargetVMVCPUCount", $TargetVMVCPUCount) if ("" -eq $CoresPerSocket) { $CoresPerSocket = 1 } else { $CoresPerSockets = Get-RMCoresPerSocket -TargetVMVCPUCount $TargetVMVCPUCount if(!($CoresPerSocket -in $CoresPerSockets)) { $CoresPerSocketsAsString = $CoresPerSockets -join ", " $Errors += "Invalid CoresPerSocket '$CoresPerSocket', valid cores per socket are: '$CoresPerSocketsAsString'" } } $UserInput.Add("CoresPerSocket", $CoresPerSocket) $UserInput.Add("TargetVMMemorySize", $TargetVMMemorySize) $UserInput.Add("DatacenterName", $DatacenterName) $UserInput.Add("PreserveIPAddress", $PreserveIPAddress) $UserInput.Add("DestinationNICConfig", $DestinationNICConfig) $UserInput.Add("PreserveMACAddress", $PreserveMACAddress) $UserInput.Add("VMTag", (Get-RMSelectedVMTagByRMVSphereTag -InputTag $VMTag -TargetInventory $TargetInventory)) $UserInput.Add("ClusterName", $ClusterName) $UserInput.Add("ResourcePoolName", $ResourcePoolName) $UserInput.Add("FolderName", $FolderName) $UserInput.Add("DatastoreClusterName", $DatastoreClusterName) $UserInput.Add("DatastoreLocation", $DatastoreName) $StorageProfileIds = Get-RMStorageProfileIdByStoragePolicyName -StoragePolicyNamePerDiskLabel $StoragePolicyNamePerDiskLabel ` -TargetInventory $TargetInventory $UserInput.Add("StorageProfileId", $StorageProfileIds) $UserInput.Add("StorageProfileName", $StoragePolicyNamePerDiskLabel) $DiskProvisioningTypes = Get-RMDiskProvisioningTypeForVMBasedSource -Source $Source ` -DiskProvisioningType $DiskProvisioningType -SelectedDiskIndex $SelectedDiskIndices ` -SelectedStorageProfileName $StoragePolicyNamePerDiskLabel -IsInteractive $false $DiskProvisioningTypes = Update-DiskProvisioningTypeForME -DiskProvisioningTypes $DiskProvisioningTypes $UserInput.Add("DiskProvisioningType", $DiskProvisioningTypes) $UserInput.Add("UpgradeTool", $UpgradeTools) $HardwareVersions, $DefaultHardwareVersion, $ToolsPackage = Get-RMHardwareVersionsAndToolsVersion -CloudAccount $CloudAccount if (0 -eq $HardwareVersion) { $HardwareVersion = $DefaultHardwareVersion } else { if ($HardwareVersions -notcontains $HardwareVersion) { $HardwareVersionsAsString = $HardwareVersions -join ", " $Errors += "Invalid HardwareVersion '$HardwareVersion', valid hardware versions are: '$HardwareVersionsAsString'" } } $UserInput.Add("HardwareVersion", $HardwareVersion) $UserInput.Add("ToolsPackage", $ToolsPackage) $MigrationInstructionsAsHashTable = $null try { if (($IgnoreValidationErrors -and $OverrideExistingMigration) -or ` (!$IgnoreValidationErrors -and $OverrideExistingMigration) -or ` $OverrideExistingMigrationWarning) { $MigrationInstructions += "override_source_migration=true" } $MigrationInstructionsAsHashTable = Get-RMStringArrayAsHashtable -InputItems $MigrationInstructions -ParameterName "MigrationInstructions" } catch { $Errors += $PSItem.Exception.Message } $UserInput.Add("MigrationInstructions", $MigrationInstructionsAsHashTable) $UserInput.Add("ShutdownSource", $ShutdownSource) $UserInput.Add("ShutdownTarget", $ShutdownTarget) $UserInput.Add("FinalizeMigration", $FinalizeMigration) $ValidationErrors = $null if ($IsRequiredParametersPresentAndValid) { $ValidationErrors = Confirm-RMVSphereValidateVMBasedMigrationProfile @UserInput } if ($null -ne $ValidationErrors) { # validation errors have already been printed, so add after the below call Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings $Errors += $ValidationErrors Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } else { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings if ($Errors.Count -gt 0 -or $ShouldExit) { return $RMMigrationReturn } } if ([string]::IsNullOrEmpty($ScheduledAt)) { $UserInput.Add("ScheduledAt", "") } else { $UserInput.Add("ScheduledAt", (Convert-RMDateTimeToUTC -InputDateTime $ScheduledAt)) } $UserInput.Add("IgnoreValidationErrors", $IgnoreValidationErrors) $Response = New-RMVSphereVMBasedMigrationProfile @UserInput $ShouldExit = Start-RMMigrationPreflight -MigrationProfileId $Response.id ` -IgnoreValidationErrors $IgnoreValidationErrors -RMMigrationReturn $RMMigrationReturn if ($ShouldExit) { return $RMMigrationReturn } $IsScheduled = ![string]::IsNullOrEmpty($ScheduledAt) $MigrationResponse = Invoke-RMMigrationPost -MigrationProfileResponse $Response return Update-RMMigrationReturnAsSuccess -MigrationResponse $MigrationResponse ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $IsScheduled ` -ReturnMessage "Migration started successfully, migration ID" } function Get-RMTargetInventory { param( [System.Object] $CloudAccount ) $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" $Uri = Get-Variable -Name "RMContext-ReactorURI" $Headers = @{ Accept = "application/rm+json" "X-Auth-Token" = $RMLoginResult.Value.token } $CollectList = New-Object Collections.Generic.List[string] $CollectList.Add("datacenter") $CollectList.Add("cluster") $CollectList.Add("datastore") $CollectList.Add("datastore_cluster") $CollectList.Add("resource_pool") $CollectList.Add("storage_profile") $CollectList.Add("vm_folder") $CollectList.Add("network") $Body = @{ "appliance_id" = $CloudAccount.appliance.id "organization_id" = $CloudAccount.organization_id "objects_to_collect" = $CollectList } | ConvertTo-Json $Params = @{ Method = "Post" Uri = $Uri.Value + "/targetinventories" Headers = $Headers Body = $Body ContentType = "application/json" } Write-Output "Starting target inventory..." | Out-Host $TargetInventory = Invoke-RMRestMethod -Param $Params return Watch-RMTargetInventoryStatus -TargetInventoryId $TargetInventory.id } function Get-RMDatacenterName { param( [System.Object] $TargetInventory ) $DatacenterNames = @() foreach ($datacenterName in $TargetInventory.attributes.vSphere.datacenters) { $DatacenterNames += $datacenterName.name } return $DatacenterNames } function Get-RMNetworkName { param ( [System.Object] $TargetInventory, [string] $datacenterName ) $NetworkNames = @() foreach ($datacenter in $TargetInventory.attributes.vSphere.datacenters) { if ($datacenterName -eq $datacenter.name) { foreach($network in $datacenter.networks) { if ([string]::IsNullOrEmpty($network.switch_name)) { $NetworkNames += $network.name } else { $NetworkNames += ($network.switch_name + "/" + $network.name) } } break } } return $NetworkNames } function Get-RMVMFolderName { param ( [System.Object] $TargetInventory, [string] $DatacenterName ) $VMFolders = @() foreach ($Datacenter in $TargetInventory.attributes.vSphere.datacenters) { if ($DatacenterName -ieq $Datacenter.name) { foreach ($Folder in $Datacenter.vm_folder.folders) { $VMFolders += Get-RMPath -Folder $Folder } } } return $VMFolders } function Get-RMPath { param( [System.Object] $Folder, [array] $Paths ) $Paths += $Folder.path if ($null -ne $Folder.folders) { foreach ($F in $Folder.folders) { $Paths = Get-RMPath -Folder $F -Paths $Paths } } return $Paths } function Get-RMCluster { param ( [System.Object] $TargetInventory, [string] $datacenterName ) $Clusters = @() foreach ($datacenter in $TargetInventory.attributes.vSphere.datacenters) { if ($datacenterName -eq $datacenter.name) { foreach($cluster in $datacenter.clusters) { $Clusters += $cluster.name } break } } return $Clusters } function Get-RMDatastoreCluster { param( [System.Object] $TargetInventory, [string] $datacenterName ) $DatastoreClusters = @() foreach ($datacenter in $TargetInventory.attributes.vSphere.datacenters) { if ($datacenterName -eq $datacenter.name) { foreach($datastoreCluster in $datacenter.datastore_clusters) { $DatastoreClusters += $datastoreCluster.name } break } } return $DatastoreClusters } function Get-RMDatastore { param ( [System.Object] $TargetInventory, [string] $DatacenterName, [string] $ClusterName ) $Datastores = @() foreach ($Datacenter in $TargetInventory.attributes.vSphere.datacenters) { if ($Datacenter.name -ne $DatacenterName) { continue } foreach ($Cluster in $Datacenter.clusters) { if ($Cluster.name -ne $ClusterName) { continue } foreach ($Datastore in $Cluster.datastores) { $Datastores += $Datastore.name } break } break } return $Datastores } function Get-RMHardwareVersionsAndToolsVersion { param( [System.Object] $CloudAccount ) $HardwareVersions = @() $HardwareVersionList = @(8, 9, 10, 11, 13, 14, 15, 17, 18, 19) $DefaultVersion = $CloudAccount.vsphere_version $ToolsPackage , $DefaultHardwareVersion = Get-RMVsphereVersionInfo -Version $DefaultVersion foreach($HardwareVersion in $HardwareVersionList) { if ($DefaultHardwareVersion -gt $HardwareVersion -or $DefaultHardwareVersion -eq $HardwareVersion) { $HardwareVersions += $HardwareVersion } } return $HardwareVersions, $DefaultHardwareVersion, $ToolsPackage } function Get-RMVsphereVersionInfo { param ( [string] $Version ) $Versions = Get-RMVsphereVersionHashtable $ToolsPackage = "" $HardwareVersion = "" foreach($VsphereVersion in $Versions.GetEnumerator()) { if ($Version -eq $VsphereVersion.Name) { $ToolsPackage = $VsphereVersion.Value.tools_version $HardwareVersion = $VsphereVersion.Value.hardware_version Break } } return $ToolsPackage, $HardwareVersion } function Get-RMVsphereVersionHashtable { param () $VersionInfo = @{ "VMC" = @{ "tools_version" = "vmwaretools-11.3.0.tar.gz" "hardware_version" = 19 } "GCVE" = @{ "tools_version" = "vmwaretools-11.3.0.tar.gz" "hardware_version" = 19 } "AVS" = @{ "tools_version" = "vmwaretools-11.3.0.tar.gz" "hardware_version" = 19 } "ESXi_7_0" = @{ "tools_version" = "vmwaretools-11.0.5.tar.gz" "hardware_version" = 17 } "ESXi_6_7_U3" = @{ "tools_version" = "vmwaretools-10.3.5.tar.gz" "hardware_version" = 15 } "ESXi_6_7_U2" = @{ "tools_version" = "vmwaretools-10.3.5.tar.gz" "hardware_version" = 15 } "ESXi_6_7" = @{ "tools_version" = "vmwaretools-10.3.2.tar.gz" "hardware_version" = 14 } "ESXi_6_5" = @{ "tools_version" = "vmwaretools-10.1.0.tar.gz" "hardware_version" = 13 } "ESXi_6_0" = @{ "tools_version" = "vmwaretools-9.10.0.tar.gz" "hardware_version" = 11 } } return $VersionInfo } function Get-RMMigrationNetworkConfig { param( [string[]] $NetworkName ) $MigrationNetworkName = Read-RMString -UserMessage "Enter migration network name" ` -ParameterName "Migration network name" -Options $NetworkName -IsRequired $true $IPType = (Read-RMString -UserMessage "Enter migration network's IP type" ` -Options "static", "DHCP" -DefaultValue "DHCP" ` -ParameterName "IP Type" -IsRequired $false).ToLower() if ($IPType -ieq "dhcp") { return [RMVSphereMigrationNetworkConfiguration]::new($MigrationNetworkName, $IPType) } $IPAddress = Read-RMIPAddress -UserMessage "Enter migration network's IP address" ` -ParameterName "IP address" -IsRequired $true $Netmask = Read-RMIPAddress -UserMessage "Enter migration network's netmask" ` -ParameterName "Netmask" -IsRequired $true $DefaultGateway = Read-RMIPAddress -UserMessage "Enter migration network's default gateway" ` -ParameterName "Default gateway" -IsRequired $true $PrimaryDNS = Read-RMIPAddress -UserMessage "Enter migration network's primary DNS" ` -ParameterName "Primary DNS" -IsRequired $true $SecondaryDNS = Read-RMIPAddress -UserMessage "Enter migration network's secondary DNS" ` -ParameterName "Secondary DNS" -DefaultValue "None" -IsRequired $false return [RMVSphereMigrationNetworkConfiguration]::new($MigrationNetworkName, $IPType, ` $IPAddress, $Netmask, $DefaultGateway, $PrimaryDNS, $SecondaryDNS) } function Get-RMIsolatedNetworkConfig { param( [string[]] $NetworkName ) $IsolatedNetworkName = Read-RMString -UserMessage "Enter isolated network name" ` -ParameterName "Isolated network name" -Options $NetworkName -IsRequired $true $IPType = (Read-RMString -UserMessage "Enter isolated network's IP type" ` -Options "static", "DHCP" -DefaultValue "DHCP" ` -ParameterName "IP Type" -IsRequired $false).ToLower() if ($IPType -ieq "dhcp") { return [RMVSphereIsolatedNetworkConfiguration]::new($IsolatedNetworkName, $IPType) } $IPAddress = Read-RMIPAddress -UserMessage "Enter isolated network's IP address" ` -ParameterName "IP address" -IsRequired $true $Netmask = Read-RMIPAddress -UserMessage "Enter isolated network's netmask" ` -ParameterName "Netmask" -IsRequired $true $DefaultGateway = Read-RMIPAddress -UserMessage "Enter isolated network's default gateway" ` -ParameterName "Default gateway" -IsRequired $true $PrimaryDNS = Read-RMIPAddress -UserMessage "Enter isolated network's primary DNS" ` -ParameterName "Primary DNS" -IsRequired $true $SecondaryDNS = Read-RMIPAddress -UserMessage "Enter isolated network's secondary DNS" ` -ParameterName "Secondary DNS" -DefaultValue "None" -IsRequired $false return [RMVSphereIsolatedNetworkConfiguration]::new($IsolatedNetworkName, $IPType, $IPAddress, ` $Netmask, $DefaultGateway, $PrimaryDNS, $SecondaryDNS) } function Get-RMDestinationNetworkConfig { param( [string[]] $NetworkName, [System.Object] $Source ) $DestinationNetworkConfigs = @() $AddMoreNIC = $false $IsGatewayDNSProvided = $false do { $DestinationNetworkName = Read-RMString -UserMessage "Enter destination network name" ` -ParameterName "Destination network name" -Options $NetworkName -IsRequired $true $IPType = (Read-RMString -UserMessage "Enter destination network's IP type" ` -Options "static", "DHCP" -DefaultValue "DHCP" ` -ParameterName "IP Type" -IsRequired $false).ToLower() if ($IPType -ieq "dhcp") { $DestinationNetworkConfigs += [RMVSphereDestinationNetworkConfiguration]::new(` $DestinationNetworkName, $IPType) $AddMoreNIC = Read-RMBoolean -UserMessage "Do you want to add more network adapters" -DefaultValue "false" if ($AddMoreNIC) { continue } return $DestinationNetworkConfigs } $IPAddress = Read-RMIPAddress -UserMessage "Enter destination network's IP address" ` -ParameterName "IP address" -IsRequired $true $Netmask = Read-RMIPAddress -UserMessage "Enter destination network's netmask" ` -ParameterName "Netmask" -IsRequired $true if (!$IsGatewayDNSProvided) { $DefaultGateway = Read-RMIPAddress -UserMessage "Enter destination network's default gateway" ` -ParameterName "Default gateway" -IsRequired $true if ($null -ne $Source -and $Source.collection_type -ieq "vm") { $DestinationNetworkConfigs += [RMVSphereDestinationNetworkConfiguration]::new($DestinationNetworkName, ` $IPType, $IPAddress, $Netmask, $DefaultGateway, "", "") $IsGatewayDNSProvided = $true } else { $PrimaryDNS = Read-RMIPAddress -UserMessage "Enter destination network's primary DNS" ` -ParameterName "Primary DNS" -IsRequired $true $SecondaryDNS = Read-RMIPAddress -UserMessage "Enter destination network's secondary DNS" ` -ParameterName "Secondary DNS" -DefaultValue "None" -IsRequired $false $DestinationNetworkConfigs += [RMVSphereDestinationNetworkConfiguration]::new($DestinationNetworkName, ` $IPType, $IPAddress, $Netmask, $DefaultGateway, $PrimaryDNS, $SecondaryDNS) $IsGatewayDNSProvided = $true } } else { $DestinationNetworkConfigs += [RMVSphereDestinationNetworkConfiguration]::new($DestinationNetworkName, ` $IPType, $IPAddress, $Netmask) } $AddMoreNIC = Read-RMBoolean -UserMessage "Do you want to add more network adapters" -DefaultValue "false" } while ($AddMoreNIC) return $DestinationNetworkConfigs } function Get-RMDatastoreBySource { param( [System.Object] $Source, [string[]] $TargetDatastores, [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." } $Datastores = @() $SortedDisks = $Source.attributes.storage.disks.psobject.Properties.Value | Sort-Object -property device foreach ($Disk in $SortedDisks) { $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 } return $Datastores } function Get-DiskProvisioningTypeBySource { param( [System.Object] $Source, [string[]] $DiskProvisioningTypes, [bool] $IsInteractive ) $ProvisioningTypes = "thick-lazy-zeroed", "thick-eager-zeroed", "thin" $SortedDisks = $Source.attributes.storage.disks.psobject.Properties.Value | Sort-Object -property device $DiskCnt = 0 $ResultProvisioningTypes = @() foreach ($Disk in $SortedDisks) { 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 $DiskProvisioningTypes -and $DiskCnt -lt $DiskProvisioningTypes.Count) { $ResultProvisioningTypes += $DiskProvisioningTypes[$DiskCnt].Trim() } else { $ResultProvisioningTypes += "thin" } } $DiskCnt ++ } return $ResultProvisioningTypes } function Update-DiskProvisioningTypeForME { param( [string[]] $DiskProvisioningTypes ) $Result = @() switch ($DiskProvisioningTypes) { "thick-lazy-zeroed" { $Result += "thick_lazy_zero" } "thick-eager-zeroed" { $Result += "thick_eager_zero" } "thin" { $Result += "thin" } } return $Result } function Get-RMDestinationNetworkAndDvSwitchName { param( [string[]] $NetworkNames, [string] $DestinationNetworkName, [bool] $IsInteractive ) if ($IsInteractive) { $DestinationNetworkName = Read-RMString -UserMessage "Enter destination network name" -Options $NetworkNames ` -ParameterName "Destination network name" -IsRequired $true } $DvSwitchName = "" [string[]] $networkNamesArray = $DestinationNetworkName -split "/" if ($networkNamesArray.Count -eq 2) { $DestinationNetworkName = $networkNamesArray[1] $DvSwitchName = $networkNamesArray[0] } return $DestinationNetworkName, $DvSwitchName } function Confirm-RMvSphereFullMigrationParameter { param( [hashtable] $UserParameter ) $Errors, $Warnings, $IsSourceAndTargetCloudPresent = Confirm-RMCommonParameter -UserParameter $UserParameter $vSphereErrors, $IsRequiredParametersPresentAndValid = Confirm-RMvSphereParameter -UserParameter $UserParameter $Errors += $vSphereErrors return $Errors, $Warnings, $IsSourceAndTargetCloudPresent, $IsRequiredParametersPresentAndValid } function Confirm-RMvSphereVMBasedFullMigrationParameter { param( [hashtable] $UserParameter ) $Errors, $Warnings, $IsSourcePresent = Confirm-RMVMBasedCommonParameter -UserParameter $UserParameter $vSphereErrors, $IsRequiredParametersPresentAndValid = Confirm-RMvSphereParameter -UserParameter $UserParameter $Errors += $vSphereErrors return $Errors, $Warnings, $IsSourcePresent, $IsRequiredParametersPresentAndValid } function Confirm-RMvSphereFullMigrationParameterWithSource { param ( [hashtable] $UserParameter, [System.Object] $Source ) $Errors = @() $IsRequiredParametersPresentAndValid = $true if ($Source.os_type -ieq "linux") { if ($UserParameter.ContainsKey("EnableDestinationNetworkIsolation") -and ` $UserParameter["EnableDestinationNetworkIsolation"] -eq $true) { $Errors += "EnableDestinationNetworkIsolation can be 'true' only for a Windows source" $IsRequiredParametersPresentAndValid = $false } $NetworkConfigErrors, $RequiredParameterState = ` Confirm-RMDestinationNetworkConfig -UserParameter $UserParameter $Errors += $NetworkConfigErrors # Update the flag only if everything is good so far if ($IsRequiredParametersPresentAndValid) { $IsRequiredParametersPresentAndValid = $RequiredParameterState } } elseif ($UserParameter.ContainsKey("EnableDestinationNetworkIsolation") ` -and $UserParameter["EnableDestinationNetworkIsolation"] -eq $true) { [string[]] $NetworkIsolationConfigs = "MigrationNetworkConfig", "IsolatedNetworkConfig" foreach ($NetworkIsolationConfig in $NetworkIsolationConfigs) { if (!$UserParameter.ContainsKey($NetworkIsolationConfig) -or ` $null -eq $UserParameter[$NetworkIsolationConfig]) { $Errors += "$NetworkIsolationConfig is required when 'EnableDestinationNetworkIsolation' is 'true'" $IsRequiredParametersPresentAndValid = $false continue } $NetworkConfig = $UserParameter[$NetworkIsolationConfig] $NetworkConfigErrors, $RequiredParameterState = ` Confirm-RMNetworkIsolationConfig -NetworkConfig $NetworkConfig $Errors += $NetworkConfigErrors # Update the flag only if everything is good so far if ($IsRequiredParametersPresentAndValid) { $IsRequiredParametersPresentAndValid = $RequiredParameterState } } } else { $NetworkConfigErrors, $RequiredParameterState = ` Confirm-RMDestinationNetworkConfig -UserParameter $UserParameter $Errors += $NetworkConfigErrors # Update the flag only if everything is good so far if ($IsRequiredParametersPresentAndValid) { $IsRequiredParametersPresentAndValid = $RequiredParameterState } } $HasDynamicDisks = Test-RMSourceHasDynamicDisks -Source $Source if ($HasDynamicDisks) { if (!$UserParameter.ContainsKey("DatastoreNames") -or [string]::IsNullOrEmpty($UserParameter["DatastoreNames"])) { $Errors += "DatastoreNames is required and since the source has dynamic disk(s), please provide only one datastore name." $IsRequiredParametersPresentAndValid = $false } elseif($UserParameter["DatastoreNames"].Count -gt 1) { $Errors += "Source has dynamic disks, please provide only one datastore name." } } else { if (!$UserParameter.ContainsKey("DatastoreNames") -or [string]::IsNullOrEmpty($UserParameter["DatastoreNames"])) { $Errors += "DatastoreNames is required." $IsRequiredParametersPresentAndValid = $false } } $Errors += Confirm-RMCommonParameterWithSource -UserParameter $UserParameter -Source $Source return $Errors, $IsRequiredParametersPresentAndValid } function Confirm-RMvSphereVMBasedFullMigrationParameterWithSource { param( [hashtable] $UserParameter, [System.Object] $Source, [System.Object] $TargetInventory ) $Errors = @() $Warnings = @() $IsRequiredParametersPresentAndValid = $true if (!$UserParameter.ContainsKey("DatastoreName") -or [string]::IsNullOrWhiteSpace($UserParameter["DatastoreName"])) { $Errors += "DatastoreName is required." $IsRequiredParametersPresentAndValid = $false } elseif ($UserParameter["DatastoreName"].Count -gt $Source.attributes.storage.vm_disks.count) { $Errors += "The parameter 'DatastoreName' contains more datastores than the disks on the source" } if ($UserParameter.ContainsKey("PreserveIPAddress") -and $UserParameter["PreserveIPAddress"] ` -and $UserParameter.ContainsKey("DestinationNICConfig")) { $NetworkConfigs = $UserParameter["DestinationNICConfig"] if ($NetworkConfigs.Count -gt 1) { $Warnings += "The parameter 'PreserveIPAddress' is true and the parameter 'DestinationNICConfig' contains more than one NIC configuration, ` only the destination network name will be used from the first NIC configuration and all other NIC configurations will be ignored." } elseif ($NetworkConfigs[0].IPType -ieq "static" ` -or ![string]::IsNullOrWhiteSpace($NetworkConfigs[0].IPAddress) ` -or ![string]::IsNullOrWhiteSpace($NetworkConfigs[0].Netmask) ` -or ![string]::IsNullOrWhiteSpace($NetworkConfigs[0].DefaultGateway) ` -or ![string]::IsNullOrWhiteSpace($NetworkConfigs[0].PrimaryDNS)) { $Warnings += "When parameter 'PreserveIPAddress' is true then only the destination network name will be used from the parameter 'DestinationNICConfig'" } if ([string]::IsNullOrWhiteSpace($NetworkConfigs[0].DestinationNetworkName)) { $Errors += "DestinationNICConfig's DestinationNetworkName is required" $IsRequiredParametersPresentAndValid = $false } } else { $NetworkConfigErrors, $RequiredParameterState = ` Confirm-RMDestinationNetworkConfig -UserParameter $UserParameter $Errors += $NetworkConfigErrors if ($IsRequiredParametersPresentAndValid) { $IsRequiredParametersPresentAndValid = $RequiredParameterState } } if ($null -ne $UserParameter["StoragePolicyNamePerDiskLabel"] ` -and $UserParameter["StoragePolicyNamePerDiskLabel"].Keys.Count -gt 0) { $DiskLabelsNotFound = @() $NotSelectedDiskLabel = @() $SourceDiskLabels = Get-RMVMBasedSourceDiskLabel -Source $Source foreach ($DiskLabel in $UserParameter["StoragePolicyNamePerDiskLabel"].Keys) { if ($SourceDiskLabels -cnotcontains $DiskLabel) { $DiskLabelsNotFound += $DiskLabel } elseif ($UserParameter.ContainsKey("SelectedDiskLabel") ` -and $UserParameter["SelectedDiskLabel"] -cnotcontains $DiskLabel) { $NotSelectedDiskLabel += $DiskLabel } } $StorageLabelsNotFound = @() $StoragePolicyNames = Get-RMStoragePolicyNameByTargetInventory -TargetInventory $TargetInventory foreach ($StoragePolicyName in $UserParameter["StoragePolicyNamePerDiskLabel"].Values) { if ($StoragePolicyNames -notcontains $StoragePolicyName) { $StorageLabelsNotFound += $StoragePolicyName } } if ($UserParameter["StoragePolicyNamePerDiskLabel"].Keys.Count -gt $SelectedDiskLabel.Count) { $StoragePolicyMappingCnt = $UserParameter["StoragePolicyNamePerDiskLabel"].Keys.Count $SelectedDiskLabelCnt = $SelectedDiskLabel.Count $Errors += "The parameter 'StoragePolicyNamePerDiskLabel' contains $StoragePolicyMappingCnt entries whereas the 'SelectedDiskLabel' count is $SelectedDiskLabelCnt. The number of entries in 'StoragePolicyNamePerDiskLabel' cannot be greater than the 'SelectedDiskLabel' count." } if ($NotSelectedDiskLabel.Count -gt 0) { $NotSelectedDiskLabelAsString = $NotSelectedDiskLabel -join ", " $Errors += "The disk label(s) '$NotSelectedDiskLabelAsString' specified in the parameter 'StoragePolicyNamePerDiskLabel' has not specified in the parameter 'SelectedDiskLabel'" } if ($DiskLabelsNotFound.Count -gt 0) { $DiskLabelsNotFoundAsString = $DiskLabelsNotFound -join ", " $Errors += "The disk label(s) '$DiskLabelsNotFoundAsString' specified in the parameter 'StoragePolicyNamePerDiskLabel' does not exist on the source" } if ($StorageLabelsNotFound.Count -gt 0) { $StorageLabelsNotFoundAsString = $StorageLabelsNotFound -join ", " $Errors += "The storage policy name(s) '$StorageLabelsNotFoundAsString' specified in the parameter 'StoragePolicyNamePerDiskLabel' does not exist on the target vCenter" } } return $Errors, $Warnings, $IsRequiredParametersPresentAndValid } function Confirm-RMNetworkIsolationConfig { param( [RMVSphereBaseNetworkConfiguration] $NetworkConfig ) $Errors = @() $IsRequiredParametersPresentAndValid = $true $NetworkConfigType = "" if ($NetworkConfig -is [RMVSphereMigrationNetworkConfiguration]) { $NetworkConfigType = "MigrationNetworkConfig's" if ([string]::IsNullOrWhiteSpace($NetworkConfig.MigrationNetworkName)) { $Errors += "$NetworkConfigType MigrationNetworkName is required" $IsRequiredParametersPresentAndValid = $false } } if ($NetworkConfig -is [RMVSphereIsolatedNetworkConfiguration]) { $NetworkConfigType = "IsolatedNetworkConfig's" if ([string]::IsNullOrWhiteSpace($NetworkConfig.IsolatedNetworkName)) { $Errors += "$NetworkConfigType IsolatedNetworkName is required" $IsRequiredParametersPresentAndValid = $false } } if (!(Confirm-RMIPType -NetworkConfig $NetworkConfig)) { $GivenIPType = $NetworkConfig.IPType $Errors += "$NetworkConfigType IPType should be 'static' or 'DHCP', given IPType is '$GivenIPType'" $IsRequiredParametersPresentAndValid = $false return $Errors, $IsRequiredParametersPresentAndValid } if ($NetworkConfig.IPType -ieq "dhcp") { return $Errors, $IsRequiredParametersPresentAndValid } $ReturnedData = Confirm-RMStaticNetworkConfig -NetworkConfig $NetworkConfig ` -NetworkConfigPrefix $NetworkConfigType -NICName $null $Errors += $ReturnedData[0] # Update the flag only if everything is good so far, to avoid overwriting bad state if ($IsRequiredParametersPresentAndValid) { $IsRequiredParametersPresentAndValid = $ReturnedData[1] } return $Errors, $IsRequiredParametersPresentAndValid } function Confirm-RMDestinationNetworkConfig { param( [hashtable] $UserParameter ) $Errors = @() if (!$UserParameter.ContainsKey("DestinationNICConfig") -or ` $null -eq $UserParameter["DestinationNICConfig"]) { $Errors += "DestinationNICConfig is required" return $Errors, $false } $IsRequiredParametersPresentAndValid = $true $SkipGatewayAndDNSValidation = $false $NetworkConfig = $UserParameter["DestinationNICConfig"] for ($Index = 0; $Index -lt $NetworkConfig.Count; $Index++) { $NICWithIndex = "NIC" + $Index if ([string]::IsNullOrWhiteSpace($NetworkConfig[$Index].DestinationNetworkName)) { $Errors += "DestinationNICConfig's DestinationNetworkName is required for $NICWithIndex" $IsRequiredParametersPresentAndValid = $false } if (!(Confirm-RMIPType -NetworkConfig $NetworkConfig[$Index])) { $GivenIPType = $NetworkConfig[$Index].IPType $Errors += "DestinationNICConfig's IPType should be 'static' or 'DHCP', given IPType for " + $NICWithIndex + " is '$GivenIPType'" $IsRequiredParametersPresentAndValid = $false continue } if ($NetworkConfig[$Index].IPType -ieq "dhcp") { continue } if ($SkipGatewayAndDNSValidation -and !([string]::IsNullOrWhiteSpace($NetworkConfig[$Index].DefaultGateway) ` -or [string]::IsNullOrWhiteSpace($NetworkConfig[$Index].PrimaryDNS))) { $Errors += "DestinationNICConfig's DefaultGateway, PrimaryDNS and optionally Secondary DNS should be provided for one NIC only" } $ReturnedData = Confirm-RMStaticNetworkConfig -NetworkConfig $NetworkConfig[$Index] ` -NetworkConfigPrefix "DestinationNICConfig's" -SkipGatewayAndDNS $SkipGatewayAndDNSValidation -NICName $NICWithIndex $Errors += $ReturnedData[0] # Update the flag only if everything is good so far, to avoid overwriting bad state if ($IsRequiredParametersPresentAndValid) { $IsRequiredParametersPresentAndValid = $ReturnedData[1] } # Validate gateway and DNS for one NIC if ($ReturnedData[2]) { $SkipGatewayAndDNSValidation = $true } } return $Errors, $IsRequiredParametersPresentAndValid } function Confirm-RMStaticNetworkConfig { param( [RMVSphereBaseNetworkConfiguration] $NetworkConfig, [string] $NetworkConfigPrefix, [string] $NICName, [bool] $SkipGatewayAndDNS ) $Errors = @() $IsRequiredParametersPresentAndValid = $true if ([string]::IsNullOrWhiteSpace($NetworkConfig.IPAddress)) { if ([string]::IsNullOrEmpty($NICName)) { $Errors += $NetworkConfigPrefix + " IPAddress is required, when IPType is 'static'" } else { $Errors += $NetworkConfigPrefix + " IPAddress is required for " + $NICName + ", when IPType is 'static'" } $IsRequiredParametersPresentAndValid = $false } else { if (!(Confirm-RMIPAddress -IPAddress $NetworkConfig.IPAddress)) { if ([string]::IsNullOrEmpty($NICName)) { $Errors += $NetworkConfigPrefix + " IPAddress is not valid" } else { $Errors += $NetworkConfigPrefix + " IPAddress is not valid for $NICName" } $IsRequiredParametersPresentAndValid = $false } } if ([string]::IsNullOrWhiteSpace($NetworkConfig.Netmask)) { if ([string]::IsNullOrEmpty($NICName)) { $Errors += $NetworkConfigPrefix + " Netmask is required, when IPType is 'static'" } else { $Errors += $NetworkConfigPrefix + " Netmask is required for " + $NICName + ", when IPType is 'static'" } $IsRequiredParametersPresentAndValid = $false } else { if (!(Confirm-RMIPAddress -IPAddress $NetworkConfig.Netmask)) { if ([string]::IsNullOrEmpty($NICName)) { $Errors += $NetworkConfigPrefix + " Netmask is not valid" } else { $Errors += $NetworkConfigPrefix + " Netmask is not valid for $NICName" } $IsRequiredParametersPresentAndValid = $false } } if ($SkipGatewayAndDNS) { return $Errors, $IsRequiredParametersPresentAndValid, $false } $IsValidGatewayAndDNS = $true if ([string]::IsNullOrWhiteSpace($NetworkConfig.DefaultGateway)) { if ([string]::IsNullOrEmpty($NICName)) { $Errors += $NetworkConfigPrefix + " DefaultGateway is required, when IPType is 'static'" } else { $Errors += $NetworkConfigPrefix + " DefaultGateway is required for " + $NICName + ", when IPType is 'static'" } $IsRequiredParametersPresentAndValid = $false $IsValidGatewayAndDNS = $false } else { if (!(Confirm-RMIPAddress -IPAddress $NetworkConfig.DefaultGateway)) { if ([string]::IsNullOrEmpty($NICName)) { $Errors += $NetworkConfigPrefix + " DefaultGateway is not valid" } else { $Errors += $NetworkConfigPrefix + " DefaultGateway is not valid for $NICName" } $IsRequiredParametersPresentAndValid = $false $IsValidGatewayAndDNS = $false } } if ([string]::IsNullOrWhiteSpace($NetworkConfig.PrimaryDNS)) { if ([string]::IsNullOrEmpty($NICName)) { $Errors += $NetworkConfigPrefix + " PrimaryDNS is required, when IPType is 'static'" } else { $Errors += $NetworkConfigPrefix + " PrimaryDNS is required for " + $NICName + ", when IPType is 'static'" } $IsRequiredParametersPresentAndValid = $false $IsValidGatewayAndDNS = $false } else { if (!(Confirm-RMIPAddress -IPAddress $NetworkConfig.PrimaryDNS)) { if ([string]::IsNullOrEmpty($NICName)) { $Errors += $NetworkConfigPrefix + " PrimaryDNS is not valid" } else { $Errors += $NetworkConfigPrefix + " PrimaryDNS is not valid for $NICName" } $IsRequiredParametersPresentAndValid = $false $IsValidGatewayAndDNS = $false } } if (![string]::IsNullOrWhiteSpace($NetworkConfig.SecondaryDNS)) { if (!(Confirm-RMIPAddress -IPAddress $NetworkConfig.PrimaryDNS)) { if ([string]::IsNullOrEmpty($NICName)) { $Errors += $NetworkConfigPrefix + " SecondaryDNS is not valid" } else { $Errors += $NetworkConfigPrefix + " SecondaryDNS is not valid for $NICName" } } } return $Errors, $IsRequiredParametersPresentAndValid, $IsValidGatewayAndDNS } function Confirm-RMIPType { param ( [RMVSphereBaseNetworkConfiguration] $NetworkConfig ) if ($NetworkConfig.IPType -ine "dhcp" -and $NetworkConfig.IPType -ine "static") { return $false } return $true } function Confirm-RMvSphereParameter { param( [hashtable] $UserParameter ) $Errors = @() $IsRequiredParametersPresentAndValid = $true if (!$UserParameter.ContainsKey("DatacenterName") -or [string]::IsNullOrWhiteSpace($UserParameter["DatacenterName"])) { $Errors += "DatacenterName is required." $IsRequiredParametersPresentAndValid = $false } if (!$UserParameter.ContainsKey("ClusterName") -or [string]::IsNullOrWhiteSpace($UserParameter["ClusterName"])) { $Errors += "ClusterName is required" $IsRequiredParametersPresentAndValid = $false } return $Errors, $IsRequiredParametersPresentAndValid } function Get-RMCoresPerSocket { param ( [int] $TargetVMVCPUCount ) $CoresPerSocketList = @() for ([int]$i = 1; $i -lt $TargetVMVCPUCount+1; $i++) { if ($TargetVMVCPUCount % $i -eq 0) { $CoresPerSocketList += $i } } return $CoresPerSocketList } Export-ModuleMember -Function Start-RMInteractiveVSphereOSBasedMigration, Start-RMNonInteractiveVsphereOsBasedMigration, ` Start-RMInteractiveVSphereVMBasedMigration, Start-RMNonInteractiveVsphereVMBasedMigration |