Import.psm1
#----------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. #----------------------------------------------------------------------- # .EXTERNALHELP Import.psm1-Help.xml function Import-AzsMarketplaceItem { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $RepositoryDir, [Parameter(Mandatory = $false)] [string] $JournalDir, [Parameter(Mandatory = $false)] [string[]] $ProductName, [Parameter(Mandatory = $false)] [ValidateSet('Upload', 'Import', 'Cleanup')] [string] $From = 'Initialize', [Parameter(Mandatory = $false)] [ValidateSet('Upload', 'Import', 'Cleanup')] [string] $UpTo = 'Cleanup', [Parameter(Mandatory = $false)] [ValidateRange(5, 60)] [int] $SleepInterval = 60 ) function Upload-AllProducts { param () function Initialize-StorageAccount { param () Start-Activity 'Initialize-StorageAccount' Select-AzSubscription -Subscription 'Default Provider Subscription' -ErrorAction Stop | Out-Null New-AzResourceGroup -Name $ResourceGroupName -Location $Location -Force -ErrorAction Stop | Out-Null $sa = Get-AzStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName -ErrorAction SilentlyContinue if (-not $sa) { $sa = New-AzStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName -Location $Location -SkuName Standard_LRS -ErrorAction Stop } Stop-Activity return $sa.Context.ConnectionString } function Invoke-Upload { param ( [ValidateNotNullOrEmpty()] [string] $ConnectionString ) Start-Activity 'Invoke-Upload' while ($true) { & "$PSScriptRoot\SyndicationClient.exe" upload $RepositoryDir $JournalDir $ConnectionString if ($LASTEXITCODE -eq 0) { break } Write-Verbose "Sleep for $SleepInterval seconds" -Verbose Start-Sleep -Seconds $SleepInterval } Stop-Activity } #----------------------------------------------------------------------- Start-Activity 'Upload-AllProducts' $productList = Get-ProductList -ProductNames $ProductName $uploadJobInfo = @{ productNames = @() + ($productList | ForEach-Object { $_.ProductName }) } $uploadJobInfo | ConvertTo-Json -Depth 99 | Set-Content -LiteralPath "$JournalDir\.upload-info.json" -Encoding UTF8 $connectionString = Initialize-StorageAccount Invoke-Upload -ConnectionString $connectionString Stop-Activity } #----------------------------------------------------------------------- function Import-AllProducts { param () function Import-Product { param ( [psobject] $ProductDetails ) Start-Activity "Import-Product, productName = $($ProductDetails.ProductName)" $productId = "$ActivationResourceId/downloadedProducts/$($productDetails.ProductName)" $requestUri = "$($productId)?api-version=2016-01-01" $response = Invoke-AzsResourceManager -Method GET -Uri $requestUri if ($response.StatusCode -eq [System.Net.HttpStatusCode]::NotFound) { $product = $null } else { Ensure-SuccessStatusCode -Response $response $product = $response.Content | ConvertFrom-Json } Write-Verbose "Provisioning state of $($productDetails.ProductName): $($product.properties.provisioningState)" -Verbose if (-not $product -or $product.properties.provisioningState -eq 'Failed') { Write-Verbose 'Initializing product import...' -Verbose $requestUri = "$($productId)?api-version=2016-01-01" $payload = Get-Content -LiteralPath "$JournalDir\$($productDetails.ProductName)\payload.json" -Raw | ConvertFrom-Json Invoke-AzsResourceManager -Method PUT -Uri $requestUri -Body @{ properties = $payload; } -ThrowOnError | Out-Null } Stop-Activity } function Wait-ForProducts { param ( [psobject[]] $ProductList ) Start-Activity 'Wait-ForProducts' $timeout = [timespan]::FromHours(6) $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() while ($true) { Write-Verbose "[$(Get-Date -Format 's')] Get product import status" -Verbose $allDone = $true foreach ($productDetails in $ProductList) { $productId = "$ActivationResourceId/downloadedProducts/$($productDetails.ProductName)" $requestUri = "$($productId)?api-version=2016-01-01" $response = Invoke-AzsResourceManager -Method GET -Uri $requestUri -ThrowOnError $product = $response.Content | ConvertFrom-Json Write-Verbose "Provisioning state of $($productDetails.ProductName): $($product.properties.provisioningState)" -Verbose if ($product.properties.provisioningState -eq 'Failed') { throw "Failed to import product, productId: $productId." } if ($product.properties.provisioningState -ne 'Succeeded') { $allDone = $false } } if ($allDone) { break } if ($stopwatch.Elapsed -gt $timeout) { throw 'Product import didn''t complete within the allotted time.' } Write-Verbose "Sleep for $SleepInterval seconds" -Verbose Start-Sleep -Seconds $SleepInterval } Stop-Activity } #----------------------------------------------------------------------- Start-Activity 'Import-AllProducts' $uploadJobInfo = Get-Content "$JournalDir\.upload-info.json" -Raw | ConvertFrom-Json $productList = Get-ProductList -ProductNames $uploadJobInfo.productNames foreach ($productDetails in $productList) { Import-Product -ProductDetails $productDetails } Wait-ForProducts -ProductList $productList Stop-Activity } #----------------------------------------------------------------------- function Invoke-Cleanup { param () Start-Activity 'Invoke-Cleanup' $rg = Get-AzResourceGroup -Name $ResourceGroupName -Location $Location -ErrorAction SilentlyContinue if ($rg) { Remove-AzResourceGroup -Name $ResourceGroupName -Force } if (Test-Path $JournalDir) { Remove-Item $JournalDir -Recurse -Force } Stop-Activity } #----------------------------------------------------------------------- function Resolve-Activation { param () $activation = Get-AzResource -ResourceType Microsoft.AzureBridge.Admin/activations | Select-Object -First 1 if (-not $activation) { throw 'Azure Stack activation not found. Make sure your stamp is activated and the selected subscription is ''Default Provider Subscription''.' } return $activation.ResourceId } function Get-ProductList { param ( [string[]]$ProductNames ) $products = @() if ($ProductNames) { $productDirs = $ProductNames | ForEach-Object { [System.IO.Path]::Combine($RepositoryDir, $_) } } else { $productDirs = Get-ChildItem -LiteralPath $RepositoryDir -Directory | ForEach-Object { $_.FullName } } foreach ($productDir in $productDirs) { $productDetailsFileName = [System.IO.Path]::Combine($productDir, "productDetails.json") $productDetails = Get-Content -LiteralPath $productDetailsFileName -Raw | ConvertFrom-Json $products += $productDetails } return $products } #----------------------------------------------------------------------- $Steps = @{ Upload = 0 Import = 1 Cleanup = 2 } $FromValue = $Steps[$From] $UpToValue = $Steps[$UpTo] $Location = (Get-AzLocation)[0].Location $ResourceGroupName = 'syndicationtemp-rg' $StorageAccountName = 'syndicationtempsa' $RepositoryDir = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($RepositoryDir) New-Item -Path $RepositoryDir -ItemType Directory -Force | Out-Null if (-not $JournalDir) { $JournalDir = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [guid]::NewGuid().ToString()) } else { $JournalDir = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($JournalDir) } New-Item -Path $JournalDir -ItemType Directory -Force | Out-Null $ActivationResourceId = Resolve-Activation Start-Activity 'Import' Write-Verbose "RepositoryDir: $RepositoryDir" -Verbose Write-Verbose "JournalDir: $JournalDir" -Verbose if ($FromValue -le $Steps.Upload -and $UpToValue -ge $Steps.Upload) { Upload-AllProducts } if ($FromValue -le $Steps.Import -and $UpToValue -ge $Steps.Import) { Import-AllProducts } if ($FromValue -le $Steps.Cleanup -and $UpToValue -ge $Steps.Cleanup) { Invoke-Cleanup } Stop-Activity } #----------------------------------------------------------------------- $ErrorActionPreference = 'Stop' $InformationPreference = 'Continue' Import-Module "$PSScriptRoot\Activities.psm1" -Force -ErrorAction Stop Import-Module "$PSScriptRoot\ResourceManager.psm1" -Force -DisableNameChecking -ErrorAction Stop Export-ModuleMember -Function @('Import-AzsMarketplaceItem') # SIG # Begin signature block # MIIjlAYJKoZIhvcNAQcCoIIjhTCCI4ECAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCChT8IL0aNsw3jq # 58KLzuFEj7IXeSyddiy15GwOdALuLqCCDXYwggX0MIID3KADAgECAhMzAAABhk0h # daDZB74sAAAAAAGGMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ2WhcNMjEwMzAzMTgzOTQ2WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQC49eyyaaieg3Xb7ew+/hA34gqzRuReb9svBF6N3+iLD5A0iMddtunnmbFVQ+lN # Wphf/xOGef5vXMMMk744txo/kT6CKq0GzV+IhAqDytjH3UgGhLBNZ/UWuQPgrnhw # afQ3ZclsXo1lto4pyps4+X3RyQfnxCwqtjRxjCQ+AwIzk0vSVFnId6AwbB73w2lJ # +MC+E6nVmyvikp7DT2swTF05JkfMUtzDosktz/pvvMWY1IUOZ71XqWUXcwfzWDJ+ # 96WxBH6LpDQ1fCQ3POA3jCBu3mMiB1kSsMihH+eq1EzD0Es7iIT1MlKERPQmC+xl # K+9pPAw6j+rP2guYfKrMFr39AgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhTFTFHuCaUCdTgZXja/OAQ9xOm4w # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW # MBQGA1UEBRMNMjMwMDEyKzQ1ODM4NDAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAEDkLXWKDtJ8rLh3d7XP # 1xU1s6Gt0jDqeHoIpTvnsREt9MsKriVGKdVVGSJow1Lz9+9bINmPZo7ZdMhNhWGQ # QnEF7z/3czh0MLO0z48cxCrjLch0P2sxvtcaT57LBmEy+tbhlUB6iz72KWavxuhP # 5zxKEChtLp8gHkp5/1YTPlvRYFrZr/iup2jzc/Oo5N4/q+yhOsRT3KJu62ekQUUP # sPU2bWsaF/hUPW/L2O1Fecf+6OOJLT2bHaAzr+EBAn0KAUiwdM+AUvasG9kHLX+I # XXlEZvfsXGzzxFlWzNbpM99umWWMQPTGZPpSCTDDs/1Ci0Br2/oXcgayYLaZCWsj # 1m/a0V8OHZGbppP1RrBeLQKfATjtAl0xrhMr4kgfvJ6ntChg9dxy4DiGWnsj//Qy # wUs1UxVchRR7eFaP3M8/BV0eeMotXwTNIwzSd3uAzAI+NSrN5pVlQeC0XXTueeDu # xDch3S5UUdDOvdlOdlRAa+85Si6HmEUgx3j0YYSC1RWBdEhwsAdH6nXtXEshAAxf # 8PWh2wCsczMe/F4vTg4cmDsBTZwwrHqL5krX++s61sLWA67Yn4Db6rXV9Imcf5UM # Cq09wJj5H93KH9qc1yCiJzDCtbtgyHYXAkSHQNpoj7tDX6ko9gE8vXqZIGj82mwD # TAY9ofRH0RSMLJqpgLrBPCKNMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq # 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 # /Xmfwb1tbWrJUnMTDXpQzTGCFXQwghVwAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAAGGTSF1oNkHviwAAAAAAYYwDQYJYIZIAWUDBAIB # BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFxy3h/H4Nm28kByNqaWjjwm # gTIKoLuGSxab2MtMiKeGMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A # cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB # BQAEggEAswNAp5Fh9+iYAnCZ/iXlGezSfbhS88h974uWPKQUoa+Xt7xDHtDxwOhc # 8xH+NAhHyxnbKP1XC41dciMv4/gSZC9hIyZBoxHjR5uEG1e1FUtnvvOXFj4FCNn+ # NTc1szK3KnEg49hUM9v0+9MksUsxYCjxWmZP402ye416g2hiGulEroAYQGMEf2vz # 6vmCpuqVKu6gvbZfya5/gSNsYldxh4VrYHf1rJ9nczBRvKgIQNxf6SkkRvyUmPRE # ZPpOu5tCKpDFIEvmRppp4qc5hEzu/m6OAVxiqccUp8468+uDj3kb/Lrhvqd/M0Ha # dmZQmrs/0ZzKN0ZjLqVkELnOxA5gb6GCEv4wghL6BgorBgEEAYI3AwMBMYIS6jCC # EuYGCSqGSIb3DQEHAqCCEtcwghLTAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFZBgsq # hkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl # AwQCAQUABCBdo6qWMzkicffhB/iRhO3lpZQGrGB16iCS7Eb6IcAWjgIGX7wJ5kCS # GBMyMDIwMTIwNDAwMDk1NC4xMDRaMASAAgH0oIHYpIHVMIHSMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl # bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO # OkEyNDAtNEI4Mi0xMzBFMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT # ZXJ2aWNloIIOTTCCBPkwggPhoAMCAQICEzMAAAE/4X7to9j/v9kAAAAAAT8wDQYJ # KoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjAx # MDE1MTcyODI2WhcNMjIwMTEyMTcyODI2WjCB0jELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3Bl # cmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpBMjQwLTRC # ODItMTMwRTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCC # ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAO1F1U5lbR+JB2ejAO7KRMFd # Lm5arpdDoKyH3TeMURCjsDo7udkW/c0a0xZCt+PCy6PuKGtY1kjArogRhjxEuyEJ # 368jnB1kbhLaY0DI8UqEMSMV6dzgixF/W2TROg92bsMG4ufWj86pBaC/XlauTNsj # YPDCHszV7tt/QOHn0agmPw4X68PyCO8cbgqa9qFV0e02EVupE1GnliCP7I+xd0sl # GYgYOUDJjDtCiR9hYwT47LNiuOcEo0HjosVUeeB2XXn7CwTJ1/NiSzeUJQ6NQP8r # DTIX7EgAd7w6AM1VamrAiOa/9HcYKtVrFXI2sG+fa4M66lqjMELX+KbSGcxWDKUC # AwEAAaOCARswggEXMB0GA1UdDgQWBBS8OgvMEaMTpYzh66JvyRaMO5iBazAfBgNV # HSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBHhkVo # dHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNUaW1T # dGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAC # hj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0YVBD # QV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUF # BwMIMA0GCSqGSIb3DQEBCwUAA4IBAQCfsvpgDi6ueE2Nlg4gpGBDnQFAmZhPo45r # so+R0LqpRn4zonl44FXcmJARMN0r3iDw9subb0N/D0nwUbGHWqasQ6wG8DJRYTBx # l6Vcr1yBuGhBFWT1PxS8MNG0tXmpBfeZiDBbS/2IdZRtTVDV6vMifHeeKOsIRRXL # v8tgb0vPtCxxVNEkzYkfPGeR847w88iqaHLd9ofhG3T8Ft/c/VVOHQDDa+aXHJJo # gO+71nKRQXYdU/tLhr4Cqpkh7xQNlsyGZCaNuoMwCKFRqRP+kkW1FqORHEhJa4AL # 6ZYNCiHpUIQaRfuVIw11fM7j7TOQU94hvvOfzk0lLk8IRb6i6KQiMIIGcTCCBFmg # AwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3Qg # Q2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcNMjUw # NzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ # MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u # MSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCASIwDQYJ # KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0VBDV # pQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEwWbEwRA/x # YIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQedGFn # kV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJUGKxXf13 # Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw2k4GkbaI # CDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0CAwEAAaOC # AeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7fEYb # xTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYw # DwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoY # xDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtp # L2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYB # BQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20v # cGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0gAQH/ # BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93d3cu # bWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYBBQUH # AgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUAbQBl # AG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9naOhIW+z # 66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtRgkQS+7lT # jMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzymXlKkVIA # rzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon/VWv # L/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3DnKOiPPp/ # fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/fmNZ # JQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110mCIIYdqw # UB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0cs0d # 9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7aKLix # qduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQcdeh # 0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+NR4I # uto229Nfj950iEkSoYIC1zCCAkACAQEwggEAoYHYpIHVMIHSMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl # bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO # OkEyNDAtNEI4Mi0xMzBFMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT # ZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQBO1zQhf9bHJcmAoCSPgmjIAjoiGKCBgzCB # gKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH # EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV # BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBBQUA # AgUA43O29zAiGA8yMDIwMTIwNDAzMTE1MVoYDzIwMjAxMjA1MDMxMTUxWjB3MD0G # CisGAQQBhFkKBAExLzAtMAoCBQDjc7b3AgEAMAoCAQACAiOjAgH/MAcCAQACAhHE # MAoCBQDjdQh3AgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAI # AgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQEFBQADgYEAbHN0Z0qkLQ3K # Fg8gcR/I1q7QPYCBfbmjm8+4G6oY0bBRptZ78G883g6tKqpTgPha4w0XLkQnRTD2 # zJKgcWhzSSu5r+XQxcdqk28VyO0BOt26ETK53chSv7srJUfThZY1d9ebpPj9LBD4 # 3jFUFuMu5eH3WeNyjiolRCB3r1i+fwYxggMNMIIDCQIBATCBkzB8MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg # VGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAT/hfu2j2P+/2QAAAAABPzANBglghkgB # ZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3 # DQEJBDEiBCCyKi1Zg8blS4/x3+GhWcyfPo/MxXnkS9DiHyE7DGbooDCB+gYLKoZI # hvcNAQkQAi8xgeowgecwgeQwgb0EIEQ7Wa+cFXjB3Kah2rWUmT7Mm8Jq+UIIjLxb # PiMZKUsgMIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0 # b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh # dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMA # AAE/4X7to9j/v9kAAAAAAT8wIgQg89MAUfqMZXmFfnG17nZlrNMOvEKdY567Ag7+ # MuGm4xgwDQYJKoZIhvcNAQELBQAEggEAHKWxukW/X0gmvR+PxHcz86pK7izuk3w/ # +O5wg5QjerqQBHr+CWg7SlPS/ILhmRCSt4Hz6/CsVKToEWJASSbfQDzGL3C0WorH # 4ZPw46jCwfcrt6N5s9FS3ugKtXaDp1n8VOZ4oe3yO4SFaecfWEjcHMycRBlyRb94 # hIZKId6Gw2nCMxlfwPtWkBS7OAPWGOniKTJAC9Yrp13lAzLjzyD//lQFfxzofW1t # q/trRjY6rioxy0JnjwWByv5c/vnFHiTqaM3IwDTu8b7OnwyCO2abhbctZUOnqEd8 # FxYxzPKLgh04h0wz/BYuv4n146D5tsdzreoIwV+yK1TMn8w9bnBOKg== # SIG # End signature block |