Migration/hpe_vme/HPEVME.psm1
|
using module '../../Common/Result' Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath .. | Join-Path -ChildPath MigrationProfile | Join-Path -ChildPath HPEVMEMigrationProfile) 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) function Start-RMHPEVMEOSBasedNonInteractiveMigration { param ( [string] $TargetCloud, [string] $SourceIP, [string] $ScheduledAt, [string] $TargetVMName, [System.Object[]] $MountPoint, [string] $Group, [string] $Cloud, [string] $Cluster, [string] $HostName, [string[]] $Datastore, [string] $Layout, [string] $ResourcePool, [string] $Plan, [string[]] $DestinationNetworkName, [string[]] $AssignmentType, [string[]] $IpAddresses, [string[]] $ResizeMountPoint, [string] $NetBIOSName, [bool] $Sysprep, [string] $ConvertFileSystem, [string] $MigrationExtension, [string] $MigrationExtensionOSM, [string] $UpgradeOSVersion, [bool] $EnableOSHardening, [string] $OSHardeningProfile, [bool] $Level1Server, [bool] $Level2Server, [bool] $Level1Computer, [bool] $Level2Computer, [bool] $Level1User, [bool] $Level2User, [string] $AdministratorName, [string] $GuestName, [string] $LegalNoticeCaption, [string] $LegalNoticeText, [bool] $InstallAzureARC, [bool] $ConnectARCAgent, [bool] $RemoveRMSAgent, [bool] $IgnoreValidationError, [bool] $InstallAWSSSMAgent, [bool] $InstallAWSCloudWatchAgent, [bool] $DisableTargetDNSRegistration, [bool] $ShutdownSource, [bool] $ShutdownTarget, [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 "hpe_vme" 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-RMHPEVMEFullMigrationParameter $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 "hpe_vme" ` -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 $OSHardening = Get-RMOSHardening -OrganizationId $CloudAccount.organization_id if ($null -ne $Source) { $SourceErrors = Confirm-RMHPEVMEFullMigrationParameterWithSource -UserParameter $PSBoundParameters -Source $Source ` -MigrationExtension $MigrationExtensionArray -MigrationExtensionOSM $MigrationExtensionOSMArray -OSHardeningProfile $OSHardening.content $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 } $MountsResize = @{} if ($null -ne $ResizeMountPoint -and $ResizeMountPoint.Count -gt 0) { $MountsResize, $MountsResizeErrors = Get-RMResizeMountsPoint -ResizeMountPoints $ResizeMountPoint -SelectedMountPoints $SelectedMountPoints -Source $Source 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, $SelectedMountPointArray, $ErrorString = Get-RMTransferMethod -Source $Source -SelectedMountPoints $SelectedMountPoints ` -TransferMethod $TransferMethod if (![string]::IsNullOrEmpty($ErrorString)) { $Errors += $ErrorString } if ($SelectedMountPointArray -and $SelectedMountPointArray.Count -gt 0) { $SelectedMountPoints = $SelectedMountPointArray } } $UserInput.Add("SelectedMount", $SelectedMountPoints) $InstallAzureARCParameter = $null if ($InstallAzureARC) { $InstallAzureARCParameter = $ProjectSettingsResponse.hpe_vme.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 -OSHardeningProfile $OSHardening.content if ($null -ne $ErrorsOSHardening) { $Errors += $ErrorsOSHardening } 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 Group = $Group Cloud = $Cloud Cluster = $Cluster HostName = $HostName Layout = $Layout ResourcePool = $ResourcePool Plan = $Plan DestinationNetworkName = $DestinationNetworkName AssignmentType = $AssignmentType IpAddresses = $IpAddresses ResizeMountPoint = $MountsResize NetBIOSName = $NetBIOSName Sysprep = $Sysprep InstallAzureARC = $InstallAzureARC ConnectARCAgent = $ConnectARCAgent InstallAzureARCParameter = $InstallAzureARCParameter RemoveRMSAgent = $RemoveRMSAgent IgnoreValidationError = $IgnoreValidationError InstallAWSSSMAgent = $InstallAWSSSMAgent InstallAWSCloudWatchAgent = $InstallAWSCloudWatchAgent DisableTargetDNSRegistration = $DisableTargetDNSRegistration ShutdownSource = $ShutdownSource ShutdownTarget = $ShutdownTarget MigrationInstruction = $MigrationInstructionsAsHashTable EnableCloudFilesMigration = $EnableCloudFilesMigration TargetInventory = $TargetInventory Datastore = $Datastore } $HashArguments += $UserInput $Response = New-RMHPEVMEMigrationProfile @HashArguments 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-RMHPEVMEFullMigrationParameter { param ( [hashtable] $UserParameter, [System.Object] $TargetInventory, [System.Object] $ProjectSettingsResponse ) $Errors, $Warnings, $IsSourceAndTargetCloudPresent = Confirm-RMCommonParameter -UserParameter $UserParameter $hpeVmeErrors, $IsRequiredParametersPresentAndValid = Confirm-RMHPEVMEParameter -UserParameter $UserParameter ` -TargetInventory $TargetInventory -ProjectSettingsResponse $ProjectSettingsResponse $Errors += $hpeVmeErrors return $Errors, $Warnings, $IsSourceAndTargetCloudPresent, $IsRequiredParametersPresentAndValid } function Confirm-RMHPEVMEFullMigrationParameterWithSource { param ( [hashtable] $UserParameter, [System.Object] $Source, [System.Array] $MigrationExtension, [System.Array] $MigrationExtensionOSM, [system.Object] $OSHardeningProfile ) $Errors = @() $ConfirmErrors = Confirm-RMCommonParameterWithSource -UserParameter $UserParameter -Source $Source ` -MigrationExtension $MigrationExtension -MigrationExtensionOSM $MigrationExtensionOSM -OSHardeningProfile $OSHardeningProfile $Errors += $ConfirmErrors if ($Source.os_type -ne 'windows' -and $UserParameter["DisableTargetDNSRegistration"]) { $Errors += "DisableTargetDNSRegistration can only be 'true', if the source type is 'windows'." } if ($UserParameter.ContainsKey("Datastore") -and ![string]::IsNullOrWhiteSpace($UserParameter["Datastore"])) { $Datastores = $UserParameter["Datastore"] if ($Datastores.Count -ne $Source.attributes.storage.disks.psobject.Properties.Value.Count) { $Errors += "The count of datastores must match the count of disks." } } return $Errors } function Confirm-RMHPEVMECommonParameter { param ( [hashtable] $UserParameter, [System.Object] $TargetInventory ) $Errors = @() $IsRequiredParametersPresentAndValid = $true $SelectedGroup = $null if (!$UserParameter.ContainsKey("Group") -or [string]::IsNullOrWhiteSpace($UserParameter["Group"])) { $Errors += "Group is required." $IsRequiredParametersPresentAndValid = $false } else { $GroupNames = $TargetInventory.attributes.hpe_vme.groups.name if ($GroupNames -notcontains $UserParameter["Group"]) { $Group = $UserParameter["Group"] $Errors += "Group '$Group' does not exist." $IsRequiredParametersPresentAndValid = $false } else { $SelectedGroup = $TargetInventory.attributes.hpe_vme.groups | Where-Object { $_.name -eq $UserParameter["Group"] } } } $SelectedCloud = $null if (!$UserParameter.ContainsKey("Cloud") -or [string]::IsNullOrWhiteSpace($UserParameter["Cloud"])) { $Errors += "Cloud is required." $IsRequiredParametersPresentAndValid = $false } else { if ($SelectedGroup) { $CloudNames = $SelectedGroup.clouds.name if ($CloudNames -notcontains $UserParameter["Cloud"]) { $Cloud = $UserParameter["Cloud"] $Errors += "Cloud '$Cloud' does not exist in the selected group." $IsRequiredParametersPresentAndValid = $false } else { $SelectedCloud = $SelectedGroup.clouds | Where-Object { $_.name -eq $UserParameter["Cloud"] } } } } $SelectedCluster = $null if (!$UserParameter.ContainsKey("Cluster") -or [string]::IsNullOrWhiteSpace($UserParameter["Cluster"])) { $Errors += "Cluster is required." $IsRequiredParametersPresentAndValid = $false } else { if ($SelectedCloud) { $ClusterNames = $SelectedCloud.clusters.name if ($ClusterNames -notcontains $UserParameter["Cluster"]) { $Cluster = $UserParameter["Cluster"] $Errors += "Cluster '$Cluster' does not exist in the selected cloud." $IsRequiredParametersPresentAndValid = $false } else { $SelectedCluster = $SelectedCloud.clusters | Where-Object { $_.name -eq $UserParameter["Cluster"] } } } } if ($UserParameter.ContainsKey("HostName") -and ![string]::IsNullOrWhiteSpace($UserParameter["HostName"])) { if ($SelectedCluster) { $HostNames = $SelectedCluster.hosts.name if ($HostNames -notcontains $UserParameter["HostName"]) { $Hosts = $UserParameter["HostName"] $Errors += "Host '$Hosts' does not exist in the selected cluster." $IsRequiredParametersPresentAndValid = $false } } } if ($UserParameter.ContainsKey("Datastore") -and ![string]::IsNullOrWhiteSpace($UserParameter["Datastore"])) { if ($SelectedCluster) { $DatastoreNames = $SelectedCluster.datastores.name foreach($Name in $UserParameter["Datastore"]) { if ($DatastoreNames -notcontains $Name) { $Errors += "Datastore '$Name' does not exist in the selected cluster." $IsRequiredParametersPresentAndValid = $false } } } } else { $Errors += "Datastore is required." $IsRequiredParametersPresentAndValid = $false } $SelectedLayout = $null if (!$UserParameter.ContainsKey("Layout") -or [string]::IsNullOrWhiteSpace($UserParameter["Layout"])) { $Errors += "Layout is required." $IsRequiredParametersPresentAndValid = $false } else { $LayoutNames = $TargetInventory.attributes.hpe_vme.instance_type_layouts.name if ($LayoutNames -notcontains $UserParameter["Layout"]) { $Layout = $UserParameter["Layout"] $Errors += "Layout '$Layout' does not exist." $IsRequiredParametersPresentAndValid = $false } else { $SelectedLayout = $TargetInventory.attributes.hpe_vme.instance_type_layouts | Where-Object { $_.name -eq $UserParameter["Layout"] } } } if (!$UserParameter.ContainsKey("ResourcePool") -or [string]::IsNullOrWhiteSpace($UserParameter["ResourcePool"])) { $Errors += "ResourcePool is required." $IsRequiredParametersPresentAndValid = $false } else { if ($SelectedLayout) { $ResourcePoolNames = $SelectedLayout.resource_pools.name if ($ResourcePoolNames -notcontains $UserParameter["ResourcePool"]) { $ResourcePool = $UserParameter["ResourcePool"] $Errors += "ResourcePool '$ResourcePool' does not exist in the selected layout." $IsRequiredParametersPresentAndValid = $false } } } $SelectedPlan = $null if (!$UserParameter.ContainsKey("Plan") -or [string]::IsNullOrWhiteSpace($UserParameter["Plan"])) { $Errors += "Plan is required." $IsRequiredParametersPresentAndValid = $false } else { $PlanNames = $TargetInventory.attributes.hpe_vme.plans.name if ($PlanNames -notcontains $UserParameter["Plan"]) { $Plan = $UserParameter["Plan"] $Errors += "Plan '$Plan' does not exist." $IsRequiredParametersPresentAndValid = $false } else { $SelectedPlan = $TargetInventory.attributes.hpe_vme.plans | Where-Object { $_.name -eq $UserParameter["Plan"] } } } return $Errors, $IsRequiredParametersPresentAndValid, $SelectedCloud, $SelectedPlan } function Confirm-RMHPEVMEParameter { param ( [hashtable] $UserParameter, [System.Object] $TargetInventory, [System.Object] $ProjectSettingsResponse ) $Errors = @() $CommonErrors, $IsRequiredParametersPresentAndValid, $SelectedCloud, $SelectedPlan = Confirm-RMHPEVMECommonParameter -UserParameter $UserParameter ` -TargetInventory $TargetInventory $Errors += $CommonErrors if (!$UserParameter.ContainsKey("DestinationNetworkName") -or $UserParameter["DestinationNetworkName"].Count -eq 0) { $Errors += "DestinationNetworkName is required." $IsRequiredParametersPresentAndValid = $false } else { if ($SelectedCloud) { $NetworkNames = $SelectedCloud.networks.name foreach ($NetworkName in $UserParameter["DestinationNetworkName"]) { if ($NetworkNames -notcontains $NetworkName) { $Errors += "Network '$NetworkName' does not exist in the selected cloud." $IsRequiredParametersPresentAndValid = $false } } } } if (!$UserParameter.ContainsKey("AssignmentType") -or $UserParameter["AssignmentType"].Count -eq 0) { $Errors += "AssignmentType is required." $IsRequiredParametersPresentAndValid = $false } else { $ValidAssignmentTypes = @("static", "dhcp") foreach ($AssignmentType in $UserParameter["AssignmentType"]) { if ($ValidAssignmentTypes -notcontains $AssignmentType.ToLower()) { $Errors += "AssignmentType '$AssignmentType' is not valid. Must be one of: $($ValidAssignmentTypes -join ', ')" $IsRequiredParametersPresentAndValid = $false } } if ($UserParameter["AssignmentType"] -contains "static") { if (!$UserParameter.ContainsKey("IpAddresses") -or $UserParameter["IpAddresses"].Count -eq 0) { $Errors += "IpAddresses cannot be null, when 'DestinationNetworkName' include 'static' value." } elseif( $UserParameter["IpAddresses"].Count -ne $UserParameter["AssignmentType"].Count) { $Errors += "'IpAddresses' count must be contains with 'DestinationNetworkName' count." } } 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 empty." } } } elseif ($UserParameter.ContainsKey("InstallAzureARC") -and $UserParameter["InstallAzureARC"] ` -and $UserParameter.ContainsKey("ConnectARCAgent") -and $UserParameter["ConnectARCAgent"] ` -and $null -ieq $ProjectSettingsResponse.hpe_vme.arc_settings) { $Errors += "'ConnectARCAgent' can not be true." } } return $Errors, $IsRequiredParametersPresentAndValid } function Confirm-RMHPEVMEVMBasedParameter { param ( [hashtable] $UserParameter, [System.Object] $TargetInventory, [System.Object] $ProjectSettingsResponse ) $Errors = @() $CommonErrors, $IsRequiredParametersPresentAndValid, $SelectedCloud, $SelectedPlan = Confirm-RMHPEVMECommonParameter -UserParameter $UserParameter ` -TargetInventory $TargetInventory $Errors += $CommonErrors if (!$UserParameter.ContainsKey("DestinationNICConfig") -or $null -eq $UserParameter["DestinationNICConfig"] -or $UserParameter["DestinationNICConfig"].Count -eq 0) { $Errors += "DestinationNICConfig is required." $IsRequiredParametersPresentAndValid = $false } else { if ($SelectedCloud) { $Networks = $SelectedCloud.networks $NetworkNames = $Networks.name foreach ($config in $UserParameter["DestinationNICConfig"]) { if ($NetworkNames -notcontains $config.DestinationNetworkName) { $NetworkName = $config.DestinationNetworkName $Errors += "Network '$NetworkName' does not exist in the selected cloud." $IsRequiredParametersPresentAndValid = $false } else { $SelectedNetwork = $Networks | Where-Object { $_.name -eq $config.DestinationNetworkName } $ValidIPTypes = @("static", "dhcp") if (-not [string]::IsNullOrEmpty($SelectedNetwork.pool_name)) { $ValidIPTypes += $SelectedNetwork.pool_name } if ($ValidIPTypes -notcontains $config.IPType.ToLower()) { $Errors += "IPType '$($config.IPType)' is not valid. Must be one of: $($ValidIPTypes -join ', ')" $IsRequiredParametersPresentAndValid = $false } } } } } if ($SelectedPlan) { $PlanName = $SelectedPlan.name if ($UserParameter.ContainsKey("Memory") -and -not [string]::IsNullOrEmpty($UserParameter["Memory"])) { if (-not $SelectedPlan.custom_memory) { $Errors += "Memory is not supported for the plan '$PlanName'." $IsRequiredParametersPresentAndValid = $false } else { $MemoryValue = [int]$UserParameter["Memory"] $MemoryMB = $MemoryValue * 1024 $MinMemoryMB = $SelectedPlan.min_memory_kb $MaxMemoryMB = $SelectedPlan.max_memory_kb $MinMemoryGB = [math]::Ceiling($MinMemoryMB / 1024) $MaxMemoryGB = [math]::Floor($MaxMemoryMB / 1024) if ($MemoryMB -lt $MinMemoryMB -or $MemoryMB -gt $MaxMemoryMB) { $Errors += "Memory must be between $MinMemoryGB GB and $MaxMemoryGB GB for the plan '$PlanName'." $IsRequiredParametersPresentAndValid = $false } } } if ($UserParameter.ContainsKey("Cores") -and -not [string]::IsNullOrEmpty($UserParameter["Cores"])) { if (-not $SelectedPlan.custom_cpus) { $Errors += "Cores is not supported for the plan '$PlanName'." $IsRequiredParametersPresentAndValid = $false } else { $CoresValue = [int]$UserParameter["Cores"] $MinCpus = $SelectedPlan.min_cpus $MaxCpus = $SelectedPlan.max_cpus if ($CoresValue -lt $MinCpus -or $CoresValue -gt $MaxCpus) { $Errors += "Cores must be between $MinCpus and $MaxCpus for the plan '$PlanName'." $IsRequiredParametersPresentAndValid = $false } } } if ($UserParameter.ContainsKey("CoresPerSocket") -and -not [string]::IsNullOrEmpty($UserParameter["CoresPerSocket"])) { $CoresPerSocketValue = [int]$UserParameter["CoresPerSocket"] if ($CoresPerSocketValue -le 0) { $Errors += "CoresPerSocket must be greater than 0." $IsRequiredParametersPresentAndValid = $false } else { $MaxCoresPerSocket = $SelectedPlan.max_cores_per_socket if ($MaxCoresPerSocket -and $CoresPerSocketValue -gt $MaxCoresPerSocket) { $Errors += "CoresPerSocket must not exceed $MaxCoresPerSocket for the plan '$PlanName'." $IsRequiredParametersPresentAndValid = $false } } } } return $Errors, $IsRequiredParametersPresentAndValid } function Start-RMHPEVMEVMBasedNonInteractiveMigration { param ( [string] $TargetCloud, [string] $SourceVMName, [string] $SourceVMFolderPath, [string] $ScheduledAt, [string] $TargetVMName, [string[]] $SelectedDiskLabel, [string] $Group, [string] $Cloud, [string] $Cluster, [string] $HostName, [string[]] $Datastore, [string] $Layout, [string] $ResourcePool, [string] $Plan, [string] $CoresPerSocket, [string] $Memory, [string] $Cores, [System.Object[]] $DestinationNICConfig, [bool] $UseCustomNetworkConfig, [string] $DefaultGateway, [string] $PrimaryDNS, [string] $SecondaryDNS, [string] $MigrationExtension, [bool] $ShutdownSource, [bool] $ShutdownTarget, [string[]] $MigrationInstruction, [bool] $IgnoreValidationError, [bool] $FinalizeMigration, [bool] $OverrideExistingMigration, [bool] $InstallAWSSSMAgent, [bool] $InstallAWSCloudWatchAgent ) $CloudAccount = $null $Source = $null $Errors = @() $UserInput = @{} $ShouldExit = $false [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new() $Errors, $Warnings, $IsSourceAndTargetCloudPresent = Confirm-RMHPEVMEVMBasedFullMigrationParameter $PSBoundParameters try { if (![string]::IsNullOrWhiteSpace($TargetCloud)) { $CloudAccount, $ErrorString = Get-RMCloudAccountByName -CloudAccountName $TargetCloud -AccountType "hpe_vme" -VMBasedAppliancesOnly $true if (![string]::IsNullOrWhiteSpace($ErrorString)) { $Errors += $ErrorString $IsSourceAndTargetCloudPresent = $false } else { $TargetInventory = Get-RMTargetInventory -CloudAccount $CloudAccount } } } catch [System.Management.Automation.ItemNotFoundException] { $Errors += $PSItem.Exception.Message $IsSourceAndTargetCloudPresent = $false } try { if (![string]::IsNullOrWhiteSpace($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-RMHPEVMEOSBasedMigration'." Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } } } catch [System.Management.Automation.ItemNotFoundException], [System.Data.DuplicateNameException] { $Errors += $PSItem.Exception.Message $IsSourceAndTargetCloudPresent = $false } if (!$IsSourceAndTargetCloudPresent) { Add-RMErrorAndWarning -RMReturnObject $RMMigrationReturn -ErrorMessage $Errors -WarningMessage $Warnings Out-RMUserParameterResult -ErrorMessage $Errors -WarningMessage $Warnings return $RMMigrationReturn } $ProjectSettingsResponse = Invoke-RMProjectSettings -OrganizationId $CloudAccount.organization_id $hpeVmeErrors, $IsRequiredParametersPresentAndValid = Confirm-RMHPEVMEVMBasedParameter -UserParameter $PSBoundParameters ` -TargetInventory $TargetInventory -ProjectSettingsResponse $ProjectSettingsResponse $Errors += $hpeVmeErrors $Entitlement = Get-RMEntitlement try { $Source, $ShouldExit, $OverrideExistingMigrationWarning, $OverrideExistingMigrationError = ` Get-RMSourceWithAttribute -Source $Source -CloudAccount $CloudAccount ` -IgnoreValidationErrors $IgnoreValidationError -RMMigrationReturn $RMMigrationReturn ` -AccountType "hpe_vme" if (!$IgnoreValidationError -and $OverrideExistingMigrationError -and !$OverrideExistingMigration) { $Errors += "Please set 'OverrideExistingMigration' to true and try again." } } catch [System.InvalidOperationException], [System.Management.Automation.RuntimeException] { $Errors += $PSItem.Exception.Message } if ($null -ne $Source) { if ($null -eq $SelectedDiskLabel -or $SelectedDiskLabel.Count -eq 0) { $Warnings += "No disk labels have been given, all the disks on the source will be migrated." $SelectedDiskLabel = Get-RMVMBasedSourceDiskLabel -Source $Source $PSBoundParameters["SelectedDiskLabel"] = $SelectedDiskLabel } $MigrationExtensionResponse = Get-RMMigrationExtension -OrganizationId $CloudAccount.organization_id $MigrationExtensionArray, $MigrationExtensionOSMArray = Get-RMMigrationExtensionFromStep -MigrationExtensionArray $MigrationExtensionResponse.content $SourceErrors = Confirm-RMHPEVMEVMBasedFullMigrationParameterWithSource -UserParameter $PSBoundParameters -Source $Source ` -MigrationExtension $MigrationExtensionArray if ($SourceErrors.Count -gt 0) { $Errors += $SourceErrors } } if ([string]::IsNullOrWhiteSpace($ScheduledAt)) { $ScheduledAt = "" } else { $ScheduledAt = Convert-RMDateTimeToUTC -InputDateTime $ScheduledAt } if ([string]::IsNullOrWhiteSpace($TargetVMName)) { $TargetVMName = $Source.host } Add-RMMigrationExtension -UpdatedParameter $UserInput -MigrationExtension $MigrationExtension ` -MigrationExtensionOSM $null -MigrationExtensionResponse $MigrationExtensionResponse $SelectedDisk = Get-RMSelectedDiskByDiskLabel -DiskLabel $SelectedDiskLabel -Source $Source if (($IgnoreValidationError -and $OverrideExistingMigration) -or ` (!$IgnoreValidationError -and $OverrideExistingMigration) -or ` $OverrideExistingMigrationWarning) { $MigrationInstruction += "override_source_migration=true" } $MigrationInstructionsAsHashTable, $MigrationInstructionErrors = Get-RMMigrationInstructionAsHashTable -OrganizationId $CloudAccount.organization_id ` -MigrationInstruction $MigrationInstruction -AccountType "hpe_vme" if ($null -ne $MigrationInstructionErrors) { $Errors += $MigrationInstructionErrors } 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 TargetVMName = $TargetVMName SelectedDisk = $SelectedDisk Group = $Group Cloud = $Cloud Cluster = $Cluster HostName = $HostName Datastore = $Datastore Layout = $Layout ResourcePool = $ResourcePool Plan = $Plan CoresPerSocket = $CoresPerSocket Memory = $Memory Cores = $Cores DestinationNICConfig = $DestinationNICConfig UseCustomNetworkConfig = $UseCustomNetworkConfig DefaultGateway = $DefaultGateway PrimaryDNS = $PrimaryDNS SecondaryDNS = $SecondaryDNS FinalizeMigration = $FinalizeMigration ShutdownSource = $ShutdownSource ShutdownTarget = $ShutdownTarget MigrationInstruction = $MigrationInstructionsAsHashTable IgnoreValidationError = $IgnoreValidationError InstallAWSSSMAgent = $InstallAWSSSMAgent InstallAWSCloudWatchAgent = $InstallAWSCloudWatchAgent TargetInventory = $TargetInventory } $HashArguments += $UserInput $Response = New-RMHPEVMEVMBasedMigrationProfile @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-RMHPEVMEVMBasedFullMigrationParameter { param( [hashtable] $UserParameter ) $Errors = @() $CommonErrors, $Warnings, $IsSourceAndTargetCloudPresent = Confirm-RMVMBasedCommonParameter -UserParameter $UserParameter $Errors += $CommonErrors if (!$UserParameter.ContainsKey("UseCustomNetworkConfig") -or !$UserParameter["UseCustomNetworkConfig"]) { if ($UserParameter.ContainsKey("DefaultGateway") -and ![string]::IsNullOrEmpty($UserParameter["DefaultGateway"])) { $Errors += "'DefaultGateway' can only be specified when 'UseCustomNetworkConfig' is true." } if ($UserParameter.ContainsKey("PrimaryDNS") -and ![string]::IsNullOrEmpty($UserParameter["PrimaryDNS"])) { $Errors += "'PrimaryDNS' can only be specified when 'UseCustomNetworkConfig' is true." } if ($UserParameter.ContainsKey("SecondaryDNS") -and ![string]::IsNullOrEmpty($UserParameter["SecondaryDNS"])) { $Errors += "'SecondaryDNS' can only be specified when 'UseCustomNetworkConfig' is true." } if ($UserParameter.ContainsKey("DestinationNICConfig") -and $null -ne $UserParameter["DestinationNICConfig"]) { foreach ($config in $UserParameter["DestinationNICConfig"]) { if (![string]::IsNullOrEmpty($config.Netmask)) { $Errors += "'Netmask' in DestinationNICConfig can only be specified when 'UseCustomNetworkConfig' is true." $IsSourceAndTargetCloudPresent = $false break } } } } else { if (!$UserParameter.ContainsKey("DefaultGateway") -or [string]::IsNullOrEmpty($UserParameter["DefaultGateway"])) { $Errors += "'DefaultGateway' is required when 'UseCustomNetworkConfig' is true." } if ($UserParameter.ContainsKey("DestinationNICConfig") -and $null -ne $UserParameter["DestinationNICConfig"]) { for ($i = 0; $i -lt $UserParameter["DestinationNICConfig"].Count; $i++) { $config = $UserParameter["DestinationNICConfig"][$i] if ([string]::IsNullOrEmpty($config.IPAddress)) { $Errors += "'IPAddress' is required for NIC $i when 'UseCustomNetworkConfig' is true." $IsSourceAndTargetCloudPresent = $false } if ([string]::IsNullOrEmpty($config.Netmask)) { $Errors += "'Netmask' is required for NIC $i when 'UseCustomNetworkConfig' is true." $IsSourceAndTargetCloudPresent = $false } } } } return $Errors, $Warnings, $IsSourceAndTargetCloudPresent } function Confirm-RMHPEVMEVMBasedFullMigrationParameterWithSource { param( [hashtable] $UserParameter, [System.Object] $Source, [System.Array] $MigrationExtension ) $Errors = @() $Errors += Confirm-RMCommonParameterWithSource -UserParameter $UserParameter -Source $Source ` -MigrationExtension $MigrationExtension if ($UserParameter.ContainsKey("Datastore") -and ![string]::IsNullOrWhiteSpace($UserParameter["Datastore"])) { $Datastores = $UserParameter["Datastore"] if ($Datastores.Count -ne $Source.attributes.storage.vm_disks.Count) { $Errors += "The count of datastores must match the count of disks." } } return $Errors } Export-ModuleMember -Function Start-RMHPEVMEOSBasedNonInteractiveMigration, Start-RMHPEVMEVMBasedNonInteractiveMigration |