Migration/openshift/openshift.psm1

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 MigrationProfile | Join-Path -ChildPath OpenshiftMigrationProfile)
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 Common | Join-Path -ChildPath Wrappers | Join-Path -ChildPath Wrappers)
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 Util | Join-Path -ChildPath MigrationUtil)
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 openshiftUtil)


function Start-RMOpenshiftOsBasedInteractiveMigration {
    param ( )
    $UserInput = @{}
    $Entitlement = Get-RMEntitlement

    $CloudAccount = Read-RMCloudAccount -AccountType "openshift" -UserMessage "Enter target cloud"
    $TargetInventory = Get-RMTargetInventory -CloudAccount $CloudAccount

    $Source = Read-RMSource -UserMessage "Enter the IP address of the source machine to be migrated" -ParameterName "Source IP address" -IsRequired $true
    $IgnoreValidationError = Read-RMBoolean -UserMessage "Ignore validation errors" -DefaultValue "false"

    [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new()
    $Source, $ShouldExit, $OverrideExistingMigrationWarning, $OverrideExistingMigrationError = Get-RMSourceWithAttribute -Source $Source -CloudAccount $CloudAccount `
        -IgnoreValidationErrors $IgnoreValidationError -RMMigrationReturn $RMMigrationReturn  -AccountType "openshift"
    if ($ShouldExit) {
        return $RMMigrationReturn
    }

    if ($OverrideExistingMigrationError) {
        $OverrideExistingMigrationError = Read-RMBoolean -UserMessage "Would you like to override the previous migration attempt" -DefaultValue "false"
        if (!$IgnoreValidationError -and !$OverrideExistingMigrationError) {
            return $RMMigrationReturn
        }
    }

    $ScheduledAt = Read-RMMigrationSchedule
    $TargetVMName = Read-RMString -UserMessage "Enter target VM Name" -DefaultValue $Source.hostname `
        -ParameterName "Target VM Name" -IsRequired $false

    #Placement Settings
    $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 )

    $ProjectDefaultValue = $TargetInventory.attributes.openshift.projects.name
    $Project = Read-RMString -UserMessage "Enter project" -Options $ProjectDefaultValue `
        -ParameterName "Project" -IsRequired $true

    $InstanceType = Read-RMInstanceType -TargetInventory $TargetInventory
    if ("" -ieq $InstanceType) {
        $RAM = Read-RMRAMOrCPU -MinValue 2 -ErrorMessage "The minimum RAM size must be greater than or equal to 2." `
            -UserMessage "Enter RAM" -DefaultValue "2" -ParameterName "RAM"

        $Sockets = Read-RMRAMOrCPU -MinValue 1 -ErrorMessage "The Sockets value must be greater than or equal to 1." `
            -UserMessage "Enter sockets" -DefaultValue "1" -ParameterName "Sockets"

        $Cores = Read-RMRAMOrCPU -MinValue 1 -ErrorMessage "The Cores value must be greater than or equal to 1." `
            -UserMessage "Enter cores" -DefaultValue "1" -ParameterName "Cores"
    }

    $StorageClassDefalutValue = $TargetInventory.attributes.openshift.storage_classes
    $StorageClass =  Read-RMString -UserMessage "Enter storage class" -Options $StorageClassDefalutValue `
        -ParameterName "StorageClass" -IsRequired $true

    $AccessModeOptions = @("Single user (RWO)", "Shared access (RWX)", "Read only (ROX)")
    $AccessMode = Read-RMString -UserMessage "Enter access mode" -Options $AccessModeOptions -DefaultValue "Single user (RWO)" `
        -ParameterName "AccessMode" -IsRequired $false
    $AccessMode = Get-RMAccountModeName -AccessMode $AccessMode

    $VolumeModeOptions = @("Filesystem", "Block")
    $VolumeMode = Read-RMString -UserMessage "Enter volume mode" -Options $VolumeModeOptions -DefaultValue "Block" `
        -ParameterName "VolumeMode" -IsRequired $false

    $ModelOptions = @("virtio", "E1000E")
    $NetworkAdapterModel = Read-RMString -UserMessage "Enter network adapter model" -Options $ModelOptions -DefaultValue "virtio" `
        -ParameterName "NetworkAdapterModel" -IsRequired $false

    $AdaptersTypeOptions = @("Masquerade", "Bridge")
    $NetworkAdaptersType = Read-RMString -UserMessage "Enter network adapter type" -Options $AdaptersTypeOptions `
        -DefaultValue "Masquerade" -ParameterName "NetworkAdaptersType" -IsRequired $false
    $NetworkAdaptersType = Get-RMNetworkAdapterType -AdapterType $NetworkAdaptersType
    
    $DestinationNetworkNameOptions = $TargetInventory.attributes.openshift.networks.name
    $ProjectDestinationNetworkNameOptions = Get-RMNetworkNameByProject -Project $Project -TargetInventory $TargetInventory
    $ProjectDestinationNetworkNameOptions += $DestinationNetworkNameOptions
    $DestinationNetworkName = Read-RMString -UserMessage "Destination network name" -Options $ProjectDestinationNetworkNameOptions `
        -ParameterName "Destination network name" -IsRequired $true

    #Optimization Settings
    $NetBIOSName = Read-RMString -UserMessage "Enter NetBIOS name" -DefaultValue $Source.hostname `
        -ParameterName "NetBIOS Name" -IsRequired $false

    $Sysprep = $false
    if ("windows" -ieq $Source.os_type) {
        $Sysprep = Read-RMBoolean -UserMessage "Enable sysprep" -DefaultValue "false"
    }

    $MountsResize = @{}
    $ResizeMountPointsFlag = Read-RMBoolean -UserMessage "Resize mount points" -DefaultValue "false"
    if ($ResizeMountPointsFlag) {
        $MountsResize = Get-RMInteractiveMountsResize -SelectedMountPoints $SelectedMountPoint -Source $Source
    }

    $MigrationExtensionResponse = Get-RMMigrationExtension -OrganizationId $CloudAccount.organization_id
    $MigrationExtensionArray, $MigrationExtensionOSMArray = Get-RMMigrationExtensionFromStep -MigrationExtensionArray $MigrationExtensionResponse.content

    Read-RMMigrationExtension -CloudAccount $CloudAccount -MigrationExtension  $MigrationExtensionArray `
        -MigrationExtensionObject $MigrationExtensionResponse.content -UpdatedUserInput $UserInput
        
    #Modernization Settings
    Read-RMOSUpgradeOption -Source $Source -UpdatedUserInput $UserInput
    if ($null -ne $UserInput['UpgradeOSVersion']) {
        Read-RMMigrationExtensionOSM -MigrationExtensionOSM $MigrationExtensionOSMArray -MigrationExtensionObject $MigrationExtensionResponse.content `
            -UpdatedUserInput $UserInput
    }

    #Security Settings
    Read-RMOSHardening -UpdatedUserInput $UserInput -Source $Source

    #Advanced Settings
    $TransferType = "file-based"
    if (!$ResizeMountPointsFlag) {
        $TransferType = (Get-RMTransferMethod -Source $Source -SelectedMountPoints $SelectedMountPoints -IsInteractive $true)[0]
    }
      
    $InstallAzureARC = Read-RMBoolean -UserMessage "Install azure ARC" -DefaultValue "false"
    $ProjectSettingsResponse = Invoke-RMProjectSettings -OrganizationId $CloudAccount.organization_id
    $InstallApplicationParameter = $null
    if ($InstallAzureARC) {
        $InstallApplicationParameter = $ProjectSettingsResponse.openshift.arc_settings
    }

    $ConnectARCAgent = $false
   
    if($null -ne $ProjectSettingsResponse.openshift.arc_settings) {
        $ConnectARCAgent = Read-RMBoolean -UserMessage "Connect ARC agent" -DefaultValue $false
    }

    $RemoveRMSAgent = Read-RMBoolean -UserMessage "Remove RMS agent post migration" -DefaultValue "false"

    $DisableTargetDNSRegistration = $false
    if ($Source.os_type -eq "windows") {
        $DisableTargetDNSRegistration = Read-RMBoolean -UserMessage "Disable automatic DNS registration on the Target" `
            -DefaultValue "false"
    }

    $ShutdownSource = Read-RMBoolean -UserMessage "Shutdown source after data is fully migrated" -DefaultValue "false"
    $ShutdownTarget = Read-RMBoolean -UserMessage "Shutdown target after data is fully migrated" -DefaultValue "false"
    

    $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 ("" -eq $ReadValue) {
            $ReadValue = "override_source_migration=true"
        } else {
            $ReadValue += ",override_source_migration=true"
        }
    }
    $MigrationInstruction = Get-RMStringAsHashtable -InputString $ReadValue

    $EnableCloudFilesMigration = Read-RMBoolean -UserMessage "Enable cloud files migration" -DefaultValue "false"

    $HashArguments = @{
        CloudAccount = $CloudAccount
        Entitlement = $Entitlement
        Source = $Source
        ScheduledAt = $ScheduledAt
        TransferMethod = $TransferType
        TargetVMName = $TargetVMName
        InstanceType = $InstanceType
        RAM = $RAM
        Sockets = $Sockets
        Cores = $Cores
        VolumeType = $StorageClass
        ResizeMountPoint = $MountsResize
        Project = $Project
        NetworkName = $DestinationNetworkName
        NetworkType = $NetworkAdaptersType
        NetworkAdapterModel = $NetworkAdapterModel
        RemoveRMSAgent = $RemoveRMSAgent
        ConnectARCAgent = $ConnectARCAgent
        InstallAzureARC = $InstallAzureARC
        InstallApplicationParameter = $InstallApplicationParameter
        NetBIOSName = $NetBIOSName
        IgnoreValidationError = $IgnoreValidationError
        ShutdownSource = $ShutdownSource
        ShutdownTarget = $ShutdownTarget
        GeneralizeSystem = $Sysprep
        DisableTargetDNSRegistration = $DisableTargetDNSRegistration
        AccessMode = $AccessMode
        VolumeMode = $VolumeMode
        MigrationInstruction = $MigrationInstruction
        EnableCloudFilesMigration = $EnableCloudFilesMigration
    }

    $HashArguments += $UserInput

    $Response = New-RMOpenshiftMigrationProfile @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 Start-RMOpenshiftOsBasedNonInteractiveMigration {
    param (
        [string] $TargetCloud,
        [string] $SourceIP,
        [string] $ScheduledAt,
        [string] $TargetVMName,
        [System.Object[]] $MountPoint,
        [string[]] $ResizeMountPoint,
        [string] $TransferMethod,
        [string] $UpgradeOSVersion,
        [string] $MigrationExtension,
        [string] $MigrationExtensionOSM,
        [string] $InstanceType,
        [int] $Cores,
        [int] $Sockets,
        [int] $RAM,
        [bool] $EnableOSHardening,
        [bool] $Level1Server,
        [bool] $Level2Server,
        [bool] $Level1Computer,
        [bool] $Level2Computer,
        [bool] $Level1User,
        [bool] $Level2User,
        [string] $AdministratorName,
        [string] $GuestName,
        [string] $LegalNoticeCaption,
        [string] $LegalNoticeText,
        [string] $StorageClass,
        [string] $Project,
        [string] $DestinationNetworkName,
        [string] $NetworkAdaptersType,
        [string] $NetworkAdapterModel,
        [bool] $RemoveRMSAgent,
        [bool] $ConnectARCAgent,
        [bool] $InstallAzureARC,
        [string] $NetBIOSName,
        [bool] $IgnoreValidationError,
        [bool] $ShutdownSource,
        [bool] $ShutdownTarget,
        [bool] $Sysprep,
        [bool] $DisableTargetDNSRegistration,
        [string] $AccessMode,
        [string] $VolumeMode,
        [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 "openshift"
            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-RMOpenshiftFullMigrationParameter $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 "openshift" `
                -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

    if ($null -ne $Source) {
        $SourceErrors = Confirm-RMOpenshiftFullMigrationParameterWithSource -UserParameter $PSBoundParameters `
            -Source $Source -MigrationExtension $MigrationExtensionArray -MigrationExtensionOSM $MigrationExtensionOSMArray

        if ($RequiredParameterState) {
            $IsRequiredParametersPresentAndValid = $RequiredParameterState
        }
        $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
    }
    $UserInput.Add("SelectedMount", $SelectedMountPoints)

    $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
    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
    if ($null -ne $ErrorsOSHardening) {
       $Errors += $ErrorsOSHardening
    }

    $AccessMode = Get-RMAccountModeName -AccessMode $AccessMode
    $NetworkAdaptersType = Get-RMNetworkAdapterType -AdapterType $NetworkAdaptersType

    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
        InstanceType = $InstanceType
        Cores = $Cores
        RAM = $RAM
        Sockets = $Sockets
        VolumeType = $StorageClass
        ResizeMountPoint = $MountsResize
        Project = $Project
        NetworkName = $DestinationNetworkName
        NetworkType = $NetworkAdaptersType
        NetworkAdapterModel = $NetworkAdapterModel
        RemoveRMSAgent = $RemoveRMSAgent
        ShutdownSource = $ShutdownSource
        ShutdownTarget =  $ShutdownTarget
        ConnectARCAgent = $ConnectARCAgent
        InstallAzureARC = $InstallAzureARC
        InstallApplicationParameter = $InstallApplicationParameter
        NetBIOSName = $NetBIOSName
        IgnoreValidationError = $IgnoreValidationError
        DisableTargetDNSRegistration = $DisableTargetDNSRegistration
        AccessMode = $AccessMode
        VolumeMode = $VolumeMode
        MigrationInstruction = $MigrationInstructionsAsHashTable
        EnableCloudFilesMigration = $EnableCloudFilesMigration
        GeneralizeSystem = $Sysprep
    }
    $HashArguments += $UserInput

    $Response = New-RMOpenshiftMigrationProfile @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-RMOpenshiftFullMigrationParameter {
    param (
        [hashtable] $UserParameter,
        [System.Object] $TargetInventory,
        [System.Object] $ProjectSettingsResponse
    )
    
    $Errors, $Warnings, $IsSourceAndTargetCloudPresent = Confirm-RMCommonParameter -UserParameter $UserParameter
    $openshiftErrors, $IsRequiredParametersPresentAndValid = Confirm-RMOpenshiftParameter -UserParameter $UserParameter `
        -TargetInventory $TargetInventory -ProjectSettingsResponse $ProjectSettingsResponse
    $Errors += $openshiftErrors
    return $Errors, $Warnings, $IsSourceAndTargetCloudPresent, $IsRequiredParametersPresentAndValid
}

function Confirm-RMOpenshiftFullMigrationParameterWithSource {
    param (
        [hashtable] $UserParameter,
        [System.Object] $Source,
        [System.Array] $MigrationExtension,
        [System.Array] $MigrationExtensionOSM
    )

    $Errors = @()
    $Errors = Confirm-RMCommonParameterWithSource -UserParameter $UserParameter -Source $Source `
        -MigrationExtension $MigrationExtension -MigrationExtensionOSM $MigrationExtensionOSM

    if ($Source.os_type -ne 'windows' -and $UserParameter["DisableTargetDNSRegistration"]) {
        $Errors += "DisableTargetDNSRegistration can only be 'true', if the source type is 'windows'."
    }
    
    return $Errors
}

function Confirm-RMOpenshiftParameter {
    param (
        [hashtable] $UserParameter,
        [System.Object] $TargetInventory,
        [System.Object] $ProjectSettingsResponse
    )

    $Errors = @()
    $IsRequiredParametersPresentAndValid = $true
    if (!$UserParameter.ContainsKey("Project") -or [string]::IsNullOrWhiteSpace($UserParameter["Project"])) {
        $Errors += "Project is reqired."
        $IsRequiredParametersPresentAndValid = $false
    } else {
        $ProjectNames = $TargetInventory.attributes.openshift.projects.name
        if ($ProjectNames -notcontains $UserParameter["Project"]) {
            $Project = $UserParameter["Project"]
            $Errors += "Project '$Project' does not exist."
            $IsRequiredParametersPresentAndValid = $false
        }
    }

    $StorageClassNames = $TargetInventory.attributes.openshift.storage_classes
    if (!$UserParameter.ContainsKey("StorageClass") -or [string]::IsNullOrWhiteSpace($UserParameter["StorageClass"])) {
        $Errors += "StorageClass is required."
        $IsRequiredParametersPresentAndValid = $false
    } else {
        $StorageClass = $UserParameter["StorageClass"]
        if ($StorageClassNames -notcontains $StorageClass) {
            $Errors += "StorageClass '$StorageClass' does not exist."
            $IsRequiredParametersPresentAndValid = $false
        }
    }

    if (!$UserParameter.ContainsKey("InstanceType") -or [string]::IsNullOrWhiteSpace($UserParameter["InstanceType"])) {
        if (!$UserParameter.ContainsKey("RAM") -or $null -ieq $UserParameter["RAM"]) {
            $Errors += "RAM or InstanceType is required."
            $IsRequiredParametersPresentAndValid = $false
        } elseif ($UserParameter["RAM"] -lt 2){
            $Errors += "The minimum RAM size must be greater than or equal to 2."
            $IsRequiredParametersPresentAndValid = $false
        }

        if (!$UserParameter.ContainsKey("Cores") -or $null -ieq $UserParameter["Cores"]) {
            $Errors += "Cores or InstanceType is required."
            $IsRequiredParametersPresentAndValid = $false
        } elseif ($UserParameter["Cores"] -lt 1) {
            $Errors += "The Cores value must be greater than or equal to 1."
            $IsRequiredParametersPresentAndValid = $false

        }

        if (!$UserParameter.ContainsKey("Sockets") -or $null -ieq $UserParameter["Sockets"]) {
            $Errors += "Sockets or InstanceType is required."
            $IsRequiredParametersPresentAndValid = $false
        } elseif ($UserParameter["Sockets"] -lt 1) {
            $Errors += "The Sockets value must be greater than or equal to 1."
            $IsRequiredParametersPresentAndValid = $false
        }
        
    } else {
        $InstanceTypeNames = $TargetInventory.attributes.openshift.instance_types.name
        if ($InstanceTypeNames -notcontains $UserParameter["InstanceType"]) {
            $InstanceType = $UserParameter["InstanceType"]
            $Errors += "InstanceType '$InstanceType' does not exist."
            $IsRequiredParametersPresentAndValid = $false
        }

        if ($UserParameter.ContainsKey("RAM") -and $null -ne $UserParameter["RAM"]) {
            $Errors += "InstanceType already exists. RAM is required when InstanceType is not used."
        }

        if ($UserParameter.ContainsKey("Cores") -and $null -ne $UserParameter["Cores"]) {
            $Errors += "InstanceType already exists. Cores is required when InstanceType is not used."
        }

        if ($UserParameter.ContainsKey("Sockets") -and $null -ne $UserParameter["Sockets"]) {
            $Errors += "InstanceType already exists. Sockets is required when InstanceType is not used."
        }
    }
    
    if (!$UserParameter.ContainsKey("NetworkAdapterModel") -or $null -ieq [string]::IsNullOrWhiteSpace($UserParameter["NetworkAdapterModel"])) {
        $Errors += "NetworkAdapterModel is required."
    }

    if (!$UserParameter.ContainsKey("NetworkAdaptersType") -or $null -ieq [string]::IsNullOrWhiteSpace($UserParameter["NetworkAdaptersType"])) {
        $Errors += "NetworkAdaptersType is required."
    }

    if (!$UserParameter.ContainsKey("DestinationNetworkName") -or $null -ieq [string]::IsNullOrWhiteSpace($UserParameter["DestinationNetworkName"])) {
        $Errors += "DestinationNetworkName is required."
    } else {
        $DestinationNetworkName = $UserParameter["DestinationNetworkName"]
        $DestinationNetworkNameOptions = $TargetInventory.attributes.openshift.networks.name
        if ($DestinationNetworkNameOptions -notcontains $DestinationNetworkName) {
           $Errors += "DestinationNetworkName '$DestinationNetworkName' is required."
        }
    }
    
    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 null."
            }
        }
    } elseif ($UserParameter.ContainsKey("InstallAzureARC") -and $UserParameter["InstallAzureARC"] `
                -and $UserParameter.ContainsKey("ConnectARCAgent") -and $UserParameter["ConnectARCAgent"] `
                -and $null -ieq $ProjectSettingsResponse.openshift.arc_settings) {
        $Errors += "'ConnectARCAgent' can not be true."
    }

    return $Errors, $IsRequiredParametersPresentAndValid
}

