Migration/GCP/GCP.psm1
Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath MigrationProfile | Join-Path -ChildPath GCPMigrationProfile) 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 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 Common | Join-Path -ChildPath Common) 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 Wrappers | Join-Path -ChildPath Wrappers) Import-Module -Name @(Join-Path $PSScriptRoot GCPUtil) function Start-RMGCPOSBasedInteractiveMigration { param() $UserInput = @{} $CloudAccount = Read-RMCloudAccount -AccountType "gcp" -UserMessage "Enter target cloud" $UserInput.Add("CloudAccount", $CloudAccount) $CloudAttributes = Get-RMCloudAttribute -CloudAccount $CloudAccount $Entitlement = Get-RMEntitlement $UserInput.Add("Entitlement", $Entitlement) $CloudAttributesSummary = Get-CloudAttributesSummary -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 "gcp" if ($ShouldExit) { return $RMMigrationReturn } $UserInput.Add("Source", $Source) 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.hostname ` -ParameterName "Target VM Name" -IsRequired $false $UserInput.Add("TargetVMName", $TargetVMName) $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) $ReadValue = Read-RMBoolean -UserMessage "Resize mount points" -DefaultValue "false" $MountsResize = @{} $TransferMethod = "file-based" if ($ReadValue) { $MountsResize = Get-RMInteractiveMountsResize -SelectedMountPoints $SelectedMountPoint -Source $Source } else { $TransferMethod = (Get-RMTransferMethod -Source $Source -SelectedMountPoints $SelectedMountPoint -IsInteractive $true)[0] } $UserInput.Add("ResizeMountPoint", $MountsResize) $UserInput.Add("TransferMethod", $TransferMethod) $ProjectMapping = Get-RMProjectIDToNameMapping -CloudAttribute $CloudAttributesSummary $DefaultProject = "" if ($ProjectMapping.ContainsKey($CloudAccount.appliance.cloud_properties.project_id)) { $DefaultProject = $ProjectMapping[$CloudAccount.appliance.cloud_properties.project_id] } $ProjectName = Read-RMString -UserMessage "Enter project name" -DefaultValue $DefaultProject -Options $ProjectMapping.values ` -ParameterName "Project Name" -IsRequired $false $ProjectId = ($ProjectMapping.GetEnumerator() | Where-Object {$_.Value -ieq $ProjectName}).Key $UserInput.Add("ProjectId", $ProjectId) $RegionsAndZones = Get-RMCloudAttributesByProjectId -CloudAccount $CloudAccount -ProjectId $ProjectId $RegionAndZoneMapping = Get-RMRegionToZonesMapping -RegionAndZone $RegionsAndZones.properties.projects[0].regions $Region = Read-RMString -UserMessage "Enter region name" -DefaultValue $CloudAccount.appliance.cloud_properties.region -Options $RegionAndZoneMapping.Keys ` -ParameterName "Region Name" -IsRequired $false $UserInput.Add("Region", $Region) $Zone = "" if ($Region -ieq $CloudAccount.appliance.cloud_properties.region) { $Zone = Read-RMString -UserMessage "Enter zone name" -DefaultValue $CloudAccount.appliance.cloud_properties.az ` -Options $RegionAndZoneMapping[$Region] -ParameterName "Zone Name" -IsRequired $false } else { $Zone = Read-RMString -UserMessage "Enter zone name" -Options $RegionAndZoneMapping[$Region] ` -ParameterName "Zone Name" -IsRequired $true } $UserInput.Add("Zone", $Zone) $DefaultNetworkName = $CloudAccount.appliance.cloud_properties.network.interfaces.eth0.network_name if ($Region -ine $CloudAccount.appliance.cloud_properties.region -or ` $Zone -ine $CloudAccount.appliance.cloud_properties.az -or ` $ProjectId -ine $CloudAccount.appliance.cloud_properties.project_id) { $CloudAttributes = Get-RMCloudAttributesByProjectIdAndRegionAndZone -CloudAccount $CloudAccount ` -ProjectId $ProjectId -Region $Region -Zone $Zone $DefaultNetworkName = "" } $UserInput.Add("NodeGroupName", (Read-RMNodeGroupName -CloudAttribute $CloudAttributes)) $UserInput.Add("MachineType", (Read-RMMachineType -CloudAttribute $CloudAttributes)) $UserInput.Add("DiskType", (Get-RMDiskTypeBySource -Source $Source -IsInteractive $true)) $ReadValue = Read-RMPair -UserMessage "Enter one or more instance labels in the format 'key=value' and separated by commas" ` -Separator "=" -DefaultValue "None" $UserInput.Add("InstanceLabel", (Get-RMStringAsHashtable -InputString $ReadValue)) $NetworksWithSubnets = Get-RMNetworkToSubnetMapping -CloudAttribute $CloudAttributes $DestinationNetworkName = "" if ([string]::IsNullOrWhiteSpace($DefaultNetworkName)) { $DestinationNetworkName = Read-RMString -UserMessage "Enter destination network name" ` -Options $NetworksWithSubnets.keys -ParameterName "Destination Network Name" -IsRequired $true } else { $DestinationNetworkName = Read-RMString -UserMessage "Enter destination network name" ` -Options $NetworksWithSubnets.keys -DefaultValue $DefaultNetworkName ` -ParameterName "Destination Network Name" -IsRequired $false } $UserInput.Add("DestinationNetworkName", (Get-RMNetworkNameByUserInput -NetworkName $DestinationNetworkName)) if ($null -eq $NetworksWithSubnets) { Throw "No networks were found, please check if the networks exist in the selected project, region and zone" } $DefaultSubnetName = "" if ($DestinationNetworkName -ieq $CloudAccount.appliance.cloud_properties.network.interfaces.eth0.network_name) { $DefaultSubnetName = $CloudAccount.appliance.cloud_properties.network.interfaces.eth0.internal_subnet_id } $SubnetNames = Get-RMSubnetNameByNetworkName -NetworkName $DestinationNetworkName -NetworkToSubnetMapping $NetworksWithSubnets if ([string]::IsNullOrWhiteSpace($DefaultSubnetName)) { $SubnetName = Read-RMString -UserMessage "Enter subnet name" -Options $SubnetNames ` -ParameterName "Subnet Name" -IsRequired $true } else { $SubnetName = Read-RMString -UserMessage "Enter subnet name" -DefaultValue $DefaultSubnetName ` -Options $SubnetNames -ParameterName "Subnet Name" -IsRequired $false } $UserInput.Add("SubnetName", $SubnetName) $IPType = "Ephemeral_Automatic" $IPtype = Read-RMString -UserMessage "Enter primary internal IP type" -Options "Ephemeral_Automatic", "Ephemeral_Custom" ` -DefaultValue "Ephemeral_Automatic" -ParameterName "Primary Internal IP" -IsRequired $false if ($IPtype -ieq "Ephemeral_Custom") { $UserInput.Add("CustomPrimaryInternalIPType", $true) #TODO: validate that the given IP address is in subnet's cidr block $PrimaryInternalIP = Read-RMIPAddress -UserMessage "Enter custom Ephemeral IP address" -IsRequired $true ` -ParameterName "Custom Ephemeral IP Address" $UserInput.Add("PrimaryInternalIP", $PrimaryInternalIP) } $ReadValue = Read-RMString -UserMessage "Do you want to assign external IP address to the target machine" ` -Options "None", "Automatic" -DefaultValue "None" -ParameterName "External IP Address" -IsRequired $false if ($ReadValue -ieq "Automatic") { $UserInput.Add("AssignPublicIP", $true) } $UserInput.Add("NetworkTier", (Read-RMString -UserMessage "Enter network tier" -Options "Premium", "Standard" ` -DefaultValue "Premium" -ParameterName "Network Tier" -IsRequired $false).ToUpper()) $DisableTargetDNSRegistration = $false if ("windows" -ieq $Source.os_type) { $DisableTargetDNSRegistration = Read-RMBoolean -UserMessage "Disable automatic DNS registration on the target" -DefaultValue "false" } $UserInput.Add("DisableAutomaticDNSRegistrationOnTheTarget", $DisableTargetDNSRegistration) $UserInput.Add("EnableSerialPortAccess", (Read-RMBoolean -UserMessage "Enable remote access through serial port" -DefaultValue "false")) $UserInput.Add("AllowHTTPTraffic", (Read-RMBoolean -UserMessage "Allow HTTP traffic through firewalls" -DefaultValue "false")) $UserInput.Add("AllowHTTPSTraffic", (Read-RMBoolean -UserMessage "Allow HTTPS traffic through firewalls" -DefaultValue "false")) $EnforceTargetNetworkIsolation = Read-RMBoolean -UserMessage "Enforce target network isolation" -DefaultValue "true" if (!$EnforceTargetNetworkIsolation) { $NetworkNameToNetworkTagsMapping = Get-RMNetworkNameToNetworkTagsMapping -CloudAttribute $CloudAttributes $NetworkTagOptions = $NetworkNameToNetworkTagsMapping[$DestinationNetworkName] $NetworkTagOptions += "rivermeadow-tw" $NetworkTags = @() $DefaultValue = "" if ("windows" -ieq $Source.os_type) { $NetworkTagOptions += "rivermeadow-ft-windows" $DefaultValue = "rivermeadow-tw, rivermeadow-ft-windows" } else { $NetworkTagOptions += "rivermeadow-agent", "rivermeadow-ft-linux" $DefaultValue = "rivermeadow-tw, rivermeadow-agent, rivermeadow-ft-linux" } $NetworkTags = Read-RMToken -UserMessage "Enter one or more network tags separated by commas" ` -Options $NetworkTagOptions -DefaultValue $DefaultValue -Separator "," ` -ParameterName "Network Tags" -IsRequired $false if ($NetworkTags -is [string]) { $NetworkTags = @($NetworkTags.split(",").Trim()) } if ("linux" -ieq $Source.os_type -and $NetworkTags -notcontains "rivermeadow-agent") { $NetworkTags += "rivermeadow-agent" } if ($NetworkTags -notcontains "rivermeadow-tw") { $NetworkTags += "rivermeadow-tw" } $UserInput.Add("NetworkTag", $NetworkTags) } $UserInput.Add("EnforceTargetNetworkIsolation", $EnforceTargetNetworkIsolation) $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")) $LinuxOSLicensing = $true $WindowsOSLicensing = $false if ("linux" -ieq $Source.os_type) { $LinuxOSLicensing = Read-RMBoolean -UserMessage "Premium OS licensing" -DefaultValue "true" } else { $WindowsOSLicensing = Read-RMBoolean -UserMessage "Bring your own OS license" -DefaultValue "false" } if (!$LinuxOSLicensing -or $WindowsOSLicensing) { $UserInput.Add("OSBYOL", "byol") } else { $UserInput.Add("OSBYOL", "") } if ("windows" -ieq $Source.os_type) { $SQLLicenses = Get-RMSQLLicenseMapping $SQLLicense = Read-RMString -UserMessage "Enter SQL license" -Options $SQLLicenses.Keys ` -DefaultValue "None" -IsRequired $false -ParameterName "SQL License" $UserInput.Add("SQLLicense", $SQLLicenses[$SQLLicense]) } else { $UserInput.Add("SQLLicense", "") } $OSMUpgradeUserInput = @{} Read-RMOSMUpgradeOption -Source $Source -UpdatedUserInput $OSMUpgradeUserInput $UserInput.Add("UpgradeOSVersion", $OSMUpgradeUserInput["UpgradeOSVersion"]) $UserInput.Add("InPlaceUpgrade", $OSMUpgradeUserInput["InPlaceUpgrade"]) $UserInput.Add("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" if (($IgnoreValidationErrors -and $OverrideExistingMigrationError) -or ` (!$IgnoreValidationErrors -and $OverrideExistingMigrationError) -or ` $OverrideExistingMigrationWarning) { if ([string]::IsNullOrWhiteSpace($ReadValue)) { $ReadValue = "override_source_migration=true" } else { $ReadValue += ",override_source_migration=true" } } $MigrationInstructions = Get-RMStringAsHashtable -InputString $ReadValue $UserInput.Add("MigrationInstruction", $MigrationInstructions) $Response = New-RMGCPMigrationProfile @UserInput $ShouldExit = Start-RMMigrationPreflight -MigrationProfileId $Response.id ` -IgnoreValidationErrors $IgnoreValidationErrors -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" } |