RiverMeadow.Source/SourceUtil/SourceUtil.psm1

Import-Module -Name $PSScriptRoot\..\..\Util\Util
function Get-RMSourcesForCurrentProject {
    param()

    $UserLoginStatus = Test-UserLoggedIn
    if (!$UserLoginStatus) {
        return
    }

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

    $Result = @()
    $Response = Get-RMSourcesInternal -OrganizationId $CurrentProjectId -PageNumber 0
    $Result += $Response
    for ($index = 1; $index -lt $Response.page.totalPages; $index++) {
        $Result += Get-RMSourcesInternal -OrganizationId $CurrentProjectId -PageNumber $index
    }

    return $Result
}

function Get-RMSourcesInternal {
    param(
        [string] $OrganizationId,
        [int] $PageNumber
    )

    $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 + "/sources?size=25&page=" + $PageNumber + "&sort=created_at%2Cdesc"
        Headers = $Headers
    }
    return Invoke-RMRestMethod -Params $Params
}

function Get-RMSourceById {
    param(
        [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 + "/sources/" + $SourceId
        Headers = $Headers
    }
    return Invoke-RMRestMethod -Params $Params
}

function Get-MountPoint {
    param(
        [System.Object] $Source
    )
    $MountPoints = @()
    if ("windows" -ieq $Source.os_type) {
        foreach ($Mount in $Source.attributes.storage.mounts.psobject.properties.value) {
            $MountPoints += @{mount_point = $Mount.path}
        }
    } else {
        foreach ($Mount in $Source.attributes.storage.mounts.psobject.properties.value) {
            if ("disk" -ieq $Mount.nature -or "subvolume" -ieq $Mount.nature -and "squashfs" -ine $Mount.fs_type) {
                $MountPoints += @{mount_point = $Mount.path}
            }
        }
    }

    return $MountPoints
}

function Get-RMSourceByIP {
    param(
        [string] $IPAddress
    )
    $PagedProjectSources = Get-RMSourcesForCurrentProject
    foreach ($PagedProjectSource in $PagedProjectSources) {
        foreach ($Source in $PagedProjectSource.content) {
            if ($IPAddress -eq $Source.host) {
                return $Source
            }
        }
    }

    $ProjectName = Get-Variable -Name "RMContext-CurrentProjectName" -ValueOnly
    $OrgName = Get-Variable -Name "RMContext-CurrentOrganizationName" -ValueOnly
    throw "Source with IP address '$IPAddress' does not exist in project '$ProjectName' of organization '$OrgName', cannot start the migration. Please add the source in the project and try again."
}

function Start-RMSourcePreflight {
    param (
        [System.Object] $Source
    )
    $RequestAttributes = @{
        "type" = "source"
        "resource_id"= $Source.id
        "overrides"= @{}
    }

    $SourceAttributesRequest = @($RequestAttributes)
    $SourceAttributesRequestJson = ConvertTo-Json $SourceAttributesRequest

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

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

    $Params = @{
        Method = "Post"
        Uri = $Uri + "/preflights"
        Body = $SourceAttributesRequestJson
        ContentType = "application/json"
        Headers = $Headers
    }

    Write-Output "Starting source attribute collection..." | Out-Host
    return Invoke-RMRestMethod -Params $Params   
}

function Get-RMSourceWithAttribute {
    param(
        [string] $IPAddress,
        [bool] $RefreshSourceAttributes,
        [System.Object] $CloudAccount
    )

    $Source = Get-RMSourceByIP -IPAddress $IPAddress
    if (-not($RefreshSourceAttributes -or $Source.attribute_state -eq "pending" -or $Source.attribute_state -eq "error")) {
        return $Source
    }

    if ($Source.attribute_state -eq "running") {
        throw "Source attribute collection state is 'running', please wait for the attribute collection to complete."
    }

    Update-RMSourceWithAppliance -SourceId $Source.id -ApplianceId $CloudAccount.appliance.id
    $Response = Start-RMSourcePreflight -Source $Source
    $PreflightResult = Watch-RMPreflightStatus -PreflightId $Response.preflights[0].id
    $Source = Get-RMSourceById -SourceId $Source.id
    if ($PreflightResult.state -eq "error" -and $PreflightResult.error_type -ne "warning") {
        $PreflightID = $Response.preflights[0].id
        $AttributeCollectionError = $Source.attribute_error
        throw "Source attribute collection with ID: $PreflightID has failed with error $AttributeCollectionError"
    }

    return $Source
}

function Update-RMSourceWithAppliance {
    param (
        [System.Object] $SourceId,
        [string] $ApplianceId
    )
    
    $RequestAttributes = @{
        "data_only_migration" = $false
        "appliance_id" = $ApplianceId
    }

    $RequestAttributesJson = ConvertTo-Json $RequestAttributes

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

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

    $Params = @{
        Method = "Put"
        Uri = $Uri + "/sources/" + $SourceId
        Body = $RequestAttributesJson
        ContentType = "application/json"
        Headers = $Headers
    }

    Invoke-RMRestMethod -Params $Params | Out-Null
}

# No Export-ModuleMember is being used which will automatically export all the functions
# of this module and we want all the functions to be exported.