function Get-RMAccountModeName {
    param (
        [string] $AccessMode
    )

    $AccessModeName = ""
    switch ($AccessMode) {
        "Single user (RWO)" {  
            $AccessModeName = "ReadWriteOnce" 
            Break; 
        }
        "Shared access (RWX)" {
            $AccessModeName = "ReadWriteMany"
            Break; 
        }
        "Read only (ROX)" {
            $AccessModeName = "ReadOnlyMany"
            Break;
        }
    }
    return $AccessModeName
}

function Get-RMNetworkAdapterType {
    param(
        [string] $AdapterType
    )

    $AdapterTypeName = ""
    switch ($AdapterType) {
        "Masquerade" { 
            $AdapterTypeName = "masquerade"
            Break;
        }
        "Bridge" {
            $AdapterTypeName = "bridge"
            Break;
        }
    }
    return  $AdapterTypeName
}

function Get-RMNetworkNameByProject {
    param (
        [string] $Project,
        [System.Object] $TargetInventory
    )

    $NetworkNames = @()
    foreach($Proj in $TargetInventory.attributes.openshift.projects) {
        if ($Project -ieq $Proj.name) {
            $NetworkNames += $Proj.network_attachment_definitions.name
            Break;
        }
    }
    return $NetworkNames
}



function Start-RMOpenshiftVMBasedInteractiveMigration {
    param()

    $UserInput = @{}
    $Entitlement = Get-RMEntitlement
    $CloudAccount = Read-RMCloudAccount -AccountType "openshift" -UserMessage "Enter target cloud that supports VM-based migrations" `
         -VMBasedAppliancesOnly $true
    $Source = Read-RMVMBasedSource -UserMessage "Enter the VM name of the source machine to be migrated" `
        -ParameterName "Source VM name" -IsRequired $true -CloudAccount $CloudAccount

    [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new()
    if ($null -eq $CloudAccount) {
        return Update-RMMigrationReturnAsError `
            -Message "The migration appliance associated with the given source is not ready for use, cannot start the migration" `
            -RMMigrationReturn $RMMigrationReturn
    }

    $TargetInventory = Get-RMTargetInventory -CloudAccount $CloudAccount -IsOpenshiftMigration $true
    $IgnoreValidationError = Read-RMBoolean -UserMessage "Ignore validation errors" -DefaultValue "false"

    $Source, $ShouldExit, $OverrideExistingMigrationWarning, $OverrideExistingMigrationError = Get-RMSourceWithAttribute -Source $Source -CloudAccount $CloudAccount `
        -IgnoreValidationErrors $IgnoreValidationError -RMMigrationReturn $RMMigrationReturn  -AccountType "openshift"
    if ($ShouldExit) {
        return $RMMigrationReturn
    }

    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
    $TargetVMName = Read-RMString -UserMessage "Enter target VM Name" -DefaultValue $Source.host `
        -ParameterName "Target VM Name" -IsRequired $false
    
    $SelectedDisks = @()
    $ReturnedValue = Get-RMSelectedDisk -Source $Source
    if ($SelectedDisks -is [hashtable]) {
        $SelectedDisks += $ReturnedValue
    } else {
        $SelectedDisks = $ReturnedValue
    }

    #Placement Settings:
    $ProjectDefaultValue = $TargetInventory.attributes.openshift.projects.name
    $Project = Read-RMString -UserMessage "Enter project" -Options $ProjectDefaultValue `
        -ParameterName "Project" -IsRequired $true

    $InstanceType = Read-RMInstanceType -TargetInventory $TargetInventory
    if ("" -ieq $InstanceType) {
        $RAM = Read-RMRAMOrCPU -MinValue 2 -ErrorMessage "The minimum RAM size must be greater than or equal to 2." `
            -UserMessage "Enter RAM" -DefaultValue "2" -ParameterName "RAM"

        $Sockets = Read-RMRAMOrCPU -MinValue 1 -ErrorMessage "The Sockets value must be greater than or equal to 1." `
            -UserMessage "Enter sockets" -DefaultValue "1" -ParameterName "Sockets"

        $Cores = Read-RMRAMOrCPU -MinValue 1 -ErrorMessage "The Cores value must be greater than or equal to 1." `
            -UserMessage "Enter cores" -DefaultValue "1" -ParameterName "Cores"
    }

    $StorageClassDefalutValue = $TargetInventory.attributes.openshift.storage_classes
    $StorageClass =  Read-RMString -UserMessage "Enter storage class" -Options $StorageClassDefalutValue `
        -ParameterName "StorageClass" -IsRequired $true

    $AccessModeOptions = @("Single user (RWO)", "Shared access (RWX)", "Read only (ROX)")
    $AccessMode = Read-RMString -UserMessage "Enter access mode" -Options $AccessModeOptions -DefaultValue "Single user (RWO)" `
        -ParameterName "AccessMode" -IsRequired $false
    $AccessMode = Get-RMAccountModeName -AccessMode $AccessMode

    $VolumeModeOptions = @("Filesystem", "Block")
    $VolumeMode = Read-RMString -UserMessage "Enter volume mode" -Options $VolumeModeOptions -DefaultValue "Block" `
        -ParameterName "VolumeMode" -IsRequired $false

    $ModelOptions = @("virtio", "E1000E")
    $NetworkAdapterModel = Read-RMString -UserMessage "Enter network adapter model" -Options $ModelOptions -DefaultValue "virtio" `
        -ParameterName "NetworkAdapterModel" -IsRequired $false

    $AdaptersTypeOptions = @("Masquerade", "Bridge")
    $NetworkAdaptersType = Read-RMString -UserMessage "Enter network adapter type" -Options $AdaptersTypeOptions `
        -DefaultValue "Masquerade" -ParameterName "NetworkAdaptersType" -IsRequired $false
    $NetworkAdaptersType = Get-RMNetworkAdapterType -AdapterType $NetworkAdaptersType
    
    $DestinationNetworkNameOptions = $TargetInventory.attributes.openshift.networks.name
    $ProjectDestinationNetworkNameOptions = Get-RMNetworkNameByProject -Project $Project -TargetInventory $TargetInventory
    $ProjectDestinationNetworkNameOptions += $DestinationNetworkNameOptions
    $DestinationNetworkName = Read-RMString -UserMessage "Destination network name" -Options $ProjectDestinationNetworkNameOptions `
        -ParameterName "Destination network name" -IsRequired $true

    #Optimization Settings:
    $MigrationExtensionResponse = Get-RMMigrationExtension -OrganizationId $CloudAccount.organization_id
    $MigrationExtensionArray, $MigrationExtensionOSMArray = Get-RMMigrationExtensionFromStep -MigrationExtensionArray $MigrationExtensionResponse.content

    Read-RMMigrationExtension -CloudAccount $CloudAccount -MigrationExtension  $MigrationExtensionArray `
        -MigrationExtensionObject $MigrationExtensionResponse.content -UpdatedUserInput $UserInput

    $ShutdownSource = Read-RMBoolean -UserMessage "Shutdown source after data is fully migrated" -DefaultValue "false"
    $ShutdownTarget = Read-RMBoolean -UserMessage "Shutdown target after data is fully migrated" -DefaultValue "false"
    
    $FinalizeMigration = Read-RMBoolean -UserMessage "Remove snapshot(s) from the Target VM in preparation for a cutover" -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 ("" -eq $ReadValue) {
            $ReadValue = "override_source_migration=true"
        } else {
            $ReadValue += ",override_source_migration=true"
        }
    }
    $MigrationInstruction = Get-RMStringAsHashtable -InputString $ReadValue

    $HashArguments = @{
        CloudAccount = $CloudAccount
        Entitlement = $Entitlement
        Source = $Source
        ScheduledAt = $ScheduledAt
        TargetVMName = $TargetVMName
        Cores = $Cores
        RAM = $RAM
        Sockets = $Sockets
        VolumeType = $StorageClass
        AccessMode = $AccessMode
        VolumeMode = $VolumeMode 
        Project = $Project
        NetworkName = $DestinationNetworkName
        NetworkType = $NetworkAdaptersType
        NetworkAdapterModel = $NetworkAdapterModel
        SelectedMount = $SelectedDisks
        ShutdownSource = $ShutdownSource
        ShutdownTarget = $ShutdownTarget
        FinalizeTarget = $FinalizeMigration
        MigrationInstruction = $MigrationInstruction
        IgnoreValidationError = $IgnoreValidationError
        InstanceType = $InstanceType
    }

    $HashArguments += $UserInput

    $Response = New-RMOpenshiftVMBasedMigrationProfile @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 Start-RMOpenshiftVMBasedNonInteractiveMigration {
    param(
        [string] $TargetCloud,
        [string] $SourceVMName,
        [string] $ScheduledAt,
        [string[]] $SelectedDiskLabel,
        [string] $TargetVMName,
        [bool] $IgnoreValidationError,
        [string] $Project,
        [string] $InstanceType,
        [int] $Cores,
        [int] $Sockets,
        [int] $RAM,
        [string] $StorageClass,
        [string] $AccessMode,
        [string] $VolumeMode,
        [string] $DestinationNetworkName,
        [string] $NetworkAdaptersType,
        [string] $NetworkAdapterModel,
        [string] $MigrationExtension,
        [bool] $ShutdownSource,
        [bool] $ShutdownTarget,
        [bool] $FinalizeMigration,
        [string[]] $MigrationInstruction
    )

    $UserInput = @{}
    $CloudAccount = $null
    $CloudAccountErrors = $null
    $Source = $null
    $Entitlement = Get-RMEntitlement

    try {
        $TargetInventory = $null
        if (![string]::IsNullOrEmpty($TargetCloud)) {
            $CloudAccount, $ErrorString = Get-RMCloudAccountByName -CloudAccountName $TargetCloud `
                -AccountType "openshift" -VMBasedAppliancesOnly $true
            if ($null -eq $CloudAccount) {
                $CloudAccountErrors += $ErrorString
                $IsSourceAndTargetCloudPresent = $false
            } else {
                $TargetInventory = Get-RMTargetInventory -CloudAccount $CloudAccount
            }
        }
    } catch [System.Management.Automation.ItemNotFoundException] {
        $CloudAccountErrors += $PSItem.Exception.Message
        $IsSourceAndTargetCloudPresent = $false
    }

    $Errors, $Warnings, $IsSourceAndTargetCloudPresent, $IsRequiredParametersPresentAndValid = Confirm-RMOpenshiftVMBasedFullMigrationParameter $PSBoundParameters `
            -TargetInventory $TargetInventory

    if ($null -ne $CloudAccountErrors) {
        $Errors += $CloudAccountErrors
        $IsSourceAndTargetCloudPresent = $false
    }

    [RMMigrationReturn] $RMMigrationReturn = [RMMigrationReturn]::new()
    try {
        if (![string]::IsNullOrEmpty($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-RMOpenshiftOSBasedMigration'."
                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 -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 "openshift" `
                -RMMigrationReturn $RMMigrationReturn
    }
    catch [System.InvalidOperationException], [System.Management.Automation.RuntimeException] {
        $Errors += $PSItem.Exception.Message
    }

    $MigrationExtensionResponse = Get-RMMigrationExtension -OrganizationId $CloudAccount.organization_id
    $MigrationExtensionArray, $MigrationExtensionOSMArray = Get-RMMigrationExtensionFromStep -MigrationExtensionArray $MigrationExtensionResponse.content

    if ($null -ne $Source) {
        if ($null -eq $SelectedDiskLabel -or $SelectedDiskLabel.Count -eq 0) {
            # When the user has not selected any disk labels to migrate,
            # select all for the source.
            $Warnings += "No disk labels have been given, all the disks on the source will be migrated."
            $SelectedDiskLabel = Get-RMVMBasedSourceDiskLabel -Source $Source
            $PSBoundParameters["SelectedDiskLabel"] = $SelectedDiskLabel
        }
        $SourceErrors = Confirm-RMOpenshiftVMBasedFullMigrationParameterWithSource -MigrationExtension $MigrationExtension -SelectedDiskLabel $SelectedDiskLabel `
            -MigrationExtensionArray $MigrationExtensionArray -Source $Source
       if ($null -ne $SourceErrors) {
            $Errors +=  $SourceErrors
       }
    }

    Add-RMMigrationExtension -UpdatedParameter $UserInput -MigrationExtension $MigrationExtension `
        -MigrationExtensionOSM $MigrationExtensionOSM -MigrationExtensionResponse $MigrationExtensionResponse

    $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
    }
    $AccessMode = Get-RMAccountModeName -AccessMode $AccessMode
    $NetworkAdaptersType = Get-RMNetworkAdapterType -AdapterType $NetworkAdaptersType
    
    $SelectedDisk = Get-RMSelectedDiskByDiskLabel -DiskLabel $SelectedDiskLabel -Source $Source

    if ([string]::IsNullOrEmpty($TargetVMName)) {
        $TargetVMName = $Source.name
    }

    $HashArguments = @{
        CloudAccount = $CloudAccount
        Entitlement = $Entitlement
        Source = $Source 
        ScheduledAt = $ScheduledAt
        TargetVMName = $TargetVMName
        Cores = $Cores
        RAM = $RAM
        Sockets = $Sockets
        VolumeType = $StorageClass
        AccessMode = $AccessMode
        VolumeMode = $VolumeMode 
        Project = $Project
        NetworkName = $DestinationNetworkName
        NetworkType = $NetworkAdaptersType
        NetworkAdapterModel = $NetworkAdapterModel
        SelectedMount = $SelectedDisk
        ShutdownSource = $ShutdownSource
        ShutdownTarget = $ShutdownTarget
        FinalizeTarget = $FinalizeMigration
        MigrationInstruction = $MigrationInstructionsAsHashTable
        IgnoreValidationError = $IgnoreValidationError
        InstanceType = $InstanceType
    }

    $HashArguments += $UserInput

    $Response = New-RMOpenshiftVMBasedMigrationProfile @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-RMOpenshiftVMBasedFullMigrationParameter {
    param (
        [hashtable] $UserParameter,
        [System.Object] $TargetInventory
    )

    $Errors, $Warnings, $IsSourcePresent = Confirm-RMVMBasedCommonParameter -UserParameter $UserParameter
    $openshiftErrors, $IsRequiredParametersPresentAndValid = Confirm-RMOpenshiftParameter -UserParameter $UserParameter `
        -TargetInventory $TargetInventory
    $Errors += $openshiftErrors
    return $Errors, $Warnings, $IsSourcePresent, $IsRequiredParametersPresentAndValid
}

function Confirm-RMOpenshiftVMBasedFullMigrationParameterWithSource {
    [string] $MigrationExtension,
    [string[]] $SelectedDiskLabel,
    [System.Object] $MigrationExtensionArray,
    [System.Object] $Source

    $Errors = @()
    if (![string]::IsNullOrWhiteSpace($MigrationExtension)) {
        if ($MigrationExtensionArray -notcontains $MigrationExtension) {
            $Errors += "MigrationExtension '$MigrationExtension' does not exist."
        }
    }

    $SourceDiskLabels = Get-RMVMBasedSourceDiskLabel -Source $Source
    $DiskLabelsNotFound = @()
    foreach ($DiskLabel in $SelectedDiskLabel) {
        if ($SourceDiskLabels -notcontains $DiskLabel) {
            $DiskLabelsNotFound += $DiskLabel
        }
    }

    if ($DiskLabelsNotFound.Count -gt 0) {
        $DiskLabelsNotFoundAsString = $DiskLabelsNotFound -join ", "
        $Errors += "The disk label(s) '$DiskLabelsNotFoundAsString' specified in the parameter 'SelectedDiskLabel' does not exist on the source"
    }
    return $Errors
}


Export-ModuleMember -Function Start-RMOpenshiftOsBasedInteractiveMigration, Start-RMOpenshiftOsBasedNonInteractiveMigration, `
Start-RMOpenshiftOsBasedInteractiveMigration, Start-RMOpenshiftVMBasedInteractiveMigration, Start-RMOpenshiftVMBasedNonInteractiveMigration