RiverMeadow.Development.Migrate.psm1

Import-Module -Name @(Join-Path $PSScriptRoot Util | Join-Path -ChildPath Util)
Import-Module -Name @(Join-Path $PSScriptRoot Util | Join-Path -ChildPath MigrationUtil)
Import-Module -Name @(Join-Path $PSScriptRoot Common | Join-Path -ChildPath Wrappers | Join-Path -ChildPath Wrappers)
Import-Module -Name @(Join-Path $PSScriptRoot Migration | Join-Path -ChildPath AZURE | Join-Path -ChildPath AZURE)
Import-Module -Name @(Join-Path $PSScriptRoot Migration | Join-Path -ChildPath vSphere | Join-Path -ChildPath vSphere)
Import-Module -Name @(Join-Path $PSScriptRoot DifferentialMigration | Join-Path -ChildPath DifferentialMigration)

function Start-RMAzureOSBasedMigration {
    param(
        [Alias("tc")]
        [string] $TargetCloud,

        [Alias("sip")]
        [string] $SourceIP,

        [Alias("tvmn")]
        [string] $TargetVMName,

        [Alias("tm")]
        [ValidateSet("file-based", "block-based")]
        [string] $TransferMethod,

        [Alias("crg")]
        [bool] $CreateResourceGroup,

        [Alias("rg")]
        [string] $ResourceGroup,

        [Alias("rgr")]
        [string] $ResourceGroupRegion,

        [Alias("vmsn")]
        [string] $VMSizeName,

        [Alias("vt")]
        [ValidateSet("Standard_SSD", "Standard_HDD", "Premium_SSD")]
        [string] $VolumeType,

        [Alias("mp")]
        [string[]] $MountPoints,

        [Alias("rmp")]
        [string[]] $ResizeMountPoints,

        [Alias("vn")]
        [string] $VirtualNetwork,

        [Alias("dnn")]
        [string] $DestinationNetworkName,

        [Alias("apip")]
        [bool] $AssignPublicIP,

        [Alias("spip")]
        [string] $StaticPrivateIP,

        [Alias("etni")]
        [bool] $EnforceTargetNetworkIsolation,

        [Alias("sg")]
        [string] $SecurityGroup,

        [Alias("dtdnsr")]
        [bool] $DisableTargetDNSRegistration,

        [Alias("it")]
        [string[]] $InstanceTags,

        #TODO: parameterset
        [Alias("ao")]
        [ValidateSet("None", "AvailabilityZone", "AvailabilitySet")]
        [string] $AvailabilityOptions,

        [Alias("az")]
        [ValidateSet(1, 2, 3)]
        [int] $AvailabilityZone,

        [Alias("cas")]
        [bool] $CreateAvailabilitySet,

        [Alias("as")]
        [string] $AvailabilitySet,

        [Alias("fd")]
        [int] $FaultDomains,

        [Alias("ud")]
        [int] $UpdateDomains,

        #TODO: parameterset
        [Alias("ebd")]
        [bool] $EnableBootDiagnostics,

        [Alias("sa")]
        [string] $StorageAccount,

        #TODO: parameterset
        [Alias("det")]
        [ValidateSet("platform-managed", "customer-managed")]
        [string] $DiskEncryptionType,

        [Alias("es")]
        [string] $EncryptionSet,

        [Alias("ehub")]
        [bool] $EnableHybridUseBenefit,

        [Alias("uosv")]
        [string] $UpgradeOSVersion,

        [Alias("ss")]
        [bool] $ShutdownSource,

        [Alias("st")]
        [bool] $ShutdownTarget,

        [Alias("rrmsa")]
        [bool] $RemoveRMSAgent,

        [Alias("mi")]
        [string[]] $MigrationInstructions,

        [Alias("ive")]
        [bool] $IgnoreValidationErrors
    )

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

    if (0 -eq $PSBoundParameters.Count) {
        Start-RMAzureOSBasedInteractiveMigration
    } else {
        Start-RMAzureOSBasedNonInteractiveMigration @PSBoundParameters
    }
}

