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.Development.Source | Join-Path -ChildPath SourceUtil | Join-Path -ChildPath SourceUtil) 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[]] $MountPoint, [string[]] $ResizeMountPoint, [string] $TransferMethod, [int] $TargetVMVCPUCount, [string] $CoresPerSocket, [int] $TargetVMMemorySize, [string] $DatacenterName, [bool] $EnableDestinationNetworkIsolation, [RMVSphereMigrationNetworkConfiguration] $MigrationNetworkConfig, [RMVSphereIsolatedNetworkConfiguration] $IsolatedNetworkConfig, [RMVSphereDestinationNetworkConfiguration[]] $DestinationNICConfig, [bool] $DisableTargetDNSRegistration, [string] $ClusterName, [bool] $CreateResourcePoolName, [string] $ResourcePoolName, [bool] $CreateFolderName, [string] $FolderName, [string] $DatastoreClusterName, [string[]] $DatastoreName, [string[]] $DiskProvisioningType, [int] $HardwareVersion, [bool] $ShutdownSource, [bool] $ShutdownTarget, [bool] $RemoveRMSAgentFromSource, [bool] $RemoveRMSAgentFromTarget, [string[]] $MigrationInstruction, [string] $UpgradeOSVersion, [string] $MigrationExtension, [string] $MigrationExtensionOSM, [hashtable[]] $UpgradeSQLServer, [bool] $IgnoreValidationError, [bool] $OverrideExistingMigration, [string] $ConvertFileSystem, [string[]] $VMTag, [bool] $ConvertBootModeUEFI, [bool] $EnableSecureBoot, [bool] $EanbleVTPM, [bool] $EnableVBS, [bool] $EnableNetAppFileMigration, [bool] $Sysprep, [string] $NetBIOSName, [bool] $KMSActivation, [bool] $KMSItopia, [bool] $EnableOSHardening, [bool] $Level1Server, [bool] $Level2Server, [bool] $Level1Computer, [bool] $Level2Computer, [bool] $Level1User, [bool] $Level2User, [string] $AdministratorName, [string] $GuestName, [string] $LegalNoticeCaption, [string] $LegalNoticeText, [string] $ReplaceWindowsLicense ) $CloudAccount = $null $CloudAccountErrors = $null $Source = $null try { if (![string]::IsNullOrEmpty($TargetCloud)) { $CloudAccount, $ErrorString = Get-RMCloudAccountByName -CloudAccountName $TargetCloud -AccountType "rivermeadow_standalone" if (![string]::IsNullOrEmpty($ErrorString)) { $CloudAccountErrors += $ErrorString $IsSourceAndTargetCloudPresent = $false } else { $TargetInventory = Get-RMTargetInventory -CloudAccount $CloudAccount } } } catch [System.Management.Automation.ItemNotFoundException] { $CloudAccountErrors += $PSItem.Exception.Message $IsSourceAndTargetCloudPresent = $false } $Errors, $Warnings, $IsSourceAndTargetCloudPresent, $IsRequiredParametersPresentAndValid = Confirm-RMvSphereFullMigrationParameter $PSBoundParameters ` -TargetInventory $TargetInventory if ($null -ne $CloudAccountErrors) { $Errors += $CloudAccountErrors $IsSourceAndTargetCloudPresent = $false } $ShouldExit = $false try { if (![string]::IsNullOrEmpty($SourceIP)) { $Source = Get-RMSourceByIP -IPAddress $SourceIP } } catch [System.Management.Automation.ItemNotFoundException] { $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 $IgnoreValidationError -AccountType "rivermeadow_standalone" ` -RMMigrationReturn $RMMigrationReturn if (!$IgnoreValidationError -and $OverrideExistingMigrationError -and !$OverrideExistingMigration) { $Errors += "Please set 'OverrideExistingMigration' to true and try again." } } catch [System.InvalidOperationException], [System.Management.Automation.RuntimeException] { $Errors += $PSItem.Exception.Message $IsRequiredParametersPresentAndValid = $false } $MigrationExtensionResponse = Get-RMMigrationExtension -OrganizationId $CloudAccount.organization_id $MigrationExtensionArray, $MigrationExtensionOSMArray = Get-RMMigrationExtensionFromStep -MigrationExtensionArray $MigrationExtensionResponse.content if ($null -ne $Source) { $ProjectSettingsResponse = Invoke-RMProjectSettings -OrganizationId $CloudAccount.organization_id $WindowsLicense = Get-RMWindowsKMSKeyMapping -WindowsLicense $ProjectSettingsResponse.rivermeadow_standalone.windows_license_keys $SourceSQLServerMapping = Get-RMSQLMMappingBySource -Source $Source $SourceErrors, $RequiredParameterState = Confirm-RMvSphereFullMigrationParameterWithSource ` -UserParameter $PSBoundParameters -Source $Source -SourceSQLServerMapping $SourceSQLServerMapping ` -MigrationExtension $MigrationExtensionArray -MigrationExtensionOSM $MigrationExtensionOSMArray ` -TargetInventory $TargetInventory -WindowsLicense $WindowsLicense 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 ($MountPoint.Count -gt 0) { $SelectedMountPoints = Get-RMSelectedMount -MountPoints $SourceMountPoints -DifferenceList $MountPoint -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 $ResizeMountPoint -and $ResizeMountPoint.Count -gt 0) { $MountsResize, $MountsResizeErrors = Get-RMResizeMountsPoint -ResizeMountPoints $ResizeMountPoint -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", $DisableTargetDNSRegistration) } 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) $DiskProvisioningType = Get-DiskProvisioningTypeBySource -Source $Source -DiskProvisioningTypes $DiskProvisioningType -IsInteractive $false $UserInput.Add("DatastoreLocations", $DatastoreName) $UserInput.Add("DisksProvisioningType", $DiskProvisioningType) $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) if (($IgnoreValidationError -and $OverrideExistingMigration) -or (!$IgnoreValidationError -and $OverrideExistingMigration) -or $OverrideExistingMigrationWarning) { $MigrationInstruction += "override_source_migration=true" } $MigrationInstructionsAsHashTable, $MigrationInstructionErrors = Get-RMMigrationInstructionAsHashTable -OrganizationId $CloudAccount.organization_id ` -MigrationInstruction $MigrationInstruction -AccountType "rivermeadow_standalone" if ($null -ne $MigrationInstructionErrors) { $Errors += $MigrationInstructionErrors } $UserInput.Add("MigrationInstructions", $MigrationInstructionsAsHashTable) $UserInput.Add("ShutdownSource", $ShutdownSource) $UserInput.Add("ShutdownTarget", $ShutdownTarget) $UserInput.Add("RemoveRMSAgentFromSource", $RemoveRMSAgentFromSource) $UserInput.Add("RemoveRMSAgentFromTarget", $RemoveRMSAgentFromTarget) $UserInput.Add("IgnoreValidationErrors", $IgnoreValidationError) if (![string]::IsNullOrWhiteSpace($ReplaceWindowsLicense)) { $ReplaceWindowsLicense = $WindowsLicense[$ReplaceWindowsLicense] } $UserInput.Add("ReplaceWindowsLicense", $ReplaceWindowsLicense) Add-RMOSUpgrade -UserParameter $PSBoundParameters -UpdatedParameter $UserInput -Source $Source $ErrorsOSHardening = Add-RMOSHardening -Source $Source -UpdatedParameter $UserInput -UserParameter $PSBoundParameters if ($null -ne $ErrorsOSHardening) { $Errors += $ErrorsOSHardening } Add-RMMigrationExtension -UpdatedParameter $UserInput -MigrationExtension $MigrationExtension ` -MigrationExtensionOSM $MigrationExtensionOSM -MigrationExtensionResponse $MigrationExtensionResponse $VMTagList = Get-RMTags -TargetInventory $TargetInventory $Tags = Get-RMVMTag -TagsValue $VMTag -Tags $VMTagList $UserInput.Add("VMTags", $Tags) $UserInput.Add("ConvertBootModeUEFI", $ConvertBootModeUEFI) $UserInput.Add("EnableSecureBoot", $EnableSecureBoot) $UserInput.Add("EanbleVTPM", $EanbleVTPM) $UserInput.Add("EnableVirtualizationBasedSecurity", $EnableVBS) $UserInput.Add("EnableNetAppFileMigration", $EnableNetAppFileMigration) $UserInput.Add("GeneralizeSystem", $Sysprep) $SQLServerUpgrade = Get-RMUpgradeSQLServer -UpgradeSQLServer $UpgradeSQLServer -Source $Source ` -SourceSQLServerMapping $SourceSQLServerMapping $UserInput.Add("SQLServerUpgrade", $SQLServerUpgrade) if ([string]::IsNullOrEmpty($ScheduledAt)) { $UserInput.Add("ScheduledAt", "") } else { $UserInput.Add("ScheduledAt", (Convert-RMDateTimeToUTC -InputDateTime $ScheduledAt)) } $ProjectSettingsResponse = Invoke-RMProjectSettings -OrganizationId $CloudAccount.organization_id $UserInput.Add("MTUSize", $ProjectSettingsResponse.rivermeadow_standalone.mtu_size) Add-RMConvertFileSystem -Source $Source -UpdatedUserInput $UserInput -ConvertFileSystem $ConvertFileSystem $KMSKey = $null if ($KMSActivation) { $KMSKey = "" if ($null -ne $ProjectSettingsResponse.rivermeadow_standalone.kms_fqdn) { $KMSKey = $ProjectSettingsResponse.rivermeadow_standalone.kms_fqdn } } elseif ($KMSItopia) { $KMSKey = $ProjectSettingsResponse.rivermeadow_standalone.itopia_kms_fqdn } $UserInput.Add("KMSKey", $KMSKey) $UserInput["DisksProvisioningType"] = Update-DiskProvisioningTypeForME -DiskProvisioningTypes $UserInput["DisksProvisioningType"] if ([string]::IsNullOrEmpty($NetBIOSName)) { $NetBIOSName = $Source.hostname } $UserInput.Add("NetBIOSName", $NetBIOSName) Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings if ($Errors.Count -gt 0 -or $ShouldExit) { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } $Response = New-RMVSphereMigrationProfile @UserInput $ShouldExit = Start-RMMigrationPreflight -MigrationProfileId $Response.id -IgnoreValidationErrors $IgnoreValidationError -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( ) $UserInput = @{} $Entitlement = Get-RMEntitlement $CloudAccount = Read-RMCloudAccount -AccountType "rivermeadow_standalone" -UserMessage "Enter target cloud" $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 #Placement Settings $DatacenterNames = Get-RMDatacenterName -TargetInventory $TargetInventory $DatacenterName = Read-RMString -UserMessage "Enter datacenter name" -Options $DatacenterNames ` -ParameterName "Datacenter name" -IsRequired $true $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 } $Tags = Get-RMTags -TargetInventory $TargetInventory $TagsValue = Read-RMToken -UserMessage "Enter one or more network tags separated by commas" ` -Options $Tags.keys -DefaultValue "None" -Separator ";" ` -ParameterName "Tags" -IsRequired $false $VMTags = Get-RMVMTag -TagsValue $TagsValue -Tags $Tags $Clusters, $DatacenterObject = Get-RMClusterAndDatacenter -TargetInventory $TargetInventory -datacenterName $DatacenterName $ClusterName = Read-RMString -UserMessage "Enter cluster name" -Options $Clusters -ParameterName "Cluster name" -IsRequired $true $ResourcePoolName = Read-RMResourcePoolName -DatacenterObject $DatacenterObject -ClusterName $ClusterName $FolderName = Read-RMFolderName -TargetInventory $TargetInventory -DatacenterName $DatacenterName $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 $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 } #Optimization Settings $NetBIOSName = Read-RMString -UserMessage "Enter NetBIOS name" -DefaultValue $Source.hostname ` -ParameterName "NetBIOS Name" -IsRequired $false $ProjectSettingsResponse = Invoke-RMProjectSettings -OrganizationId $CloudAccount.organization_id $ReplaceWindowsLicense, $ReplaceWindowsLicenseKey = Read-RMReplaceWindowsLicense -Source $Source -ProjectSettingsResponse $ProjectSettingsResponse -CloudType "rivermeadow_standalone" $KMSActivation = Read-RMBoolean -UserMessage "Enable KMS Activation" -DefaultValue "false" $KMSKey = $null if ($KMSActivation) { $KMSKey = "" if ($null -ne $ProjectSettingsResponse.rivermeadow_standalone.kms_fqdn) { $KMSKey = $ProjectSettingsResponse.rivermeadow_standalone.kms_fqdn } } $Sysprep = $false if ("windows" -ieq $Source.os_type) { $Sysprep = Read-RMBoolean -UserMessage "Enable sysprep" -DefaultValue "false" } $ReadValue = Read-RMBoolean -UserMessage "Change Target CPUs?" -DefaultValue "false" $CoresPerSocket = 1 $TargetVMVCPUCount = $Source.attributes.cpu.processors.Count if ($ReadValue) { $TargetVMVCPUCount = Read-RMInt -UserMessage "Enter virtual CPU count" -DefaultValue $TargetVMVCPUCount ` -ParameterName "Virtual CPUs count" -IsRequired $false $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 $MountsResize = @{} $ResizeMountPointsFlag = Read-RMBoolean -UserMessage "Resize mount points" -DefaultValue "false" if ($ResizeMountPointsFlag) { $MountsResize = Get-RMInteractiveMountsResize -SelectedMountPoints $SelectedMountPoints -Source $Source } $MigrationExtensionResponse = Get-RMMigrationExtension -OrganizationId $CloudAccount.organization_id $MigrationExtensionArray, $MigrationExtensionOSMArray = Get-RMMigrationExtensionFromStep -MigrationExtensionArray $MigrationExtensionResponse.content Read-RMMigrationExtension -CloudAccount $CloudAccount -MigrationExtension $MigrationExtensionArray ` -MigrationExtensionObject $MigrationExtensionResponse.content -UpdatedUserInput $UserInput if ("windows" -ieq $Source.os_type -and !$KMSActivation) { $KMSItopia = Read-RMBoolean -UserMessage "Enable itopia KMS" -DefaultValue "false" if ($KMSItopia) { $KMSKey = $ProjectSettingsResponse.rivermeadow_standalone.itopia_kms_fqdn } } #Modernization Settings Read-RMOSUpgradeOption -Source $Source -UpdatedUserInput $UserInput -ReplaceWindowsLicenseKey $ReplaceWindowsLicenseKey ` -MigrationExtensionOSMArray $MigrationExtensionOSMArray -MigrationExtensionResponse $MigrationExtensionResponse $SQLServerUpgrade = Read-RMSQLServerUpgradeOption -Source $Source #Security Settings Read-RMOSHardening -UpdatedUserInput $UserInput -Source $Source $EnableSecureBoot = $false $ConvertBootModeUEFI = $false $MigrationState = $Source.attributes.os.source_migration_state | ConvertFrom-Json if ("uefi" -ieq $MigrationState.boot_mode_conversion_option) { $ConvertBootModeUEFI = Read-RMBoolean -UserMessage "Convert boot mode /UEFI" -DefaultValue "false" if ($ConvertBootModeUEFI) { $EnableSecureBoot = Read-RMBoolean -UserMessage "Enable secure boot" -DefaultValue "false" } } else { $EnableSecureBoot = Read-RMBoolean -UserMessage "Enable secure boot" -DefaultValue "false" } $EanbleVTPM = Read-RMBoolean -UserMessage "Enable vTPM" -DefaultValue "false" $EnableVirtualizationBasedSecurity = $false $ShowingEnableVirtualizationBasedSecurity = Get-RMEnableVirtualizationBasedSecurity -Source $Source if ($ShowingEnableVirtualizationBasedSecurity) { $EnableVirtualizationBasedSecurity = Read-RMBoolean -UserMessage "Enable virtualization based security" -DefaultValue "false" } #Advanced Settings $TransferType = "file-based" if (!$ResizeMountPointsFlag) { $TransferType = (Get-RMTransferMethod -Source $Source -SelectedMountPoints $SelectedMountPoints -IsInteractive $true)[0] } $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" $DisableAutomaticDNSRegistrationOnTheTarget = $false if ($Source.os_type -eq "windows") { $DisableAutomaticDNSRegistrationOnTheTarget = Read-RMBoolean -UserMessage "Disable automatic DNS registration on the Target" ` -DefaultValue "false" } $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" $MigrationInstructionResponse = Get-RMMigrationInstruction -OrganizationId $CloudAccount.organization_id $MigrationInstructionDefaultValue = "None" if ($null -ne $MigrationInstructionResponse.rivermeadow_standalone) { $MigrationInstructionDefaultValue = $MigrationInstructionResponse.rivermeadow_standalone -replace ":", "=" ` -replace "@", "" -replace "{", "" -replace "}", "" } $ReadValue = Read-RMPair -UserMessage "Enter migration instructions in the format 'key=value' and separated by commas" ` -Separator "=" -DefaultValue $MigrationInstructionDefaultValue 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 $EnableNetAppFileMigration = $false if ("data_store" -ne $Source.collection_type) { $EnableNetAppFileMigration = Read-RMBoolean -UserMessage "Enable NetApp file migration" -DefaultValue $EnableNetAppFileMigration } $MTUSize = $ProjectSettingsResponse.rivermeadow_standalone.mtu_size $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 SQLServerUpgrade = $SQLServerUpgrade IgnoreValidationErrors = $IgnoreValidationErrors VMTags = $VMTags MTUSize = $MTUSize ConvertBootModeUEFI = $ConvertBootModeUEFI EnableSecureBoot = $EnableSecureBoot EanbleVTPM = $EanbleVTPM EnableVirtualizationBasedSecurity = $EnableVirtualizationBasedSecurity EnableNetAppFileMigration = $EnableNetAppFileMigration GeneralizeSystem = $Sysprep NetBIOSName = $NetBIOSName KMSKey = $KMSKey ReplaceWindowsLicense = $ReplaceWindowsLicense } $HashArguments += $UserInput $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 = @{} $CloudAccount = Read-RMCloudAccount -AccountType "rivermeadow_standalone" ` -UserMessage "Enter target cloud that supports VM-based migrations" -VMBasedAppliancesOnly $true $Source = Read-RMVMBasedSource -UserMessage "Enter the VM name of the source machine to be migrated" ` -ParameterName "Source VM name" -IsRequired $true -CloudAccount $CloudAccount $Entitlement = Get-RMEntitlement $UserInput.Add("Entitlement", $Entitlement) [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() 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) #Placement Settings $DatacenterNames = Get-RMDatacenterName -TargetInventory $TargetInventory $DatacenterName = Read-RMString -UserMessage "Enter datacenter name" -Options $DatacenterNames ` -ParameterName "Datacenter name" -IsRequired $true $UserInput.Add("DatacenterName", $DatacenterName) 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) $Tags = Get-RMTags -TargetInventory $TargetInventory $TagsValue = Read-RMToken -UserMessage "Enter one or more network tags separated by commas" ` -Options $Tags.keys -DefaultValue "None" -Separator ";" ` -ParameterName "Tags" -IsRequired $false $VMTags = Get-RMVMTag -TagsValue $TagsValue -Tags $Tags $UserInput.Add("VMTag", $VMTags) $Clusters, $DatacenterObject = Get-RMClusterAndDatacenter -TargetInventory $TargetInventory -datacenterName $DatacenterName $ClusterName = Read-RMString -UserMessage "Enter cluster name" -Options $Clusters ` -ParameterName "Cluster name" -IsRequired $true $UserInput.Add("ClusterName", $ClusterName) $ResourcePoolName = Read-RMResourcePoolName -DatacenterObject $DatacenterObject -ClusterName $ClusterName $UserInput.Add("ResourcePoolName", $ResourcePoolName) $FolderName = Read-RMFolderName -TargetInventory $TargetInventory -DatacenterName $DatacenterName $UserInput.Add("FolderName", $FolderName) $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)) $VMConfig = $SourceAttributeResult.attributes.vm_config if ("toolsNotInstalled" -ne $VMConfig.toolsStatus -and "guestToolsUnmanaged" -ne $VMConfig.toolsVersionStatus) { $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) $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")) #Optimization Settings $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) #Advanced Settings $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")) $MigrationInstructionResponse = Get-RMMigrationInstruction -OrganizationId $CloudAccount.organization_id $MigrationInstructionDefaultValue = "None" if ($null -ne $MigrationInstructionResponse.rivermeadow_standalone) { $MigrationInstructionDefaultValue = $MigrationInstructionResponse.rivermeadow_standalone -replace ":", "=" ` -replace "@", "" -replace "{", "" -replace "}", "" } $ReadValue = Read-RMPair -UserMessage "Enter migration instructions in the format 'key=value' and separated by commas" ` -Separator "=" -DefaultValue $MigrationInstructionDefaultValue 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) $MTUSizeResponse = Invoke-RMProjectSettings -OrganizationId $CloudAccount.organization_id $MTUSize = $MTUSizeResponse.rivermeadow_standalone.mtu_size $UserInput.Add("MTUSize", $MTUSize) $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] $SourceVMFolderPath, [string] $TargetCloud, [string] $ScheduledAt, [string] $TargetVMName, [string[]] $SelectedDiskLabel, [int] $TargetVMVCPUCount, [string] $CoresPerSocket, [int] $TargetVMMemorySize, [string] $DatacenterName, [bool] $PreserveIPAddress, [RMVSphereDestinationNetworkConfiguration[]] $DestinationNICConfig, [bool] $PreserveMACAddress, [RMVSphereTag[]] $VMTag, [string] $ClusterName, [bool] $CreateResourcePoolName, [string] $ResourcePoolName, [bool] $CreateFolderName, [string] $FolderName, [string] $DatastoreClusterName, [string[]] $DatastoreName, [string[]] $StoragePolicyName, [string[]] $DiskProvisioningType, [bool] $UpgradeTool, [int] $HardwareVersion, [bool] $ShutdownSource, [bool] $ShutdownTarget, [bool] $FinalizeMigration, [string[]] $MigrationInstruction, [bool] $IgnoreValidationError, [bool] $OverrideExistingMigration ) $CloudAccountErrors = $null try { $TargetInventory = $null if (![string]::IsNullOrEmpty($TargetCloud)) { $CloudAccount, $ErrorString = Get-RMCloudAccountByName -CloudAccountName $TargetCloud ` -AccountType "rivermeadow_standalone" -VMBasedAppliancesOnly $true if ($null -eq $CloudAccount) { $CloudAccountErrors += $ErrorString $IsSourceAndTargetCloudPresent = $false } else { $TargetInventory = Get-RMTargetInventory -CloudAccount $CloudAccount } } } catch [System.Management.Automation.ItemNotFoundException] { $CloudAccountErrors += $PSItem.Exception.Message $IsSourceAndTargetCloudPresent = $false } $Errors, $Warnings, $IsSourceAndTargetCloudPresent, $IsRequiredParametersPresentAndValid = ` Confirm-RMvSphereVMBasedFullMigrationParameter $PSBoundParameters -TargetInventory $TargetInventory if ($null -ne $CloudAccountErrors) { $Errors += $CloudAccountErrors } $Source = $null [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() try { if (![string]::IsNullOrEmpty($SourceVMName) -and $null -ne $CloudAccount) { $Source = Get-RMSourceByVMName -VMName $SourceVMName -SourceVMFolderPath $SourceVMFolderPath ` -CloudAccount $CloudAccount 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.ItemNotFoundException], [System.Data.DuplicateNameException] { $Errors += $PSItem.Exception.Message $IsSourceAndTargetCloudPresent = $false } 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 $IgnoreValidationError -RMMigrationReturn $RMMigrationReturn ` -AccountType "rivermeadow_standalone" if (!$IgnoreValidationError -and $OverrideExistingMigrationError -and !$OverrideExistingMigration) { $Errors += "Please set 'OverrideExistingMigration' to true and try again." } } catch [System.InvalidOperationException], [System.Management.Automation.RuntimeException] { $Errors += $PSItem.Exception.Message $IsRequiredParametersPresentAndValid = $false } if ($null -ne $Source) { if ($null -eq $SelectedDiskLabel -or $SelectedDiskLabel.Count -eq 0) { # When the user has not selected any disk labels to migrate, # select all for the source. $Warnings += "No disk labels have been given, all the disks on the source will be migrated." $SelectedDiskLabel = Get-RMVMBasedSourceDiskLabel -Source $Source $PSBoundParameters["SelectedDiskLabel"] = $SelectedDiskLabel } $SourceErrors, $SourceWarnings, $RequiredParameterState = Confirm-RMvSphereVMBasedFullMigrationParameterWithSource ` -UserParameter $PSBoundParameters -Source $Source -TargetInventory $TargetInventory ` -SourceAttributeResult $Source if ($IsRequiredParametersPresentAndValid) { $IsRequiredParametersPresentAndValid = $RequiredParameterState } $Errors += $SourceErrors $Warnings += $SourceWarnings } $StoragePolicyNamePerDiskLabel = Get-RMDiskLabelToStoragePolicyMapping ` -StoragePolicyName $StoragePolicyName -UserParameter $PSBoundParameters $UserInput = @{} $Entitlement = Get-RMEntitlement $UserInput.Add("CloudAccount", $CloudAccount) $UserInput.Add("Entitlement", $Entitlement) $UserInput.Add("Source", $Source) if ([string]::IsNullOrEmpty($TargetVMName)) { $TargetVMName = $Source.host } $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) $DiskProvisioningType = Get-RMDiskProvisioningTypeForVMBasedSource -Source $Source ` -DiskProvisioningType (Get-RMValidDiskProvisioningType -DiskProvisioningType $DiskProvisioningType) ` -SelectedDiskIndex $SelectedDiskIndices -SelectedStorageProfileName $StoragePolicyNamePerDiskLabel -IsInteractive $false $UserInput.Add("DiskProvisioningType", $DiskProvisioningType) $UserInput.Add("UpgradeTool", $UpgradeTool) $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) if (($IgnoreValidationError -and $OverrideExistingMigration) -or ` (!$IgnoreValidationError -and $OverrideExistingMigration) -or ` $OverrideExistingMigrationWarning) { $MigrationInstruction += "override_source_migration=true" } $MigrationInstructionsAsHashTable, $MigrationInstructionErrors = Get-RMMigrationInstructionAsHashTable -OrganizationId $CloudAccount.organization_id ` -MigrationInstruction $MigrationInstruction -AccountType "rivermeadow_standalone" if ($null -ne $MigrationInstructionErrors) { $Errors += $MigrationInstructionErrors } $UserInput.Add("MigrationInstructions", $MigrationInstructionsAsHashTable) $UserInput.Add("ShutdownSource", $ShutdownSource) $UserInput.Add("ShutdownTarget", $ShutdownTarget) $UserInput.Add("FinalizeMigration", $FinalizeMigration) Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings if ($Errors.Count -gt 0 -or $ShouldExit) { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } if ([string]::IsNullOrEmpty($ScheduledAt)) { $UserInput.Add("ScheduledAt", "") } else { $UserInput.Add("ScheduledAt", (Convert-RMDateTimeToUTC -InputDateTime $ScheduledAt)) } $MTUSizeResponse = Invoke-RMProjectSettings -OrganizationId $CloudAccount.organization_id $MTUSize = $MTUSizeResponse.rivermeadow_standalone.mtu_size $UserInput.Add("MTUSize", $MTUSize) $UserInput.Add("IgnoreValidationErrors", $IgnoreValidationError) $UserInput["DiskProvisioningType"] = Update-DiskProvisioningTypeForME -DiskProvisioningTypes $UserInput["DiskProvisioningType"] $Response = New-RMVSphereVMBasedMigrationProfile @UserInput $ShouldExit = Start-RMMigrationPreflight -MigrationProfileId $Response.id ` -IgnoreValidationErrors $IgnoreValidationError -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-RMInteractiveRevertInSituMigration { param () $OrganizationId = Get-Variable -Name "RMContext-CurrentProjectId" -ValueOnly $Source = Read-RMSource -UserMessage "Enter the IP address of the source machine whose modernization needs to be reverted." -ParameterName "Source IP address" -IsRequired $true [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() $SourceErrors += Confirm-RMInSituSource -Source $Source if ($SourceErrors.Count -gt 0) { throw $SourceErrors } $Response = Get-RMMigrationListBySourceId -OrganizationId $OrganizationId -SourceId $Source.id -MigrationType 'IN_SITU_MODERNIZATION' $Migration = $Response[0] #$Migration = Get-RMInSituMigration -Migration $Response $HashArguments = @{ ApplianceId = $Migration.cloud_appliance_id MigrationId = $Migration.id SourceId = $Source.id } $RevertResponse = New-RMRevertInSituProfile @HashArguments $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" $Uri = Get-Variable -Name "RMContext-ReactorURI" $Headers = @{ Accept = "application/json" "X-Auth-Token" = $RMLoginResult.Value.token } $Params = @{ Method = "Post" Uri = $Uri.Value + "/differentialprofiles/" + $RevertResponse.id + "/migrations" Headers = $Headers ContentType = "application/json" } $Response = Invoke-RMRestMethod -Params $Params return Update-RMMigrationReturnAsSuccess -MigrationResponse $Response ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $false ` -ReturnMessage "Revert from Snapshot started successfully, migration ID" } function Start-RMNonInteractiveRevertInSituMigration { param ( [string] $SourceIP ) $Errors = @() $OrganizationId = Get-Variable -Name "RMContext-CurrentProjectId" -ValueOnly try { if (![string]::IsNullOrEmpty($SourceIP)) { $Source = Get-RMSourceByIP -IPAddress $SourceIP } } catch [System.Management.Automation.ItemNotFoundException] { $Errors += $PSItem.Exception.Message } $SourceErrors += Confirm-RMInSituSource -Source $Source if ($SourceErrors.Count -gt 0) { $Errors += $SourceErrors } [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() if ($Errors.Count -gt 0) { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } $Response = Get-RMMigrationListBySourceId -OrganizationId $OrganizationId -SourceId $Source.id -MigrationType 'IN_SITU_MODERNIZATION' $Migration = $Response[0] $HashArguments = @{ ApplianceId = $Migration.cloud_appliance_id MigrationId = $Migration.id SourceId = $Source.id } $RevertResponse = New-RMRevertInSituProfile @HashArguments $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" $Uri = Get-Variable -Name "RMContext-ReactorURI" $Headers = @{ Accept = "application/json" "X-Auth-Token" = $RMLoginResult.Value.token } $Params = @{ Method = "Post" Uri = $Uri.Value + "/differentialprofiles/" + $RevertResponse.id + "/migrations" Headers = $Headers ContentType = "application/json" } $Response = Invoke-RMRestMethod -Params $Params return Update-RMMigrationReturnAsSuccess -MigrationResponse $Response ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $false ` -ReturnMessage "Revert from Snapshot started successfully, migration ID" } function Start-RMInteractiveInSituMigration { param () $UserInput = @{} $Source = Read-RMSource -UserMessage "Enter the IP address of the source machine to be modernized" -ParameterName "Source IP address" -IsRequired $true $IsInSituSource = Confirm-RMInSituMigrationSource -Source $Source if (!$IsInSituSource) { throw "Unable to configure In-Situ Upgrade because the selection contains sources which are not upgradeable and/or have been upgraded already." } [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() $Entitlement = Get-RMEntitlement $CloudAccount = Read-RMCloudAccount -AccountType "rivermeadow_standalone" -UserMessage "Enter target cloud" $IgnoreValidationError = Read-RMBoolean -UserMessage "Ignore validation errors" -DefaultValue "false" $TargetInventory = Get-RMTargetInventory -CloudAccount $CloudAccount [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() $Source, $ShouldExit, $OverrideExistingMigrationWarning, $OverrideExistingMigrationError = Get-RMSourceWithAttribute -Source $Source -CloudAccount $CloudAccount ` -IgnoreValidationErrors $IgnoreValidationError -RMMigrationReturn $RMMigrationReturn -AccountType "rivermeadow_standalone" -Type "in_situ_modernization" if ($OverrideExistingMigrationError) { return $RMMigrationReturn } $ReplaceWindowsLicense = "" $ReplaceWindowsLicenseKey = "" # Optimization Settings if ("windows" -ieq $Source.os_type) { $ProjectSettingsResponse = Invoke-RMProjectSettings -OrganizationId $CloudAccount.organization_id $WindowsLicense = Get-RMWindowsKMSKeyMapping -WindowsLicense $ProjectSettingsResponse.rivermeadow_standalone.windows_license_keys $ReplaceWindowsLicenseKey = Read-RMString -UserMessage "Replace Windows License" -Options $WindowsLicense.keys -ParameterName "KMSActivation" ` -DefaultValue "None" -IsRequired $false if ("" -ne $ReplaceWindowsLicenseKey) { $ReplaceWindowsLicense = $WindowsLicense[$ReplaceWindowsLicenseKey] } } $MigrationExtensionResponse = Get-RMMigrationExtension -OrganizationId $CloudAccount.organization_id $MigrationExtensionArray, $MigrationExtensionOSMArray = Get-RMMigrationExtensionFromStep -MigrationExtensionArray $MigrationExtensionResponse.content Read-RMMigrationExtension -CloudAccount $CloudAccount -MigrationExtension $MigrationExtensionArray ` -MigrationExtensionObject $MigrationExtensionResponse.content -UpdatedUserInput $UserInput #Modernization Settings Read-RMOSUpgradeOption -Source $Source -UpdatedUserInput $UserInput if ($null -ne $UserInput['UpgradeOSVersion']) { $OSVersion = Get-RMWindowsOSMapping if ("windows" -ieq $Source.os_type -and "" -ne $ReplaceWindowsLicenseKey -and $OSVersion[$UserInput['UpgradeOSVersion']] -ne $ReplaceWindowsLicenseKey) { throw "The selected licence key version ($ReplaceWindowsLicenseKey) does not match the OS Modernization version." } Read-RMMigrationExtensionOSM -MigrationExtensionOSM $MigrationExtensionOSMArray -MigrationExtensionObject $MigrationExtensionResponse.content ` -UpdatedUserInput $UserInput } else { throw "OS Modernization is required" } #Advanced Settings $RemoveRMSAgentPostModernizatoin = Read-RMBoolean -UserMessage "Remove RMS agent post modernization from source" -DefaultValue "false" $MigrationInstructionResponse = Get-RMMigrationInstruction -OrganizationId $CloudAccount.organization_id $MigrationInstructionDefaultValue = "None" if ($null -ne $MigrationInstructionResponse.rivermeadow_standalone) { $MigrationInstructionDefaultValue = $MigrationInstructionResponse.rivermeadow_standalone -replace ":", "=" ` -replace "@", "" -replace "{", "" -replace "}", "" } $ReadValue = Read-RMPair -UserMessage "Enter migration instructions in the format 'key=value' and separated by commas" ` -Separator "=" -DefaultValue $MigrationInstructionDefaultValue $MigrationInstruction = Get-RMStringAsHashtable -InputString $ReadValue $HashArguments = @{ CloudAccount = $CloudAccount Entitlement = $Entitlement Name = $Source.hostname IgnoreValidationError = $IgnoreValidationError Source = $Source RemoveTargetAgent = $RemoveRMSAgentPostModernizatoin MigrationInstruction = $MigrationInstruction ReplaceWindowsLicense = $ReplaceWindowsLicense } $HashArguments += $UserInput $Response = New-RMInSituMigrationProfile @HashArguments $ShouldExit = Start-RMMigrationPreflight -MigrationProfileId $Response.id -IgnoreValidationErrors $IgnoreValidationError ` -RMMigrationReturn $RMMigrationReturn if ($ShouldExit) { return $RMMigrationReturn } $MigrationResponse = Invoke-RMMigrationPost -MigrationProfileResponse $Response return Update-RMMigrationReturnAsSuccess -MigrationResponse $MigrationResponse ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $false ` -ReturnMessage "Migration started successfully, migration ID" } function Start-RMNonInteractiveInSituMigration { param ( [string] $SourceIP, [string] $TargetCloud, [bool] $IgnoreValidationError, [string] $UpgradeOSVersion, [string] $MigrationExtension, [string] $MigrationExtensionOSM, [bool] $RemoveRMSAgentPostModernizatoin, [string[]] $MigrationInstruction, [string] $ReplaceWindowsLicense ) $UserInput = @{} $Entitlement = Get-RMEntitlement $SourceErrors = @() $CloudAccount = $null $Source = $null try { if (![string]::IsNullOrEmpty($TargetCloud)) { $CloudAccount, $ErrorString = Get-RMCloudAccountByName -CloudAccountName $TargetCloud ` -AccountType "rivermeadow_standalone" if ($null -eq $CloudAccount) { $CloudAccountErrors += $ErrorString } else { $TargetInventory = Get-RMTargetInventory -CloudAccount $CloudAccount } } } catch [System.Management.Automation.ItemNotFoundException] { $CloudAccountErrors += $PSItem.Exception.Message } $Errors = Confirm-RMInSituMigrationParameter $PSBoundParameters -Source $Source try { if (![string]::IsNullOrEmpty($SourceIP)) { $Source = Get-RMSourceByIP -IPAddress $SourceIP } } catch [System.Management.Automation.ItemNotFoundException] { $Errors += $PSItem.Exception.Message } if ($null -ne $SourceErrors) { $Errors += $SourceErrors } if ($null -ne $CloudAccountErrors) { $Errors += $CloudAccountErrors } [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() if ($Errors.Count -gt 0) { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() $Source, $ShouldExit, $OverrideExistingMigrationWarning, $OverrideExistingMigrationError = Get-RMSourceWithAttribute -Source $Source -CloudAccount $CloudAccount ` -IgnoreValidationErrors $IgnoreValidationError -RMMigrationReturn $RMMigrationReturn -AccountType "rivermeadow_standalone" -Type "in_situ_modernization" $MigrationExtensionResponse = Get-RMMigrationExtension -OrganizationId $CloudAccount.organization_id $MigrationExtensionArray, $MigrationExtensionOSMArray = Get-RMMigrationExtensionFromStep -MigrationExtensionArray $MigrationExtensionResponse.content if ($null -ne $Source) { $ProjectSettingsResponse = Invoke-RMProjectSettings -OrganizationId $CloudAccount.organization_id $WindowsLicense = Get-RMWindowsKMSKeyMapping -WindowsLicense $ProjectSettingsResponse.rivermeadow_standalone.windows_license_keys $SourceAttributeErrors += Confirm-RMInSituMigrationParameterWithSource -UserParameter $PSBoundParameters -Source $Source -MigrationExtension $MigrationExtensionArray ` -MigrationExtensionOSM $MigrationExtensionOSMArray -WindowsLicense $WindowsLicense if ($null -ne $SourceAttributeErrors) { $Errors += $SourceAttributeErrors } } if (![string]::IsNullOrWhiteSpace($ReplaceWindowsLicense)) { $ReplaceWindowsLicense = $WindowsLicense[$ReplaceWindowsLicense] } Add-RMOSUpgrade -UserParameter $PSBoundParameters -UpdatedParameter $UserInput -Source $Source Add-RMMigrationExtension -UpdatedParameter $UserInput -MigrationExtension $MigrationExtension ` -MigrationExtensionOSM $MigrationExtensionOSM -MigrationExtensionResponse $MigrationExtensionResponse $MigrationInstructionsAsHashTable, $MigrationInstructionErrors = Get-RMMigrationInstructionAsHashTable -OrganizationId $CloudAccount.organization_id ` -MigrationInstruction $MigrationInstruction -AccountType "rivermeadow_standalone" if ($null -ne $MigrationInstructionErrors) { $Errors += $MigrationInstructionErrors } Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings if ($Errors.Count -gt 0) { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } $HashArguments = @{ CloudAccount = $CloudAccount Entitlement = $Entitlement Name = $Source.hostname IgnoreValidationError = $IgnoreValidationError Source = $Source RemoveTargetAgent = $RemoveRMSAgentPostModernizatoin MigrationInstruction = $MigrationInstructionsAsHashTable ReplaceWindowsLicense = $ReplaceWindowsLicense } $HashArguments += $UserInput $Response = New-RMInSituMigrationProfile @HashArguments $ShouldExit = Start-RMMigrationPreflight -MigrationProfileId $Response.id -IgnoreValidationErrors $IgnoreValidationError ` -RMMigrationReturn $RMMigrationReturn if ($ShouldExit) { return $RMMigrationReturn } $MigrationResponse = Invoke-RMMigrationPost -MigrationProfileResponse $Response return Update-RMMigrationReturnAsSuccess -MigrationResponse $MigrationResponse ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $false ` -ReturnMessage "Migration started successfully, migration ID" } function Confirm-RMInSituMigrationParameter { param ( [hashtable] $UserParameter, [System.Object] $Source ) $Errors = @() if (!$UserParameter.ContainsKey("SourceIP") -or [string]::IsNullOrWhiteSpace($UserParameter["SourceIP"])) { $Errors += "SourceIP is required" } else { $IsInSituSource = Confirm-RMInSituMigrationSource -Source $Source if (!$IsInSituSource) { $Errors += "Unable to configure In-Situ Upgrade because the selection contains sources which are not upgradeable and/or have been upgraded already." } } if (!$UserParameter.ContainsKey("TargetCloud") -or [string]::IsNullOrWhiteSpace($UserParameter["TargetCloud"])) { $Errors += "TargetCloud is required" } return $Errors } function Confirm-RMInSituMigrationParameterWithSource { param ( [hashtable] $UserParameter, [System.Object] $Source, [System.Array] $MigrationExtension, [System.Array] $MigrationExtensionOSM, [hashtable] $WindowsLicense ) $Errors = @() if ($UserParameter.ContainsKey("UpgradeOSVersion") -and ![string]::IsNullOrEmpty($UserParameter["UpgradeOSVersion"])) { $UpgradeOSVersion = $UserParameter["UpgradeOSVersion"] $SourceOSMMapping = Get-RMOSMMappingBySource -Source $Source if ($SourceOSMMapping.Keys.Count -eq 0) { $Errors += "No OS upgrade options are available for the given source OS" } else { $OSMLabels = $SourceOSMMapping.keys -join ", " $UpgradeOSVersion = $UpgradeOSVersion.Trim('"') $UpgradeOSVersion = $UpgradeOSVersion.Trim("'") if ($SourceOSMMapping.keys -notcontains $UpgradeOSVersion) { $Errors += "UpgradeOSVersion should be one of '$OSMLabels'" } } } else { $Errors += "UpgradeOSVersion is required." } if ($UserParameter.ContainsKey("MigrationExtension") -and ![string]::IsNullOrWhiteSpace($UserParameter["MigrationExtension"])) { $MigrationExtensionValue = $UserParameter["MigrationExtension"] if ($MigrationExtension -notcontains $MigrationExtensionValue) { $Errors += "MigrationExtension '$MigrationExtensionValue' does not exist." } } if ($UserParameter.ContainsKey("MigrationExtensionOSM") -and ![string]::IsNullOrWhiteSpace($UserParameter["MigrationExtensionOSM"])) { $MigrationExtensionOSMValue = $UserParameter["MigrationExtensionOSM"] if ((!$UserParameter.ContainsKey("UpgradeOSVersion") -or [string]::IsNullOrWhiteSpace($UserParameter["UpgradeOSVersion"]))) { $Errors += "'UpgradeOSVersion' is required, when parameter 'MigrationExtensionOSM' is not null." } elseif ($MigrationExtensionOSM -notcontains $MigrationExtensionOSMValue) { $Errors += "MigrationExtensionOSM '$MigrationExtensionOSMValue' does not exist." } } if ("windows" -ieq $Source.os_type) { if ($UserParameter.ContainsKey("ReplaceWindowsLicense") -and ![string]::IsNullOrWhiteSpace($UserParameter["ReplaceWindowsLicense"])) { $ReplaceWindowsLicense = $UserParameter["ReplaceWindowsLicense"] if ($UserParameter.ContainsKey("UpgradeOSVersion") -and ![string]::IsNullOrEmpty($UserParameter["UpgradeOSVersion"]) -and ` $UserParameter["UpgradeOSVersion"] -ne $UserParameter["ReplaceWindowsLicense"]) { $Errors += "The selected licence key version ($ReplaceWindowsLicense) does not match the 'UpgradeOSVersion' version." } $License = $WindowsLicense[$ReplaceWindowsLicense] if ($null -ieq $License) { $Errors += "ReplaceWindowsLicense '$ReplaceWindowsLicense' does not exist." } } } elseif ($UserParameter.ContainsKey("ReplaceWindowsLicense") -and ![string]::IsNullOrWhiteSpace($UserParameter["ReplaceWindowsLicense"])) { $Errors += "'ReplaceWindowsLicense' can be not null only for a Windows source" } return $Errors } function Confirm-RMInSituMigrationSource { param ( [System.Object] $Source ) $IsInSituSource = $true if ("vm" -ieq $Source.collection_type -or "data_store" -ieq $Source.collection_type) { $IsInSituSource = $false } elseif ($null -ne $Source.os_type -and $null -ne $Source.attributes.os) { if ("linux" -ieq $Source.os_type) { [double] $Version = $Source.attributes.os.version if ("Red Hat Enterprise Linux Server" -ne $Source.attributes.os.vendor -or (!($Version -gt 7 -or 7 -ieq $Version) -and $Version -lt 9)) { $IsInSituSource = $false } } else { $NotAllowedOsVersions = @("2003", "2008", "XP", "Vista", "7", "8", "8.1", "10.0") $MatchingOsVersions = $Source.attributes.os.version | Where-Object { $NotAllowedOsVersions -contains $_ } if ($MatchingOsVersions.Count -gt 0) { $IsInSituSource = $false } if ($null -ne $Source.attributes -and $null -ne $Source.attributes.hardware) { if ("vmware" -ne $Source.attributes.hardware.platform) { $IsInSituSource = $false } } } if ($null -ne $Source.attributes.os.source_migration_state) { $MigrationState = $Source.attributes.os.source_migration_state | ConvertFrom-Json $NotAllowedState = @("running", "success", "error", "cancelled") if ($null -ne $MigrationState.upgrade_state) { $MatchingState = $MigrationState.upgrade_state.state | Where-Object {$NotAllowedState -contains $_} #check if ($MatchingState.Count -gt 0) { $IsInSituSource = $false } } $UpgradeOptions = $Source.attributes.os.source_migration_state | ConvertFrom-Json if ($null -ieq $UpgradeOptions.upgrade_options -or 0 -ieq $UpgradeOptions.upgrade_options.Count) { $IsInSituSource = $false } } } return $IsInSituSource } function Update-RMInteractiveVsphereSource { param () $CloudAccountHeartBeatingOptions, $CloudAccountNonHeartBeatingOptions = Get-RMCloudAccountsForCurrentProject $HeartBeatingVMBasedAppliance = Get-RMVMBasedHeartBeatingAppliance -CloudAccountObject $CloudAccountHeartBeatingOptions $CloudAccountName = Read-RMString -UserMessage "Enter target cloud" -Options $HeartBeatingVMBasedAppliance.keys ` -ParameterName "Target Cloud" -IsRequired $true $CloudAccount = $HeartBeatingVMBasedAppliance[$CloudAccountName] $All = Read-RMBoolean -UserMessage "Would you like to refresh all sources?" -DefaultValue "false" $Filters = @{} if (!$All) { $SourceInventory = Get-RMSourceInventory -ApplianceId $CloudAccount.appliance.id -IsCollect $true ` -CollectCloud $true -CollectVm $false -AddSource $false $Datacenter = Read-RMString -UserMessage "Enter datacenter name" -Options $SourceInventory.properties.datacenters.name ` -ParameterName "Datacenter" -IsRequired $true $ClusterObject, $DatacenterObject = Get-ClusterAndDatacenterObject -SourceInventory $SourceInventory -DatacenterName $Datacenter $Cluster = Read-RMString -UserMessage "Enter cluster name" -Options $ClusterObject.name -ParameterName "Cluster" ` -DefaultValue "None" -IsRequired $false $ResourcePool = "" if ("" -ne $Cluster ) { $ResourcePoolOptions = Get-RMVMResourcePoolname -DatacenterObject $DatacenterObject -ClusterName $Cluster if ($ResourcePoolOptions.Count -gt 0) { $ResourcePool = Read-RMString -UserMessage "Enter resource pool" -ParameterName "Resource Pool" -Options $ResourcePoolOptions ` -DefaultValue "None" -IsRequired $false } } $FolderNameOptions = Get-RMFolderNameByDatacenter -DatacenterObject $DatacenterObject $FolderName = Read-RMVMFolderString -UserMessage "Enter folder name" -VMFolders $FolderNameOptions -DefaultValue "None" $Filters = @{ "datacenter_name" = $Datacenter "cluster_name" = $Cluster "resource_pool" = $ResourcePool "folder_name" = $FolderName } } $SourceInventoryResponse = Get-RMSourceInventory -ApplianceId $CloudAccount.appliance.id -IsCollect $false ` -CollectCloud $false -CollectVm $true -AddSource $true -CollectPerfMetric $true -Filters $Filters $UserMessage = "Attempting to refresh vSphere sources." -f $SourceInventoryResponse.id Write-Output $UserMessage | Out-Host return [RMReturn]::new([RMReturn]::SUCCESS, @{"Result" = $UserMessage}) } function Update-RMNonInteractiveVsphereSource { param ( [string] $TargetCloud, [bool] $All, [string] $Datacenter, [string] $Cluster, [string] $ResourcePool, [string] $FolderName ) $CloudAccountHeartBeatingOptions, $CloudAccountNonHeartBeatingOptions = Get-RMCloudAccountsForCurrentProject $HeartBeatingVMBasedAppliance = Get-RMVMBasedHeartBeatingAppliance -CloudAccountObject $CloudAccountHeartBeatingOptions $Errors += Confirm-RMVsphereUpdateSourceParameter -UserParameter $PSBoundParameters -HeartBeatingVMBasedAppliance $HeartBeatingVMBasedAppliance ` -NonHeartBeatingVMBasedAppliance $CloudAccountNonHeartBeatingOptions [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() if ($Errors.Count -gt 0) { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } $Filters = @{} if (!$All) { $CloudAccount = $HeartBeatingVMBasedAppliance[$TargetCloud] $SourceInventory = Get-RMSourceInventory -ApplianceId $CloudAccount.appliance.id -IsCollect $true ` -CollectCloud $true -CollectVm $false -AddSource $false $Errors = Confirm-RMVsphereUpdateSourceParameterWithSourceInventory -UserParameter $PSBoundParameters -SourceInventory $SourceInventory Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings if ($Errors.Count -gt 0) { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } $Filters = @{ "datacenter_name" = $Datacenter "cluster_name" = $Cluster "resource_pool" = $ResourcePool "folder_name" = $FolderName } } $SourceInventoryResponse = Get-RMSourceInventory -ApplianceId $CloudAccount.appliance.id -IsCollect $false ` -CollectCloud $false -CollectVm $true -AddSource $true -CollectPerfMetric $true -Filters $Filters $UserMessage = "Attempting to refresh vSphere sources." -f $SourceInventoryResponse.id Write-Output $UserMessage | Out-Host return [RMReturn]::new([RMReturn]::SUCCESS, @{"Result" = $UserMessage}) } function Confirm-RMInSituSource { param ( [System.Object] $Source ) $Errors = @() if ($null -ne $Source -and $null -ne $Source.attributes.os) { if ($null -ne $Source.attributes.os.source_migration_state) { $SourceMigrationState = $Source.attributes.os.source_migration_state | ConvertFrom-Json $UpgradeState = $SourceMigrationState.upgrade_state if ($null -ieq $UpgradeState.created_snapshot_name) { $Errors += "Unable to revert to the snapshot." } } } return $Errors } function Start-RMInteractiveRemoveInSituMigration { param ( ) $Source = Read-RMSource -UserMessage "Enter the IP address of the source machine to be migrated" -ParameterName "Source IP address" -IsRequired $true [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() $SourceErrors += Confirm-RMRemoveInSituSource -Source $Source if ($SourceErrors.Count -gt 0) { throw $SourceErrors } $Response = Get-RMMigrationBySourceId -SourceId $Source.id $Migration = Get-RMInSituMigration -MigrationArray $Response.content $HashArguments = @{ ApplianceId = $Migration.cloud_appliance_id MigrationId = $Migration.id SourceId = $Source.id } $RemoveResponse = New-RMRemoveInSituProfile @HashArguments $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" $Uri = Get-Variable -Name "RMContext-ReactorURI" $Headers = @{ Accept = "application/json" "X-Auth-Token" = $RMLoginResult.Value.token } $Params = @{ Method = "Post" Uri = $Uri.Value + "/differentialprofiles/" + $RemoveResponse.id + "/migrations" Headers = $Headers ContentType = "application/json" } $Response = Invoke-RMRestMethod -Params $Params return Update-RMMigrationReturnAsSuccess -MigrationResponse $Response ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $false ` -ReturnMessage "Remove Snapshot started successfully, migration ID" } function Start-RMNonInteractiveRemoveInSituMigration { param ( [string] $SourceIP ) $Errors = @() try { if (![string]::IsNullOrEmpty($SourceIP)) { $Source = Get-RMSourceByIP -IPAddress $SourceIP } } catch [System.Management.Automation.ItemNotFoundException] { $Errors += $PSItem.Exception.Message } $SourceErrors += Confirm-RMRemoveInSituSource -Source $Source if ($SourceErrors.Count -gt 0) { $Errors += $SourceErrors } [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() if ($Errors.Count -gt 0) { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } $Response = Get-RMMigrationBySourceId -SourceId $Source.id $Migration = Get-RMInSituMigration -MigrationArray $Response.content $HashArguments = @{ ApplianceId = $Migration.cloud_appliance_id MigrationId = $Migration.id SourceId = $Source.id } $RemoveResponse = New-RMRemoveInSituProfile @HashArguments $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" $Uri = Get-Variable -Name "RMContext-ReactorURI" $Headers = @{ Accept = "application/json" "X-Auth-Token" = $RMLoginResult.Value.token } $Params = @{ Method = "Post" Uri = $Uri.Value + "/differentialprofiles/" + $RemoveResponse.id + "/migrations" Headers = $Headers ContentType = "application/json" } $Response = Invoke-RMRestMethod -Params $Params return Update-RMMigrationReturnAsSuccess -MigrationResponse $Response ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $false ` -ReturnMessage "Remove Snapshot started successfully, migration ID" } function Confirm-RMRemoveInSituSource { param ( [System.Object] $Source ) $Errors = @() $State = @("running", "error", "cancelled") if ($null -ne $Source -and $null -ne $Source.attributes.os) { if ($null -ne $Source.attributes.os.source_migration_state) { $SourceMigrationState = $Source.attributes.os.source_migration_state | ConvertFrom-Json $UpgradeState = $SourceMigrationState.upgrade_state if ($null -ieq $UpgradeState -or $State -contains $UpgradeState.state) { $Errors += "Unable to remove the snapshot." } } } return $Errors } function Confirm-RMVsphereUpdateSourceParameter { param( [hashtable] $UserParameter, [System.Object] $HeartBeatingVMBasedAppliance, [System.Object] $NonHeartBeatingVMBasedAppliance ) $Errors += @() if (!$UserParameter.ContainsKey("TargetCloud") -or [string]::IsNullOrWhiteSpace($UserParameter["TargetCloud"])) { $Errors += "TargetCloud is reqiured." } else { $CloudAccount = $HeartBeatingVMBasedAppliance[$UserParameter["TargetCloud"]] if ($null -ieq $CloudAccount) { $TargetCloudName = $UserParameter["TargetCloud"] if ($null -ne $NonHeartBeatingVMBasedAppliance[$UserParameter["TargetCloud"]]-and $NonHeartBeatingVMBasedAppliance[$UserParameter["TargetCloud"]].appliance.vm_level_migration_enabled) { $Errors += "The Target Cloud '$TargetCloudName' is not ready for use." } else { $Errors += "TargetCloud '$TargetCloudName' does not exist." } } } if (!$UserParameter.ContainsKey("All") -or !$UserParameter["All"]) { if (!$UserParameter.ContainsKey("Datacenter") -or [string]::IsNullOrWhiteSpace($UserParameter["Datacenter"])) { $Errors += "Datacenter is required." } } return $Errors } function Confirm-RMVsphereUpdateSourceParameterWithSourceInventory { param ( [hashtable] $UserParameter, [System.Object] $SourceInventory ) $Errors = @() $DatacenterNames = $SourceInventory.properties.datacenters.name $Datacenter = $UserParameter["Datacenter"] if ($DatacenterNames -notcontains $Datacenter) { $Errors += "Datacenter '$Datacenter' does not exist." } else { $ClusterObject, $DatacenterObject = Get-ClusterAndDatacenterObject -SourceInventory $SourceInventory -DatacenterName $Datacenter if ($UserParameter.ContainsKey("Cluster") -and ![string]::IsNullOrWhiteSpace($UserParameter["Cluster"])) { $Cluster = $UserParameter["Cluster"] if ($ClusterObject.name -notcontains $Cluster) { $Errors += "Cluster '$Cluster' does not exist." } else { if ($UserParameter.ContainsKey("ResourcePool") -and ![string]::IsNullOrWhiteSpace($UserParameter["ResourcePool"])) { $ResourcePoolList = Get-RMVMResourcePoolname -DatacenterObject $DatacenterObject -ClusterName $Cluster if ($ResourcePoolList.Count -gt 0) { $ResourcePool = $UserParameter["ResourcePool"] if ($ResourcePoolList -notcontains $ResourcePool) { $Errors += "ResourcePool '$ResourcePool' does not exist." } } else { $Errors += "ResourcePool '$ResourcePool' does not exist." } } } } if ($UserParameter.ContainsKey("FolderName") -and ![string]::IsNullOrWhiteSpace($UserParameter["FolderName"])) { $FolderName = $UserParameter["FolderName"] $FolderNameList = Get-RMFolderNameByDatacenter -DatacenterObject $DatacenterObject if ($FolderNameList -notcontains $FolderName) { $Errors += "FolderName '$FolderName' does not exist." } } } return $Errors } function Get-RMSourceInventory { param( [string] $ApplianceId, [bool] $IsCollect, [System.Object] $Filters, [bool] $CollectCloud, [bool] $CollectVm, [bool] $AddSource, [bool] $CollectPerfMetric ) $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" $Uri = Get-Variable -Name "RMContext-ReactorURI" $OrganizationId = Get-Variable -Name "RMContext-CurrentProjectId" -ValueOnly $Headers = @{ Accept = "application/json" "X-Auth-Token" = $RMLoginResult.Value.token } $CollectList = New-Object Collections.Generic.List[string] $CollectList.Add("datacenter") $CollectList.Add("cluster") $CollectList.Add("vm_folder") $CollectList.Add("resource_pool") $Body = @{ "organization_id" = $OrganizationId "appliance_id" = $ApplianceId "objects_to_collect" = if ($IsCollect) { $CollectList } else { $null } "filters" = $Filters "collect_cloud" = $CollectCloud "collect_vms" = $CollectVm "add_sources" = $AddSource "collect_perf_metrics" = $CollectPerfMetric } | ConvertTo-Json $Params = @{ Method = "Post" Uri = $Uri.Value + "/sourceinventories" Headers = $Headers Body = $Body ContentType = "application/json" } if ($IsCollect) { Write-Output "Starting source inventory..." | Out-Host $SourceInventory = Invoke-RMRestMethod -Param $Params return Watch-RMSourceInventoryStatus -SourceInventoryId $SourceInventory.id } else { return Invoke-RMRestMethod -Param $Params } } function Get-RMEnableVirtualizationBasedSecurity { param ( [System.Object] $Source ) $Showing = $true if ($null -ne $Source.attributes.os.source_migration_state) { $MigrationState = $Source.attributes.os.source_migration_state | ConvertFrom-Json } $OSVersions = $MigrationState.upgrade_options $OSVersions += $MigrationState.conversion_options $IsLaterVersion = @("2003", "2008", "XP", "Vista", "7", "8", "8.1", "2012") foreach ($OSVersion in $OSVersions) { foreach ($Version in $IsLaterVersion) { if ($OSVersion -like "*$Version*") { $Showing = $false break } } } return $Showing } function Get-RMTags { param ( [System.Object] $TargetInventory ) $TagCategories = $TargetInventory.attributes.vsphere.tag_categories $Tags = @{} foreach ($TagCategory in $TagCategories) { foreach ($Tag in $TagCategory.tags) { $TagCategoryName = $TagCategory.name $Name = $Tag.name + "[$TagCategoryName]" $Value = @{ "tag_name" = $Tag.name "tag_id" = $Tag.identifier "category_name" = $TagCategory.name } $Tags.Add($Name, $Value) } } return $Tags } function Get-RMVMTag { param( [array] $TagsValue, [hashtable] $Tags ) $TagArray= @() if ($TagsValue.Count -gt 0) { foreach ($Tag in $TagsValue) { $TagArray += $Tags[$Tag] } } return $TagArray } 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-RMClusterAndDatacenter { param ( [System.Object] $TargetInventory, [string] $datacenterName ) $Clusters = @() $DatacenterObject = $null foreach ($datacenter in $TargetInventory.attributes.vSphere.datacenters) { if ($datacenterName -eq $datacenter.name) { $DatacenterObject = $datacenter foreach($cluster in $datacenter.clusters) { $Clusters += $cluster.name } break } } return $Clusters, $DatacenterObject } 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" } default { $Result += $null } } 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, [System.Object] $TargetInventory ) $Errors, $Warnings, $IsSourceAndTargetCloudPresent = Confirm-RMCommonParameter -UserParameter $UserParameter $vSphereErrors, $IsRequiredParametersPresentAndValid = Confirm-RMvSphereParameter -UserParameter $UserParameter ` -TargetInventory $TargetInventory $Errors += $vSphereErrors return $Errors, $Warnings, $IsSourceAndTargetCloudPresent, $IsRequiredParametersPresentAndValid } function Confirm-RMvSphereVMBasedFullMigrationParameter { param( [hashtable] $UserParameter, [System.Object] $TargetInventory ) $Errors, $Warnings, $IsSourcePresent = Confirm-RMVMBasedCommonParameter -UserParameter $UserParameter $vSphereErrors, $IsRequiredParametersPresentAndValid = Confirm-RMvSphereParameter -UserParameter $UserParameter ` -TargetInventory $TargetInventory $Errors += $vSphereErrors return $Errors, $Warnings, $IsSourcePresent, $IsRequiredParametersPresentAndValid } function Confirm-RMvSphereFullMigrationParameterWithSource { param ( [hashtable] $UserParameter, [System.Object] $Source, [System.Object] $SourceSQLServerMapping, [System.Array] $MigrationExtension, [System.Array] $MigrationExtensionOSM, [System.Object] $TargetInventory, [hashtable] $WindowsLicense ) $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 } [string[]] $NetworkIsolationConfigs = "MigrationNetworkConfig", "IsolatedNetworkConfig" foreach($NetworkIsolationConfig in $NetworkIsolationConfigs) { if ($UserParameter.ContainsKey($NetworkIsolationConfig) -or ` $null -ne $UserParameter[$NetworkIsolationConfig]) { $Errors += "$NetworkIsolationConfig can be not null only for a Windows source" } } $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 { if ($UserParameter.ContainsKey("MigrationNetworkConfig") -and $null -ne $UserParameter["MigrationNetworkConfig"] -and ` $UserParameter.ContainsKey("IsolatedNetworkConfig") -and $null -ne $UserParameter["IsolatedNetworkConfig"]) { $Errors += "'EnableDestinationNetworkIsolation' is required when 'MigrationNetworkConfig' and 'IsolatedNetworkConfig' are not null." $IsRequiredParametersPresentAndValid = $false } $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("DatastoreName") -or $UserParameter["DatastoreName"].Count -eq 0) { $Errors += "DatastoreName is required and since the source has dynamic disk(s), please provide only one datastore name." $IsRequiredParametersPresentAndValid = $false } elseif ($UserParameter["DatastoreName"].Count -gt 1) { $Errors += "Source has dynamic disks, please provide only one datastore name." } if (!$UserParameter.ContainsKey("DiskProvisioningType") -or $UserParameter["DiskProvisioningType"].Count -eq 0) { $Errors += "DiskProvisioningType is required and since the source has dynamic disk(s), please provide only one disk provisioning type." $IsRequiredParametersPresentAndValid = $false } elseif ($UserParameter["DiskProvisioningType"].Count -gt 1) { $Errors += "Source has dynamic disks, please provide only one disk provisioning type." } } else { $SourceDiskCnt = $Source.attributes.storage.disks.psobject.properties.name.Count if (!$UserParameter.ContainsKey("DatastoreName") -or $UserParameter["DatastoreName"].Count -eq 0) { $Errors += "DatastoreName is required." $IsRequiredParametersPresentAndValid = $false } elseif ($UserParameter["DatastoreName"].Count -lt $SourceDiskCnt) { $DatastoreCnt = $UserParameter["DatastoreName"].Count $Errors += "The parameter 'DatastoreName' contains '$DatastoreCnt' datastore names but the number of disks found on the source are '$SourceDiskCnt'. The number of datastore names given should be equal to the number of disks on the source." $IsRequiredParametersPresentAndValid = $false } if (!$UserParameter.ContainsKey("DiskProvisioningType") -or $UserParameter["DiskProvisioningType"].Count -eq 0) { $Errors += "DiskProvisioningType is required." $IsRequiredParametersPresentAndValid = $false } elseif ($UserParameter["DiskProvisioningType"].Count -lt $SourceDiskCnt) { $DiskProvCnt = $UserParameter["DiskProvisioningType"].Count $Errors += "The parameter 'DiskProvisioningType' contains '$DiskProvCnt' disk provisioning types but the number of disks found on the source are '$SourceDiskCnt'. The number of disk provisioning types given should be equal to the number of disks on the source." $IsRequiredParametersPresentAndValid = $false } } if ($null -ne $Source.attributes.os.source_migration_state) { $MigrationState = $Source.attributes.os.source_migration_state | ConvertFrom-Json if ($UserParameter.ContainsKey("ConvertBootModeUEFI") -and $UserParameter["ConvertBootModeUEFI"]) { if ("uefi" -ne $MigrationState.boot_mode_conversion_option) { $Errors += "'ConvertBootModeUEFI' can not be 'true'" } } elseif($UserParameter.ContainsKey("EnableSecureBoot") -and $UserParameter["EnableSecureBoot"] ` -and "uefi" -ieq $MigrationState.boot_mode_conversion_option) { $Errors += "'ConvertBootModeUEFI' is required when 'EnableSecureBoot' is 'true'." } } if ($UserParameter.ContainsKey("EanbleVTPM") -and $UserParameter["EanbleVTPM"] ` -and ((!$UserParameter.ContainsKey("ConvertBootModeUEFI") -or !$UserParameter["ConvertBootModeUEFI"]) ` -or (!$UserParameter.ContainsKey("EnableSecureBoot") -or !$UserParameter["EnableSecureBoot"]))) { $Errors += "'ConvertBootModeUEFI' and 'EnableSecureBoot' are both required when 'EanbleVTPM' is 'true'." } if ("data_store" -ieq $Source.collection_type ` -and $UserParameter.ContainsKey("EnableNetAppFileMigration") -and $UserParameter["EnableNetAppFileMigration"]) { $Errors += "'EnableNetAppFileMigration' is not supported for the given source." } $CheckEnableVBS = Get-RMEnableVirtualizationBasedSecurity -Source $Source if (!$CheckEnableVBS -and $UserParameter.ContainsKey("EnableVBS") -and $UserParameter["EnableVBS"]) { $Errors += "'EnableVBS' can not be true." } if ($UserParameter.ContainsKey("VMTag") -and $UserParameter["VMTag"].Count -gt 0) { $Tags = Get-RMTags -TargetInventory $TargetInventory $VMTags = $UserParameter["VMTag"] foreach($VMTag in $VMTags) { if ($Tags.Keys -notcontains $VMTag) { $Errors += "The vm tag(s) '$VMTag' does not exist." } } } if ($UserParameter.ContainsKey("DisableTargetDNSRegistration") -and $UserParameter["DisableTargetDNSRegistration"] ` -and "windows" -ne $Source.os_type) { $Errors += "'DisableTargetDNSRegistration' can be 'true' only for Windows source." } $Errors += Confirm-RMCommonParameterWithSource -UserParameter $UserParameter -Source $Source ` -SourceSQLServerMapping $SourceSQLServerMapping -MigrationExtension $MigrationExtension ` -CloudType 'rivermeadow_standalone' -MigrationExtensionOSM $MigrationExtensionOSM -WindowsLicense $WindowsLicense return $Errors, $IsRequiredParametersPresentAndValid } function Confirm-RMvSphereVMBasedFullMigrationParameterWithSource { param( [hashtable] $UserParameter, [System.Object] $Source, [System.Object] $TargetInventory, [System.Object] $SourceAttributeResult ) $Errors = @() $Warnings = @() $IsRequiredParametersPresentAndValid = $true $SelectedDiskLabelCnt = $UserParameter["SelectedDiskLabel"].Count if (!$UserParameter.ContainsKey("DatastoreName") -or [string]::IsNullOrWhiteSpace($UserParameter["DatastoreName"])) { $Errors += "DatastoreName is required." $IsRequiredParametersPresentAndValid = $false } elseif ($UserParameter["DatastoreName"].Count -ne $UserParameter["SelectedDiskLabel"].Count) { $GivenDatastoreCount = $UserParameter["DatastoreName"].Count $Errors += "The parameter 'DatastoreName' contains '$GivenDatastoreCount' datastore names but there are '$SelectedDiskLabelCnt' selected disks on the source. Please provide the same number of datastore names as the disks selected for migration." } 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 ($UserParameter.ContainsKey("VMTag") -and $UserParameter["VMTag"].Count -gt 0) { $Tags = Get-RMTags -TargetInventory $TargetInventory $VMTags = $UserParameter["VMTag"] foreach($VMTag in $VMTags) { if ($Tags.Keys -notcontains $VMTag) { $Errors += "The vm tag(s) '$VMTag' does not exist." } } } if ($UserParameter.ContainsKey("UpgradeTool") -and $UserParameter["UpgradeTool"]) { $VMConfig = $SourceAttributeResult.attributes.vm_config if ("toolsNotInstalled" -ieq $VMConfig.toolsStatus -or "guestToolsUnmanaged" -ieq $VMConfig.toolsVersionStatus) { $Errors += "'UpgradeTool' is not supportes for the given source." } } $SourceDiskLabels = Get-RMVMBasedSourceDiskLabel -Source $Source $DiskLabelsNotFound = @() foreach ($DiskLabel in $UserParameter["SelectedDiskLabel"]) { if ($SourceDiskLabels -notcontains $DiskLabel) { $DiskLabelsNotFound += $DiskLabel } } if ($DiskLabelsNotFound.Count -gt 0) { $DiskLabelsNotFoundAsString = $DiskLabelsNotFound -join ", " $Errors += "The disk label(s) '$DiskLabelsNotFoundAsString' specified in the parameter 'SelectedDiskLabel' does not exist on the source" } if ($null -ne $UserParameter["StoragePolicyName"] ` -and $UserParameter["StoragePolicyName"].Count -gt 0) { $ValidPolicyNames, $InvalidPolicyNames = Confirm-RMStoragePolicy -TargetInventory $TargetInventory ` -StoragePolicyName $UserParameter["StoragePolicyName"] $ValidPolicyCnt = $ValidPolicyNames.Count if ($InvalidPolicyNames.Count -gt 0) { $InvalidPolicyNamesAsString = $InvalidPolicyNames -join ", " $Errors += "The storage policy name(s) '$InvalidPolicyNamesAsString' specified by the parameter 'StoragePolicyName' do not exist on the target vCenter" } $StoragePolicyCnt = $UserParameter["StoragePolicyName"].Count if ($StoragePolicyCnt -ne $SelectedDiskLabel.Count) { $Errors += "The parameter 'StoragePolicyName' has '$StoragePolicyCnt' storage policy names but '$SelectedDiskLabelCnt' disks have been selected for migration. When the parameter 'StoragePolicyName' is used it should either provide a storage policy name or 'none' for each selected disk. Use 'none' when you do not want to assign a storage policy to a disk but a disk provisioning type should be given for that disk." } else { if ($ValidPolicyNames.Count -eq $SelectedDiskLabel.Count -and ` ($null -ne $UserParameter["DiskProvisioningType"] -and ` $UserParameter["DiskProvisioningType"].Count -gt 0 -and ` $UserParameter["DiskProvisioningType"] -notcontains 'none')) { $Warnings += "The parameter 'StoragePolicyName' has '$ValidPolicyCnt' valid storage policy names and there are '$SelectedDiskLabelCnt' selected disks for migration. The given disk provisioning types will be ignored." } elseif ($ValidPolicyNames.Count -gt $SelectedDiskLabel.Count) { $Errors += "The parameter 'StoragePolicyName' has '$ValidPolicyCnt' valid storage policy names and the number of disks selected for migration are '$SelectedDiskLabelCnt'. The number of storage policy names should be equal to the number of disks selected for migration." } elseif ($ValidPolicyNames.Count -lt $SelectedDiskLabel.Count ` -and $null -eq $UserParameter["DiskProvisioningType"]) { $Errors += "The parameter 'StoragePolicyName' has '$ValidPolicyCnt' valid storage policy names but '$SelectedDiskLabelCnt' disk(s) have been selected for migration. Please provide additional storage policy names or disk provisioning types for the remaining disks." } elseif ($null -ne $UserParameter["DiskProvisioningType"] ` -and $UserParameter["DiskProvisioningType"].Count -gt 0) { $ValidDiskProvisioningTypes = Get-RMValidDiskProvisioningType -DiskProvisioningType $UserParameter["DiskProvisioningType"] $SumOfPolicyAndDiskProvCnt = $ValidPolicyCnt + $ValidDiskProvisioningTypes.Count if ($SumOfPolicyAndDiskProvCnt -lt $SelectedDiskLabelCnt) { $Errors += "The sum of given storage policies and disk provisioning types is less than the number of disks selected for migration. When using both storage policies and disk provisioning types, the sum of storage policy names and disk provisioning types should be equal to the number of selected disks." } elseif ($SumOfPolicyAndDiskProvCnt -gt $SelectedDiskLabelCnt) { $Errors += "The sum of given storage policies and disk provisioning types is greater than the number of disks selected for migration. When using both storage policies and disk provisioning types, the sum of storage policy names and disk provisioning types should be equal to the number of selected disks." } } } } elseif ($null -ne $UserParameter["DiskProvisioningType"] -and ` $UserParameter["DiskProvisioningType"].Count -gt 0) { $ValidDiskProvisioningTypes = Get-RMValidDiskProvisioningType -DiskProvisioningType $UserParameter["DiskProvisioningType"] $DiskProvCnt = $ValidDiskProvisioningTypes.Count if ($DiskProvCnt -ne $SelectedDiskLabelCnt) { $Errors += "The parameter 'DiskProvisioningType' contains '$DiskProvCnt' disk provisioning types whereas the number of disks selected for migration are '$SelectedDiskLabelCnt'. The number of disk provisioning types should be equal to the number of disks selected for migration." } } else { $Errors += "Please provide the storage policy name(s) by using the parameter 'StoragePolicyName' or disk provisioning type(s) by using parameter 'DiskProvisioningType'. You can also use a combination of these two parameters such that any disk that you want to assign a storage policy should have a 'none' value for the corresponding disk in the parameter 'DiskProvisioningType' and vice versa." } 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, [System.Object] $TargetInventory ) $Errors = @() $IsRequiredParametersPresentAndValid = $true if (!$UserParameter.ContainsKey("DatacenterName") -or [string]::IsNullOrWhiteSpace($UserParameter["DatacenterName"])) { $Errors += "DatacenterName is required." $IsRequiredParametersPresentAndValid = $false } else { $DatacenterNames = Get-RMDatacenterName -TargetInventory $TargetInventory if ($DatacenterNames -notcontains $UserParameter["DatacenterName"]) { $DatacenterName = $UserParameter["DatacenterName"] $Errors += "DatacenterName '$DatacenterName' does not exist." $IsRequiredParametersPresentAndValid = $false } else { $NetworkConfig = $UserParameter["DestinationNICConfig"] if ($null -ne $NetworkConfig -and $NetworkConfig.Count -gt 0) { $DestinationNetworkName = $NetworkConfig[0].DestinationNetworkName $NetworkNames = Get-RMNetworkName -TargetInventory $TargetInventory -datacenterName $DatacenterName if (![string]::IsNullOrWhiteSpace($DestinationNetworkName) -and $NetworkNames -notcontains $DestinationNetworkName) { $Errors += "DestinationNetworkName '$DestinationNetworkName' does not exist." $IsRequiredParametersPresentAndValid = $false } } if ($UserParameter.ContainsKey("ClusterName") -and ![string]::IsNullOrWhiteSpace($UserParameter["ClusterName"])) { $Clusters, $DatacenterObject = Get-RMClusterAndDatacenter -TargetInventory $TargetInventory -datacenterName $UserParameter["DatacenterName"] if (![string]::IsNullOrWhiteSpace($UserParameter["ClusterName"])) { $ClusterName = $UserParameter["ClusterName"] if ($Clusters -notcontains $UserParameter["ClusterName"]) { $Errors += "ClusterName '$ClusterName' does not exist." $IsRequiredParametersPresentAndValid = $false } else { $Datastores = Get-RMDatastore -TargetInventory $TargetInventory -DatacenterName $UserParameter["DatacenterName"] ` -ClusterName $ClusterName $DatastoreNames = $UserParameter["DatastoreName"] if ($null -ne $DatastoreNames -and $DatacenterNames.Count -gt 0) { foreach($Datastore in $DatastoreNames) { if ($Datastores -notcontains $Datastore) { $Errors += "DatastoreName '$Datastore' does not exist." $IsRequiredParametersPresentAndValid = $false } } } } } } if ($UserParameter.ContainsKey("CreateFolderName") -and $UserParameter["CreateFolderName"]) { if (!$UserParameter.ContainsKey("FolderName") -or [string]::IsNullOrWhiteSpace($UserParameter["FolderName"])) { $Errors += "'FolderName' is required, when 'CreateFolderName' is true." } } else { if ($UserParameter.ContainsKey("FolderName") -and ![string]::IsNullOrWhiteSpace($UserParameter["FolderName"])) { $VMFolders = Get-RMVMFolderName -TargetInventory $TargetInventory -DatacenterName $UserParameter["DatacenterName"] if ($VMFolders -notcontains $UserParameter["FolderName"]) { $FolderName = $UserParameter["FolderName"] $Errors += "FolderName '$FolderName' does not exist." } } } } } if (!$UserParameter.ContainsKey("ClusterName") -or [string]::IsNullOrWhiteSpace($UserParameter["ClusterName"])) { $Errors += "ClusterName is required" $IsRequiredParametersPresentAndValid = $false } else { if ($UserParameter.ContainsKey("CreateResourcePoolName") -and $UserParameter["CreateResourcePoolName"]) { if (!$UserParameter.ContainsKey("ResourcePoolName") -or [string]::IsNullOrWhiteSpace($UserParameter["ResourcePoolName"])) { $Errors += "'ResourcePoolName' is required, when 'CreateResourcePoolName' is true." } } else { if ($UserParameter.ContainsKey("ResourcePoolName") -and ![string]::IsNullOrWhiteSpace($UserParameter["ResourcePoolName"])) { $Clusters, $DatacenterObject = Get-RMClusterAndDatacenter -TargetInventory $TargetInventory -datacenterName $DatacenterName $ResourcePools = Get-RMVMResourcePoolname -DatacenterObject $DatacenterObject -ClusterName $UserParameter["ClusterName"] $ResourcePoolName = $UserParameter["ResourcePoolName"] if ($ResourcePools -notcontains $ResourcePoolName) { $Errors += "ResourcePoolName '$ResourcePoolName' does not exist." } } } } if (!$UserParameter.ContainsKey("DatastoreName") -or [string]::IsNullOrWhiteSpace($UserParameter["DatastoreName"])) { $Errors += "DatastoreName 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, Update-RMInteractiveVsphereSource, Update-RMNonInteractiveVsphereSource, ` Start-RMInteractiveRevertInSituMigration, Start-RMNonInteractiveRevertInSituMigration, Start-RMInteractiveRemoveInSituMigration, Start-RMNonInteractiveRemoveInSituMigration, ` Start-RMInteractiveInSituMigration, Start-RMNonInteractiveInSituMigration |