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/rm+json"
        "X-Auth-Token" = $RMLoginResult.Value.token
    }

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

    return Invoke-RMRestMethod -Params $Params
}

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

    $Headers = @{
        Accept = "application/rm+json"
        "X-Auth-Token" = $RMLoginResult.Value.token
    }

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

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

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

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

    $MigrationIdString  = $MigrationIds -join ","

    $Headers = @{
        Accept = "application/rm+json"
        "X-Auth-Token" = $RMLoginResult.Value.token
    }

    $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 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 Read-RMOSMUpgradeOption {
    param(
        [System.Object] $Source,
        [hashtable] $UpdatedUserInput
    )
    $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)
        } else {
            $UpdatedUserInput.Add("UpgradeOSVersion", $null)
            $UpdatedUserInput.Add("InPlaceUpgrade", $false)
        }
    } else {
        $UpdatedUserInput.Add("UpgradeOSVersion", $null)
        $UpdatedUserInput.Add("InPlaceUpgrade", $false)
    }
}

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
}