function Start-RMVSphereOSBasedMigration {
    param(
        [Alias('tc')]
        [string] $TargetCloud,

        [Alias("sip")]
        [string] $SourceIP,

        [Alias("tvmn")]
        [string] $TargetVMName,

        [Alias("mp")]
        [string[]] $MountPoints,

        [Alias("rmp")]
        [string[]] $ResizeMountPoints,

        [Alias("tm")]
        [ValidateSet("file-based", "block-based")]
        [string] $TransferMethod,

        [Alias("tvmvcpuc")]
        [int] $TargetVMVCPUCount,

        [Alias("cps")]
        [int] $CoresPerSocket,

        [Alias("tvmms")]
        [int] $TargetVMMemorySize,

        [Alias("dcn")]
        [string] $DatacenterName,

        [Alias("edni")]
        [bool] $EnableDestinationNetworkIsolation,

        [Alias("dnn")]
        [string] $DestinationNetworkName,

        [Alias("ipt")]
        [ValidateSet("static", "DHCP")]
        [string] $IPType,

        [Alias("ipa")]
        [string] $IPAddress,

        [Alias("nm")]
        [string] $Netmask,

        [Alias("dg")]
        [string] $DefaultGateway,

        [Alias("pdns")]
        [string] $PrimaryDNS,

        [Alias("sdns")]
        [string] $SecondaryDNS,

        [Alias("inn")]
        [string] $IsolatedNetworkName,

        [Alias("iipt")]
        [ValidateSet("static", "DHCP")]
        [string] $IsolatedIPType,

        [Alias("iipa")]
        [string] $IsolatedIPAddress,

        [Alias("in")]
        [string] $IsolatedNetmask,

        [Alias("idg")]
        [string] $IsolatedDefaultGateway,

        [Alias("ipdns")]
        [string] $IsolatedPrimaryDNS,

        [Alias("isdns")]
        [string] $IsolatedSecondaryDNS,

        [Alias("dadnsrot")]
        [bool] $DisableAutomaticDNSRegistrationOnTheTarget,

        [Alias("cln")]
        [string] $ClusterName,

        [Alias("rpn")]
        [string] $ResourcePoolName,

        [Alias("fn")]
        [string] $FolderName,

        [Alias("dcln")]
        [string] $DatastoreClusterName,

        [Alias("dsn")]
        [string[]] $DatastoreNames,

        [Alias("dpt")]
        [ValidateSet("thick-lazy-zeroed", "thick-eager-zeroed", "thin")]
        [string[]] $DiskProvisioningTypes,

        [Alias("hv")]
        [int] $HardwareVersion,

        [Alias("ss")]
        [bool] $ShutdownSource,

        [Alias("st")]
        [bool] $ShutdownTarget,

        [Alias("rrmsas")]
        [bool] $RemoveRMSAgentFromSource,

        [Alias("rrmsat")]
        [bool] $RemoveRMSAgentFromTarget,

        [Alias("mi")]
        [hashtable] $MigrationInstructions,

        [Alias("uosv")]
        [string]  $UpgradeOSVersion,

        [Alias("ive")]
        [bool] $IgnoreValidationErrors
    )

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

    if (0 -eq $PSBoundPArameters.Count) {
        return Start-RMInteractiveVSphereOSBasedMigration
    } else {
        return Start-RMNonInteractiveVsphereOsBasedMigration  @PSBoundParameters
    }
}

function Start-RMDifferentialMigration {
    param(
        [Alias("mid")]
        [System.Guid] $MigrationId,

        [Alias("ive")]
        [bool] $IgnoreValidationErrors
    )

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

    if (0 -eq $PSBoundPArameters.Count) {
        $UserMigrationId = @()
        $UserMigrationId = Read-RMUUID -UserMessage "Enter the full migration ID" -ParameterName "Full migration ID" -IsRequired $true
        $MigrationId = $UserMigrationId[0]
        $IgnoreValidationErrors = Read-RMBoolean -UserMessage "Ignore validation errors" -DefaultValue "false"
    }

    Start-RMDM -MigrationId $MigrationId -IgnoreValidationErrors $IgnoreValidationErrors
}

