DifferentialMigration/DifferentialMigration.psm1
using module '../Common/Result' Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath DifferentialProfile | Join-Path -ChildPath DifferentialProfile) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath Util | Join-Path -ChildPath MigrationUtil) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath Preflight | Join-Path -ChildPath Preflight) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath Common | Join-Path -ChildPath Common) Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath CloudAccount | Join-Path -ChildPath CloudAccount) <<<<<<< HEAD (fb6a53 RM-19127: Bug fix for RMMigrationReturn.) function Start-RMDM { ======= function Start-RMInteractiveDM { param () $OrganizationId = Get-Variable -Name "RMContext-CurrentProjectId" -ValueOnly $Name = "PowerShell - Differential Profile - " + [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds() [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() $Migration, $Source = Read-RMFullMigrationId $MigrationList = Get-RMMigrationListBySourceId -OrganizationId $OrganizationId -SourceId $Source.id foreach ($Mig in $MigrationList) { if ("running" -eq $Mig.state) { $UserMessage = "Currently there is a migration running for the source of the given migration ID, this differential migration might fail." Write-Warning $UserMessage $RMMigrationReturn.AddRMWarning([RMWarning]::new($UserMessage)) Break; } } $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 $RemoveRMSAgent = Read-RMBoolean -UserMessage "Remove RMS agent post migration" -DefaultValue $false $ReadValue = Read-RMPair -UserMessage "Enter migration instructions in the format 'key=value' and separated by commas" ` -Separator "=" -DefaultValue "None" $MigrationInstructions = Get-RMStringAsHashtable -InputString $ReadValue $IgnoreValidationErrors = Read-RMBoolean -UserMessage "Ignore Validation Errors" -DefaultValue $false if (!('windows' -eq $Migration.os_type -or $Migration.source.discovered_features.features_list -contains 'linux_block_based')) { $UpdateMountsPoints = Read-RMBoolean -UserMessage "Update mounts points" -DefaultValue $false } else { $UpdateMountsPoints = $true } $SelectedMounts = @() if ($UpdateMountsPoints) { $UpdateIncludesAndExcludes = $true $SelectedMounts = $Migration.target.properties.selected_mounts.PSObject.properties.Name $TransferMethod = (Get-RMTransferMethod -Source $Source -SelectedMountPoints $SelectedMounts -IsInteractive $true)[0] if ('block-based' -eq $TransferMethod) { $UpdateIncludesAndExcludes = $false } $MountPointsAsString = $SelectedMounts -join "," Write-Output "Mount points to be migrated [$MountPointsAsString]" $SelectedMountPoints = @() if ($SelectedMounts.Count -gt 1) { $ExcludedMountPoints = Get-RMExcludedMountPoint -OSType $Migration.os_type -MountPoints $SelectedMounts -IsDifferentialMigration $true if ("" -ne $ExcludedMountPoints) { $ExcludedList = $ExcludedMountPoints.Split(",").Trim() $Results = Compare-Object -ReferenceObject $SelectedMounts -DifferenceObject $ExcludedList -IncludeEqual foreach ($Result in $Results) { if (!($Result.SideIndicator -contains "==")) { $SelectedMountPoints += $Result.InputObject } } } } if ($SelectedMountPoints.Count -eq 0) { $SelectedMountPoints = $SelectedMounts } if (!$UpdateIncludesAndExcludes) { $MountPoints = Update-RMDefaultMountPoints -UpdateSelectedMounts $SelectedMountPoints -Migration $Migration } else { foreach($MountPoint in $Migration.target.properties.selected_mounts.PSObject.properties) { $MountName = $MountPoint.name if ($SelectedMountPoints -contains $MountName) { $Includes = @() if ('linux' -eq $Migration.os_type) { $OverwriteIncludes = Read-RMBoolean -UserMessage "Overwrite Includes for mount point '$MountName'" -DefaultValue $false if ($OverwriteIncludes) { $IncludesAsString = Read-RMString -UserMessage "For mount point '$MountName', update one or more include paths, separated by commas " ` -DefaultValue 'None' -ParameterName "Includes" -IsRequired $false if ("" -ne $IncludesAsString) { $Includes = $IncludesAsString -split "," } } } $Excludes = @() $DefaultExcludes = 'None' if ("linux" -eq $Migration.os_type) { $DefaultExcludes = '**/.snapshot' } $OverwriteExcludes = Read-RMBoolean -UserMessage "Overwrite Excludes for mount point '$MountName'" -DefaultValue $false if ($OverwriteExcludes) { $ExcludesAsString = Read-RMString -UserMessage "For mount point '$MountName', update one or more exclude paths, separated by commas"` -DefaultValue $DefaultExcludes -ParameterName "Excludes" -IsRequired $false if ("" -ne $ExcludesAsString) { $Excludes = $ExcludesAsString -split "," } } elseif ("linux" -eq $Migration.os_type) { $Excludes += '**/.snapshot' } $MountPoints += @{$MountName = @{"includes" = $Includes "excludes" = $Excludes } } } } } } else { $MountPoints = Update-RMDefaultMountPoints -UpdateSelectedMounts $Migration.target.properties.selected_mounts.PSObject.properties.Name -Migration $Migration } $TargetProperties = Edit-RMMountPoints -TargetProperties $Migration.target.properties -MountPoints $MountPoints $UpdateSourceCredentials = Read-RMBoolean -UserMessage "Update Source Cresentials" -DefaultValue $false if ($UpdateSourceCredentials) { $SourceUserName = Read-RMString -UserMessage "Enter the username" -ParameterName "Username" -IsRequired $true $SourceUseSSHPrivateKey = Read-RMBoolean -UserMessage "Use SSH private key" -DefaultValue $false if ($SourceUseSSHPrivateKey) { $SourcePrivateKey = Read-RMString -UserMessage "Enter the private key" -ParameterName "Private Key" -IsRequired $true $SourcePassword = Read-RMSecureString -UserMessage "Enter the passphrase" -ParameterName "Passphrase" ` -ConfirmMessage "Confirm the passphrase" -ConfirmParameterName "Confirm passphrase" -IsRequired $false } else { $SourcePassword = Read-RMSecureString -UserMessage "Enter the password" -ParameterName "Password" ` -ConfirmMessage "Confirm the password" -ConfirmParameterName "Confirm password" -IsRequired $true } $SourceDomain = Read-RMString -UserMessage "Enter the domain" -ParameterName "Domain" -IsRequired $false } $UpdateTargetInstance = Read-RMBoolean -UserMessage "Update target instance/VM cresentials" -DefaultValue $false if ($UpdateTargetInstance) { $TargetUserName = Read-RMString -UserMessage "Enter the username" -ParameterName "Username" -IsRequired $true $TargetUseSSHPrivateKey = Read-RMBoolean -UserMessage "Use SSH private key" -DefaultValue $false if ($TargetUseSSHPrivateKey) { $TargetPrivateKey = Read-RMString -UserMessage "Enter the private key" -ParameterName "Private Key" -IsRequired $true $TargetPassword = Read-RMSecureString -UserMessage "Enter the passphrase" -ParameterName "Passphrase" ` -ConfirmMessage "Confirm the passphrase" -ConfirmParameterName "Confirm passphrase" -IsRequired $false } else { $TargetPassword = Read-RMSecureString -UserMessage "Enter the password" -ParameterName "Password" ` -ConfirmMessage "Confirm the password" -ConfirmParameterName "Confirm password" -IsRequired $true } $TargetDomain = Read-RMString -UserMessage "Enter the domain" -ParameterName "Domain" -IsRequired $false } $UpdateTargetIPAddress = Read-RMBoolean -UserMessage "Update target IP address" -DefaultValue $false $TargetIPAddress = $Migration.target.ip if ($UpdateTargetIPAddress) { $TargetIPAddress = Read-RMIPAddress -UserMessage "Enter new target IP address" -ParameterName "Target IP Address" ` -DefaultValue "$TargetIPAddress" -IsRequired $false } $HashArguments = @{ Name = $Name OrganizationId = $OrganizationId ApplianceId = $Migration.cloud_appliance_id MigrationId = $Migration.id ShutdownSource = $ShutdownSource ShutdownTarget = $ShutdownTarget RemoveTargetAgent = $RemoveRMSAgent MigrationInstructions = $MigrationInstructions TargetProperties = $TargetProperties IgnoreValidationErrors = $IgnoreValidationErrors SourceUsername = $SourceUserName SourcePrivateKey = $SourcePrivateKey SourcePassword = $SourcePassword SourceDomain = $SourceDomain SourceHost = $Migration.source_hostname TargetUsername = $TargetUsername TargetPrivateKey = $TargetPrivateKey TargetPassword = $TargetPassword TargetDomain = $TargetDomain TargetHost = $Migration.target_hostname TargetIPAddress = $TargetIPAddress SourceId = $Migration.source_id TransferMethod = $TransferMethod } $Response = New-RMDifferentialProfile @HashArguments $ShouldExit = Start-RMDifferentialMigrationPreflight -DifferentialProfileId $Response.id -IgnoreValidationErrors $IgnoreValidationErrors -RMMigrationReturn $RMMigrationReturn if ($ShouldExit) { return $RMMigrationReturn } $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" $Uri = Get-Variable -Name "RMContext-ReactorURI" $Headers = @{ Accept = "application/rm+json" "X-Auth-Token" = $RMLoginResult.Value.token } $Params = @{ Method = "Post" Uri = $Uri.Value + "/differentialprofiles/" + $Response.id + "/migrations" Headers = $Headers ContentType = "application/json" } $MigrationResponse = Invoke-RMRestMethod -Params $Params $DifferentialMigrationId = Get-RMMigrationIdFromResponse -Response $MigrationResponse Write-Output "Differential migration started successfully, migration ID: $DifferentialMigrationId" | Out-Host $RMMigrationReturn.SetMigrationId($DifferentialMigrationId) $RMMigrationReturn.SetReturnCode([RMReturn]::SUCCESS) return $RMMigrationReturn } function Start-RMNonInteractiveDM { >>>>>>> CHANGE (4432f1 RM-19034: Bug fix for preflight.) param ( [string] $MigrationId, [bool] $IgnoreValidationErrors ) [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() $Errors, $IsValidMigrationId = Confirm-RMDMParameter -UserParameter $PSBoundParameters if (!$IsValidMigrationId) { $RMMigrationReturn.SetReturnCode([RMReturn]::ERROR) $Errors | ForEach-Object -Process {$RMMigrationReturn.AddRMError([RMError]::new($_))} Out-RMUserParameterResult -ErrorMessage $Errors return $RMMigrationReturn } $OrganizationId = Get-Variable -Name "RMContext-CurrentProjectId" -ValueOnly $Migration = $null $Migration = Get-RMMigrationByIdAndStatus -MigrationId $MigrationId $MigrationType = $Migration.migration_type $HeartbeatStatus = Test-RMApplianceHeartbeating -ApplianceId $Migration.cloud_appliance_id -AccountType $Migration.target_cloud_type if (!$HeartbeatStatus) { $Errors += "Migration appliance is not ready, cannot start differential migration" } if ("full" -ne $MigrationType) { $Errors += "Migration type for the given migration ID is '$MigrationType', differential migration can only be started for a full migration." } else { $SourceId = $Migration.source_id $MigrationList = Get-RMMigrationListBySourceId -OrganizationId $OrganizationId -SourceId $SourceId foreach ($Mig in $MigrationList) { if ("running" -eq $Mig.state) { $UserMessage = "Currently there is a migration running for the source of the given migration ID, this differential migration might fail." Write-Warning $UserMessage $RMMigrationReturn.AddRMWarning([RMWarning]::new($UserMessage)) Break; } } } if ($Errors.Count -gt 0) { $RMMigrationReturn.SetReturnCode([RMReturn]::ERROR) $Errors | ForEach-Object -Process {$RMMigrationReturn.AddRMError([RMError]::new($_))} Out-RMUserParameterResult -ErrorMessage $Errors return $RMMigrationReturn } $TransferType = $Migration.transfer_type $TargetProperties = $Migration.target.properties $MigrationInstructions = $Migration.migration_instructions $Name = "PowerShell - Differential Profile - " + [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds() $HashArguments = @{ Name = $Name OrganizationId = $OrganizationId Description = $Description ApplianceId = $Migration.cloud_appliance_id Schedule = $Schedule TransferMode = $TransferMode MigrationId = $Migration.id SourceId = $Migration.source_id Target = $Target Source = @{ "host" = $Migration.source_hostname } ShutdownSource = $false ShutdownTarget = $false RemoveTargetAgent = $false PublishMigrationHub = $false TransferType = $TransferType MigrationInstructions = $MigrationInstructions TargetProperties = $TargetProperties TargetIp = $Migration.target.ip IgnoreValidationErrors = $IgnoreValidationErrors } $Response = New-RMDifferentialProfile @HashArguments $ShouldExit = Start-RMDifferentialMigrationPreflight -DifferentialProfileId $Response.id ` -IgnoreValidationErrors $IgnoreValidationErrors -RMMigrationReturn $RMMigrationReturn if ($ShouldExit) { return $RMMigrationReturn } $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" $Uri = Get-Variable -Name "RMContext-ReactorURI" $Headers = @{ Accept = "application/rm+json" "X-Auth-Token" = $RMLoginResult.Value.token } $Params = @{ Method = "Post" Uri = $Uri.Value + "/differentialprofiles/" + $Response.id + "/migrations" Headers = $Headers ContentType = "application/json" } $MigrationResponse = Invoke-RMRestMethod -Params $Params $DifferentialMigrationId = Get-RMMigrationIdFromResponse -Response $MigrationResponse Write-Output "Differential migration started successfully, migration ID: $DifferentialMigrationId" | Out-Host $RMMigrationReturn.SetMigrationId($DifferentialMigrationId) $RMMigrationReturn.SetReturnCode([RMReturn]::SUCCESS) return $RMMigrationReturn } function Test-RMApplianceHeartbeating { param( [string] $ApplianceId, [string] $AccountType ) $HeartBeatingCloudAccounts, $NonHeartBeatingCloudAccounts = Get-RMCloudAccountsForCurrentProject -AccountType $AccountType foreach ($CloudAccount in $HeartBeatingCloudAccounts.Values) { if ($CloudAccount.appliance.id -eq $ApplianceId) { return $true } } return $false } function Confirm-RMDMParameter { param( [hashtable] $UserParameter ) $Errors = @() $IsValidMigrationId = $true if (!$UserParameter.ContainsKey("MigrationId") -or [string]::IsNullOrEmpty($UserParameter["MigrationId"])) { $Errors += "MigrationId is required" $IsValidMigrationId = $false } return $Errors, $IsValidMigrationId } |