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.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,
        [bool] $EnableConvertFileSystem,
        [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($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
    if ($EnableConvertFileSystem) {
        Add-RMConvertFileSystem -Source $Source -UpdatedUserInput $UserInput
    }

    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
        RemoveRMSAgent = $RemoveRMSAgent
        IgnoreValidationError = $IgnoreValidationError
        InstallAWSSSMAgent = $InstallAWSSSMAgent
        InstallAWSCloudWatchAgent = $InstallAWSCloudWatchAgent
        DisableTargetDNSRegistration = $DisableTargetDNSRegistration
        ShutdownSource = $ShutdownSource
        ShutdownTarget = $ShutdownTarget
        MigrationInstruction = $MigrationInstructionsAsHashTable
        EnableCloudFilesMigration = $EnableCloudFilesMigration
        TargetInventory = $TargetInventory
        SelectedMount = $SelectedMountPoints
        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-RMHPEVMEParameter {
    param (
        [hashtable] $UserParameter,
        [System.Object] $TargetInventory,
        [System.Object] $ProjectSettingsResponse
    )
    
    $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
            }
        }
    }

    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
        }
    }

    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."
            }
        }
    }


    return $Errors, $IsRequiredParametersPresentAndValid
}

Export-ModuleMember -Function Start-RMHPEVMEOSBasedNonInteractiveMigration