FastTrack-TransactionQuery.psm1

Add-Type -AssemblyName System.Web -ErrorAction SilentlyContinue

function Convert-StatusValue {
    <#
.SYNOPSIS
    Converts numeric status to textual status
.DESCRIPTION
    The Convert-Status cmdlet takes an intput numeric-id of the status and converts it to an english-translation of the status. The converted value is returned to the calling function.
 
    In order to use this cmdlet, you must first login using the Login-FastTrackAccount cmdlet.
.PARAMETER Status to be set
.EXAMPLE
    $i.Status = (Convert-StatusValue -status:$i.Status)
.INPUTS
    System.Integer
.OUTPUTS
    PSObject status
.LINK
#>

    param
    (
        [int] $status
    )
    $returnStatus = ""
    switch ($status) {
        0 { $returnStatus = "Created" }
        1 { $returnStatus = "Completed" }
        2 { $returnStatus = "Failed" }
        3 { $returnStatus = "InProgress" }
        4 { $returnStatus = "OnHold" }
    }
    return $returnStatus
}

Function Get-FastTrackMigrationTransactionStatus {
    <#
.SYNOPSIS
    Get transaction status
.DESCRIPTION
    The Get-FastTrackMigrationTransationStatus invokes the REST API using input TransactionId parameter to retrieve the statuses of a FastTrack migration. The returned statuses are returned to the caller as an array of webresponse objects.
 
    In order to use this cmdlet, you must first login using the Login-FastTrackAccount cmdlet.
.PARAMETER Transaction ID of FastTrack migration event
.EXAMPLE
    $Transaction = Get-FastTrackMigrationTransactionStatus -TransactionID $TransactionID
.INPUTS
    System.String
.OUTPUTS
    HtmlWebResponeObject
.LINK
#>

    param
    (
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [string] $TransactionID
    )

    if ($global:MsoAdminProperties.Count -eq 0) {
        Write-Warning "Unable to retrieve Office 365 credentials! :: Please call [Login-FastTrackAccount] function."
        return
    }

    try {
        $header = @{ }
        $header.Add("Authorization", $global:MsoAdminProperties["AuthorizationResult"].CreateAuthorizationHeader())
        $header.Add("TENANT_ID", $global:MsoAdminProperties["MSO-CompanyTenantInfo"])
        $header.Add("Accept", "application/json")
        $query = ""

        if ($TransactionID -ne [string]::Empty) {
            $query += "transactionId=$TransactionID&environmentType=$global:MsoComOrGov"
        }
        else {
            $query += "environmentType=$global:MsoComOrGov"
        }

        $transactionStatus = Invoke-GetRequest -Uri ([string]::Format("{0}{1}/transactions?$($query)", $global:CsiApiBaseUriFormat, $global:MsoAdminProperties["MSO-CompanyTenantInfo"])) -Headers $header

        if ($null -eq $transactionStatus -or $transactionStatus -eq 'null' -or $transactionStatus -eq "") {
            Write-Warning "Transaction ID $TransactionID was not found"
        }
        else {
            $results = @()
            Foreach ($i in $transactionStatus) {
                $i.Status = (Convert-StatusValue -status:$i.Status)

                if ($i.Status -eq 'Failed') {
                    $results += (New-Object PSObject |
                            Add-Member -PassThru NoteProperty TransactionGuid $i.TransactionGuid |
                            Add-Member -PassThru NoteProperty Status $i.Status |
                            Add-Member -PassThru NoteProperty Message $i.Message)
                }
                else {
                    $results += (New-Object PSObject |
                            Add-Member -PassThru NoteProperty TransactionGuid $i.TransactionGuid |
                            Add-Member -PassThru NoteProperty Status $i.Status |
                            Add-Member -PassThru NoteProperty Message '')
                }
            }
            return $results
        }
    }
    catch {
        Write-Error $_.Exception.ToString()
    }
}

