Util/MigrationUtil.psm1

Import-Module -Name @(Join-Path $PSScriptRoot Util)

function Get-RMMigrationByIdAndStatus {
    param(
        [string] $MigrationId,
        [bool] $StatusOnly = $false
    )

    $RMLoginResult = Get-Variable -Name "RMContext-UserLogin"
    $Uri = Get-Variable -Name "RMContext-ReactorURI"

    $Headers = @{
        Accept = "application/json"
        Cookie = $RMLoginResult.Value
    }

    $Params = @{
        Method = "Get"
        Uri = $Uri.Value + "/migrations/" + $MigrationId + "?status_only=$StatusOnly"
        Headers = $Headers
        ContentType = "application/json"
    }

    return Invoke-RMRestMethod -Params $Params
}

function Get-RMMigrationInstruction {
    param (
        [string] $OrganizationId
    )

    $RMLoginResult = Get-Variable -Name "RMContext-UserLogin"
    $Uri = Get-Variable -Name "RMContext-ReactorURI"
    
    $Headers = @{
        Accept = "application/json"
        Cookie = $RMLoginResult.Value
    }

    $Params = @{
        Method = "Get"
        Uri = $Uri.Value + "/organizations/$OrganizationId/migrationinstructions"
        Headers = $Headers
        ContentType = "application/json"
    }

    return Invoke-RMRestMethod -Params $Params
}

