Migration/vSphere/vSphere.psm1
Import-Module -Name $PSScriptRoot\..\..\MigrationProfile\VSphereMigrationProfile Import-Module -Name $PSScriptRoot\..\..\DifferentialProfile\DifferentialProfile Import-Module -Name $PSScriptRoot\..\..\Preflight\Preflight Import-Module -Name $PSScriptRoot\..\..\Util\Util Import-Module -Name $PSScriptRoot\..\..\CloudAccount\CloudAccount Import-Module -Name $PSScriptRoot\..\..\RiverMeadow.Source\SourceUtil\SourceUtil Import-Module -Name $PSScriptRoot\..\..\Validate\Validate function Start-RMNonInteractiveVsphereOsBasedMigration { param ( [string] $CloudAccountName, [string] $SourceIP, [bool] $RefreshSourceAttributes, [string] $TargetVMName, [string[]] $MountPoints, [string[]] $ResizeMountPoints, [string] $TransferMethod, [string] $CoresPerSocket, [bool] $OverrideMemory, [int] $OverrideMemorySize, [string] $DatacenterName, [bool] $EnableDestinationNetworkIsolation, [string] $DestinationNetworkName, [string] $IpType, [string] $IpAddress, [string] $Netmask, [string] $DefaultGateway, [string] $PrimaryDNS, [string] $SecondaryDNS, [string] $IsolatedNetworkName, [string] $IsolatedIpType, [string] $IsolatedIpAddress, [string] $IsolatedNetmask, [string] $IsolatedDefaultGateway, [string] $IsolatedPrimaryDNS, [string] $IsolatedSecondaryDNS, [bool] $DisableAuthomaticDNSRegistrationOnTheTarget, [string] $Cluster, [string] $ResourcePool, [string] $FolderName, [string] $DatastoreCluster, [string[]] $DatastoreNames, [string[]] $DiskProvisioningTypes, [string] $HardwareVersion, [bool] $ShutdownSource, [bool] $ShutdownTarget, [bool] $RemoveRMSAgent, [hashtable] $MigrationInstructions, [string] $UpgradeOSVersion ) $Entitlement = Get-RMEntitlement $UserInput = @{} $CloudAccount = Get-RMCloudAccountByName -CloudAccountName $CloudAccountName if ($null -eq $CloudAccount) { $ProjectName = Get-Variable -Name "RMContext-CurrentProjectName" -ValueOnly $OrgName = Get-Variable -Name "RMContext-CurrentOrganizationName" -ValueOnly throw "Cloud account '$CloudAccountName' does not exist in current project '$ProjectName' of organization '$OrgName'" } $UserInput.Add("CloudAccount", $CloudAccount) $UserInput.Add("Entitlement", $Entitlement) $Source = $null if ("" -eq $SourceIP) { throw "Source IP address is required to start a migration." } else { $Source = Get-RMSourceWithAttribute -IPAddress $SourceIP -RefreshSourceAttributes $RefreshSourceAttributes -CloudAccount $CloudAccount } $UserInput.Add("Source", $Source) if ("" -eq $TargetVMName) { throw "Target VM name is required." } $UserInput.Add("TargetVMName", $TargetVMName) $SourceMountPoints = Get-MountPoint -Source $Source Compare-RMMountPoint -Source $Source -SourceMountPoints $SourceMountPoints -UserInputMountPoints $MountPoints $SelectedMountPoints = Get-RMSelectedMount -MountPoints $SourceMountPoints -DifferenceList $MountPoints -IncludeEqual $true $UserInput.Add("SelectedMounts", $SelectedMountPoints) $MountsResize = @{} if (![string]::IsNullOrEmpty($ResizeMountPoints)) { $MountsResize = Get-RMResizeMountsPoint -ResizeMountPoints $ResizeMountPoints -SelectedMountPoints $SelectedMountPoints -Source $Source if ("" -ne $TransferMethod -and "block-based" -eq $TransferMethod ) { throw "Transfer method needs to be 'file-based' if you want to resize the mount points." } else { $TransferMethod = "file-based" } } elseif ("" -eq $TransferMethod) { $TransferMethod = Get-TransferType -Source $Source } $UserInput.Add("MountsResize", $MountsResize) $UserInput.Add("TransferType", $TransferMethod) if ("" -eq $CoresPerSocket) { $CoresPerSocket = 1 } $UserInput.Add("CoresPerSocket", $CoresPerSocket) if ("" -ne $OverrideMemory -and $OverrideMemory) { if (0 -eq $OverrideMemorySize ) { throw "Override memory size is required" } } $UserInput.Add("OverrideMemory", $OverrideMemory) $UserInput.Add("OverrideMemorySize", $OverrideMemorySize) if ($Source.os_type -eq "windows") { $UserInput.Add("DisableAuthomaticDNSRegistrationOnTheTarget", $DisableAuthomaticDNSRegistrationOnTheTarget) } else { $UserInput.Add("DisableAuthomaticDNSRegistrationOnTheTarget", $false) } if ("" -eq $DatacenterName) { throw "Datacenter Name is required, please provide the datacenter name." } $UserInput.Add("DatacenterName", $DatacenterName) $UserInput.Add("EnableDestinationNetworkIsolation", $EnableDestinationNetworkIsolation) if ($Source.os_type -eq "windows" -and "" -ne $EnableDestinationNetworkIsolation -and $EnableDestinationNetworkIsolation) { if ([string]::IsNullOrEmpty($IpType)) { $IpType = "dhcp" } else { $IpType = $IpType.ToLower() } $UserInput.Add("IpType", $IpType) if ($IpType -eq "static") { if ([string]::IsNullOrEmpty($IpAddress)) { throw "IP Address is required." } $UserInput.Add("IpAddress", $IpAddress) if ([string]::IsNullOrEmpty($Netmask)) { throw "Netmask is required." } $UserInput.Add("Netmask", $Netmask) if ([string]::IsNullOrEmpty($DefaultGateway)) { throw "Default gateway is required." } $UserInput.Add("DefaultGateway", $DefaultGateway) if ([string]::IsNullOrEmpty($PrimaryDNS)) { throw "Primary DNS is required." } $UserInput.Add("PrimaryDNS", $PrimaryDNS) $UserInput.Add("SecondaryDNS", $SecondaryDNS) } $DestinationNetworkName, $DvSwitchName = Get-DestinationNetworkAndDvSwitchName -DestinationNetworkName $DestinationNetworkName -IsInteractive $false $UserInput.Add("DestinationNetworkName", $DestinationNetworkName) $UserInput.Add("DvSwitchName", $DvSwitchName) if ([string]::IsNullOrEmpty($IsolatedNetworkName)) { throw "Isolated network name is required." } [string[]] $networkNames = $IsolatedNetworkName -split "/" if ($networkNames.Count -eq 2) { $IsolatedNetworkName = $networkNames[1] $IsolatedDvSwitchName = $networkNames[0] } $UserInput.Add("IsolatedNetworkName", $IsolatedNetworkName) $UserInput.Add("IsolatedDvSwitchName", $IsolatedDvSwitchName) if ([string]::IsNullOrEmpty($IsolatedIpType)) { $IsolatedIpType = "dhcp" } else { $IsolatedIpType = $IsolatedIpType.ToLower() } $UserInput.Add("IsolatedIpType", $IsolatedIpType) if ($IsolatedIpType -eq "static") { if ([string]::IsNullOrEmpty($IsolatedIpAddress)) { throw "Isolated network IP Address is required." } $UserInput.Add("IsolatedIpAddress", $IsolatedIpAddress) if ([string]::IsNullOrEmpty($IsolatedNetmask)) { throw "Isolated network netmask is required." } $UserInput.Add("IsolatedNetmask", $IsolatedNetmask) if ([string]::IsNullOrEmpty($IsolatedDefaultGateway)) { throw "Isolated network default gateway is required." } $UserInput.Add("IsolatedDefaultGateway", $IsolatedDefaultGateway) if ([string]::IsNullOrEmpty($IsolatedPrimaryDNS)) { throw "Isolated network primary DNS is required." } $UserInput.Add("IsolatedPrimaryDNS", $IsolatedPrimaryDNS) $UserInput.Add("IsolatedSecondaryDNS", $IsolatedSecondaryDNS) } } else { $DestinationNetworkName, $DvSwitchName = Get-DestinationNetworkAndDvSwitchName -DestinationNetworkName $DestinationNetworkName -IsInteractive $false $UserInput.Add("DestinationNetworkName", $DestinationNetworkName) $UserInput.Add("DvSwitchName", $DvSwitchName) if ([string]::IsNullOrEmpty($IpType)) { $IpType = "dhcp" } else { $IpType = $IpType.ToLower() } $UserInput.Add("IpType", $IpType) if ($IpType -eq "static") { if ([string]::IsNullOrEmpty($IpAddress)) { throw " IP Address is required." } $UserInput.Add("IpAddress", $IpAddress) if ([string]::IsNullOrEmpty($Netmask)) { throw "Netmask is required." } $UserInput.Add("Netmask", $Netmask) if ([string]::IsNullOrEmpty($DefaultGateway)) { throw "Default gateway is required." } $UserInput.Add("DefaultGateway", $DefaultGateway) if ([string]::IsNullOrEmpty($PrimaryDNS)) { throw "Primary DNS is required." } $UserInput.Add("PrimaryDNS", $PrimaryDNS) $UserInput.Add("SecondaryDNS", $SecondaryDNS) } } if ([string]::IsNullOrEmpty($Cluster)) { throw "Cluster name is required" } $UserInput.Add("Cluster", $Cluster) $UserInput.Add("ResourcePool", $ResourcePool) $UserInput.Add("FolderName", $FolderName) $UserInput.Add("DatastoreCluster", $DatastoreCluster) if ($DatastoreNames.Count -ne $Source.attributes.storage.disks.psobject.Properties.Value.Count) { Throw "The number of datastore names given are '" + $DatastoreNames.Count + "' but source has '" + $Source.attributes.storage.disks.psobject.Properties.Value.Count +"' disks" } $DiskProvisioningTypes = Get-DiskProvisioningTypeBySource -Source $Source -DiskProvisioningTypes $DiskProvisioningTypes -IsInteractive $false $UserInput.Add("DatastoreLocations", $DatastoreNames) $UserInput.Add("DisksProvisioningType", $DiskProvisioningTypes) if ([string]::IsNullOrEmpty($HardwareVersion)) { $HardwareVersion = Get-Hardware-Version -CloudAccount $CloudAccount } $UserInput.Add("HardwareVersion", $HardwareVersion) $ToolsPackage = Get-Tools-Package -CloudAccount $CloudAccount -HardwareVersion $HardwareVersion $UserInput.Add("ToolsPackage", $ToolsPackage) if ("" -eq $MigrationInstructions) { $MigrationInstructions = @{} } $UserInput.Add("MigrationInstructions", $MigrationInstructions) $UserInput.Add("ShutdownSource", $ShutdownSource) $UserInput.Add("ShutdownTarget", $ShutdownTarget) $UserInput.Add("RemoveRMSAgent", $RemoveRMSAgent) if ("" -ne $UpgradeOSVersion) { $SourceOSMMapping = Get-RMOSMMappingBySource -Source $Source $OSMLabels = $SourceOSMMapping.keys -join ", " $UpgradeOSVersion = $UpgradeOSVersion.Trim('"') $UpgradeOSVersion = $UpgradeOSVersion.Trim("'") if ($SourceOSMMapping.keys -notcontains $UpgradeOSVersion) { throw "Please enter one of '$OSMLabels' and try again" } $UserInput.Add("UpgradeOSVersion", $SourceOSMMapping[$UpgradeOSVersion]) $UserInput.Add("InPlaceUpgrade", $true) } else { $UserInput.Add("UpgradeOSVersion", $null) $UserInput.Add("InPlaceUpgrade", $false) } $Valid = Confirm-RMVSphereValidateOSBasedMigrationProfile @UserInput if (!$Valid) { return } $UserInput["DisksProvisioningType"] = Update-DiskProvisioningTypeForME -DiskProvisioningTypes $UserInput["DisksProvisioningType"] $Response = New-RMVSphereMigrationProfile @UserInput $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 + "/migrationprofiles/" + $Response.id + "/migrations" Headers = $Headers ContentType = "application/json" } $Response = Invoke-RMRestMethod -Params $Params Out-MigrationIdFromResponse -Response $Response } function Start-RMInteractiveVSphereOSBasedMigration { param( ) $Entitlement = Get-RMEntitlement $CloudAccountName = Read-Host "Enter cloud account name" $CloudAccount = Get-RMCloudAccountByName -CloudAccountName $CloudAccountName if ($null -eq $CloudAccount) { $ProjectName = Get-Variable -Name "RMContext-CurrentProjectName" -ValueOnly $OrgName = Get-Variable -Name "RMContext-CurrentOrganizationName" -ValueOnly throw "Cloud account '$CloudAccountName' does not exist in current project '$ProjectName' of organization '$OrgName'" } $Source = $null $SourceIP = Read-Host "Enter the IP address of the source machine to be migrated" if ("" -eq $SourceIP) { throw "Source IP address is required to start a migration." } $RefreshSourceAttributes = $false $ReadValue = Read-Host "Refresh source attributes (true/false)[false]" if ("" -ne $ReadValue) { $RefreshSourceAttributes = [System.Convert]::ToBoolean($ReadValue) } $Source = Get-RMSourceWithAttribute -IPAddress $SourceIP -RefreshSourceAttributes $RefreshSourceAttributes -CloudAccount $CloudAccount $TargetInventory = Get-RMTargetInventory -CloudAccount $CloudAccount $TargetVMName = Read-Host "Enter target VM Name" $MountPoints = Get-MountPoint -Source $Source if (0 -eq $MountPoints.count) { Write-Error "Source has no mount points, cannot be migrated" return } $MountPointsAsString = $MountPoints.values -join ", " Write-Output "Mount points to be migrated [$MountPointsAsString]" | Out-Host $ExcludedMountPoints = Get-RMExcludedMountPoint -Source $Source $SelectedMountPoints = $MountPoints if ("" -ne $ExcludedMountPoints) { $ExcludedList = $ExcludedMountPoints.Split(",").Trim() $SelectedMountPoints = Get-RMSelectedMount -MountPoints $MountPoints -DifferenceList $ExcludedList -IncludeEqual $false } $ReadValue = Read-Host "Resize mount points (true/false) [false]" $MountsResize = @{} $ResizeMountsBool = $false if ("" -ne $ReadValue) { $ReadValue = [System.Convert]::ToBoolean($ReadValue) if ($ReadValue) { $ResizeMountsBool = $true $MountsResize = Get-RMInteractiveMountsResize -SelectedMountPoints $SelectedMountPoints -Source $Source } } if (!$ResizeMountsBool) { $TransferType = Get-TransferType -Source $Source $ReadValue = Read-Host "Enter transfer type (file-based/block-based)[$TransferType]" if ("" -ne $ReadValue) { $TransferType = $ReadValue } } else { $TransferType = "file-based" } $CoresPerSocket = 1 $ReadValue = Read-Host "Enter cores per socket (1,2)[1]" if ("" -ne $ReadValue) { if (!($ReadValue -eq "1" -or $ReadValue -eq "2")) { Throw "Cores per socket can be 1 or 2" } $CoresPerSocket = $ReadValue } $OverrideMemory = $false $ReadValue = Read-Host "Override memory (true/false)[false]" if ("" -ne $ReadValue) { $OverrideMemory = [System.Convert]::ToBoolean($ReadValue) if ($OverrideMemory) { $OverrideMemorySize = Read-Host "Enter the memory in GB" } } $DatacenterNames = Get-DatacenterList -TargetInventory $TargetInventory $DatecenterNamesAsString = $DatacenterNames -join ", " $DatacenterName = Read-Host "Enter datacenter name ($DatecenterNamesAsString)" if ("" -eq $DatacenterName) { Throw "Datacenter name is required" } elseif (!($DatacenterName -in $DatacenterNames)) { Throw "Datacenter '$DatacenterName' does not exists." } $NetworkNames = Get-NetworkName -TargetInventory $TargetInventory -datacenterName $DatacenterName $NetworkNamesAsString = $NetworkNames -join ", " $EnableDestinationNetworkIsolation = $false if ($Source.os_type -eq "windows") { $ReadValue = Read-Host "Enable Destination network isolation (true/false)[false]" if ("" -ne $ReadValue) { $EnableDestinationNetworkIsolation = [System.Convert]::ToBoolean($ReadValue) if ($EnableDestinationNetworkIsolation) { $IpType, $IpAddress, $Netmask, $DefaultGateway, $PrimaryDNS, $SecondaryDNS = Get-MigrationNetworkIPConfig $DestinationNetworkName, $DvSwitchName = Get-DestinationNetworkAndDvSwitchName -NetworkNames $NetworkNames -NetworkNamesAsString $NetworkNamesAsString -IsInteractive $true $IsolatedNetworkName = Read-Host "Enter isolated network name ($NetworkNamesAsString)" if ("" -eq $IsolatedNetworkName) { Throw "Isolated network name is required" } elseif(!($IsolatedNetworkName -in $NetworkNames)) { Throw "Isolated network name '$IsolatedNetworkName' does not exists." } [string[]] $networkNamesArray = $IsolatedNetworkName -split "/" if ($networkNamesArray.Count -eq 2) { $IsolatedNetworkName = $networkNamesArray[1] $IsolatedDvSwitchName = $networkNamesArray[0] } $IsolatedIpType = "dhcp" $ReadValue = Read-Host "Enter isolated IP type (static/DHCP)[DHCP]" if ("" -ne $ReadValue) { if (!($ReadValue -ieq "static" -or $ReadValue -ieq "DHCP")) { Throw "IP type can be 'static' or 'DHCP'" } $IpType = $ReadValue.ToLower() } if ($ReadValue -ieq "static") { $IsolatedIpType = $ReadValue $IsolatedIpAddress = Read-Host "Enter isolated IP address" $IsolatedNetmask = Read-Host "Enter isolated netmask" $IsolatedDefaultGateway = Read-Host "Enter isolated default gateway" $IsolatedPrimaryDNS = Read-Host "Enter isolated primary DNS" $IsolatedSecondaryDNS = Read-Host "Enter isolated Secondary DNS" } } else { $IpType, $IpAddress, $Netmask, $DefaultGateway, $PrimaryDNS, $SecondaryDNS = Get-MigrationNetworkIPConfig $DestinationNetworkName, $DvSwitchName = Get-DestinationNetworkAndDvSwitchName -NetworkNames $NetworkNames -NetworkNamesAsString $NetworkNamesAsString -IsInteractive $true } } else { $IpType, $IpAddress, $Netmask, $DefaultGateway, $PrimaryDNS, $SecondaryDNS = Get-MigrationNetworkIPConfig $DestinationNetworkName, $DvSwitchName = Get-DestinationNetworkAndDvSwitchName -NetworkNames $NetworkNames -NetworkNamesAsString $NetworkNamesAsString -IsInteractive $true } } else { $IpType, $IpAddress, $Netmask, $DefaultGateway, $PrimaryDNS, $SecondaryDNS = Get-MigrationNetworkIPConfig $DestinationNetworkName, $DvSwitchName = Get-DestinationNetworkAndDvSwitchName -NetworkNames $NetworkNames -NetworkNamesAsString $NetworkNamesAsString -IsInteractive $true } if ($Source.os_type -eq "windows") { $DisableAuthomaticDNSRegistrationOnTheTarget = $false $ReadValue = Read-Host "Disable automatic DNS registration on the Target (true/false)[false]" if ("" -ne $ReadValue) { $DisableAuthomaticDNSRegistrationOnTheTarget = [System.Convert]::ToBoolean($ReadValue) } } else { $DisableAuthomaticDNSRegistrationOnTheTarget = $false } $Clusters = Get-Cluster -TargetInventory $TargetInventory -datacenterName $DatacenterName $ClustersAsString = $Clusters -join ", " $Cluster = Read-Host "Enter cluster name ($ClustersAsString)" if ("" -eq $Cluster) { Throw "Cluster name is required" } elseif(!($Cluster -in $Clusters)) { Throw "Cluster '$Cluster' does not exists." } $ResourcePool = Read-Host "Enter resource pool [None]" $FolderName = Read-Host "Enter VM folder name [None]" $DatastoreClusters = Get-Datastore-Cluster -TargetInventory $TargetInventory -datacenterName $DatacenterName $DatastoreClustersAsString = $DatastoreClusters -join ", " $ReadValue = Read-Host "Enter datastore cluster ($DatastoreClustersAsString)[None]" if ("" -ne $ReadValue) { if (!($ReadValue -in $DatastoreClusters)) { Throw "Datastore cluster '$ReadValue' does not exists." } $DatastoreCluster = $ReadValue } $Datastores = Get-Datastore -TargetInventory $TargetInventory -datacenterName $DatacenterName $SelectedDatastores = Get-DatastoreBySource -Source $Source -TargetDatastores $Datastores -IsInteractive $true $SelectedProvisioningTypes = Get-DiskProvisioningTypeBySource -Source $Source -IsInteractive $true $HardwareVersions = Get-Hardware-Version -CloudAccount $CloudAccount $HardwareVersion = Read-Host "Enter VM hardware version [$HardwareVersions]" if ("" -eq $HardwareVersion) { $HardwareVersion = $HardwareVersions } $ShutdownSource = $false $ReadValue = Read-Host "Shutdown source after data is fully migrated (true/false)[false]" if ("" -ne $ReadValue) { $ShutdownSource = [System.Convert]::ToBoolean($ReadValue) } $ShutdownTarget = $false $ReadValue = Read-Host "Shutdown target after data is fully migrated (true/false)[false]" if ("" -ne $ReadValue) { $ShutdownTarget = [System.Convert]::ToBoolean($ReadValue) } $SourceOSMMapping = Get-RMOSMMappingBySource -Source $Source $OSMLabels = $SourceOSMMapping.keys -join ", " $ReadValue = Read-Host "Enter the OS version to upgrade to ($OSMLabels)[None]" if ("" -ne $ReadValue) { $ReadValue = $ReadValue.Trim('"') $ReadValue = $ReadValue.Trim("'") if ($SourceOSMMapping.keys -notcontains $ReadValue) { throw "Please enter one of $OSMLabels and try again" } $UpgradeOSVersion = $SourceOSMMapping[$ReadValue] $InPlaceUpgrade = $true } else { $UpgradeOSVersion = $null $InPlaceUpgrade = $false } $RemoveRMSAgent = $false $ReadValue = Read-Host "Remove RMS agent post migration (true/false)[false]" if ("" -ne $ReadValue) { $RemoveRMSAgent = [System.Convert]::ToBoolean($ReadValue) } $ReadValue = Read-Host "Enter migration instructions in the format 'key/value' and separated by commas [None]" $MigrationInstructions = Get-RMStringAsHashtable -InputString $ReadValue $ToolsPackage = Get-Tools-Package -CloudAccount $CloudAccount -HardwareVersion $HardwareVersion $HashArguments = @{ CloudAccount = $CloudAccount Entitlement = $Entitlement Source = $Source TargetVMName = $TargetVMName SelectedMounts = $SelectedMountPoints MountsResize = $MountsResize ShutdownSource = $ShutdownSource ShutdownTarget = $ShutdownTarget RemoveRMSAgent = $RemoveRMSAgent DatacenterName = $DatacenterName EnableDestinationNetworkIsolation = $EnableDestinationNetworkIsolation DestinationNetworkName = $DestinationNetworkName IpType = $IpType IpAddress = $IpAddress Netmask = $Netmask DefaultGateway = $DefaultGateway PrimaryDNS = $PrimaryDNS SecondaryDNS = $SecondaryDNS IsolatedNetworkName = $IsolatedNetworkName IsolatedDvSwitchName = $IsolatedDvSwitchName IsolatedIpType = $IsolatedIpType IsolatedIpAddress = $IsolatedIpAddress IsolatedNetmask = $IsolatedNetmask IsolatedDefaultGateway = $IsolatedDefaultGateway IsolatedPrimaryDNS = $IsolatedPrimaryDNS IsolatedSecondaryDNS = $IsolatedSecondaryDNS DvSwitchName = $DvSwitchName DisableAuthomaticDNSRegistrationOnTheTarget = $DisableAuthomaticDNSRegistrationOnTheTarget Cluster = $Cluster DatastoreCluster = $DatastoreCluster DatastoreLocations = $SelectedDatastores FolderName = $FolderName DisksProvisioningType = $SelectedProvisioningTypes TransferType = $TransferType CoresPerSocket = $CoresPerSocket OverrideMemory = $OverrideMemory OverrideMemorySize = $OverrideMemorySize ResourcePool = $ResourcePool HardwareVersion = $HardwareVersion ToolsPackage = $ToolsPackage MigrationInstructions = $MigrationInstructions UpgradeOSVersion = $UpgradeOSVersion InPlaceUpgrade = $InPlaceUpgrade } $Response = New-RMVSphereMigrationProfile @HashArguments $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 + "/migrationprofiles/" + $Response.id + "/migrations" Headers = $Headers ContentType = "application/json" } $MigrationResponse = Invoke-RMRestMethod -Params $Params Out-MigrationIdFromResponse -Response $MigrationResponse } function Start-RMVSphereOSBasedDifferentialMigration { param ( [string] $MigrationId ) Import-Module -Name $PSScriptRoot\..\..\DifferentialProfile\DifferentialProfile -Force $OrganizationId = Get-Variable -Name "RMContext-CurrentProjectId" -ValueOnly $Name = "PowerShell - Differential Profile - " + [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds() $Entitlement = Get-RMEntitlement $Migration = Get-Migration -MigrationId $MigrationId $MigrationProfile = Get-MigrationProfile -MigrationProfileId $Migration.migration_profile $Source = @{ "host" = $Migration.hostname } $TransferType = $Migration.transfer_type $TargetProperties = $Migration.target.properties $MigrationInstructions = $Migration.migration_instructions $HashArguments = @{ Name = $Name Entitlement = $Entitlement OrganizationId = $OrganizationId Description = $Description ApplianceId = $MigrationProfile.appliance_id Schedule = $Schedule TransferMode = $TransferMode MigrationId = $Migration.id SourceId = $Migration.source_id Target = $Target Source = $Source ShutdownSource = $false ShutdownTarget = $false RemoveTargetAgent = $false PublishMigrationHub = $false TransferType = $TransferType MigrationInstructions = $MigrationInstructions TargetProperties = $TargetProperties TargetIp = $Migration.target.ip } $Response = New-RMDifferentialProfile @HashArguments $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" } return Invoke-RMRestMethod -Params $Params |Out-Null } function Get-RMTargetInventory { param( [System.Object] $CloudAccount ) $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" $Uri = Get-Variable -Name "RMContext-ReactorURI" $Headers = @{ Accept = "application/rm+json" "X-Auth-Token" = $RMLoginResult.Value.token } $CollectList = New-Object Collections.Generic.List[string] $CollectList.Add("datacenter") $CollectList.Add("cluster") $CollectList.Add("datastore") $CollectList.Add("datastore_cluster") $CollectList.Add("resource_pool") $CollectList.Add("storage_profile") $CollectList.Add("vm_folder") $CollectList.Add("network") $Body = @{ "appliance_id" = $CloudAccount.appliance.id "organization_id" = $CloudAccount.organization_id "objects_to_collect" = $CollectList } | ConvertTo-Json $Params = @{ Method = "Post" Uri = $Uri.Value + "/targetinventories" Headers = $Headers Body = $Body ContentType = "application/json" } Write-Output "Starting target inventory..." | Out-Host $TargetInventory = Invoke-RMRestMethod -Param $Params return Watch-RMTargetInventoryStatus -TargetInventoryId $TargetInventory.id } function Get-DatacenterList { param( [System.Object] $TargetInventory ) $DatacenterNames = @() foreach ($datacenterName in $TargetInventory.attributes.vSphere.datacenters) { $DatacenterNames += $datacenterName.name } return $DatacenterNames } function Get-NetworkName { 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) } } } } return $NetworkNames } function Get-Cluster { param ( [System.Object] $TargetInventory, [string] $datacenterName ) $Clusters = @() foreach ($datacenter in $TargetInventory.attributes.vSphere.datacenters) { if ($datacenterName -eq $datacenter.name) { foreach($cluster in $datacenter.clusters) { $Clusters += $cluster.name } } } return $Clusters } function Get-Datastore-Cluster { 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 } } } return $DatastoreClusters } function Get-Datastore { param ( [System.Object] $TargetInventory, [string] $datacenterName ) $Datastores = @() foreach ($datacenter in $TargetInventory.attributes.vSphere.datacenters) { if ($datacenterName -eq $datacenter.name) { foreach($datastore in $datacenter.datastores) { $Datastores += $datastore.name } } } return $Datastores } function Get-Hardware-Version { param( [System.Object] $CloudAccount ) $HardwareVersions = @() $Version = $CloudAccount.vsphere_version switch ($Version) { "VMC" { $HardwareVersions += "19" } "GCVE" { $HardwareVersions += "18" } "ESXi_7_0" { $HardwareVersions += "17" } "ESXi_6_7_U3" { $HardwareVersions += "15" } "ESXi_6_7_U2" { $HardwareVersions += "15" } "ESXi_6_7" { $HardwareVersions += "14" } "ESXi_6_5" { $HardwareVersions += "13" } "ESXi_6_0" { $HardwareVersions += "11" } } return $HardwareVersions -join ", " } function Get-TransferType { param ( [System.Object] $Source ) $TransferType = "file-based" if ($Source.os_type -eq "windows") { $TransferType = "block-based" } else { if($Source.attributes.discovered_features.features_list -contains "linux_block_based") { $fs = @("ext2", "ext3", "ext4", "xfs") $check = $true foreach($Mount in $Source.attributes.storage.mounts.psobject.properties.value){ if ($Mount.nature -eq "disk") { if ($fs -notcontains $Mount.fs_type) { $check = $false; break } } } if ($check) { $TransferType = "block-based" } } } return $TransferType } function Get-Tools-Package { param ( [System.Object] $CloudAccount, [string] $HardwareVersion ) $Version = $CloudAccount.vsphere_version switch ($Version) { "VMC" { return "vmwaretools-10.3.10.tar.gz" } "GCVE" { return "vmwaretools-10.3.10.tar.gz" } "ESXi_7_0" { return "vmwaretools-10.3.10.tar.gz" } "ESXi_6_7_U3" { return "vmwaretools-10.3.5.tar.gz" } "ESXi_6_7_U2" { return "vmwaretools-10.3.5.tar.gz" } "ESXi_6_7" { return "vmwaretools-10.3.2.tar.gz" } "ESXi_6_5" { return "vmwaretools-10.1.0.tar.gz" } "ESXi_6_0" { return "vmwaretools-9.10.0.tar.gz" } } } function Get-MigrationNetworkIPConfig { $IpType = "dhcp" $ReadValue = Read-Host "Enter IP type (static/DHCP)[DHCP]" if ("" -ne $ReadValue) { if (!($ReadValue -ieq "static" -or $ReadValue -ieq "DHCP")) { Throw "IP type can be 'static' or 'DHCP'" } $IpType = $ReadValue.ToLower() } $IPAddress = "" $Netmask = "" $DefaultGateway = "" $PrimaryDNS = "" $SecondaryDNS = "" if ($IpType -ieq "static") { $IPAddress = Read-Host "Enter IP address" $Netmask = Read-Host "Enter netmask" $DefaultGateway = Read-Host "Enter default gateway" $PrimaryDNS = Read-Host "Enter primary DNS" $SecondaryDNS = Read-Host "Enter Secondary DNS" } return $IpType, $IPAddress, $Netmask, $DefaultGateway, $PrimaryDNS, $SecondaryDNS } function Get-DatastoreBySource { param( [System.Object] $Source, [string[]] $TargetDatastores, [bool] $IsInteractive ) if (!$IsInteractive) { Throw "The function Get-DatastoreBySource does not support non-interactive case" } if ($TargetDatastores.Count -eq 0) { Throw "No datastores were found, migration cannot be started." } $TargetDatastoresAsString = $TargetDatastores -join ", " $Datastores = @() $SortedDisks = $Source.attributes.storage.disks.psobject.Properties.Value | Sort-Object -property device foreach ($Disk in $SortedDisks) { if ($IsInteractive) { $Size = $Disk.size_kb/(1024*1024) $Size = [math]::round($Size, 2) $DefaultDatastore = $TargetDatastores[0] $ReadValue = Read-Host "Enter the datastore name for disk of size $Size GiB ($TargetDatastoresAsString)[$DefaultDatastore]" if ("" -ne $ReadValue) { if (!($ReadValue -in $TargetDatastores)) { Throw "Datastore '$ReadValue' does not exist in the given cluster" } $Datastores += $ReadValue.Trim() } else { $Datastores += $DefaultDatastore } } } 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) $ProvisioningTypesAsString = $ProvisioningTypes -join ", " $ReadValue = Read-Host "Enter disk provisioning type for disk of size $Size GiB ($ProvisioningTypesAsString)[thin]" if ("" -ne $ReadValue) { if (!($ReadValue -in $ProvisioningTypes)) { Throw "Disk provisioning type '$ReadValue' is not valid" } $ResultProvisioningTypes += $ReadValue.Trim() } else { $ResultProvisioningTypes += "thin" } } else { if ($null -ne $DiskProvisioningTypes -and $DiskCnt -lt $DiskProvisioningTypes.Count) { $ResultProvisioningTypes += $DiskProvisioningTypes[$DiskCnt].Trim() } else { $ResultProvisioningTypes += "thin" } } $DiskCnt ++ } return $ResultProvisioningTypes } function Update-DiskProvisioningTypeForME { param( [string[]] $DiskProvisioningTypes ) $Result = @() switch ($DiskProvisioningTypes) { "thick-lazy-zeroed" { $Result += "thick_lazy_zero" } "thick-eager-zeroed" { $Result += "thick_eager_zero" } "thin" { $Result += "thin" } } return $Result } function Get-DestinationNetworkAndDvSwitchName { param( [string[]] $NetworkNames, [string] $NetworkNamesAsString, [string] $DestinationNetworkName, [bool] $IsInteractive ) if ($IsInteractive) { $DestinationNetworkName = Read-Host "Enter destination network name ($NetworkNamesAsString)" if ([string]::IsNullOrEmpty($DestinationNetworkName)) { Throw "Destination network name is required" } elseif (!($DestinationNetworkName -in $NetworkNames)) { Throw "Destination network name '$DestinationNetworkName' does not exists." } } else { if ([string]::IsNullOrEmpty($DestinationNetworkName)) { Throw "Destination network name is required" } } $DvSwitchName = "" [string[]] $networkNamesArray = $DestinationNetworkName -split "/" if ($networkNamesArray.Count -eq 2) { $DestinationNetworkName = $networkNamesArray[1] $DvSwitchName = $networkNamesArray[0] } return $DestinationNetworkName, $DvSwitchName } Export-ModuleMember -Function Start-RMInteractiveVSphereOSBasedMigration, Start-RMNonInteractiveVsphereOsBasedMigration, Start-RMVSphereOSBasedDifferentialMigration |