function Get-FastTrackTransactionDetail {
    <#
.SYNOPSIS
    Get transaction details
.DESCRIPTION
    cmdlet retrieves details of transaction provided
 
    In order to use this cmdlet, you must first login using the Login-FastTrackAccount cmdlet.
.PARAMETER Transaction ID of FastTrack migration event
.EXAMPLE
    $Transaction = Get-FastTrackTransactionDetail -TransactionID:"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
.INPUTS
    System.String
.OUTPUTS
    HtmlWebResponseObject
.LINK
#>

    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string] $TransactionID
    )

    if ($global:MsoAdminProperties.Count -eq 0) {
        Write-Warning "Unable to retrieve Office 365 credentials! :: Please call [Login-FastTrackAccount] function."
        Exit
    }

    $header = @{ }
    $header.Add("Authorization", $global:MsoAdminProperties["AuthorizationResult"].CreateAuthorizationHeader())
    $header.Add("TENANT_ID", $global:MsoAdminProperties["MSO-CompanyTenantInfo"])
    
    Write-Host "Sending Transaction Request..."

    $response = Invoke-GetRequest -Uri ([System.String]::Format("{0}transaction/{1}/html", $global:CsiApiBaseUriFormat, $TransactionID)) -Headers $header

    if ($null -ne $response.StatusCode) {
        # Error?
        Write-Warning "Request failed! : $($response.StatusCode) - Error Message: $($response)"
    }
    else {
        Write-Host "Get request completed"
    }

    return $response
}