function Get-RMMigrationInstructionAsHashTable {
    param (
        [string] $OrganizationId,
        [string[]] $MigrationInstruction,
        [string] $AccountType
    )

    $Errors = @()
    $MigrationInstructionsAsHashTable = $null
        try {
            $Response = Get-RMMigrationInstruction -OrganizationId $OrganizationId
            if ($null -ne $Response.$AccountType) {
                [string[]] $MigrationInstructionResponse = $Response.$AccountType
                $MigrationInstruction +=  $MigrationInstructionResponse -replace ":", "=" `
                    -replace "@", "" -replace "{", "" -replace "}", ""
            }
            $MigrationInstructionsAsHashTable = Get-RMStringArrayAsHashtable -InputItems $MigrationInstruction -ParameterName "MigrationInstruction"
         } catch {
             $Errors += $PSItem.Exception.Message
        }

        return $MigrationInstructionsAsHashTable, $Errors
}

function Get-RMMigrationListBySourceId {
    param (
        [string] $OrganizationId,
        [string] $SourceId,
        [string] $MigrationType
    )
    $RMLoginResult = Get-Variable -Name "RMContext-UserLogin"
    $Uri = Get-Variable -Name "RMContext-ReactorURI"

    $Headers = @{
        Accept = "application/json"
        Cookie = $RMLoginResult.Value
    }

    if (![string]::IsNullOrEmpty($MigrationType)) {
        $URI = $Uri.Value + "/organizations/" + $OrganizationId + "/migrations?source=$SourceId&migration_type=$MigrationType"
    } else {
        $URI = $Uri.Value + "/organizations/" + $OrganizationId + "/migrations?source=$SourceId"
    }

    $Params = @{
        Method = "Get"
        Uri = $URI
        Headers = $Headers
        ContentType = "application/json"
    }

    $Response = Invoke-RMRestMethod -Params $Params
    
    return $Response.content
}

function Get-RMScheduledMigration {
    param (
        [int] $Page,
        [int] $Size,
        [String] $Filter
    )
    
    $RMLoginResult = Get-Variable -Name "RMContext-UserLogin"
    $Uri = Get-Variable -Name "RMContext-ReactorURI"

    $OrganizationId = Get-Variable -Name "RMContext-CurrentProjectId" -ValueOnly

    $Uri = $Uri.Value + "/organizations/" + $OrganizationId + "/scheduledmigrations?size=$Size&page=$Page"

    if (![string]::IsNullOrEmpty($Filter)) {
        $Uri = $Uri + "&combined_search=$Filter"
    }

    $Headers = @{
        Accept = "application/json"
        Cookie = $RMLoginResult.Value
    }

    $Params = @{
        Method = "Get"
        Uri = $Uri
        Headers = $Headers
        ContentType = "application/json"
    }

    return Invoke-RMRestMethod -Params $Params
}

function Get-RMMigrationsByFilter {
    param(
        [string] $OSType,
        [string] $CloudType,
        [string] $MigrationType,
        [string] $State, 
        [bool] $Archived,
        [string] $CombinedSearch,
        [int] $Page,
        [int] $Size
    )

    $RMLoginResult = Get-Variable -Name "RMContext-UserLogin"
    $Uri = Get-Variable -Name "RMContext-ReactorURI"

    $OrganizationId = Get-Variable -Name "RMContext-CurrentProjectId" -ValueOnly

    $Headers = @{
        Accept = "application/json"
        Cookie = $RMLoginResult.Value
    }

    $Uri = $Uri.Value + "/organizations/$OrganizationId/migrations?size=$Size&page=$Page&sort=created_at,desc&archived=$Archived" 

    if (![string]::IsNullOrWhiteSpace($OSType)) {
        $Uri = $Uri + "&source_os_type=$OSType"
    }

    if (![string]::IsNullOrWhiteSpace($CloudType)) {
        $CloudType = Get-RMCloudType -Name $CloudType
        $Uri = $Uri + "&cloud_type=$CloudType"
    }

    if (![string]::IsNullOrWhiteSpace($MigrationType)) {
        $MigrationType = Get-RMMigrationType -Name $MigrationType
        $Uri = $Uri + "&migration_type=$MigrationType"
    }

    if (![string]::IsNullOrWhiteSpace($State)) {
        $State = Get-RMMigrationState -Name $State
        $Uri = $Uri + "&state=$State"
    }

    if(![string]::IsNullOrWhiteSpace($CombinedSearch)) {
        $Uri = $Uri + "&combined_search=$CombinedSearch"
    }

    $Params = @{
        Method = "Get"
        Uri = $Uri
        Headers = $Headers
        ContentType = "application/json"
    }

    return Invoke-RMRestMethod -Params $Params
}

function Get-RMCloudType {
    param (
        [string] $Name
    )

    $CloudType = ""
    switch ($Name) {
        "AWS" {
            $CloudType = "aws"
            break
        }

        "Azure" {
            $CloudType = "azure"
            break
        }

        "GoogleCloud" {
            $CloudType = "gcp"
            break
        }

        "vSphere" {
            $CloudType = "rivermeadow_standalone"
            break
        }

        "OpenStack" {
            $CloudType = "openstack"
            break
        }
    }
    return $CloudType
}

function Get-RMMigrationType {
    param(
        [string] $Name
    )

    $MigrationType = ""
    switch ($Name) {
        "Workload" {
            $MigrationType = "full"
            break
        }

        "WorkloadDelta" {
            $MigrationType = "differential"
            break
        } 
        
        "Continuous" {
            $MigrationType = "continuous"
            break
        }
         
        "DOM" {
            $MigrationType = "data_only_full"
            break
        } 
        
        "DataOnly" {
            $MigrationType = "data_only_differential"
            break
        } 
        
        "NetAppFilesFull" {
            $MigrationType = "netapp_full"
            break
        }
        
        "NetAppFilesDifferential" {
            $MigrationType = "netapp_differential"
            break
        } 
                    
        "OSModernization" {
            $MigrationType = "in_situ_osm"
            break
        } 
        
        "RevertFromSnapshot" {
            $MigrationType = "in_situ_osm_restore"
            break
        } 
        
        "RemoveSnapshot" {
            $MigrationType = "in_situ_osm_cleanup"
            break
        }  
    }

    return $MigrationType
}

function Get-RMMigrationState () {
    param(
        [string] $Name
    )

    $State = ""
    switch ($Name) {
        "InProgress" {
            $State = "running"
            break
        }

        "Paused" {
            $State = "paused"
            break
        }

        "Completed" {
            $State = "success"
            break
        }

        "Failed" {
            $State = "error"
            break
        }

        "Pending" {
            $State = "pending"
            break
        }

        "Cancelled" {
            $State = "cancelled"
            break
        }
    }
    return $State
}

function Get-RMDisplayMigrationType {
    param (
        [string] $Name,
        [System.Object] $Migration
    )

    $State = $Name
    switch ($Name) {
        "full" {
            if ($Migration.is_data_only) {
                if ("data_store" -ieq $Migration.source.collection_type) {
                    $State = "Workload"
                    break
                } else {
                    if ($Migration.is_vdi) {
                        $State = "VDI Migration"
                    } else {
                        $State = "DOM Setup"
                    }
                    break
                } 
            }
            $State = "Workload"
            break
          }
       
        "in_situ_osm"  {
            $State = "OS Modernization"
            break
        }

        "in_situ_modernization" {
            $State = "OS Modernization"
            break
        }

        "in_situ_osm_cleanup" {
            $State = "Remove Snapshot"
            break
        }

        "in_situ_modernization_cleanup" {
            $State = "Remove Snapshot"
            break
        }

        "in_situ_osm_restore" {
            $State = "Revert from Snapshot"
            break
        }

        "in_situ_modernization_restore" {
            $State = "Revert from Snapshot"
            break
        }

        "cold_full" {
            $State = "Cold"
            break
        }

        "warm_full" {
            $State = "Warm"
        }

        "differential" {
            if ("continuous" -ieq $Migration.transfer_mode -and $Migration.is_data_only) {
                $State = "Continuous, Data Only"
                break
            } elseif ($Migration.is_data_only) {
                $State = "data_store" -ieq $Migration.source.collection_type ? "Workload Delta" : "Data Only"
                break
            } elseif ("continuous" -ieq $Migration.transfer_mode) {
                $State = "Continuous"
                break
            }

            $State = "Workload Delta"
            break
        }
    }

    return $State
    
}

function Get-RMMigrationsByIds {
    param(
        [string[]] $MigrationIds
    )

    $RMLoginResult = Get-Variable -Name "RMContext-UserLogin"
    $Uri = Get-Variable -Name "RMContext-ReactorURI"

    $MigrationIdString  = $MigrationIds -join ","

    $Headers = @{
        Accept = "application/json"
        Cookie = $RMLoginResult.Value
    }

    $Params = @{
        Method = "Get"
        Uri = $Uri.Value + "/migrations?migration_ids=" + $MigrationIdString
        Headers = $Headers
        ContentType = "application/json"
    }

    return Invoke-RMRestMethod -Params $Params
}

function Get-RMCurrentStepIndex {
    param(
        [system.Object] $Migration
    )
    $Index = 0
    switch ($Migration.state) {
        "success" {
            $Index = $Migration.steps.Count
            break
        }
        {($_ -ieq "running") -or ($_ -ieq "error")} {
            while ($Migration.steps.Count -gt ($Index + 1) -and $Migration.steps[$Index + 1].state -ine "pending") {
                $Index++
            }
            break
        }
    }

    return $Index
}

function Get-RMFirstPendingStepIndex {
    param(
        [System.Object] $Migration
    )
    $Index = -1
    foreach ($Step in $Migration.steps) {
        $Index ++
        if ($Step.state -ieq "pending") {
            return $Index
        }
    }

    return $Index
}

function Get-RMMigrationProgress {
    param(
        [System.Object] $Migration
    )
    $StepIndex = 0
    if ($Migration.state -ieq "pending") {
        $StepIndex = Get-RMFirstPendingStepIndex -Migration $Migration
    } else {
        $StepIndex = Get-RMCurrentStepIndex -Migration $Migration
    }

    return [int](($StepIndex/$Migration.steps.Count) * 100)
}

function Test-RMMigrationStalled {
    param(
        [System.Object] $Migration
    )

    if ($Migration.state -ne "running") {
        return $false
    }
    foreach ($Step in $Migration.steps) {
        if ($Step.state -eq "running" -and $null -ne $Step.recoverable_errors -and $Step.recoverable_errors.Count -gt 0) {
            return $true
        }
    }

    return $false
}

function Get-RMMigrationsNotFound {
    param(
        [string[]] $ReceivedMigrationIds,
        [string[]] $UserInputMigrationIds
    )

    $NotFoundMigrationIds = @()
    $CompareResults = Compare-Object -ReferenceObject $UserInputMigrationIds -DifferenceObject $ReceivedMigrationIds
    foreach ($CompareResult in $CompareResults) {
        if ($CompareResult.SideIndicator -contains "<=") {
            $NotFoundMigrationIds += $CompareResult.InputObject
        }
    }

    return $NotFoundMigrationIds
}

function Get-RMMigrationIdFromResponse {
    param(
        [System.Object] $Response
    )
    $MigrationId = ""
    if ($Response.links[1].rel -ine "migration") {
        return $MigrationId
    }

    $SplitData = $Response.links[1].href.split("/")
    if ($SplitData.Count -lt 7) {
        return $MigrationId
    }

    if ($SplitData[6].Contains("{")) {
        $MigrationId = $SplitData[6].SubString(0, $SplitData[6].IndexOf("{"))
    } else {
        $MigrationId = $SplitData[6].SubString(0, $SplitData[6].Length)
    }
    return $MigrationId
}

function Read-RMOSHardening {
    param (
        [hashtable] $UpdatedUserInput,
        [System.Object] $Source
    )

    $OSHardening = $null
    $IsOsHardeningSupported = Get-RMEnableOSHardening -Source $Source -UpgradeOSVersion $UpdatedUserInput['UpgradeOSVersion']

    if ($IsOsHardeningSupported) {
        $EnableOSHardening = $false
        $EnableOSHardening = Read-RMBoolean -UserMessage "Enable OS Hardening" -DefaultValue $EnableOSHardening
        if ($EnableOSHardening) {
            if ("linux" -ieq $Source.os_type) {
                $Level1 = Read-RMBoolean -UserMessage "Level 1 - Server" -DefaultValue "false"
                $Level2 = Read-RMBoolean -UserMessage "Level 2 - Server" -DefaultValue "false"
    
                $OSHardening = @{
                    "levels" = @( 
                        if (($Level1 -and $Level2) -or $Level2) { "s_l2" } elseif ($Level1) { "s_l1" }
                    )
                }  
            } else {
                $ReadValue = Read-RMBoolean -UserMessage "Do you want make computer configuration?" -DefaultValue "false"
                if ($ReadValue) {
                    $Level1Computer = Read-RMBoolean -UserMessage "Level 1 - Member Server" -DefaultValue "false"
                    $Level2Computer = Read-RMBoolean -UserMessage "Level 2 - Member Server" -DefaultValue "false"
                } 
    
                if ($Level1Computer -or $Level2Computer) {
                    $AdministratorName = Read-RMString -UserMessage "Enter administrator name" -DefaultValue "None" -IsRequired $false `
                        -ParameterName "Administrator Name"
                    
                    $GuestName = Read-RMString -UserMessage "Enter guest name" -DefaultValue "None" -IsRequired $false `
                        -ParameterName "Guest Name"
    
                    $LegalNoticeCaption = Read-RMString -UserMessage "Enter legal notice caption" -DefaultValue "None" -IsRequired $false `
                        -ParameterName "Legal Notice Caption"
    
                    $LegalNoticeText = Read-RMString -UserMessage "Enter legal notice text" -DefaultValue "None" -IsRequired $false `
                        -ParameterName "Legal Notice Text"
                    
                    $OSHardening = @{
                        "admin_name" = if ([string]::IsNullOrEmpty($AdministratorName)) { $null } else { $AdministratorName }
                        "guest_name" = if ([string]::IsNullOrEmpty($GuestName)) { $null } else { $GuestName }
                        "legal_notice_caption" = if ([string]::IsNullOrEmpty($LegalNoticeCaption)) { $null } else { $LegalNoticeCaption }
                        "legal_notice_text" =  if ([string]::IsNullOrEmpty($LegalNoticeText)) { $null } else { $LegalNoticeText }
                        "levels" = @(
                            if (($Level2Computer -and $Level1Computer) -or $Level2Computer) { "ms_l2" } elseif ($Level1Computer) { "ms_l1" }
                        )
                    }
                    
                } 
    
                $ReadValue =  Read-RMBoolean -UserMessage "Do you want make user configuration?" -DefaultValue "false"
                if ($ReadValue) {
                    $Level1User = Read-RMBoolean -UserMessage "Level 1 - Member Server" -DefaultValue "false"
                    $Level2User = Read-RMBoolean -UserMessage "Level 2 - Member Server" -DefaultValue "false"
    
                    $OSHardeningUser = $null
                    if (($Level2User -and $Level1User) -or $Level2User) {
                        $OSHardeningUser = @{
                            "levels" = @("user_l2")
                        }
                    } elseif ($Level1User) {
                        $OSHardeningUser = @{
                            "levels" = @("user_l1")
                        }
                    }
    
                    if ($null -ne $OSHardeningUser) {
                        if ($null -ieq  $OSHardening) {
                            $OSHardening = $OSHardeningUser 
                        } else {
                            $OSHardening.levels += $OSHardeningUser.levels
                        }
                    }
                }
            }
        }
       
    }

    $UpdatedUserInput.Add("OSHardening", $OSHardening)
}

function Add-RMOSHardening {
    param (
        [System.Object] $Source,
        [hashtable] $UpdatedParameter,
        [hashtable] $UserParameter
    )
     

    $OSHardening = $null
    
    if ($UserParameter["EnableOSHardening"]) {
        
        $IsOsHardeningSupported = Get-RMEnableOSHardening -Source $Source -UpgradeOSVersion $UpdatedParameter['UpgradeOSVersion']
        if ($IsOsHardeningSupported ) {
            if ("linux" -ieq $Source.os_type) {
                $OSHardening = @{
                    "levels" = @( 
                        if (($UserParameter["Level1Server"] -and $UserParameter["Level2Server"]) -or $UserParameter["Level2Server"]) { "s_l2" } 
                            elseif ($UserParameter["Level1Server"]) { "s_l1" }
                    )
                }
            } else {
                $OSHardening = @{
                    "admin_name" = $UserParameter["AdministratorName"]
                    "guest_name" = $UserParameter["GuestName"]
                    "legal_notice_caption" = $UserParameter["LegalNoticeCaption"]
                    "legal_notice_text" =  $UserParameter["LegalNoticeText"]
                    "levels" = @(
                        if (($UserParameter["Level2Computer"] -and $UserParameter["Level1Computer"]) -or $UserParameter["Level2Computer"]) { "ms_l2" } 
                            elseif ($UserParameter["Level1Computer"]) { "ms_l1" }
                        if (($UserParameter["Level2User"] -and $UserParameter["Level1User"]) -or $UserParameter["Level2User"]) { "user_l2" } 
                            elseif ($UserParameter["Level1User"]) { "user_l1" }
                    )
                }
            }
        } else {
            $Errors += "'EnableOSHardening' is not supported for the given source."
        }
    } 
    $UpdatedParameter.Add("OSHardening", $OSHardening)

    return $Errors
}


function Add-RMOSUpgrade {
    param (
        [hashtable] $UserParameter,
        [hashtable] $UpdatedParameter,
        [System.Object] $Source
    )
    $SourceOSMMapping = Get-RMOSMMappingBySource -Source $Source
    $UpgradeOSVersion = $UserParameter["UpgradeOSVersion"]
    if (![string]::IsNullOrEmpty($UpgradeOSVersion) -and $null -ne $SourceOSMMapping[$UpgradeOSVersion] `
            -and $SourceOSMMapping.Keys.Count -gt 0) {
        $UpgradeOSVersion = $UpgradeOSVersion.Trim('"')
        $UpgradeOSVersion = $UpgradeOSVersion.Trim("'")
        $UpdatedParameter.Add("UpgradeOSVersion", $SourceOSMMapping[$UpgradeOSVersion])
        $UpdatedParameter.Add("InPlaceUpgrade", $true)
    } else {
        $UpdatedParameter.Add("UpgradeOSVersion", $null)
        $UpdatedParameter.Add("InPlaceUpgrade", $false)
    }    
}

function Add-RMMigrationExtension {
    param (
        [hashtable] $UpdatedParameter,
        [string] $MigrationExtension,
        [string] $MigrationExtensionOSM,
        [System.Object] $MigrationExtensionResponse
    )

    if (![string]::IsNullOrEmpty($MigrationExtension)) {
        $MigrationExtensionId = Get-RMMigrationExtensionId -MigrationExtension $MigrationExtension -MigrationExtensionArray $MigrationExtensionResponse.content `
            -ExecutionStep 3
        $UpdatedParameter.Add("MigrationExtension", $MigrationExtension)
        $UpdatedParameter.Add("MigrationExtensionId", $MigrationExtensionId)
    }

    if (![string]::IsNullOrEmpty($MigrationExtensionOSM)) {
        $MigrationExtensionIdOSM = Get-RMMigrationExtensionId -MigrationExtension $MigrationExtensionOSM -MigrationExtensionArray $MigrationExtensionResponse.content `
            -ExecutionStep 4
        $UpdatedParameter.Add("MigrationExtensionOSM", $MigrationExtensionOSM)
        $UpdatedParameter.Add("MigrationExtensionIdOSM", $MigrationExtensionIdOSM)
    }
}

function Read-RMMigrationExtension {
    param(
        [System.Object] $CloudAccount,
        [System.Array] $MigrationExtension,
        [System.Object] $MigrationExtensionObject,
        [hashtable] $UpdatedUserInput
    )

    if ($MigrationExtension.Count -gt 0) {
        $ReadValue = Read-RMString -UserMessage "Enter migration extensions" -Options  $MigrationExtension -ParameterName "Migration Extension" `
            -IsRequired $false -DefaultValue "None"
        $MigrationExtensionId = Get-RMMigrationExtensionId -MigrationExtension $ReadValue -MigrationExtensionArray $MigrationExtensionObject `
            -ExecutionStep 3
        $UpdatedUserInput.Add("MigrationExtension", $ReadValue)
        $UpdatedUserInput.Add("MigrationExtensionId", $MigrationExtensionId)
    } else {
        $UpdatedUserInput.Add("MigrationExtension", $null)
        $UpdatedUserInput.Add("MigrationExtensionId", $null)
    }
}

function Read-RMMigrationExtensionOSM {
    param (
       [System.Array] $MigrationExtensionOSM,
       [System.Object] $MigrationExtensionObject,
       [hashtable] $UpdatedUserInput
    )

    if ($MigrationExtensionOSM.Count -gt 0) {
        $ReadValue = Read-RMString -UserMessage "Enter migration extension name" -Options  $MigrationExtensionOSM -ParameterName "Migration Extension" `
            -IsRequired $false -DefaultValue "None"
        $MigrationExtensionIdOSM = Get-RMMigrationExtensionId -MigrationExtension $ReadValue -MigrationExtensionArray $MigrationExtensionObject `
            -ExecutionStep 4 
        $UpdatedUserInput.Add("MigrationExtensionOSM", $ReadValue)
        $UpdatedUserInput.Add("MigrationExtensionIdOSM", $MigrationExtensionIdOSM)
    } else {
        $UpdatedUserInput.Add("MigrationExtensionOSM", $null)
        $UpdatedUserInput.Add("MigrationExtensionIdOSM", $null)
    }
}

function Read-RMReplaceWindowsLicense {
    param (
        [System.Object] $Source,
        [System.Object] $ProjectSettingsResponse,
        [string] $CloudType
    )
    
    $ReplaceWindowsLicense = ""
    $ReplaceWindowsLicenseKey = ""
    if ("windows" -ieq $Source.os_type) {
        $WindowsLicense = Get-RMWindowsKMSKeyMapping -WindowsLicense $ProjectSettingsResponse.$CloudType.windows_license_keys

        $ReplaceWindowsLicenseKey = Read-RMString -UserMessage "Replace Windows License" -Options $WindowsLicense.keys -ParameterName "ReplaceWindowsLicense" `
                -DefaultValue "None" -IsRequired $false
        if ("" -ne $ReplaceWindowsLicenseKey) {
            $ReplaceWindowsLicense = $WindowsLicense[$ReplaceWindowsLicenseKey]
        }
    }

    return $ReplaceWindowsLicense, $ReplaceWindowsLicenseKey
}

function Read-RMOSUpgradeOption {
    param(
        [System.Object] $Source,
        [hashtable] $UpdatedUserInput,
        [string] $ReplaceWindowsLicenseKey,
        [System.Object] $MigrationExtensionOSMArray,
        [System.Object] $MigrationExtensionResponse
    )

    $SourceOSMMapping = Get-RMOSMMappingBySource -Source $Source

    if ($SourceOSMMapping.Keys.Count -gt 0) {
        $ReadValue = Read-RMString -UserMessage "Enter the OS version to upgrade to" -Options $SourceOSMMapping.keys -DefaultValue "None" `
            -ParameterName "Upgrade OS version" -IsRequired $false
        if ("" -ne $ReadValue) {
            $ReadValue = $ReadValue.Trim('"')
            $ReadValue = $ReadValue.Trim("'")
            $UpdatedUserInput.Add("UpgradeOSVersion", $SourceOSMMapping[$ReadValue])
            $UpdatedUserInput.Add("InPlaceUpgrade", $true)

            $OSVersion = Get-RMWindowsOSMapping
            if ("windows" -ieq $Source.os_type -and  "" -ne $ReplaceWindowsLicenseKey -and `
                $OSVersion[$SourceOSMMapping[$ReadValue]] -ne $ReplaceWindowsLicenseKey)  {
                throw "The selected licence key version ($ReplaceWindowsLicenseKey) does not match the OS Modernization version."
            }

            Read-RMConvertFileSystem -Source $Source -UpdatedUserInput $UpdatedUserInput

            Read-RMMigrationExtensionOSM -MigrationExtensionOSM $MigrationExtensionOSMArray -MigrationExtensionObject $MigrationExtensionResponse.content `
                -UpdatedUserInput $UpdatedUserInput

        } else {
            $UpdatedUserInput.Add("UpgradeOSVersion", $null)
            $UpdatedUserInput.Add("InPlaceUpgrade", $false)
        }
    } else {
        $UpdatedUserInput.Add("UpgradeOSVersion", $null)
        $UpdatedUserInput.Add("InPlaceUpgrade", $false)
    }    

    if ("windows" -ieq $Source.os_type -and $null -ieq $UpdatedUserInput["UpgradeOSVersion"] -and ![string]::IsNullOrEmpty($ReplaceWindowsLicenseKey)) {
        throw "'UpgradeOSVersion' is required, when 'ReplaceWindowsLicense' is not null."
    }
}

function Read-RMConvertFileSystem {
    param (
        [System.Object] $Source,
        [hashtable] $UpdatedUserInput
    ) 

    $ConvertFileSystemObject = @{}
    
    if ("linux" -ieq $Source.os_type -and  `
        $Source.attributes.storage.mounts.psobject.properties.value.fs_type -contains 'ext4') {
            $ReadValue = Read-RMBoolean -UserMessage "Linux filesystem converter" -DefaultValue "false"
           if ($null -ne $UpdatedUserInput['MountPoints']) {
                $SelectedMountPoints = $UpdatedUserInput['MountPoints']
            } else {
                $SelectedMountPoints = $UpdatedUserInput['SelectedMount']
            }
            if ($ReadValue) {
                foreach($MointPoint in $SelectedMountPoints.Values) {
                    $ConvertFileSystemObject.Add($MointPoint, "xfs")
                }
            }   
    }  
    
    $UpdatedUserInput.Add("ConvertFileSystem", $ConvertFileSystemObject)
}

function Add-RMConvertFileSystem {
    param (
        [System.Object] $Source,
        [hashtable] $UpdatedUserInput,
        [string] $ConvertFileSystem
    )

    $ConvertFileSystemObject = @{}

    if ("linux" -ieq $Source.os_type -and  `
        $Source.attributes.storage.mounts.psobject.properties.value.fs_type -contains 'ext4') {
            if($null -ne $UpdatedUserInput['MountPoints']) {
                $SelectedMountPoints =  $UpdatedUserInput['MountPoints']
            } else {
                $SelectedMountPoints =  $UpdatedUserInput['SelectedMount']
            }
      
        foreach($MointPoint in $SelectedMountPoints.Values) {
            $ConvertFileSystemObject.Add($MointPoint, "xfs")
        }
    }
    $UpdatedUserInput.Add("ConvertFileSystem", $ConvertFileSystemObject)
}

function Read-RMSQLServerUpgradeOption {
    param (
        [System.Object] $Source
    )

    $SQLServerUpgradeArray = @()
    $SourceSQLServerMapping = Get-RMSQLMMappingBySource -Source $Source
    
    if ($SourceSQLServerMapping.Count -lt 1) {
        return $SQLServerUpgradeArray
    }

    $ReadValue = Read-RMBoolean -UserMessage "Do you want to upgrade SQL server?" -DefaultValue $false

    if (!$ReadValue) {
        return $SQLServerUpgradeArray
    }

    if ($SourceSQLServerMapping.Count -gt 0) { 
        foreach ($SQLServerObject in $SourceSQLServerMapping) {
            $Instance = $SQLServerObject.display_name
            $UpgradeVersion = Read-RMString -UserMessage "Enter the SQL version to upgrade to for $Instance" -Options  $SQLServerObject.upgrade_options -DefaultValue "None" `
                -ParameterName "Upgrade Version" -IsRequired $false
            if (![string]::IsNullOrWhiteSpace($UpgradeVersion)) {
                $AdditionalProperty = Read-RMString -UserMessage "Enter any additional parameters:" -DefaultValue "None" -ParameterName "Additional Parameters" `
                    -IsRequired $false
                $SQLServerMapping = Get-RMSQLServerMapping -GUID $SQLServerObject.guid -UpgradeVersion $UpgradeVersion -UpgradeDisplayName $SQLServerObject.display_name `
                    -AdditionalParam $AdditionalProperty
                $SQLServerUpgradeArray +=  $SQLServerMapping
            }
        }
    }

    return $SQLServerUpgradeArray
}

function Get-RMUpgradeSQLServer {
    param(
        [hashtable[]] $UpgradeSQLServer,
        [System.Object] $Source,
        [System.Object] $SourceSQLServerMapping
    )
    $SQLServerUpgradeArray = @()

    foreach($Upgrade in $UpgradeSQLServer) {
        foreach($SQLServerObject in $SourceSQLServerMapping) {
            if ($Upgrade.InstanceName -ieq $SQLServerObject.instance_name) {
                $SQLServerMapping =  Get-RMSQLServerMapping -GUID $SQLServerObject.guid -UpgradeVersion $Upgrade.UpgradeVersion `
                    -UpgradeDisplayName $SQLServerObject.display_name -AdditionalParam $Upgrade.AdditionalParams
                $SQLServerUpgradeArray += $SQLServerMapping
            }
        }
    }
    
    return  $SQLServerUpgradeArray
}

function Get-RMSQLServerMapping {
    param(
        [string] $GUID,
        [string] $UpgradeVersion,
        [string] $UpgradeDisplayName,
        [string] $AdditionalParam
    )

    $UpgradeDisplayName =  $UpgradeDisplayName -replace " -" , ","
    $UpgradeDisplayName = $UpgradeDisplayName + " : " + $UpgradeVersion
    $UpgradeVersion = "MSSQL" + $UpgradeVersion
    $GUID = $GUID.ToUpper()
    $SQLServiceMapping = @{
        "product_family" = "mssql"
        "guid" = "{$GUID}"
        "upgrade_version" = $UpgradeVersion
        "upgrade_display_name" = $UpgradeDisplayName
        "upgrade_parameters" = @{
            "additional_setup_params" =  $AdditionalParam
        }
    }

    return  $SQLServiceMapping
}

function Test-RMSourceHasRunningMigration {
    param(
        [string] $OrganizationId,
        [string] $SourceId
    )
    $MigrationList = Get-RMMigrationListBySourceId -OrganizationId $OrganizationId -SourceId $SourceId
    foreach ($Mig in $MigrationList) {
        if ("running" -eq $Mig.state) {
            return $true
        }
    }

    return $false
}

function Get-RMMigrationExtensionFromStep {
    param (
        [System.Object] $MigrationExtensionArray
    )

    $MigrationExtension = @()
    $MigrationExtensionOSM = @()

    foreach ($Me in $MigrationExtensionArray) {
        if (4 -eq $Me.execution_step) {
            $MigrationExtensionOSM += $Me.name
        } else {
            $MigrationExtension += $Me.name
        }
    }
    
    return $MigrationExtension, $MigrationExtensionOSM 
}


function Get-RMMigrationExtensionId {
    param (
        [string] $MigrationExtension,
        [System.Object] $MigrationExtensionArray,
        [int] $ExecutionStep
    )
    
    $MigrationExtensionId = ""
    if ("" -ne  $MigrationExtension) {
        foreach ($Me in $MigrationExtensionArray) {
            if ($MigrationExtension -ieq $Me.name -and $ExecutionStep -eq $Me.execution_step) {
                $MigrationExtensionId = $Me.id
                break
            }
        }
    }
    return $MigrationExtensionId
}

function Get-RMEnableOSHardening {
    param (
        [System.Object] $Source,
        [string] $UpgradeOSVersion
    )
    
    $Showing = $false
    if ($null -ne $Source.attributes.os.source_migration_state) {
        $MigrationState = $Source.attributes.os.source_migration_state | ConvertFrom-Json
    }

    $WindowsIsLaterVersion = @("2016", "2019", "2022")
    
    [array] $OSUpgradeVersion =  $MigrationState.upgrade_options
    [array] $OSConversionVersion = $MigrationState.conversion_options

    [double] $Version = $Source.attributes.os.version
    if ("windows" -ieq $Source.os_type) {
        if ($WindowsIsLaterVersion -contains $Source.attributes.os.version -or ($OSUpgradeVersion.Count -gt 0 -and $OSUpgradeVersion -contains $UpgradeOSVersion) `
        -or ($OSConversionVersion.Count -gt 0 -and $OSConversionVersion -contains $UpgradeOSVersion)) {
            $Showing = $true
        }
    } else {
        if ('Red Hat Enterprise Linux Server' -ieq $Source.attributes.os.vendor -and ` ((8 -ieq $Version -or 8 -lt $Version) -and $Version -lt 10) -or `
            ($OSUpgradeVersion.Count -gt 0 -and $OSUpgradeVersion -contains $UpgradeOSVersion -and !($UpgradeOSVersion -match '7'))) {
                $Showing = $true
        }
    }
    return $Showing
}