AzStackHci.EnvironmentChecker.Operations.psm1
<#############################################################
# # # Copyright (C) Microsoft Corporation. All rights reserved. # # # #############################################################> function Invoke-EnvironmentValidator { <# .SYNOPSIS Wrapper command to Test Environment Readiness .DESCRIPTION Wrapper command to test environment readiness, run locally on HCI system. .PARAMETER OperationType Type of Operation. .PARAMETER WaitForResult Wait for action plan to complete. #> [CmdletBinding()] Param( [Parameter(Mandatory = $true)] [ValidateSet('AddNode','Deploy','ScaleOut','Upgrade','Update')] [String] $OperationType, [Parameter(Mandatory = $true, ParameterSetName = "AddNode")] [ValidateNotNullOrEmpty()] [String] $Name, [Parameter(Mandatory = $false, ParameterSetName = "AddNode", HelpMessage = 'Use Host IPv4 address to simulate AddNode. Omit for RepairNode.')] [ValidateNotNullOrEmpty()] [String] $HostIpv4, [Parameter(Mandatory = $false, HelpMessage = 'Start step for the action plan. Use Get-EnvironmentValidatorActionPlan to get the steps.')] [int] $Start, [Parameter(Mandatory = $false, HelpMessage = 'End step for the action plan. Use Get-EnvironmentValidatorActionPlan to get the steps.')] [int] $End, [Parameter(Mandatory = $false, ParameterSetName = "Update")] [ValidateNotNullOrEmpty()] [String] $EnvironmentCheckerResultPath, [Parameter(Mandatory = $false, HelpMessage = 'Wait for action plan to conclude. Shows progress if running on the ECE owning node.')] [switch]$Wait ) $ErrorActionPreference = 'Stop' # Check if we are running Orchestrator as a service or lite $Script:OrchestratorSvc = IsOrchestratorSvc # Check if action plan is running $RunningActionPlans = Get-AzStackHciEnvironmentCheckerActionPlan | Where-Object Status -In 'Running', 'Queued' if ($RunningActionPlans) { throw "Environment Validator action plan in progress" } if ($OperationType -in 'AddNode', 'ScaleOut' -and [string]::IsNullOrEmpty($Name) -and [string]::IsNullOrEmpty($HostIpv4)) { throw "Parameters missing: Name and HostIpv4 must be supplied when OperationType is AddNode or ScaleOut." } # Archive Log file ArchiveLogFiles $ActionType = Get-EnvironmentValidatorActionPlan -OperationType $OperationType Write-Verbose "Starting Environment Validator for $OperationType" # TODO check if Deploy, Upgrade or AddNode ops are running here? $params = @{ RolePath = 'Cloud\Infrastructure\EnvironmentValidator' ActionType = $ActionType } # Add needs a node name and IP, take these from the user # TO DO: Remove EnvironmentValidatorAddNode if ($ActionType -in 'EnvironmentValidatorAddNode','EnvironmentValidatorScaleOut') { if ([string]::IsNullOrEmpty($Name)) { throw "Parameters missing: Name and HostIpv4 must be supplied when OperationType is AddNode." } $params += @{ runtimeParameters = @{ NodeName = $Name } } if ($HostIpv4) { $params += @{ runtimeParameters = @{ IpAddress = $HostIpv4 } } } else { Write-Verbose "HostIpv4 not supplied, simiulating RepairNode" } } # Update needs a path to the result file, take this from the user, or set to a test value so we dont overwrite the real one. if ($ActionType -eq 'EnvironmentValidatorPreUpdate') { if ([string]::IsNullOrEmpty($EnvironmentCheckerResultPath)) { $EnvironmentCheckerResultPath = "$($env:LocalRootFolderPath)\MasLogs\Invoke-EnvironmentValidator-EnvironmentCheckerUpdateResult.json" } $params += @{ runtimeParameters = @{ EnvironmentCheckerResultPath = $EnvironmentCheckerResultPath } } } if ($Script:OrchestratorSvc) { if ($Start -and $End) { Write-Verbose "Starting Environment Validator for $OperationType from step $StartStep to $EndStep" $params += @{ Start = $Start End = $End } } else { Write-Verbose "Starting Environment Validator for $OperationType" } Write-Verbose "Invoke-ActionPlanInstance with params: `r`n $($params | Out-String)" $ActionPlanInstanceId = Invoke-ActionPlanInstance @params 4>$null if (-not $wait) { Write-Verbose "To check progress, open a powershell session to $(GetOrchestratorOwner) and call: 'Get-AzStackHciEnvironmentCheckerProgress -Path $($env:LocalRootFolderPath)\MasLogs\AzStackHciEnvironmentProgress.json'" Write-Verbose "Run the following to get the action plan progress Get-ActionPlanInstance -actionPlanInstanceID $ActionPlanInstanceId" } } else { Invoke-EceAction @params if (-not $wait) { Write-Verbose "To check progress, call: 'Get-AzStackHciEnvironmentCheckerProgress -Path $($env:LocalRootFolderPath)\MasLogs\AzStackHciEnvironmentProgress.json'" } } Start-Sleep -Seconds 5 for ($i = 0; $i -lt 30; $i++) { $ActionPlan = Get-AzStackHciEnvironmentCheckerActionPlan | Sort-Object LastModifiedDateTime -Descending | Select-Object -First 1 switch ($ActionPlan.Status) { { $_ -in "Failed", "Cancelled" } { throw "$ActionType is $($actionPlan.Status). Please resume please review: `n $($actionPlan.ProgressAsXml)" } { $_ -in "Waiting", "Pending" } { Write-Verbose "$ActionType is currently $($actionPlan.Status)" } { $_ -eq "Running" } { Write-Verbose "$ActionType is currently $($actionPlan.Status)" if ($Wait) { if ($ENV:COMPUTERNAME -eq (GetOrchestratorOwner)) { Get-AzStackHciEnvironmentCheckerProgress | Format-Table Result, StartTime, EndTime, DurationSeconds, Name, Description -AutoSize } } else { break outer } } { $_ -eq 'Completed' } { if ($ENV:COMPUTERNAME -eq (GetOrchestratorOwner)) { Get-AzStackHciEnvironmentCheckerProgress | Format-Table Result, StartTime, EndTime, DurationSeconds, Name, Description -AutoSize } break outer } default { Write-Warning "$ActionType cannot be started due to unknown status of last run" return } } Start-Sleep -Seconds 30 } Write-Verbose "$ActionType $($ActionPlanResult.Status) Action Plan ID: $($ActionPlanInstanceId.Guid)" } function Get-AzStackHciEnvironmentCheckerActionPlan { <# .SYNOPSIS Get all Environment Validator action plan instances #> [CmdletBinding()] param () $validatorLookup = 'EnvironmentValidator*' if (IsOrchestratorSvc) { Get-ActionPlanInstances | Where-Object { $_.ActionTypeName -like $validatorLookup } } else { Get-ActionProgress -ActionType $validatorLookup } } function Get-AzStackHciEnvironmentCheckerProgress { <# .SYNOPSIS Intended for internal-use to retrieve multi-validator invocation progress using action plan #> [CmdletBinding()] param ( [Parameter()] [string] $Path = "$($env:LocalRootFolderPath)\MasLogs\AzStackHciEnvironmentProgress.json" ) Get-Content $Path -ErrorAction SilentlyContinue | ConvertFrom-Json } function ArchiveLogFiles { <# .SYNOPSIS INTERNAL USE ONLY - Archives any supporting files for environment checker. #> [CmdletBinding()] param ( [Parameter()] [string] $Path = "$($env:LocalRootFolderPath)\MASLogs" ) # Archive any logs 'AzStackHciEnvironmentChecker.log', 'AzStackHciEnvironmentProgress.json', 'AzStackHciEnvironmentReport.json', 'AzStackHciEnvironmentReport.xml' | ForEach-Object { Get-ChildItem -Path $Path -Filter $PSITEM -ErrorAction SilentlyContinue | ForEach-Object { Rename-Item -Path $PSITEM.FullName -NewName ($PSITEM.fullname -replace '(\.)', ('_{0}.' -f (Get-Date -Format yyyyMMdd-HHmmss))) } } } function IsOrchestratorSvc { [CmdletBinding()] param () $orchestratorSvc = Get-Service | Where-Object {$_.Name -eq 'ECE Windows Service' -or $_.Name -eq 'Azure Stack HCI Orchestrator Service'} if ($orchestratorSvc) { return $true } else { Import-Module C:\CloudDeployment\ECEngine\EnterpriseCloudEngine.psd1 -Force return $false } } function GetOrchestratorOwner { [CmdletBinding()] param () try { Get-ClusterGroup | Where-Object {$_.Name -eq 'ECE Windows Service Cluster Group' -or $_.Name -eq 'Azure Stack HCI Orchestrator Service Cluster Group'} | Select-Object -expandProperty OwnerNode | Select-Object -ExpandProperty Name } catch { return $null } } function Get-EnvironmentValidatorActionPlan { param ( [Parameter(Mandatory = $true)] [ValidateSet('AddNode','Deploy','ScaleOut','Upgrade','Update')] [string] $OperationType ) $ActionType = switch ($OperationType) { 'Deploy' { 'EnvironmentValidatorFull' } 'Upgrade' { 'EnvironmentValidatorUpgrade' } 'AddNode' { 'EnvironmentValidatorPreAddNode' } 'ScaleOut' { 'EnvironmentValidatorScaleOut' } 'Update' { 'EnvironmentValidatorPreUpdate' } Default {} } if ($Script:OrchestratorSvc) { [xml]$xml = (Get-CloudDefinition).CloudDefinitionAsXmlString } else { [xml]$xml = (Get-EceConfiguration).xml } $apDef = $xml.SelectNodes("//Action[@Type='$ActionType']") $Steps = $apDef.Steps.Step Write-Verbose ($Steps | Out-String) -Verbose return $ActionType } # If this is a CI environment log module load and session information try { if (Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\SQMClient -Name IsCIEnv -ErrorAction SilentlyContinue) { try {$Query = quser 2>&1 } catch { $Query = "Failed to query session information" } try {$of = openfiles /query 2>&1} catch { $of = "Failed to query open files" } $pscall = Get-PSCallStack | Format-List * -force | Out-String $psinfo = Get-PSHostProcessInfo | Format-List * -force | Out-String $str = @" -------------------------------------------------------------- $(Get-Date) : $(whoami) query user: $Query Open Files: $of CallStack: $pscall psinfo: $psinfo -------------------------------------------------------------- "@ $str | out-file C:\maslogs\AzStackHciEnvironmentChecker-Debug.log -Force -Append } } catch {} # SIG # Begin signature block # MIIoQwYJKoZIhvcNAQcCoIIoNDCCKDACAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDHK7O93cLdD3n5 # doE6HMF+7PsdKg+IxhEC0YzXAeCPGKCCDXYwggX0MIID3KADAgECAhMzAAAEBGx0 # 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 # /Xmfwb1tbWrJUnMTDXpQzTGCGiMwghofAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAAQEbHQG/1crJ3IAAAAABAQwDQYJYIZIAWUDBAIB # BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIKjsragMmeIQbsv5UN9+haoX # QMBMsF/tC0/Pm98hECCCMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A # cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB # BQAEggEAanL7gYm99wCWiQrg4gl8GPJnp4QyYqhiTTod7XXeoZbL1n63HtwM12iZ # CD/yG/nLdIBIRHoOMphTc4Oyb68DUrewUw5hO66lVl+G/QTOGi50J0KKwsn82mOX # tY17avUYqJsPXBODMfvpDR2xrvqQDYhGkuy/sorz06hmYWyqqwZe0N5e1rBdnuAm # jOeH6Fnpv7mrhjjAk5tG9oh6UmhWUMCp3DkoZ8LKzI0TAHCCKT3au5dXyM+cAslr # cVOK8O3tsKN3PvGMoFwiRsnhc3GELO3/Q0P9lTg5qg+8JEybP2tHQgaC/fQ+fOKg # 51aCSYp+VCEYEL1Z3xvV+ChGnekkKKGCF60wghepBgorBgEEAYI3AwMBMYIXmTCC # F5UGCSqGSIb3DQEHAqCCF4YwgheCAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFaBgsq # hkiG9w0BCRABBKCCAUkEggFFMIIBQQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl # AwQCAQUABCA5LHKf8ER15RZ3KE13ZIuVzsVX+vOf7yyVf9m+2ZcAIQIGZ0hn7L80 # GBMyMDI0MTIwNDE1MDM1My4yODNaMASAAgH0oIHZpIHWMIHTMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl # bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVT # Tjo2QjA1LTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAg # U2VydmljZaCCEfswggcoMIIFEKADAgECAhMzAAAB9oMvJmpUXSLBAAEAAAH2MA0G # CSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTI0 # MDcyNTE4MzEwNFoXDTI1MTAyMjE4MzEwNFowgdMxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9w # ZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjZCMDUt # MDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNl # MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0UJeLMR/N9WPBZhuKVFF # +eWJZ68Wujdj4X6JR05cxO5CepNXo17rVazwWLkm5AjaVh19ZVjDChHzimxsoaXx # Nu8IDggKwpXvpAAItv4Ux50e9S2uVwfKv57p9JKG+Q7VONShujl1NCMkcgSrPdmd # /8zcsmhzcNobLomrCAIORZ8IwhYy4siVQlf1NKhlyAzmkWJD0N+60IiogFBzg3yI # SsvroOx0x1xSi2PiRIQlTXE74MggZDIDKqH/hb9FT2kK/nV/aXjuo9LMrrRmn44o # YYADe/rO95F+SG3uuuhf+H4IriXr0h9ptA6SwHJPS2VmbNWCjQWq5G4YkrcqbPMa # x7vNXUwu7T65E8fFPd1IuE9RsG4TMAV7XkXBopmPNfvL0hjxg44kpQn384V46o+z # dQqy5K9dDlWm/J6vZtp5yA1PyD3w+HbGubS0niEQ1L6wGOrPfzIm0FdOn+xFo48E # Rl+Fxw/3OvXM5CY1EqnzEznPjzJc7OJwhJVR3VQDHjBcEFTOvS9E0diNu1eocw+Z # Ckz4Pu/oQv+gqU+bfxL8e7PFktfRDlM6FyOzjP4zuI25gD8tO9zJg6g6fRpaZc43 # 9mAbkl3zCVzTLDgchv6SxQajJtvvoQaZxQf0tRiPcbr2HWfMoqqd9uiQ0hTUEhG4 # 4FBSTeUPZeEenRCWadCW4G8CAwEAAaOCAUkwggFFMB0GA1UdDgQWBBRIwZsJuOcJ # fScPWcXZuBA4B89K8jAfBgNVHSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBf # BgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz # L2NybC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmww # bAYIKwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29m # dC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0El # MjAyMDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUF # BwMIMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAgEA13kBirH1cHu1 # WYR1ysj125omGtQ0PaQkEzwGb70xtqSoI+svQihsgdTYxaPfp2IVFdgjaMaBi81w # B8/nu866FfFKKdhdp3wnMZ91PpP4Ooe7Ncf6qICkgSuwgdIdQvqE0h8VQ5QW5sDV # 4Q0Jnj4f7KHYx4NiM8C4jTw8SQtsuxWiTH2Hikf3QYB71a7dB9zgHOkW0hgUEeWO # 9mh2wWqYS/Q48ASjOqYw/ha54oVOff22WaoH+/Hxd9NTEU/4vlvsRIMWT0jsnNI7 # 1jVArT4Q9Bt6VShWzyqraE6SKUoZrEwBpVsI0LMg2X3hOLblC1vxM3+wMyOh97aF # Os7sFnuemtI2Mfj8qg16BZTJxXlpPurWrG+OBj4BoTDkC9AxXYB3yEtuwMs7pRWL # yxIxw/wV9THKUGm+x+VE0POLwkrSMgjulSXkpfELHWWiCVslJbFIIB/4Alv+jQJS # KAJuo9CErbm2qeDk/zjJYlYaVGMyKuYZ+uSRVKB2qkEPcEzG1dO9zIa1Mp32J+zz # W3P7suJfjw62s3hDOLk+6lMQOR04x+2o17G3LceLkkxJm41ErdiTjAmdClen9yl6 # HgMpGS4okjFCJX+CpOFX7gBA3PVxQWubisAQbL5HgTFBtQNEzcCdh1GYw/6nzzNN # t+0GQnnobBddfOAiqkzvItqXjvGyK1QwggdxMIIFWaADAgECAhMzAAAAFcXna54C # m0mZAAAAAAAVMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UE # CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z # b2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZp # Y2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0yMTA5MzAxODIyMjVaFw0zMDA5MzAxODMy # MjVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH # EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV # BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0B # AQEFAAOCAg8AMIICCgKCAgEA5OGmTOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51 # yMo1V/YBf2xK4OK9uT4XYDP/XE/HZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY # 6GB9alKDRLemjkZrBxTzxXb1hlDcwUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9 # cmmvHaus9ja+NSZk2pg7uhp7M62AW36MEBydUv626GIl3GoPz130/o5Tz9bshVZN # 7928jaTjkY+yOSxRnOlwaQ3KNi1wjjHINSi947SHJMPgyY9+tVSP3PoFVZhtaDua # Rr3tpK56KTesy+uDRedGbsoy1cCGMFxPLOJiss254o2I5JasAUq7vnGpF1tnYN74 # kpEeHT39IM9zfUGaRnXNxF803RKJ1v2lIH1+/NmeRd+2ci/bfV+AutuqfjbsNkz2 # K26oElHovwUDo9Fzpk03dJQcNIIP8BDyt0cY7afomXw/TNuvXsLz1dhzPUNOwTM5 # TI4CvEJoLhDqhFFG4tG9ahhaYQFzymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZk # i1ugpoMhXV8wdJGUlNi5UPkLiWHzNgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9Q # BXpsxREdcu+N+VLEhReTwDwV2xo3xwgVGD94q0W29R6HXtqPnhZyacaue7e3Pmri # Lq0CAwEAAaOCAd0wggHZMBIGCSsGAQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUC # BBYEFCqnUv5kxJq+gpE8RjUpzxD/LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJl # pxtTNRnpcjBcBgNVHSAEVTBTMFEGDCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIB # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9y # eS5odG0wEwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUA # YgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU # 1fZWy4/oolxiaNE9lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2Ny # bC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIw # MTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0w # Ni0yMy5jcnQwDQYJKoZIhvcNAQELBQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/yp # b+pcFLY+TkdkeLEGk5c9MTO1OdfCcTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulm # ZzpTTd2YurYeeNg2LpypglYAA7AFvonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM # 9W0jVOR4U3UkV7ndn/OOPcbzaN9l9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECW # OKz3+SmJw7wXsFSFQrP8DJ6LGYnn8AtqgcKBGUIZUnWKNsIdw2FzLixre24/LAl4 # FOmRsqlb30mjdAy87JGA0j3mSj5mO0+7hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3Uw # xTSwethQ/gpY3UA8x1RtnWN0SCyxTkctwRQEcb9k+SS+c23Kjgm9swFXSVRk2XPX # fx5bRAGOWhmRaw2fpCjcZxkoJLo4S5pu+yFUa2pFEUep8beuyOiJXk+d0tBMdrVX # VAmxaQFEfnyhYWxz/gq77EFmPWn9y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/AsGC # onsXHRWJjXD+57XQKBqJC4822rpM+Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU # 5nR0W2rRnj7tfqAxM328y+l7vzhwRNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEG # ahC0HVUzWLOhcGbyoYIDVjCCAj4CAQEwggEBoYHZpIHWMIHTMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl # bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVT # Tjo2QjA1LTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAg # U2VydmljZaIjCgEBMAcGBSsOAwIaAxUAFU9eSpdxs0a06JFIuGFHIj/I+36ggYMw # gYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYD # VQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQsF # AAIFAOr6zy0wIhgPMjAyNDEyMDQxMjUzMDFaGA8yMDI0MTIwNTEyNTMwMVowdDA6 # BgorBgEEAYRZCgQBMSwwKjAKAgUA6vrPLQIBADAHAgEAAgIcMDAHAgEAAgITOjAK # AgUA6vwgrQIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB # AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBCwUAA4IBAQB7CslUnsKaAjzU # Z4A2PljoVEZSoVnPzpBDMtAQnyVgkzSMfmNpnDUoXoTyeqyHCSWHRa46HVuMHZRo # q31PEXEETP+KVSKQROzhCPmLyfgcL2c3wz/0PUqyJgA5cmo1uARZgaiT7IZOF4Xe # OzkSX97rbBGGgogaxoJrS8EwvwsvrxmnSy61dr3naiwOuAT6/FtAX6M0IW7NwzbK # 2xg6JjOiD57nmHjn9ljh4j12msTOrHEsca5sf5P9Qu7iMk8XxHM2T5mEhQ7hqFXe # EzjOTmvhmElmr/FhdHTrTRnXWFrZsoP8pkGQW6zvEwCU+2quvegAPXqWMP7R83sr # ZnQmoSxeMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD # b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw # MTACEzMAAAH2gy8malRdIsEAAQAAAfYwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqG # SIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgTSDs/VPwEZU/ # LmFfCWNmbKX88F821PAMjOloMYf6On4wgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHk # MIG9BCArYUzxlF6m5USLS4f8NXL/8aoNEVdsCZRmF+LlQjG2ojCBmDCBgKR+MHwx # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p # Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB9oMvJmpUXSLBAAEAAAH2 # MCIEIMJx0vTZNkt04+1v2tiNaf7i6oDb2vlY/gbX2/I7Yo8AMA0GCSqGSIb3DQEB # CwUABIICAH71gHGP3b0gvFlE0qqMeNnS2kFb9E9IAYEihLTBEk9LGYiVwJXBLmCw # HS7J2EzMC+utz1aXe0HXW5D77xshvhkAolUmy9SMU4HgdUlOnnUh0KExQOh43TSN # AI6h0tlw1W6oUqu7PvBGsMEABDj+e6ffTQOUFf48WCwj3+wDlPOsOdqwOdzaavDR # V3mal3rUXLy2gec5HIzVKBH9FmNft3WlTD4BNJsGyKO21A4zf+287MADEVSWVhA4 # ehbE5unboW+wSkMOW0dnU1qNAkSwrr9qZosm9CDtGKQai9ezgTPC4OIRBnnDFQCB # Kb9cfhdhxtzvjHhtoCZic7vs25CBDFiJoCRfTnPexBxlLyJzA6VuVaLpnGM1zKyn # LRqvVvKLnHevwwTNry8RKCnyu4Wkzc1IfvLaREAMgKLJOgVMtnFNw+6a2cfuNS9u # 6nI27vRSjCCKtfgIinVNs59XO/LehvK17vu8W+zIpiAdF/v3NxS7fTnWW1idNXLd # g3hfgzlK4QQKiRcZ33qLil3EA2VputnpG8kntEN1NOXzDEaKOM8ncPBu79UcDXLw # 9u3h8Hx65Y4jA5D6ZxxuWKjYislmVoBKGWeHbQ76Impsv+AgioMZz2D+no1SGjmh # aR7C1s1TzcS5YXIYHjY3JSMkfXXw1xfIOZvPqHv3DQYZrAwtTWq5 # SIG # End signature block |