Migration/openshift/openshift.psm1
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 MigrationProfile | Join-Path -ChildPath OpenshiftMigrationProfile) 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 Common | Join-Path -ChildPath Wrappers | Join-Path -ChildPath Wrappers) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath Util | Join-Path -ChildPath Util) 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 Common | Join-Path -ChildPath Common) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath RiverMeadow.Source | Join-Path -ChildPath SourceUtil | Join-Path -ChildPath SourceUtil) Import-Module -Name @(Join-Path $PSScriptRoot openshiftUtil) function Start-RMOpenshiftOsBasedInteractiveMigration { param ( ) $UserInput = @{} $Entitlement = Get-RMEntitlement $CloudAccount = Read-RMCloudAccount -AccountType "openshift" -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 $IgnoreValidationError = Read-RMBoolean -UserMessage "Ignore validation errors" -DefaultValue "false" [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() $Source, $ShouldExit, $OverrideExistingMigrationWarning, $OverrideExistingMigrationError = Get-RMSourceWithAttribute -Source $Source -CloudAccount $CloudAccount ` -IgnoreValidationErrors $IgnoreValidationError -RMMigrationReturn $RMMigrationReturn -AccountType "openshift" if ($ShouldExit) { return $RMMigrationReturn } if ($OverrideExistingMigrationError) { $OverrideExistingMigrationError = Read-RMBoolean -UserMessage "Would you like to override the previous migration attempt" -DefaultValue "false" if (!$IgnoreValidationError -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 $MountPoint = Get-MountPoint -Source $Source if (0 -eq $MountPoint.count) { throw "Source has no mount points, cannot be migrated" } $MountPointsAsString = $MountPoint.values -join ", " Write-Output "Mount points to be migrated [$MountPointsAsString]" | Out-Host $ExcludedMountPoint = Get-RMExcludedMountPoint -OSType $Source.os_type -MountPoints $MountPoints.Values $SelectedMountPoint = $MountPoint if ("" -ne $ExcludedMountPoint) { $ExcludedList = $ExcludedMountPoint.Split(",").Trim() $SelectedMountPoint = Get-RMSelectedMount -MountPoints $MountPoints -DifferenceList $ExcludedList -IncludeEqual $false } $UserInput.Add("SelectedMount", $SelectedMountPoint ) $ProjectDefaultValue = $TargetInventory.attributes.openshift.projects.name $Project = Read-RMString -UserMessage "Enter project" -Options $ProjectDefaultValue ` -ParameterName "Project" -IsRequired $true $InstanceType = Read-RMInstanceType -TargetInventory $TargetInventory if ("" -ieq $InstanceType) { $RAM = Read-RMRAMOrCPU -MinValue 2 -ErrorMessage "The minimum RAM size must be greater than or equal to 2." ` -UserMessage "Enter RAM" -DefaultValue "2" -ParameterName "RAM" $Sockets = Read-RMRAMOrCPU -MinValue 1 -ErrorMessage "The Sockets value must be greater than or equal to 1." ` -UserMessage "Enter sockets" -DefaultValue "1" -ParameterName "Sockets" $Cores = Read-RMRAMOrCPU -MinValue 1 -ErrorMessage "The Cores value must be greater than or equal to 1." ` -UserMessage "Enter cores" -DefaultValue "1" -ParameterName "Cores" } $StorageClassDefalutValue = $TargetInventory.attributes.openshift.storage_classes $StorageClass = Read-RMString -UserMessage "Enter storage class" -Options $StorageClassDefalutValue ` -ParameterName "StorageClass" -IsRequired $true $AccessModeOptions = @("Single user (RWO)", "Shared access (RWX)", "Read only (ROX)") $AccessMode = Read-RMString -UserMessage "Enter access mode" -Options $AccessModeOptions -DefaultValue "Single user (RWO)" ` -ParameterName "AccessMode" -IsRequired $false $AccessMode = Get-RMAccountModeName -AccessMode $AccessMode $VolumeModeOptions = @("Filesystem", "Block") $VolumeMode = Read-RMString -UserMessage "Enter volume mode" -Options $VolumeModeOptions -DefaultValue "Block" ` -ParameterName "VolumeMode" -IsRequired $false $ModelOptions = @("virtio", "E1000E") $NetworkAdapterModel = Read-RMString -UserMessage "Enter network adapter model" -Options $ModelOptions -DefaultValue "virtio" ` -ParameterName "NetworkAdapterModel" -IsRequired $false $AdaptersTypeOptions = @("Masquerade", "Bridge") $NetworkAdaptersType = Read-RMString -UserMessage "Enter network adapter type" -Options $AdaptersTypeOptions ` -DefaultValue "Masquerade" -ParameterName "NetworkAdaptersType" -IsRequired $false $NetworkAdaptersType = Get-RMNetworkAdapterType -AdapterType $NetworkAdaptersType $DestinationNetworkNameOptions = $TargetInventory.attributes.openshift.networks.name $ProjectDestinationNetworkNameOptions = Get-RMNetworkNameByProject -Project $Project -TargetInventory $TargetInventory $ProjectDestinationNetworkNameOptions += $DestinationNetworkNameOptions $DestinationNetworkName = Read-RMString -UserMessage "Destination network name" -Options $ProjectDestinationNetworkNameOptions ` -ParameterName "Destination network name" -IsRequired $true #Optimization Settings $NetBIOSName = Read-RMString -UserMessage "Enter NetBIOS name" -DefaultValue $Source.hostname ` -ParameterName "NetBIOS Name" -IsRequired $false $Sysprep = $false if ("windows" -ieq $Source.os_type) { $Sysprep = Read-RMBoolean -UserMessage "Enable sysprep" -DefaultValue "false" } $MountsResize = @{} $ResizeMountPointsFlag = Read-RMBoolean -UserMessage "Resize mount points" -DefaultValue "false" if ($ResizeMountPointsFlag) { $MountsResize = Get-RMInteractiveMountsResize -SelectedMountPoints $SelectedMountPoint -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 #Modernization Settings Read-RMOSUpgradeOption -Source $Source -UpdatedUserInput $UserInput if ($null -ne $UserInput['UpgradeOSVersion']) { Read-RMMigrationExtensionOSM -MigrationExtensionOSM $MigrationExtensionOSMArray -MigrationExtensionObject $MigrationExtensionResponse.content ` -UpdatedUserInput $UserInput } #Security Settings Read-RMOSHardening -UpdatedUserInput $UserInput -Source $Source #Advanced Settings $TransferType = "file-based" if (!$ResizeMountPointsFlag) { $TransferType = (Get-RMTransferMethod -Source $Source -SelectedMountPoints $SelectedMountPoints -IsInteractive $true)[0] } $InstallAzureARC = Read-RMBoolean -UserMessage "Install azure ARC" -DefaultValue "false" $ProjectSettingsResponse = Invoke-RMProjectSettings -OrganizationId $CloudAccount.organization_id $InstallApplicationParameter = $null if ($InstallAzureARC) { $InstallApplicationParameter = $ProjectSettingsResponse.openshift.arc_settings } $ConnectARCAgent = $false if($null -ne $ProjectSettingsResponse.openshift.arc_settings) { $ConnectARCAgent = Read-RMBoolean -UserMessage "Connect ARC agent" -DefaultValue $false } $RemoveRMSAgent = Read-RMBoolean -UserMessage "Remove RMS agent post migration" -DefaultValue "false" $DisableTargetDNSRegistration = $false if ($Source.os_type -eq "windows") { $DisableTargetDNSRegistration = 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" $ReadValue = Read-RMPair -UserMessage "Enter migration instructions in the format 'key=value' and separated by commas" ` -Separator "=" -DefaultValue "None" if (($IgnoreValidationErrors -and $OverrideExistingMigrationError) -or (!$IgnoreValidationErrors -and $OverrideExistingMigrationError) -or $OverrideExistingMigrationWarning) { if ("" -eq $ReadValue) { $ReadValue = "override_source_migration=true" } else { $ReadValue += ",override_source_migration=true" } } $MigrationInstruction = Get-RMStringAsHashtable -InputString $ReadValue $EnableCloudFilesMigration = Read-RMBoolean -UserMessage "Enable cloud files migration" -DefaultValue "false" $HashArguments = @{ CloudAccount = $CloudAccount Entitlement = $Entitlement Source = $Source ScheduledAt = $ScheduledAt TransferMethod = $TransferType TargetVMName = $TargetVMName InstanceType = $InstanceType RAM = $RAM Sockets = $Sockets Cores = $Cores VolumeType = $StorageClass ResizeMountPoint = $MountsResize Project = $Project NetworkName = $DestinationNetworkName NetworkType = $NetworkAdaptersType NetworkAdapterModel = $NetworkAdapterModel RemoveRMSAgent = $RemoveRMSAgent ConnectARCAgent = $ConnectARCAgent InstallAzureARC = $InstallAzureARC InstallApplicationParameter = $InstallApplicationParameter NetBIOSName = $NetBIOSName IgnoreValidationError = $IgnoreValidationError ShutdownSource = $ShutdownSource ShutdownTarget = $ShutdownTarget GeneralizeSystem = $Sysprep DisableTargetDNSRegistration = $DisableTargetDNSRegistration AccessMode = $AccessMode VolumeMode = $VolumeMode MigrationInstruction = $MigrationInstruction EnableCloudFilesMigration = $EnableCloudFilesMigration } $HashArguments += $UserInput $Response = New-RMOpenshiftMigrationProfile @HashArguments $ShouldExit = Start-RMMigrationPreflight -MigrationProfileId $Response.id -IgnoreValidationErrors $IgnoreValidationError -RMMigrationReturn $RMMigrationReturn if ($ShouldExit) { return $RMMigrationReturn } $IsScheduled = ![string]::IsNullOrWhiteSpace($ScheduledAt) $MigrationResponse = Invoke-RMMigrationPost -MigrationProfileResponse $Response return Update-RMMigrationReturnAsSuccess -MigrationResponse $MigrationResponse ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $IsScheduled ` -ReturnMessage "Migration started successfully, migration ID" } function Start-RMOpenshiftOsBasedNonInteractiveMigration { param ( [string] $TargetCloud, [string] $SourceIP, [string] $ScheduledAt, [string] $TargetVMName, [System.Object[]] $MountPoint, [string[]] $ResizeMountPoint, [string] $TransferMethod, [string] $UpgradeOSVersion, [string] $MigrationExtension, [string] $MigrationExtensionOSM, [string] $InstanceType, [int] $Cores, [int] $Sockets, [int] $RAM, [bool] $EnableOSHardening, [bool] $Level1Server, [bool] $Level2Server, [bool] $Level1Computer, [bool] $Level2Computer, [bool] $Level1User, [bool] $Level2User, [string] $AdministratorName, [string] $GuestName, [string] $LegalNoticeCaption, [string] $LegalNoticeText, [string] $StorageClass, [string] $Project, [string] $DestinationNetworkName, [string] $NetworkAdaptersType, [string] $NetworkAdapterModel, [bool] $RemoveRMSAgent, [bool] $ConnectARCAgent, [bool] $InstallAzureARC, [string] $NetBIOSName, [bool] $IgnoreValidationError, [bool] $ShutdownSource, [bool] $ShutdownTarget, [bool] $Sysprep, [bool] $DisableTargetDNSRegistration, [string] $AccessMode, [string] $VolumeMode, [string[]] $MigrationInstruction, [bool] $EnableCloudFilesMigration ) $UserInput = @{} $CloudAccount = $null $CloudAccountErrors = $null $Source = $null $Entitlement = Get-RMEntitlement try { if (![string]::IsNullOrEmpty($TargetCloud)) { $CloudAccount, $ErrorString = Get-RMCloudAccountByName -CloudAccountName $TargetCloud -AccountType "openshift" 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 } $ProjectSettingsResponse = Invoke-RMProjectSettings -OrganizationId $CloudAccount.organization_id $Errors, $Warnings, $IsSourceAndTargetCloudPresent, $IsRequiredParametersPresentAndValid = Confirm-RMOpenshiftFullMigrationParameter $PSBoundParameters ` -TargetInventory $TargetInventory -ProjectSettingsResponse $ProjectSettingsResponse 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 -or !$IsRequiredParametersPresentAndValid) { 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 "openshift" ` -RMMigrationReturn $RMMigrationReturn } 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) { $SourceErrors = Confirm-RMOpenshiftFullMigrationParameterWithSource -UserParameter $PSBoundParameters ` -Source $Source -MigrationExtension $MigrationExtensionArray -MigrationExtensionOSM $MigrationExtensionOSMArray if ($RequiredParameterState) { $IsRequiredParametersPresentAndValid = $RequiredParameterState } $Errors += $SourceErrors } if ([string]::IsNullOrEmpty($TargetVMName)) { $TargetVMName = $Source.hostname } $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("SelectedMount", $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 } } $InstallApplicationParameter = $null if ($InstallAzureARC) { $InstallApplicationParameter = $ProjectSettingsResponse.openshift.arc_settings } if ([string]::IsNullOrEmpty($NetBIOSName)) { $NetBIOSName = $Source.hostname } $MigrationInstructionsAsHashTable = $null try { if (($IgnoreValidationError -and $OverrideExistingMigration) -or (!$IgnoreValidationError -and $OverrideExistingMigration) -or $OverrideExistingMigrationWarning) { $MigrationInstruction += "override_source_migration=true" } $MigrationInstructionsAsHashTable = Get-RMStringArrayAsHashtable -InputItems $MigrationInstruction -ParameterName "MigrationInstruction" } catch { $Errors += $PSItem.Exception.Message } Add-RMOSUpgrade -UserParameter $PSBoundParameters -UpdatedParameter $UserInput -Source $Source Add-RMConvertFileSystem -Source $Source -UpdatedUserInput $UserInput -ConvertFileSystem $ConvertFileSystem Add-RMMigrationExtension -UpdatedParameter $UserInput -MigrationExtension $MigrationExtension ` -MigrationExtensionOSM $MigrationExtensionOSM -MigrationExtensionResponse $MigrationExtensionResponse if (![string]::IsNullOrEmpty($ScheduledAt)) { $ScheduledAt = Convert-RMDateTimeToUTC -InputDateTime $ScheduledAt } $ErrorsOSHardening = Add-RMOSHardening -Source $Source -UpdatedParameter $UserInput -UserParameter $PSBoundParameters if ($null -ne $ErrorsOSHardening) { $Errors += $ErrorsOSHardening } $AccessMode = Get-RMAccountModeName -AccessMode $AccessMode $NetworkAdaptersType = Get-RMNetworkAdapterType -AdapterType $NetworkAdaptersType Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings if ($Errors.Count -gt 0 -or $ShouldExit) { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } $HashArguments = @{ CloudAccount = $CloudAccount Entitlement = $Entitlement Source = $Source ScheduledAt = $ScheduledAt TransferMethod = $TransferMethod TargetVMName = $TargetVMName InstanceType = $InstanceType Cores = $Cores RAM = $RAM Sockets = $Sockets VolumeType = $StorageClass ResizeMountPoint = $MountsResize Project = $Project NetworkName = $DestinationNetworkName NetworkType = $NetworkAdaptersType NetworkAdapterModel = $NetworkAdapterModel RemoveRMSAgent = $RemoveRMSAgent ShutdownSource = $ShutdownSource ShutdownTarget = $ShutdownTarget ConnectARCAgent = $ConnectARCAgent InstallAzureARC = $InstallAzureARC InstallApplicationParameter = $InstallApplicationParameter NetBIOSName = $NetBIOSName IgnoreValidationError = $IgnoreValidationError DisableTargetDNSRegistration = $DisableTargetDNSRegistration AccessMode = $AccessMode VolumeMode = $VolumeMode MigrationInstruction = $MigrationInstructionsAsHashTable EnableCloudFilesMigration = $EnableCloudFilesMigration GeneralizeSystem = $Sysprep } $HashArguments += $UserInput $Response = New-RMOpenshiftMigrationProfile @HashArguments $ShouldExit = Start-RMMigrationPreflight -MigrationProfileId $Response.id -IgnoreValidationErrors $IgnoreValidationError -RMMigrationReturn $RMMigrationReturn if ($ShouldExit) { return $RMMigrationReturn } $IsScheduled = ![string]::IsNullOrWhiteSpace($ScheduledAt) $MigrationResponse = Invoke-RMMigrationPost -MigrationProfileResponse $Response return Update-RMMigrationReturnAsSuccess -MigrationResponse $MigrationResponse ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $IsScheduled ` -ReturnMessage "Migration started successfully, migration ID" } function Confirm-RMOpenshiftFullMigrationParameter { param ( [hashtable] $UserParameter, [System.Object] $TargetInventory, [System.Object] $ProjectSettingsResponse ) $Errors, $Warnings, $IsSourceAndTargetCloudPresent = Confirm-RMCommonParameter -UserParameter $UserParameter $openshiftErrors, $IsRequiredParametersPresentAndValid = Confirm-RMOpenshiftParameter -UserParameter $UserParameter ` -TargetInventory $TargetInventory -ProjectSettingsResponse $ProjectSettingsResponse $Errors += $openshiftErrors return $Errors, $Warnings, $IsSourceAndTargetCloudPresent, $IsRequiredParametersPresentAndValid } function Confirm-RMOpenshiftFullMigrationParameterWithSource { param ( [hashtable] $UserParameter, [System.Object] $Source, [System.Array] $MigrationExtension, [System.Array] $MigrationExtensionOSM ) $Errors = @() $Errors = Confirm-RMCommonParameterWithSource -UserParameter $UserParameter -Source $Source ` -MigrationExtension $MigrationExtension -MigrationExtensionOSM $MigrationExtensionOSM if ($Source.os_type -ne 'windows' -and $UserParameter["DisableTargetDNSRegistration"]) { $Errors += "DisableTargetDNSRegistration can only be 'true', if the source type is 'windows'." } return $Errors } function Confirm-RMOpenshiftParameter { param ( [hashtable] $UserParameter, [System.Object] $TargetInventory, [System.Object] $ProjectSettingsResponse ) $Errors = @() $IsRequiredParametersPresentAndValid = $true if (!$UserParameter.ContainsKey("Project") -or [string]::IsNullOrWhiteSpace($UserParameter["Project"])) { $Errors += "Project is reqired." $IsRequiredParametersPresentAndValid = $false } else { $ProjectNames = $TargetInventory.attributes.openshift.projects.name if ($ProjectNames -notcontains $UserParameter["Project"]) { $Project = $UserParameter["Project"] $Errors += "Project '$Project' does not exist." $IsRequiredParametersPresentAndValid = $false } } $StorageClassNames = $TargetInventory.attributes.openshift.storage_classes if (!$UserParameter.ContainsKey("StorageClass") -or [string]::IsNullOrWhiteSpace($UserParameter["StorageClass"])) { $Errors += "StorageClass is required." $IsRequiredParametersPresentAndValid = $false } else { $StorageClass = $UserParameter["StorageClass"] if ($StorageClassNames -notcontains $StorageClass) { $Errors += "StorageClass '$StorageClass' does not exist." $IsRequiredParametersPresentAndValid = $false } } if (!$UserParameter.ContainsKey("InstanceType") -or [string]::IsNullOrWhiteSpace($UserParameter["InstanceType"])) { if (!$UserParameter.ContainsKey("RAM") -or $null -ieq $UserParameter["RAM"]) { $Errors += "RAM or InstanceType is required." $IsRequiredParametersPresentAndValid = $false } elseif ($UserParameter["RAM"] -lt 2){ $Errors += "The minimum RAM size must be greater than or equal to 2." $IsRequiredParametersPresentAndValid = $false } if (!$UserParameter.ContainsKey("Cores") -or $null -ieq $UserParameter["Cores"]) { $Errors += "Cores or InstanceType is required." $IsRequiredParametersPresentAndValid = $false } elseif ($UserParameter["Cores"] -lt 1) { $Errors += "The Cores value must be greater than or equal to 1." $IsRequiredParametersPresentAndValid = $false } if (!$UserParameter.ContainsKey("Sockets") -or $null -ieq $UserParameter["Sockets"]) { $Errors += "Sockets or InstanceType is required." $IsRequiredParametersPresentAndValid = $false } elseif ($UserParameter["Sockets"] -lt 1) { $Errors += "The Sockets value must be greater than or equal to 1." $IsRequiredParametersPresentAndValid = $false } } else { $InstanceTypeNames = $TargetInventory.attributes.openshift.instance_types.name if ($InstanceTypeNames -notcontains $UserParameter["InstanceType"]) { $InstanceType = $UserParameter["InstanceType"] $Errors += "InstanceType '$InstanceType' does not exist." $IsRequiredParametersPresentAndValid = $false } if ($UserParameter.ContainsKey("RAM") -and $null -ne $UserParameter["RAM"]) { $Errors += "InstanceType already exists. RAM is required when InstanceType is not used." } if ($UserParameter.ContainsKey("Cores") -and $null -ne $UserParameter["Cores"]) { $Errors += "InstanceType already exists. Cores is required when InstanceType is not used." } if ($UserParameter.ContainsKey("Sockets") -and $null -ne $UserParameter["Sockets"]) { $Errors += "InstanceType already exists. Sockets is required when InstanceType is not used." } } if (!$UserParameter.ContainsKey("NetworkAdapterModel") -or $null -ieq [string]::IsNullOrWhiteSpace($UserParameter["NetworkAdapterModel"])) { $Errors += "NetworkAdapterModel is required." } if (!$UserParameter.ContainsKey("NetworkAdaptersType") -or $null -ieq [string]::IsNullOrWhiteSpace($UserParameter["NetworkAdaptersType"])) { $Errors += "NetworkAdaptersType is required." } if (!$UserParameter.ContainsKey("DestinationNetworkName") -or $null -ieq [string]::IsNullOrWhiteSpace($UserParameter["DestinationNetworkName"])) { $Errors += "DestinationNetworkName is required." } else { $DestinationNetworkName = $UserParameter["DestinationNetworkName"] $DestinationNetworkNameOptions = $TargetInventory.attributes.openshift.networks.name if ($DestinationNetworkNameOptions -notcontains $DestinationNetworkName) { $Errors += "DestinationNetworkName '$DestinationNetworkName' is required." } } if (!$UserParameter.ContainsKey("InstallAzureARC") -or !$UserParameter["InstallAzureARC"]) { if ($UserParameter.ContainsKey("ConnectARCAgent")) { if ($UserParameter["ConnectARCAgent"]) { $Errors += "'InstallAzureARC' is must be true, when parameter 'ConnectARCAgent' is not null." } } } elseif ($UserParameter.ContainsKey("InstallAzureARC") -and $UserParameter["InstallAzureARC"] ` -and $UserParameter.ContainsKey("ConnectARCAgent") -and $UserParameter["ConnectARCAgent"] ` -and $null -ieq $ProjectSettingsResponse.openshift.arc_settings) { $Errors += "'ConnectARCAgent' can not be true." } return $Errors, $IsRequiredParametersPresentAndValid } function Get-RMAccountModeName { param ( [string] $AccessMode ) $AccessModeName = "" switch ($AccessMode) { "Single user (RWO)" { $AccessModeName = "ReadWriteOnce" Break; } "Shared access (RWX)" { $AccessModeName = "ReadWriteMany" Break; } "Read only (ROX)" { $AccessModeName = "ReadOnlyMany" Break; } } return $AccessModeName } function Get-RMNetworkAdapterType { param( [string] $AdapterType ) $AdapterTypeName = "" switch ($AdapterType) { "Masquerade" { $AdapterTypeName = "masquerade" Break; } "Bridge" { $AdapterTypeName = "bridge" Break; } } return $AdapterTypeName } function Get-RMNetworkNameByProject { param ( [string] $Project, [System.Object] $TargetInventory ) $NetworkNames = @() foreach($Proj in $TargetInventory.attributes.openshift.projects) { if ($Project -ieq $Proj.name) { $NetworkNames += $Proj.network_attachment_definitions.name Break; } } return $NetworkNames } function Start-RMOpenshiftVMBasedInteractiveMigration { param() $UserInput = @{} $Entitlement = Get-RMEntitlement $CloudAccount = Read-RMCloudAccount -AccountType "openshift" -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 [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 } $TargetInventory = Get-RMTargetInventory -CloudAccount $CloudAccount -IsOpenshiftMigration $true $IgnoreValidationError = Read-RMBoolean -UserMessage "Ignore validation errors" -DefaultValue "false" $Source, $ShouldExit, $OverrideExistingMigrationWarning, $OverrideExistingMigrationError = Get-RMSourceWithAttribute -Source $Source -CloudAccount $CloudAccount ` -IgnoreValidationErrors $IgnoreValidationError -RMMigrationReturn $RMMigrationReturn -AccountType "openshift" 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.host ` -ParameterName "Target VM Name" -IsRequired $false $SelectedDisks = @() $ReturnedValue = Get-RMSelectedDisk -Source $Source if ($SelectedDisks -is [hashtable]) { $SelectedDisks += $ReturnedValue } else { $SelectedDisks = $ReturnedValue } #Placement Settings: $ProjectDefaultValue = $TargetInventory.attributes.openshift.projects.name $Project = Read-RMString -UserMessage "Enter project" -Options $ProjectDefaultValue ` -ParameterName "Project" -IsRequired $true $InstanceType = Read-RMInstanceType -TargetInventory $TargetInventory if ("" -ieq $InstanceType) { $RAM = Read-RMRAMOrCPU -MinValue 2 -ErrorMessage "The minimum RAM size must be greater than or equal to 2." ` -UserMessage "Enter RAM" -DefaultValue "2" -ParameterName "RAM" $Sockets = Read-RMRAMOrCPU -MinValue 1 -ErrorMessage "The Sockets value must be greater than or equal to 1." ` -UserMessage "Enter sockets" -DefaultValue "1" -ParameterName "Sockets" $Cores = Read-RMRAMOrCPU -MinValue 1 -ErrorMessage "The Cores value must be greater than or equal to 1." ` -UserMessage "Enter cores" -DefaultValue "1" -ParameterName "Cores" } $StorageClassDefalutValue = $TargetInventory.attributes.openshift.storage_classes $StorageClass = Read-RMString -UserMessage "Enter storage class" -Options $StorageClassDefalutValue ` -ParameterName "StorageClass" -IsRequired $true $AccessModeOptions = @("Single user (RWO)", "Shared access (RWX)", "Read only (ROX)") $AccessMode = Read-RMString -UserMessage "Enter access mode" -Options $AccessModeOptions -DefaultValue "Single user (RWO)" ` -ParameterName "AccessMode" -IsRequired $false $AccessMode = Get-RMAccountModeName -AccessMode $AccessMode $VolumeModeOptions = @("Filesystem", "Block") $VolumeMode = Read-RMString -UserMessage "Enter volume mode" -Options $VolumeModeOptions -DefaultValue "Block" ` -ParameterName "VolumeMode" -IsRequired $false $ModelOptions = @("virtio", "E1000E") $NetworkAdapterModel = Read-RMString -UserMessage "Enter network adapter model" -Options $ModelOptions -DefaultValue "virtio" ` -ParameterName "NetworkAdapterModel" -IsRequired $false $AdaptersTypeOptions = @("Masquerade", "Bridge") $NetworkAdaptersType = Read-RMString -UserMessage "Enter network adapter type" -Options $AdaptersTypeOptions ` -DefaultValue "Masquerade" -ParameterName "NetworkAdaptersType" -IsRequired $false $NetworkAdaptersType = Get-RMNetworkAdapterType -AdapterType $NetworkAdaptersType $DestinationNetworkNameOptions = $TargetInventory.attributes.openshift.networks.name $ProjectDestinationNetworkNameOptions = Get-RMNetworkNameByProject -Project $Project -TargetInventory $TargetInventory $ProjectDestinationNetworkNameOptions += $DestinationNetworkNameOptions $DestinationNetworkName = Read-RMString -UserMessage "Destination network name" -Options $ProjectDestinationNetworkNameOptions ` -ParameterName "Destination network name" -IsRequired $true #Optimization Settings: $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 $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" $FinalizeMigration = Read-RMBoolean -UserMessage "Remove snapshot(s) from the Target VM in preparation for a cutover" -DefaultValue "false" $ReadValue = Read-RMPair -UserMessage "Enter migration instructions in the format 'key=value' and separated by commas" ` -Separator "=" -DefaultValue "None" if (($IgnoreValidationErrors -and $OverrideExistingMigrationError) -or (!$IgnoreValidationErrors -and $OverrideExistingMigrationError) -or $OverrideExistingMigrationWarning) { if ("" -eq $ReadValue) { $ReadValue = "override_source_migration=true" } else { $ReadValue += ",override_source_migration=true" } } $MigrationInstruction = Get-RMStringAsHashtable -InputString $ReadValue $HashArguments = @{ CloudAccount = $CloudAccount Entitlement = $Entitlement Source = $Source ScheduledAt = $ScheduledAt TargetVMName = $TargetVMName Cores = $Cores RAM = $RAM Sockets = $Sockets VolumeType = $StorageClass AccessMode = $AccessMode VolumeMode = $VolumeMode Project = $Project NetworkName = $DestinationNetworkName NetworkType = $NetworkAdaptersType NetworkAdapterModel = $NetworkAdapterModel SelectedMount = $SelectedDisks ShutdownSource = $ShutdownSource ShutdownTarget = $ShutdownTarget FinalizeTarget = $FinalizeMigration MigrationInstruction = $MigrationInstruction IgnoreValidationError = $IgnoreValidationError InstanceType = $InstanceType } $HashArguments += $UserInput $Response = New-RMOpenshiftVMBasedMigrationProfile @HashArguments $ShouldExit = Start-RMMigrationPreflight -MigrationProfileId $Response.id -IgnoreValidationErrors $IgnoreValidationError -RMMigrationReturn $RMMigrationReturn if ($ShouldExit) { return $RMMigrationReturn } $IsScheduled = ![string]::IsNullOrWhiteSpace($ScheduledAt) $MigrationResponse = Invoke-RMMigrationPost -MigrationProfileResponse $Response return Update-RMMigrationReturnAsSuccess -MigrationResponse $MigrationResponse ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $IsScheduled ` -ReturnMessage "Migration started successfully, migration ID" } function Start-RMOpenshiftVMBasedNonInteractiveMigration { param( [string] $TargetCloud, [string] $SourceVMName, [string] $ScheduledAt, [string[]] $SelectedDiskLabel, [string] $TargetVMName, [bool] $IgnoreValidationError, [string] $Project, [string] $InstanceType, [int] $Cores, [int] $Sockets, [int] $RAM, [string] $StorageClass, [string] $AccessMode, [string] $VolumeMode, [string] $DestinationNetworkName, [string] $NetworkAdaptersType, [string] $NetworkAdapterModel, [string] $MigrationExtension, [bool] $ShutdownSource, [bool] $ShutdownTarget, [bool] $FinalizeMigration, [string[]] $MigrationInstruction ) $UserInput = @{} $CloudAccount = $null $CloudAccountErrors = $null $Source = $null $Entitlement = Get-RMEntitlement try { $TargetInventory = $null if (![string]::IsNullOrEmpty($TargetCloud)) { $CloudAccount, $ErrorString = Get-RMCloudAccountByName -CloudAccountName $TargetCloud ` -AccountType "openshift" -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-RMOpenshiftVMBasedFullMigrationParameter $PSBoundParameters ` -TargetInventory $TargetInventory if ($null -ne $CloudAccountErrors) { $Errors += $CloudAccountErrors $IsSourceAndTargetCloudPresent = $false } [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-RMOpenshiftOSBasedMigration'." 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 -or !$IsRequiredParametersPresentAndValid) { 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 "openshift" ` -RMMigrationReturn $RMMigrationReturn } catch [System.InvalidOperationException], [System.Management.Automation.RuntimeException] { $Errors += $PSItem.Exception.Message } $MigrationExtensionResponse = Get-RMMigrationExtension -OrganizationId $CloudAccount.organization_id $MigrationExtensionArray, $MigrationExtensionOSMArray = Get-RMMigrationExtensionFromStep -MigrationExtensionArray $MigrationExtensionResponse.content 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 = Confirm-RMOpenshiftVMBasedFullMigrationParameterWithSource -MigrationExtension $MigrationExtension -SelectedDiskLabel $SelectedDiskLabel ` -MigrationExtensionArray $MigrationExtensionArray -Source $Source if ($null -ne $SourceErrors) { $Errors += $SourceErrors } } Add-RMMigrationExtension -UpdatedParameter $UserInput -MigrationExtension $MigrationExtension ` -MigrationExtensionOSM $MigrationExtensionOSM -MigrationExtensionResponse $MigrationExtensionResponse $MigrationInstructionsAsHashTable = $null try { if (($IgnoreValidationError -and $OverrideExistingMigration) -or (!$IgnoreValidationError -and $OverrideExistingMigration) -or $OverrideExistingMigrationWarning) { $MigrationInstruction += "override_source_migration=true" } $MigrationInstructionsAsHashTable = Get-RMStringArrayAsHashtable -InputItems $MigrationInstruction -ParameterName "MigrationInstruction" } catch { $Errors += $PSItem.Exception.Message } $AccessMode = Get-RMAccountModeName -AccessMode $AccessMode $NetworkAdaptersType = Get-RMNetworkAdapterType -AdapterType $NetworkAdaptersType $SelectedDisk = Get-RMSelectedDiskByDiskLabel -DiskLabel $SelectedDiskLabel -Source $Source if ([string]::IsNullOrEmpty($TargetVMName)) { $TargetVMName = $Source.name } $HashArguments = @{ CloudAccount = $CloudAccount Entitlement = $Entitlement Source = $Source ScheduledAt = $ScheduledAt TargetVMName = $TargetVMName Cores = $Cores RAM = $RAM Sockets = $Sockets VolumeType = $StorageClass AccessMode = $AccessMode VolumeMode = $VolumeMode Project = $Project NetworkName = $DestinationNetworkName NetworkType = $NetworkAdaptersType NetworkAdapterModel = $NetworkAdapterModel SelectedMount = $SelectedDisk ShutdownSource = $ShutdownSource ShutdownTarget = $ShutdownTarget FinalizeTarget = $FinalizeMigration MigrationInstruction = $MigrationInstructionsAsHashTable IgnoreValidationError = $IgnoreValidationError InstanceType = $InstanceType } $HashArguments += $UserInput $Response = New-RMOpenshiftVMBasedMigrationProfile @HashArguments $ShouldExit = Start-RMMigrationPreflight -MigrationProfileId $Response.id -IgnoreValidationErrors $IgnoreValidationError -RMMigrationReturn $RMMigrationReturn if ($ShouldExit) { return $RMMigrationReturn } $IsScheduled = ![string]::IsNullOrWhiteSpace($ScheduledAt) $MigrationResponse = Invoke-RMMigrationPost -MigrationProfileResponse $Response return Update-RMMigrationReturnAsSuccess -MigrationResponse $MigrationResponse ` -RMMigrationReturn $RMMigrationReturn -IsScheduledMigration $IsScheduled ` -ReturnMessage "Migration started successfully, migration ID" } function Confirm-RMOpenshiftVMBasedFullMigrationParameter { param ( [hashtable] $UserParameter, [System.Object] $TargetInventory ) $Errors, $Warnings, $IsSourcePresent = Confirm-RMVMBasedCommonParameter -UserParameter $UserParameter $openshiftErrors, $IsRequiredParametersPresentAndValid = Confirm-RMOpenshiftParameter -UserParameter $UserParameter ` -TargetInventory $TargetInventory $Errors += $openshiftErrors return $Errors, $Warnings, $IsSourcePresent, $IsRequiredParametersPresentAndValid } function Confirm-RMOpenshiftVMBasedFullMigrationParameterWithSource { [string] $MigrationExtension, [string[]] $SelectedDiskLabel, [System.Object] $MigrationExtensionArray, [System.Object] $Source $Errors = @() if (![string]::IsNullOrWhiteSpace($MigrationExtension)) { if ($MigrationExtensionArray -notcontains $MigrationExtension) { $Errors += "MigrationExtension '$MigrationExtension' does not exist." } } $SourceDiskLabels = Get-RMVMBasedSourceDiskLabel -Source $Source $DiskLabelsNotFound = @() foreach ($DiskLabel in $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" } return $Errors } Export-ModuleMember -Function Start-RMOpenshiftOsBasedInteractiveMigration, Start-RMOpenshiftOsBasedNonInteractiveMigration, ` Start-RMOpenshiftOsBasedInteractiveMigration, Start-RMOpenshiftVMBasedInteractiveMigration, Start-RMOpenshiftVMBasedNonInteractiveMigration |