function Stop-RMMigration {
    param (
        [Alias("mid")]
        [System.Guid] $MigrationId
    )

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

    if (0 -eq $PSBoundParameters.Count) {
        $UserMigrationId = @()
        $UserMigrationId = Read-RMUUID -UserMessage "Enter the ID of the migration that you want to stop" `
            -ParameterName "Migration ID" -IsRequired $true
        $MigrationId = $UserMigrationId[0]
    }

    $Migration = Get-RMMigrationByIdAndStatus -MigrationId $MigrationId -StatusOnly $true

    if ($null -eq $Migration) {
        # Show-RMError has already displayed the error, hence return
        return
    }

    if("error" -ne $Migration.state -and "success" -ne $Migration.state -and "cancelled" -ne $Migration.state) {

        $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 = "Post"
            Uri = $Uri.Value + "/migrations/" + $MigrationId + "/cancel"
            Headers = $Headers
            ContentType = "application/json"
        }

        $Response = Invoke-RMRestMethod -Params $Params
        return "Migration " + $Response.id + " is cancelled."
    }
    throw "Migration is in final state " +  $Migration.state + ", cannot be cancelled."
}

function Get-RMMigrations {
    param (
        # ID's of the migrations that needs to be fetched
        [Alias("mid")]
        [System.Guid[]] $MigrationIds
    )

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

    if (0 -eq $PSBoundParameters.Count) {
        $MigrationIds = Read-RMUUID -UserMessage "Enter one or more migration IDs, separated by commas" -ParameterName "Migration ID" -IsRequired $true
    }

    $Migrations = Get-RMMigrationsByIds -MigrationIds $MigrationIds
    $Result = @()
    $ReceivedMigrationIds = @()
    foreach ($Migration in $Migrations.content) {
        switch ($Migration.state) {
            "success" {
                $MigrationStatus = [MigrationStatus]::new($Migration.id, $Migration.state, "100%")
            }
            "running" {
                $Progress = [string] (Get-RMMigrationProgress -Migration $Migration)
                $IsStalled = Test-RMMigrationStalled -Migration $Migration
                if ($IsStalled) {
                    $MigrationStatus = [MigrationStatus]::new($Migration.id, "stalled", "N/A")
                } else {
                    $MigrationStatus = [MigrationStatus]::new($Migration.id, $Migration.state, $Progress+"%")
                }
            }
            default {
                $MigrationStatus = [MigrationStatus]::new($Migration.id, $Migration.state, "N/A")
            }
        }
        $Result += $MigrationStatus 
        $ReceivedMigrationIds += $Migration.id
    }

    if ($Migrations.content.Count -ne $MigrationIds.Count) {
        $MigrationsNotFound = Get-RMMigrationsNotFound -ReceivedMigrationIds $ReceivedMigrationIds -UserInputMigrationIds $MigrationIds
        $MigrationsNotFoundAsString = $MigrationsNotFound -join ", "
        Write-RMError -Message "Could not find migrations with IDs: $MigrationsNotFoundAsString"
    }

    return $Result 
}

class MigrationStatus {
    [string] $MigrationId
    [string] $Status
    [string] $Progress

    MigrationStatus( [string] $MigrationId, [string] $Status, [string] $Progress) {
        $this.MigrationId = $MigrationId
        $this.Status = $Status
        $this.Progress = $Progress
    }
}
Export-ModuleMember -Function Start-RMVSphereOSBasedMigration, Start-RMAzureOSBasedMigration, Get-RMMigrations, Start-RMVSphereDifferentialMigration, Stop-RMMigration