Function Wait-TransactionComplete {
    <#
    .SYNOPSIS
        Find status of Transaction
    .DESCRIPTION
        The Wait-TransactionComplete cmdlet calls Get-FastTrackMigrationStatus repetatively while migration is not complete or not failed. When the transaction has completed or failed, Wait-TransactionComplete returns the transaction object to caller.
     
        In order to use this cmdlet, you must first login using the Login-FastTrackAccount cmdlet.
    .PARAMETER
        TransactionId is the GUID representing the specified transaction
    .EXAMPLE
        Wait-TransactionComplete -TransactionID ($JsonResult.TransactionId)
    .INPUTS
        System.String
    .OUTPUTS
        System.Management.Automation.PSObject
            This cmdlet generates System.Management.Automation.PSObject object that represents transaction ID.
    .LINK
    #>

    param([string] $TransactionID = $(throw "Transaction ID unable to find, Please try again."))
    
    [array]$FinalResults = "Completed", "Failed"
    
    $current = $previous = 1;
    do {
        $Transaction = Get-FastTrackMigrationTransactionStatus -TransactionID $TransactionID
    
        for ($j = 1; (!$FinalResults.Contains($Transaction.Status) -and $j -le $current); $j++) {
            Start-Sleep -Milliseconds 1000
            Write-Progress -Id 1 -Activity Waiting -Status 'Next attempt will start ' -PercentComplete ($j / $current * 100) -SecondsRemaining ($current - $j)
        }
        $current, $previous = ($current + $previous), $current
    
    } while ($current -lt 60 -and !$FinalResults.Contains($Transaction.Status))
    return $Transaction
}
# SIG # Begin signature block
# MIIkTQYJKoZIhvcNAQcCoIIkPjCCJDoCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBneIlquysFwssM
# ObpvQx0KuSBz3m7Gw44hiwEV6jzNaKCCDXYwggX0MIID3KADAgECAhMzAAABUMiP
# lnfeTPFHAAAAAAFQMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMTkwNTAyMjEzNzQ1WhcNMjAwNTAyMjEzNzQ1WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQCh2V193EGtu49awDgcJ1E8WB5mAim/gAFVpWUVOlk/haZWAiffh/k3W/GPhgYl
# t2WH/FQS4BcGpeWRb2Wi4seOUWb5lbgIuUKBORF0iiEiPNMLueuD3PAChl/h3WE2
# N1T8zsQg6UMrWtNRdby48xCI6zdD+26yNei3tOccrOWWullOehpBF5Z4vp8Xvq1n
# ysaSkGgAZNaKrb3F6et3V5Tq+gJ0DaLm/TGxATcTJ1mrHJOx+cHorSIeGKKzwa19
# uBuUbGALZx8Isus+3KiK7h2YcZ+AHU+qeUCLbKhU3l97Kg9E6/dvAMa+42/BXSmZ
# 9+F3WfagixcbNWGaZA1Pn8mPAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUGxNB+9SPshuMPQ+xlMnFMiKVkDgw
# RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW
# MBQGA1UEBRMNMjMwMDEyKzQ1NDEzNDAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci
# tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG
# CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu
# Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0
# MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBADSrnbMt49ZGUc9KnW7S
# VkzITe55ApMwgxE8jl06lBkMZLd9QatyUt6g2/0RG0boaMHpWzypk6pGDLRD5y/P
# 6sj6fQYkrGihAw3W4ObLE3rrY8e5GPTrp/AlMFzsywHhD0+ETwgU8PuMvwQfB6ak
# 2ejWP0M1a1tkyAHfEMEGKd7RVPRmlLX+kPkJoFPz/uSlKxXi/acGH1qISQc0pkRt
# UE/ufrfpR+LlEOPg5aNZdAwIJAuDWInMeQM7kIoUTShSAJTzT58mrwVXgrfBbZnA
# NpsC/v8/amGL43MhTN0V2sWBHZNL7N0X9Z2qldu+jj8HdaNRGQyuru1W+IjNV914
# nk3qp9T/bZmy0elNYkCdNFjapARu6TZ0wwlEkvFW0HuzwtQ2gGDddGuhRFQRrdbU
# 68ifXf3dtvUDb0Nr+tnw9k0mV4s9jkTraDBaSJV0v1ixeR6WEBgGcc+uL/rHnci8
# 9cMcZqqcY8gGw0T1GpdDbWYLsYsqfPu5ZP4ga0kZa/ne7Bi3zu8XZ72kM893t5Ib
# Z96/2xp2Q+I6vIVfZJ7fh7vQ3OcLAZDvN+y6jNq3jtnQSYHuhX+Du074DXhQeVTB
# qTzBiuZPbnJhmI525u1GVoGemw0fqwk4cpeh3d1cDMN5eWlmqEdRwgaWozpj3a4I
# BzxVWkDJSJ4ZEq2odtK6eoYcMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq
# hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
# IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg
# Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
# CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03
# a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr
# rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg
# OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy
# 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9
# sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh
# dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k
# A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB
# w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn
# Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90
# lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w
# ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o
# ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD
# VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa
# BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny
# bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG
# AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t
# L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV
# HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3
# dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG
# AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl
# AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb
# C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l
# hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6
# I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0
# wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560
# STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam
# ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa
# J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah
# XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA
# 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt
# Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr
# /Xmfwb1tbWrJUnMTDXpQzTGCFi0wghYpAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp
# Z25pbmcgUENBIDIwMTECEzMAAAFQyI+Wd95M8UcAAAAAAVAwDQYJYIZIAWUDBAIB
# BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIO3yT3i+5uix3TwyeIDrugbv
# BiJD8/htUOq9nFbHIzZFMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A
# cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB
# BQAEggEASwiTj1NBlH0uxh+xWvsDYSpWMCY0BJOeYfT1wlYvni6us5KiAv9uSNyl
# D7giMBr9f85gXilRexpiNusF9ZsRyf0vx7J5ik11HiaHgCq4cw4KoZp6oKc7QASr
# kwSjuxySNYYZs6ozNIrI1ifPfPoAQqjMOMqZnmeZcVb787ewv/5MU9ySJxgctzdA
# 8wJKziMYBiX/6Zsea4iDJH/2qnA38a8tnIrUVJ5s7C8FZiL8XiA67KUpJyglh/Mx
# 5Uy0EDC06YhE1H+QfR69TgQkkiN6jJS7S3Zky6Kk/xho8gZeJDuVs1KQV6eaI0N8
# tTnRBu+Aih5LgcOPSTs/N0G9WljHAaGCE7cwghOzBgorBgEEAYI3AwMBMYITozCC
# E58GCSqGSIb3DQEHAqCCE5AwghOMAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFYBgsq
# hkiG9w0BCRABBKCCAUcEggFDMIIBPwIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl
# AwQCAQUABCDfheOQ9uegMnX9+0JghHq1OWRo7+a9Peh+qd9+rCRNfgIGXfpkVwQc
# GBMyMDIwMDEwOTA2NDkzMS40NTVaMAcCAQGAAgH0oIHUpIHRMIHOMQswCQYDVQQG
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQLEyBNaWNyb3NvZnQg
# T3BlcmF0aW9ucyBQdWVydG8gUmljbzEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046
# NzI4RC1DNDVGLUY5RUIxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNl
# cnZpY2Wggg8fMIIE9TCCA92gAwIBAgITMwAAAQQJAXUIWIctKQAAAAABBDANBgkq
# hkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ
# MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
# MSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAeFw0xOTA5
# MDYyMDQxMThaFw0yMDEyMDQyMDQxMThaMIHOMQswCQYDVQQGEwJVUzETMBEGA1UE
# CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z
# b2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQLEyBNaWNyb3NvZnQgT3BlcmF0aW9ucyBQ
# dWVydG8gUmljbzEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046NzI4RC1DNDVGLUY5
# RUIxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggEiMA0G
# CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDILQegEboYZpaU4WD8FoJrTtqDVU02
# ch4GEAXNxh/ydcOm4YE3IKTYmZxmXtpL9QG8oOwAUj+npIKUYVqQcseYDnjsaZZT
# 15AsaYjJShRcfvkZ8YNDdWBTdmgLFY/RkTFnN0eoTyrYBTB11Cz8Y4t37ug04I3z
# otqYoea/zvnKdTovCr3U/vKeSZUTpNf/OZ7E4IBPNArnT/zYboiK0r5gzSlZjjBd
# 2n1FlLMFT+r+rfXBo0lhtxjBjWXvBQd1VTi/qTbQm0VfN6oULZMiMgPB7xmnIgH6
# 12Yv0A+Qv7yu13L6Hh24s4e4+ZV1A9z4h9H36h7zKefJbFPwI6aq+WRnAgMBAAGj
# ggEbMIIBFzAdBgNVHQ4EFgQUmNVe38JEGg4XAYvxmdPDIrDomuowHwYDVR0jBBgw
# FoAU1WM6XIoxkPNDe3xGG8UzaFqFbVUwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDov
# L2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljVGltU3RhUENB
# XzIwMTAtMDctMDEuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0
# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNUaW1TdGFQQ0FfMjAx
# MC0wNy0wMS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDCDAN
# BgkqhkiG9w0BAQsFAAOCAQEAPRXUs3dpfDQDF9e0RXli4TqpzgIMlyIx/LXVtcgP
# eGXc8p/DXrpHI8iC+/z5I/EeyhLRFC9HH0Z3bOiiE2jwV8ZaLM9YvpDIX3eneJEo
# Jz1ptKqANeH6sSVDOj+X2X1kRlK7ZDSYWujfCHdQorsom6uytNxJ0y4JYtxF9S15
# cwTsssozN4QxlcYD5PQ+wcOYpIFY7vmKpfrV444Bv6BcPlib8ATe2Lp2kVdOiSmc
# LGBj7DmANasnPFVwaMnihhSoSNqE4U/z+yDN4QsSzXOH4sd7C2inuDWbWtK43bLG
# PCs/meLK/E/XWl0hWu5FKSlcOdu+/tEBQnOm5Kx45Sgf5TCCBnEwggRZoAMCAQIC
# CmEJgSoAAAAAAAIwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRp
# ZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTEwMDcwMTIxMzY1NVoXDTI1MDcwMTIx
# NDY1NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV
# BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG
# A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggEiMA0GCSqGSIb3
# DQEBAQUAA4IBDwAwggEKAoIBAQCpHQ28dxGKOiDs/BOX9fp/aZRrdFQQ1aUKAIKF
# ++18aEssX8XD5WHCdrc+Zitb8BVTJwQxH0EbGpUdzgkTjnxhMFmxMEQP8WCIhFRD
# DNdNuDgIs0Ldk6zWczBXJoKjRQ3Q6vVHgc2/JGAyWGBG8lhHhjKEHnRhZ5FfgVSx
# z5NMksHEpl3RYRNuKMYa+YaAu99h/EbBJx0kZxJyGiGKr0tkiVBisV39dx898Fd1
# rL2KQk1AUdEPnAY+Z3/1ZsADlkR+79BL/W7lmsqxqPJ6Kgox8NpOBpG2iAg16Hgc
# sOmZzTznL0S6p/TcZL2kAcEgCZN4zfy8wMlEXV4WnAEFTyJNAgMBAAGjggHmMIIB
# 4jAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQU1WM6XIoxkPNDe3xGG8UzaFqF
# bVUwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
# EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYD
# VR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwv
# cHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEB
# BE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9j
# ZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwgaAGA1UdIAEB/wSBlTCB
# kjCBjwYJKwYBBAGCNy4DMIGBMD0GCCsGAQUFBwIBFjFodHRwOi8vd3d3Lm1pY3Jv
# c29mdC5jb20vUEtJL2RvY3MvQ1BTL2RlZmF1bHQuaHRtMEAGCCsGAQUFBwICMDQe
# MiAdAEwAZQBnAGEAbABfAFAAbwBsAGkAYwB5AF8AUwB0AGEAdABlAG0AZQBuAHQA
# LiAdMA0GCSqGSIb3DQEBCwUAA4ICAQAH5ohRDeLG4Jg/gXEDPZ2joSFvs+umzPUx
# vs8F4qn++ldtGTCzwsVmyWrf9efweL3HqJ4l4/m87WtUVwgrUYJEEvu5U4zM9GAS
# inbMQEBBm9xcF/9c+V4XNZgkVkt070IQyK+/f8Z/8jd9Wj8c8pl5SpFSAK84Dxf1
# L3mBZdmptWvkx872ynoAb0swRCQiPM/tA6WWj1kpvLb9BOFwnzJKJ/1Vry/+tuWO
# M7tiX5rbV0Dp8c6ZZpCM/2pif93FSguRJuI57BlKcWOdeyFtw5yjojz6f32WapB4
# pm3S4Zz5Hfw42JT0xqUKloakvZ4argRCg7i1gJsiOCC1JeVk7Pf0v35jWSUPei45
# V3aicaoGig+JFrphpxHLmtgOR5qAxdDNp9DvfYPw4TtxCd9ddJgiCGHasFAeb73x
# 4QDf5zEHpJM692VHeOj4qEir995yfmFrb3epgcunCaw5u+zGy9iCtHLNHfS4hQEe
# gPsbiSpUObJb2sgNVZl6h3M7COaYLeqN4DMuEin1wC9UJyH3yKxO2ii4sanblrKn
# QqLJzxlBTeCG+SqaoxFmMNO7dDJL32N79ZmKLxvHIa9Zta7cRDyXUHHXodLFVeNp
# 3lfB0d4wwP3M5k37Db9dT+mdHhk4L7zPWAUu7w2gUDXa7wknHNWzfjUeCLraNtvT
# X4/edIhJEqGCA60wggKVAgEBMIH+oYHUpIHRMIHOMQswCQYDVQQGEwJVUzETMBEG
# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj
# cm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQLEyBNaWNyb3NvZnQgT3BlcmF0aW9u
# cyBQdWVydG8gUmljbzEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046NzI4RC1DNDVG
# LUY5RUIxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiJQoB
# ATAJBgUrDgMCGgUAAxUAs0Yef0dI8yhMiFS2cxh4FtwVCn2ggd4wgdukgdgwgdUx
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p
# Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMScwJQYDVQQLEx5uQ2lwaGVy
# IE5UUyBFU046NERFOS0wQzVFLTNFMDkxKzApBgNVBAMTIk1pY3Jvc29mdCBUaW1l
# IFNvdXJjZSBNYXN0ZXIgQ2xvY2swDQYJKoZIhvcNAQEFBQACBQDhwIhDMCIYDzIw
# MjAwMTA5MDA1NjM1WhgPMjAyMDAxMTAwMDU2MzVaMHQwOgYKKwYBBAGEWQoEATEs
# MCowCgIFAOHAiEMCAQAwBwIBAAICBGswBwIBAAICF2wwCgIFAOHB2cMCAQAwNgYK
# KwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAaAKMAgCAQACAxbjYKEKMAgCAQAC
# AwehIDANBgkqhkiG9w0BAQUFAAOCAQEAIY1uxDXbZQLkPvOMhHf3+RpmYlnFQu8Y
# lphzuQcXkImD650iaT/d7fyR3GwzgNQbEMoDC5tz+8+JDPz4lDtPTa9X4Rv/sMSJ
# mCIHaHF5jJ957k9mgiL1sbkvWxeUDXBQegk2RmWrwZndB0i8YA43B6wyxyLkko73
# JXjU02TqJI8ak/DN9NdGaS8TWxac9tzmGc7kjy0F+NdiTDGeukfapTJ177dpQcvI
# Jjhw4v7KE9Y3bJpGZ2DUpgpeWDmHymbyofXE9PuF8vw3B3f5M4b6numwip9ZEFL3
# wW4Mv5eRl8Dq6UobftRnJ0Pq7vtLT2H4aQYuK1KnTgBJzEAY6/yvZjGCAvUwggLx
# AgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD
# VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAk
# BgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABBAkBdQhY
# hy0pAAAAAAEEMA0GCWCGSAFlAwQCAQUAoIIBMjAaBgkqhkiG9w0BCQMxDQYLKoZI
# hvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEIEkMwQv8Y4L45eku7lZQtfd+RemUfjRO
# LOp4RoZ5hpdpMIHiBgsqhkiG9w0BCRACDDGB0jCBzzCBzDCBsQQUs0Yef0dI8yhM
# iFS2cxh4FtwVCn0wgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAx
# MAITMwAAAQQJAXUIWIctKQAAAAABBDAWBBTeisd3Oa9tib6dASG7WLcTBUMokTAN
# BgkqhkiG9w0BAQsFAASCAQCnMImEMFYl/RiGhfjNOOZTye6IsDNjqMPylXHyOAMO
# 0+ZX92JdCa7NB9H5YAPP9ZvSgSsbmj8uld0dp6kMIFU52CNOI8yUhal9m2iQ3dk6
# TPCsuUm2wU3yvP4czNcH1flQye1LjpVgkH+l7z/MeTZ5knUhYBPA7bRNRKryWBBI
# U83kAvm0s4UiP0QiX0BHqbk6G6SvVoZOk4ZPuV5LpPGWyOLksmrJQZA0BsEFCJHT
# MmsWl50LtKG04/vH/0NzWzvKvfudhWPAQzDIW6joaMIPuRSRxZnq2RxoqorEY8L6
# HL9KJU7RsEiuEQIVGEvTv0He4Tz/wvn3SL0LcGHYMWPu
# SIG # End signature block