Obs/scripts/Install-StandaloneObservability.ps1

##------------------------------------------------------------------
## <copyright file="Install-StandaloneObservability.ps1" company="Microsoft">
## Copyright (C) Microsoft. All rights reserved.
## </copyright>
##------------------------------------------------------------------

[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = "Medium", PositionalBinding = $false, DefaultParameterSetName = "DefaultSet")]
param(
    [Parameter(Mandatory = $true)]
    [System.String] $ResourceGroupName,

    [Parameter(Mandatory = $true)]
    [System.String] $SubscriptionId,

    [Parameter(Mandatory = $true)]
    [System.String] $TenantId,

    [Parameter(Mandatory=$false)]
    [System.String] $RegistrationRegion = "eastus",

    [Parameter(Mandatory = $true, ParameterSetName = "DefaultSet")]
    [PSCredential] $RegistrationCredential,

    [Parameter(Mandatory = $true, ParameterSetName = "Interactive")]
    [Switch] $Interactive,

    [Parameter(Mandatory = $true, ParameterSetName = "PassThrough")]
    [Switch] $PassThrough,

    [Parameter(Mandatory = $true, ParameterSetName = "ServicePrincipal")]
    [PSCredential] $RegistrationSPCredential,

    [Parameter(Mandatory=$true)]
    [System.String] $FactoryLogShare,

    [Parameter(Mandatory=$false)]
    [System.String] $ClusterName,

    [Parameter(Mandatory=$false)]
    [System.String] $ObsRootFolderPath = "C:\StandaloneObservability",

    [Parameter(Mandatory=$false)]
    [Switch] $ParseOnce,

    [Parameter(Mandatory=$false)]
    [System.String] $Cloud = "AzureCloud",

    [Parameter(Mandatory=$false)]
    [System.String] $GcsRegion = "eastus",

    [Parameter(Mandatory=$false)]
    [System.Boolean] $SkipArcForServer = $false
)

    Import-Module "$PSScriptRoot\GMATenantJsonHelper.psm1" -Force
    Import-Module "$PSScriptRoot\ExtensionHelper.psm1" -Force
    Import-Module "$PSScriptRoot\StandaloneObservabilityHelper.psm1" -Force
    Import-Module "$PSScriptRoot\StandaloneObservabilityConstants.psm1" -Force

try {
    $ErrorActionPreference = "Stop"    
    $functionName = $MyInvocation.MyCommand.Name

    if ([string]::IsNullOrEmpty($ClusterName)) {
        Write-Host "ClusterName is empty. So setting it to computer name $($env:COMPUTERNAME)"
        $ClusterName = $env:COMPUTERNAME
    }

    if(-not (Test-Path -Path $ObsRootFolderPath -PathType Container))
    {
        Write-Host "ObsRootFolderPath: $ObsRootFolderPath is not present. So creating it"
        New-Item -Path $ObsRootFolderPath -ItemType Directory -Force
    }

    $transcriptFileName = "{0}.{1:yyyy-MM-dd-hh-mm-ss}.log" -f $functionName, $(Get-Date)
    $transcriptFilePath = Join-Path -Path $ObsRootFolderPath -ChildPath $transcriptFileName
    Start-Transcript -Path $transcriptFilePath -Append

    Add-Type -Path "$PSScriptRoot\Microsoft.AzureStack.Observability.ObservabilityCommon.dll"

    ## Create pre-requisites for Extension
    New-GmaStateFolders -ObsRootFolderPath $ObsRootFolderPath
    Set-HandlerEnvInfo -ObsRootFolderPath $ObsRootFolderPath -CloudName $Cloud -RegionName $RegistrationRegion

    $gcsEnvironment = "Prod" ## default environment

    ## Check if the reg key created for CI exists or not, if yes then change the GCSEnvironment to point to PPE.
    $isSddcTestDevice = Test-RegKeyExists -Path $MiscConstants.SddcRegKey.Path -Name $MiscConstants.SddcRegKey.Name -LogFile $LogFile -GetValueIfExists

    if (Test-RegKeyExists -Path "HKLM:\Software\Microsoft\SQMClient\" -Name "IsCIEnv") {
        $gcsEnvironment = "Ppe"
    }
    elseif ($null -ne $isSddcTestDevice -and $isSddcTestDevice -ne 0) {
        $gcsEnvironment = "Ppe"

        Write-Host "[$functionName] As $($MiscConstants.SddcRegKey.Path)\$($MiscConstants.SddcRegKey.Name) reg key is present, setting gcsEnvironmentName value to $gcsEnvironmentName."
    }
    elseif (Confirm-IsArcAEnvironment) {
        $gcsEnvironment = "ArcAPpe"
    }

    $envInfoFilePath = "$PSScriptRoot\EnvironmentInfo.json"
    $tenantInfoContent = Get-Content $envInfoFilePath -Raw | ConvertFrom-Json
    $envInfo = $tenantInfoContent.$gcsEnvironment

    # Settings from EnvironmentInfo.json
    $gcsEndpoint = $envInfo.EndPoint
    $gcsAccount = $envInfo.Account
    $genevaConfigVersion = $envInfo.ConfigVersion

    ## Install Azure Connected Machine agent
    $StampId = Set-StampGuid
    $resourceName = "$(hostname)-$StampId"

    if ($skipArcForServer -eq $false) {
        Write-Host "$functionName Azure identity is not enabled. Going to install Arc for server agent" -Verbose

        if(-not (Get-Module -Name Az.Accounts -ListAvailable)) {
            Install-Module -Name Az.Accounts -AllowClobber -Force
        }

        if ($PSCmdlet.ParameterSetName -eq "ServicePrincipal") {
            Connect-AzAccount -Credential $RegistrationSPCredential -ServicePrincipal -Environment $Cloud -Tenant $TenantId -Subscription $SubscriptionId
            Install-AzureConnectedMachineAgent -ResourceName $resourceName -ResourceGroupName $ResourceGroupName -TenantId $TenantId `
                                                -RegionName $RegistrationRegion -SubscriptionId $SubscriptionId -Cloud $Cloud `
                                                -StampId $StampId -RegistrationSPCredential $RegistrationSPCredential
        }
        elseif ($PSCmdlet.ParameterSetName -eq "Interactive") {
            Connect-AzAccount -UseDeviceAuthentication -Environment $Cloud -Tenant $TenantId -Subscription $SubscriptionId
            $token = Get-AzAccessToken
            Install-AzureConnectedMachineAgent -ResourceName $resourceName -ResourceGroupName $ResourceGroupName -TenantId $TenantId `
                                                -RegionName $RegistrationRegion -SubscriptionId $SubscriptionId -Cloud $Cloud `
                                                -StampId $StampId -AccessToken $token.Token
        }
        elseif ($PSCmdlet.ParameterSetName -eq "PassThrough") {
            $token = Get-AzAccessToken
            Install-AzureConnectedMachineAgent -ResourceName $resourceName -ResourceGroupName $ResourceGroupName -TenantId $TenantId `
                                                -RegionName $RegistrationRegion -SubscriptionId $SubscriptionId -Cloud $Cloud `
                                                -StampId $StampId -AccessToken $token.Token
        }
        else {
            Connect-AzAccount -Credential $RegistrationCredential -Environment $Cloud -Tenant $TenantId -Subscription $SubscriptionId
            $token = Get-AzAccessToken
            Install-AzureConnectedMachineAgent -ResourceName $resourceName -ResourceGroupName $ResourceGroupName -TenantId $TenantId `
                                                -RegionName $RegistrationRegion -SubscriptionId $SubscriptionId -Cloud $Cloud `
                                                -StampId $StampId -AccessToken $token.Token
        }
    }

    ## Start Pipeline installation using Extension Install interface
    $deviceArmResourceUri = $PipelineConstants.DeviceArmUriFormat -f $SubscriptionId, $ResourceGroupName, $resourceName
    $osBuild = Get-OsBuildVersion
    $logFile = Get-HandlerLogFile
    Set-StandaloneScenarioRegistry -ErrorAction Stop
    $configTypes = @([Microsoft.AzureStack.Observability.ObservabilityCommon.TenantConfigGenerator.Contract.TenantConfigType]::Telemetry, [Microsoft.AzureStack.Observability.ObservabilityCommon.TenantConfigGenerator.Contract.TenantConfigType]::Diagnostics)
    foreach($configType in $configTypes)
    {
        $gcsNameSpace = $envInfo.Namespaces.$configType
        [Microsoft.AzureStack.Observability.ObservabilityCommon.TenantConfigGenerator.TenantConfigRegistrySetter]::Current.SetTenantConfigRegistryKeys(
        $configType,
        "1.0",
        "AuthMSIToken",
        $gcsEndpoint,
        $gcsAccount,
        $gcsNameSpace,
        $GcsRegion,
        $genevaConfigVersion,
        $LocalPath,
        "true",
        "true",
        $GcsRegion,
        $deviceArmResourceUri,
        $StampId,
        $ClusterName,
        $osBuild,
        "1.0",
        $resourceName,
        $deviceArmResourceUri,
        $ClusterName,
        [string]::Empty)
    }

    Write-Host "Setting version environment variable for extension script"
    [System.Environment]::SetEnvironmentVariable(
        $PipelineConstants.ExtVerEnvironment.VariableName,
        $PipelineConstants.ExtVerEnvironment.VariableValue,
        [System.EnvironmentVariableTarget]::Process)

    Write-Host "Starting Install-Extension script with DeviceArmResourceUri: $deviceArmResourceUri StampId: $StampId ClusterName: $ClusterName CloudName: $Cloud RegistrationRegion: $RegistrationRegion"

    & "$PSScriptRoot\Install-Extension.ps1" `
                       -ErrorAction Stop
    if($LASTEXITCODE -ne 0) {
        Write-Error "Error during Extension installation $LASTEXITCODE"
    }

    & "$PSScriptRoot\Enable-Extension.ps1"
    if($LASTEXITCODE -ne 0) {
        Write-Error "Error during Extension enable $LASTEXITCODE"
    }

    # Sleep for sometime and check for GCS Config
    Wait-ForGcsConfigSync -TimeInSeconds 180 -LogFile $logFile

    $transcriptFolderPath = Join-Path -Path $(Get-LogFolderPath) -ChildPath $PipelineConstants.TranscriptsFolderName

    $obsAgentPackagePath = Get-ObsAgentPackageContentPath
    $parsingEnginePath = Join-Path -Path $obsAgentPackagePath -ChildPath "LogParsingEngine"
    $parsingEngineScript = Join-Path -Path $PSScriptRoot -ChildPath "Invoke-ParsingEngine.ps1"

    if($ParseOnce)
    {
        ## Run ParsingEngine with given log location
        Write-Host "Starting Parser scripts arguments: $parsingEngineScript -FactorySharePath $FactoryLogShare -ParsingEnginePackagePath $parsingEnginePath -TranscriptFolderPath $transcriptFolderPath"
        
        & $parsingEngineScript -FactorySharePath $FactoryLogShare `
                                -ParsingEnginePackagePath $parsingEnginePath `
                                -TranscriptFolderPath $transcriptFolderPath `
                                -ParseOnce `
                                -ErrorAction Stop
    }
    else
    {
        ## Create ParsingEngine scheduled tasks
        $scriptArguments = "-TaskName $($PipelineConstants.ParserScheduledTaskName) -FactorySharePath $FactoryLogShare -ParsingEnginePackagePath $parsingEnginePath -TranscriptFolderPath $transcriptFolderPath"
        Write-Host "Creating Parser scheduled task with arguments: $scriptArguments"

        New-ScheduledTaskForObservability -TaskName $PipelineConstants.ParserScheduledTaskName `
                                    -TaskPath $PipelineConstants.ParserScheduledTaskPath `
                                    -Description $PipelineConstants.ParserScheduledTaskDescription `
                                    -ScriptPath $parsingEngineScript `
                                    -ScriptArguments $scriptArguments `
                                    -DisableOnRegistration `
                                    -ErrorAction Stop

        ScheduledTasks\Enable-ScheduledTask -TaskPath $PipelineConstants.ParserScheduledTaskPath `
        -TaskName $PipelineConstants.ParserScheduledTaskName `
        -ErrorAction Stop
    }

    Set-Status -Name $functionName `
                -Operation "Install and Enable succeeded" `
                -Message "$functionName : Successfully installed and enabled Standalone Observability pipeline components." `
                -Status "success" `
                -Code 0

    Write-Host "Standalone Observability pipeline installation complete."
    Stop-Transcript -ErrorAction SilentlyContinue
}
catch {
    if ((Get-Command GMATenantJsonHelper\Get-ExceptionDetails -ErrorAction Ignore) -and (Get-Command ExtensionHelper\Set-Status -ErrorAction Ignore)) {
        $exceptionDetails = Get-ExceptionDetails -ErrorObject $_

        $errorMessage = "$functionName : Failed to install and enable Standalone Observability pipeline components. Exception is as follows: $exceptionDetails."
    
        Set-Status -Name $functionName `
                -Operation "Install and Enable failed" `
                -Message $errorMessage `
                -Status "error" `
                -Code 1

        Write-Error $errorMessage
    }
    else {
        Write-Error $_
    }
    Stop-Transcript -ErrorAction SilentlyContinue
}
# SIG # Begin signature block
# MIIoKgYJKoZIhvcNAQcCoIIoGzCCKBcCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCB6CgyMgjuEy95
# Rf2IaTovg1bxysrgkydtQTluJoH/WqCCDXYwggX0MIID3KADAgECAhMzAAAEBGx0
# Bv9XKydyAAAAAAQEMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjQwOTEyMjAxMTE0WhcNMjUwOTExMjAxMTE0WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQC0KDfaY50MDqsEGdlIzDHBd6CqIMRQWW9Af1LHDDTuFjfDsvna0nEuDSYJmNyz
# NB10jpbg0lhvkT1AzfX2TLITSXwS8D+mBzGCWMM/wTpciWBV/pbjSazbzoKvRrNo
# DV/u9omOM2Eawyo5JJJdNkM2d8qzkQ0bRuRd4HarmGunSouyb9NY7egWN5E5lUc3
# a2AROzAdHdYpObpCOdeAY2P5XqtJkk79aROpzw16wCjdSn8qMzCBzR7rvH2WVkvF
# HLIxZQET1yhPb6lRmpgBQNnzidHV2Ocxjc8wNiIDzgbDkmlx54QPfw7RwQi8p1fy
# 4byhBrTjv568x8NGv3gwb0RbAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQU8huhNbETDU+ZWllL4DNMPCijEU4w
# RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW
# MBQGA1UEBRMNMjMwMDEyKzUwMjkyMzAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci
# tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG
# CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu
# Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0
# MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAIjmD9IpQVvfB1QehvpC
# Ge7QeTQkKQ7j3bmDMjwSqFL4ri6ae9IFTdpywn5smmtSIyKYDn3/nHtaEn0X1NBj
# L5oP0BjAy1sqxD+uy35B+V8wv5GrxhMDJP8l2QjLtH/UglSTIhLqyt8bUAqVfyfp
# h4COMRvwwjTvChtCnUXXACuCXYHWalOoc0OU2oGN+mPJIJJxaNQc1sjBsMbGIWv3
# cmgSHkCEmrMv7yaidpePt6V+yPMik+eXw3IfZ5eNOiNgL1rZzgSJfTnvUqiaEQ0X
# dG1HbkDv9fv6CTq6m4Ty3IzLiwGSXYxRIXTxT4TYs5VxHy2uFjFXWVSL0J2ARTYL
# E4Oyl1wXDF1PX4bxg1yDMfKPHcE1Ijic5lx1KdK1SkaEJdto4hd++05J9Bf9TAmi
# u6EK6C9Oe5vRadroJCK26uCUI4zIjL/qG7mswW+qT0CW0gnR9JHkXCWNbo8ccMk1
# sJatmRoSAifbgzaYbUz8+lv+IXy5GFuAmLnNbGjacB3IMGpa+lbFgih57/fIhamq
# 5VhxgaEmn/UjWyr+cPiAFWuTVIpfsOjbEAww75wURNM1Imp9NJKye1O24EspEHmb
# DmqCUcq7NqkOKIG4PVm3hDDED/WQpzJDkvu4FrIbvyTGVU01vKsg4UfcdiZ0fQ+/
# V0hf8yrtq9CkB8iIuk5bBxuPMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq
# 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
# /Xmfwb1tbWrJUnMTDXpQzTGCGgowghoGAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp
# Z25pbmcgUENBIDIwMTECEzMAAAQEbHQG/1crJ3IAAAAABAQwDQYJYIZIAWUDBAIB
# BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEINXMOpT1oXFT6yuf2mn8GvXx
# 2XLBn1iISMw+jl5DZALtMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A
# cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB
# BQAEggEARB2Xdv7aIZeeimO/iIp+47+TlvXBtnTxGMKT8fjbZU62kLU+Gt+5Yx2E
# LqJ8FSTqmvmXQ154RtNw7VFfTb7TQDa3FXXHAeZKmjtxmz53hZVqz+bSlyRdB4jK
# YQ+YccRroPLiC3OuyP0ZlRqFCa0+Nyj4/rBnAXdHPcZhQLEwWw9ZCM/XchP8rLcn
# xFUAmSCZBASo3I0m9DcAln8uqkI0rtpaH6p1bC3gvMyytnxXrIYjZ1J49C34dgr3
# CcvByvvBPek7fbtKXMK/j0VtbAXgBmVfjuY32tHCffFFIHAEy4jFSzhtY1GOrBsq
# hyjOwhUFFoagAP9jyjhV5nGJJ9Ggn6GCF5QwgheQBgorBgEEAYI3AwMBMYIXgDCC
# F3wGCSqGSIb3DQEHAqCCF20wghdpAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFSBgsq
# hkiG9w0BCRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl
# AwQCAQUABCDd51W7F23iEXdzaklbl1pe5av0zq7OGREiTlf9pWh3QQIGZ5JHidhG
# GBMyMDI1MDEyNjA3MjUwMS42OTRaMASAAgH0oIHRpIHOMIHLMQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l
# cmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046N0YwMC0w
# NUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Wg
# ghHqMIIHIDCCBQigAwIBAgITMwAAAfAqfB1ZO+YfrQABAAAB8DANBgkqhkiG9w0B
# AQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYD
# VQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAeFw0yMzEyMDYxODQ1
# NTFaFw0yNTAzMDUxODQ1NTFaMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25z
# MScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046N0YwMC0wNUUwLUQ5NDcxJTAjBgNV
# BAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQC1Hi1Tozh3O0czE8xfRnrymlJNCaGWommPy0eINf+4
# EJr7rf8tSzlgE8Il4Zj48T5fTTOAh6nITRf2lK7+upcnZ/xg0AKoDYpBQOWrL9Ob
# FShylIHfr/DQ4PsRX8GRtInuJsMkwSg63bfB4Q2UikMEP/CtZHi8xW5XtAKp95cs
# 3mvUCMvIAA83Jr/UyADACJXVU4maYisczUz7J111eD1KrG9mQ+ITgnRR/X2xTDMC
# z+io8ZZFHGwEZg+c3vmPp87m4OqOKWyhcqMUupPveO/gQC9Rv4szLNGDaoePeK6I
# U0JqcGjXqxbcEoS/s1hCgPd7Ux6YWeWrUXaxbb+JosgOazUgUGs1aqpnLjz0YKfU
# qn8i5TbmR1dqElR4QA+OZfeVhpTonrM4sE/MlJ1JLpR2FwAIHUeMfotXNQiytYfR
# BUOJHFeJYEflZgVk0Xx/4kZBdzgFQPOWfVd2NozXlC2epGtUjaluA2osOvQHZzGO
# oKTvWUPX99MssGObO0xJHd0DygP/JAVp+bRGJqa2u7AqLm2+tAT26yI5veccDmNZ
# sg3vDh1HcpCJa9QpRW/MD3a+AF2ygV1sRnGVUVG3VODX3BhGT8TMU/GiUy3h7ClX
# OxmZ+weCuIOzCkTDbK5OlAS8qSPpgp+XGlOLEPaM31Mgf6YTppAaeP0ophx345oh
# twIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFNCCsqdXRy/MmjZGVTAvx7YFWpslMB8G
# A1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRYMFYwVKBSoFCG
# Tmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUy
# MFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEFBQcBAQRgMF4w
# XAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2Vy
# dHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwG
# A1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQD
# AgeAMA0GCSqGSIb3DQEBCwUAA4ICAQA4IvSbnr4jEPgo5W4xj3/+0dCGwsz863QG
# Z2mB9Z4SwtGGLMvwfsRUs3NIlPD/LsWAxdVYHklAzwLTwQ5M+PRdy92DGftyEOGM
# Hfut7Gq8L3RUcvrvr0AL/NNtfEpbAEkCFzseextY5s3hzj3rX2wvoBZm2ythwcLe
# ZmMgHQCmjZp/20fHWJgrjPYjse6RDJtUTlvUsjr+878/t+vrQEIqlmebCeEi+VQV
# xc7wF0LuMTw/gCWdcqHoqL52JotxKzY8jZSQ7ccNHhC4eHGFRpaKeiSQ0GXtlbGI
# bP4kW1O3JzlKjfwG62NCSvfmM1iPD90XYiFm7/8mgR16AmqefDsfjBCWwf3qheIM
# fgZzWqeEz8laFmM8DdkXjuOCQE/2L0TxhrjUtdMkATfXdZjYRlscBDyr8zGMlprF
# C7LcxqCXlhxhtd2CM+mpcTc8RB2D3Eor0UdoP36Q9r4XWCVV/2Kn0AXtvWxvIfyO
# Fm5aLl0eEzkhfv/XmUlBeOCElS7jdddWpBlQjJuHHUHjOVGXlrJT7X4hicF1o23x
# 5U+j7qPKBceryP2/1oxfmHc6uBXlXBKukV/QCZBVAiBMYJhnktakWHpo9uIeSnYT
# 6Qx7wf2RauYHIER8SLRmblMzPOs+JHQzrvh7xStx310LOp+0DaOXs8xjZvhpn+Wu
# Zij5RmZijDCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZI
# hvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw
# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
# MjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAy
# MDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVowfDELMAkGA1UEBhMC
# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp
# bWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
# AQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX9gF/bErg4r25Phdg
# M/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPF
# dvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6
# GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byNpOORj7I5LFGc6XBp
# Dco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2krnopN6zL64NF50Zu
# yjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4dPf0gz3N9QZpGdc3E
# XzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0
# lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1q
# GFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ
# +QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzFER1y7435UsSFF5PA
# PBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkw
# EgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxG
# NSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARV
# MFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWlj
# cm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAK
# BggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC
# AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX
# zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v
# cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI
# KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG
# 9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0x
# M7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN3Zi6th542DYunKmC
# VgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449
# xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5KYnDvBewVIVCs/wM
# nosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDS
# PeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB62FD+CljdQDzHVG2d
# Y3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxn
# GSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+Crvs
# QWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcdFYmNcP7ntdAoGokL
# jzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL
# 6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggNN
# MIICNQIBATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
# b3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEn
# MCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjdGMDAtMDVFMC1EOTQ3MSUwIwYDVQQD
# ExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQDC
# KAZKKv5lsdC2yoMGKYiQy79p/6CBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w
# IFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA60ARlzAiGA8yMDI1MDEyNjAxNDI0
# N1oYDzIwMjUwMTI3MDE0MjQ3WjB0MDoGCisGAQQBhFkKBAExLDAqMAoCBQDrQBGX
# AgEAMAcCAQACAg/GMAcCAQACAhJGMAoCBQDrQWMXAgEAMDYGCisGAQQBhFkKBAIx
# KDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZI
# hvcNAQELBQADggEBACp8emer3GEr0oVxrNEYaDzxFdj7Ozp2Zm/zdeRe3KUAAVyV
# znonwJOLnnHSuxT5ASFf9zufp6ypZm2lvBTvs9jBpVwk1UxE4K8G5FEJHMrOxuJl
# cziosMUj+lS/jbF9jwAmhauWqIQE0mc1ENbQt+fFFYsxFRfx/MjF2Uo+jNZMwuen
# noif9wEwc8TXV/T+YBk3CW82qeK5dk8Yz6IWz1qF/wXu6RrO+4lX2HTVPGGq9IAQ
# L6HvE/bS4d8jM428YZ+Cye8b7LkKUpx0uLLC1rWZj70sprSceEwt+GIgD/ZUDNQ2
# JE+eh+i7YF2XfdDJX2anyygfF+I21a3wBDKd2YkxggQNMIIECQIBATCBkzB8MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNy
# b3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAfAqfB1ZO+YfrQABAAAB8DAN
# BglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8G
# CSqGSIb3DQEJBDEiBCBIbujHKBRwZqI/wFUjjFtX1a8I2FAOJhdZ34lSnGYL6zCB
# +gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EIFwBmqOlcv3kU7mAB5sWR74QFAiS
# 6mb+CM6asnFAZUuLMIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh
# c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD
# b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw
# MTACEzMAAAHwKnwdWTvmH60AAQAAAfAwIgQgR5aSUZGhmNoBkOf1AAqzUH4WIsQw
# BwjmQ85KYC5RsgYwDQYJKoZIhvcNAQELBQAEggIACD06+VQ4p+zqNIzG/5nfKzNd
# F9QeGmw6akp+GvP7Wqf9CCQCfjewmdv2mzCf+tMB2gCmAveMPKkuNPDRSjtqYQHV
# MCwUIw0Dr2xG1oV8ZdjZSBLN+4v2Xp07auaIadgU2Hs23jWw3GP2km9ylCMKX9bn
# DZuRwyeoh7rUOdFrbOf7ngsxPWtsTKF/JiYqp2kyELN22h4jInCRA8dmXYImFuuT
# hgTz95RChDCHJjk6B0GE5fFtAU9z2QpmiyhjqpYhPvwdUYBl+KuZPnDoQVp6kvKi
# rL/Ia0653VgUfKgt+RM+de2YKC3DUuTZ998allGOmSvnGximCIVtFdAXU49FPfoK
# cOQ65kU/P11kpyU197sbvE99vt/82EUkUiHIL5faTHKb31fffTPTb5P5539zpUCf
# VcxN/OixYS0/r51202Z+puAvANL08rDa9DUNLNm5LBbiDwZOLrR1tMsZLRZbI68r
# zSh0pvkYe8sqasi3vTZFsz5uNRgu4BOdzjT8wP/5wdtlh4jP5NmujKgyLBpdnkYx
# PFZq/6t+qtVMmnPnpJRakn9KIHOVZKJuyqBxt3e9h6AhMzP2wvJWDyIjE70PHkmA
# qREz4zAwhqZuamhTKpim8iX6RJ0A44OYfdqaBKgRSg6MMVzbqds6DCpkH8x4RuwU
# ANY20GAdYpiNixoc1A8=
# SIG # End signature block