modules/AzStack.Ece/AzStack.Ece.psm1
|
################################################################# # # # Copyright (C) Microsoft Corporation. All rights reserved. # # # ################################################################# ################################################################# # # # STARTUP ACTIONS ON IMPORT # # # ################################################################# Import-LocalizedData -BindingVariable 'msg' -BaseDirectory "$PSScriptRoot\locale" -UICulture (Get-Culture) -WarningAction SilentlyContinue Import-Module $PSScriptRoot\..\AzStack.Core\AzStack.Core.psm1 -WarningAction SilentlyContinue Import-Module $PSScriptRoot\..\AzStack.Common\AzStack.Common.psm1 -WarningAction SilentlyContinue # import the EceClient module if it is not already imported if (-not (Get-Module -Name 'EceClient')) { Import-Module -Name 'EceClient' -Global -ErrorAction Continue 4> $null 3> $null } $configurationData = Import-PowerShellDataFile -Path "$PSScriptRoot\AzStack.Ece.Config.psd1" New-Variable -Name 'CSSTools_AzStack_ECE' -Scope 'Global' -Force -Value @{ Config = $configurationData } ################################################################# # # # ENUMS AND CLASSES # # # ################################################################# ################################################################# # # # FUNCTIONS # # # ################################################################# function Show-AzsSupportEceData { <# .SYNOPSIS Show ECE data for the current Azure Stack HCI cluster. .DESCRIPTION This function retrieves and displays information about the ECE deployment, including the deployment status, policy #> Confirm-AzsSupportOSVersion -MinimumVersion 23H2 $clusterNodes = Get-ClusterNode $policyInfoJob = Start-DiagnosticCheck -ComputerNames $clusterNodes -DiagCheck { return @{ "policyInfo" = Get-ASLocalWDACPolicyInfo } } # in some deployments there is no deployment xml - we will now output this information. if (Test-Path -Path $Global:CSSTools_AzStack_ECE.Config.EceStore.Files.Deployment) { $deploymentActionPlan = [xml](Get-Content -Raw -Path $Global:CSSTools_AzStack_ECE.Config.EceStore.Files.Deployment) $deploymentAction = $deploymentActionPlan.Action } else { $deploymentAction = @{"status" = "Unknown - Deployment file not found. You may not be on the Seed node." } } $policyInfo = Reconcile-DiagnosticCheck -jobs $policyInfoJob # 1. List Deployment information Write-Host "====[ $($msg.eceClusterOverview) ]====" -ForegroundColor White -BackgroundColor DarkGray Get-StampInformation | Select-Object DeploymentID, *version*, Hardware*, NumberOfNodes Write-Host "`n" # 2. Check if cluster is deployed Write-Host "====[ $($msg.eceClusterDeployment) ]====" -ForegroundColor White -BackgroundColor DarkGray if ($deploymentAction.status -eq "Error") { Trace-Output -Level:Exception -Message $msg.eceClusterDeploymentFail } else { Trace-Output -Level:Success -Message $msg.eceClusterDeploymentSuccess } Write-Host "`n" # 3. Check policy mode Write-Host "====[ $($msg.eceWdacState) ]====" -ForegroundColor White -BackgroundColor DarkGray foreach ($info in $policyInfo) { Trace-Output -Level:Information -Message ($msg.eceWdacStateNode -f $info.name) $info.output.policyInfo | Select-Object PolicyMode, PolicyName, PolicyVersion, Status, PolicyScope, MicrosoftProvided, IsSigned | Format-Table -AutoSize } # 3. Cluster Action Plan State Write-Host "====[ $($msg.eceActionPlanState) ]====" -ForegroundColor White -BackgroundColor DarkGray Get-ActionPlanInstances | Select-Object InstanceID, ActionPlanName, ActionTypeName, Status, StartDateTime, EndDateTime | Sort-Object -Property StartDateTime | Select-Object -Last 20 | Format-Table -AutoSize Write-Host "`n" } function Show-AzsSupportEceDeploymentDetail { <# .SYNOPSIS Show ECE deployment details for the current Azure Stack HCI cluster. .DESCRIPTION This function retrieves and displays detailed information about the ECE deployment action plan, including all steps and their statuses. .EXAMPLE PS> Show-AzsSupportEceDeploymentDetail #> Confirm-AzsSupportOSVersion -MinimumVersion 23H2 $deploymentActionPlan = [xml](Get-Content -Raw -Path $Global:CSSTools_AzStack_ECE.Config.EceStore.Files.Deployment) $deploymentAction = $deploymentActionPlan.Action Write-Host "====[ $($msg.eceDeploymentOverview) ]====" -ForegroundColor White -BackgroundColor DarkGray Trace-Output -Level:Information -Message ($msg.eceDeploymentStart -f $deploymentAction.StartTimeUtc) Trace-Output -Level:Information -Message ($msg.eceDeploymentEnd -f $deploymentAction.EndTimeUtc) Trace-Output -Level:Information -Message ($msg.eceDeploymentState -f $deploymentAction.Status) # get all steps from the deployment Write-Host "====[ $($msg.eceActionplanAnalysis) ]====" -ForegroundColor White -BackgroundColor DarkGray Show-EceStep -obj $deploymentAction -showException $true } function Show-AzsSupportEceUpdateDetail { [CmdletBinding()] param( $MaxUpdateRuns = 20 ) Confirm-AzsSupportOSVersion -MinimumVersion 23H2 $actionPlanInstances = Get-ActionPlanInstances | Where-Object { $_.ActionPlanName -like "*MAS Update*" } | Select-Object InstanceID, ActionPlanName, ActionTypeName, Status, StartDateTime, EndDateTime if ($actionPlanInstances) { $actionPlanInstances | Sort-Object -Property StartDateTime | Select-Object -Last $MaxUpdateRuns | Format-Table -AutoSize $actionPlanInstanceID = Read-Host -Prompt $msg.eceUpdateActionPlan if (-not [string]::IsNullOrEmpty($actionPlanInstanceID)) { $actionPlanObj = Get-ActionPlanInstance -actionPlanInstanceID $actionPlanInstanceID $actionPlanXml = [xml]$actionPlanObj.ProgressAsXml Show-EceStep -obj $actionPlanXml.Action -showException $true } } } function Show-EceStep { param ( $obj, [int]$indentLevel = 0, [bool]$showException ) $spaceBuffer = "" for ($i = 0; $i -lt $indentLevel; $i++) { $spaceBuffer += "|--" } $spaceBuffer += "->" if ($null -ne $obj.Action) { # Next move: Action foreach ($action in $obj.Action) { Show-EceStep -obj $action -indentLevel $indentLevel -showException $showException } } elseif ($null -ne $obj.Steps) { Trace-Output -Message ("{0} {1}" -f $spaceBuffer, $obj.Type) # Next move: Steps foreach ($steps in $obj.Steps) { Show-EceStep -obj $steps -indentLevel $indentLevel -showException $showException } } elseif ($null -ne $obj.Step) { # Next move: Step foreach ($step in $obj.Step) { Show-EceStep -obj $step -indentLevel $indentLevel -showException $showException } } elseif ($null -ne $obj.Task) { if ($obj.Status -eq "Error") { Trace-Output -Level:Error -Message ("{0}[{1}] {2}" -f $spaceBuffer, $obj.FullStepIndex , $obj.Name) } elseif ($obj.Status -eq "" -or $null -ieq $obj.Status) { Trace-Output -Message ("{0}[{1}] {2}" -f $spaceBuffer, $obj.FullStepIndex , $obj.Name) } else { Trace-Output -Message ("{0}[{1}] {2}" -f $spaceBuffer, $obj.FullStepIndex , $obj.Name) } $indentLevel = $obj.FullStepIndex.Split(".").Length # Next move: Task foreach ($task in $obj.Task) { Show-EceStep -obj $task -indentLevel $indentLevel -showException $showException } } elseif ($null -ne $obj.Exception) { if ($showException) { # we are in a task which has an exception linked to it. Trace-Output -Level:Exception -Message ($obj.Exception.Message) } } } function Get-AzsSupportECECloudDefinitionXml { <# .SYNOPSIS Retrieves the cloud definition from ECE and returns it as an XML object. .DESCRIPTION This function retrieves the cloud definition from the ECE deployment and returns it as an XML object .EXAMPLE PS> Get-AzsSupportECECloudDefinitionXml #> [CmdletBinding()] param() Confirm-AzsSupportOSVersion -MinimumVersion 23H2 $cloudDef = Get-CloudDefinition -ErrorAction Stop return ([Xml]($cloudDef.CloudDefinitionAsXmlString)).CustomerConfiguration } function Invoke-AzsSupportECECustomActionPlan { <# .SYNOPSIS Executes a custom Enterprise Cloud Engine (ECE) action plan that are included as part of the Azs.Support module .PARAMETER Name The name of the action plan that should be executed via Enterprise Cloud Engine (ECE). This only looks at ECE action plans packaged within the Azs.Support module. .PARAMETER FilePath The full path to a custom ECE action plan xml file. .PARAMETER WaitForResult Waits for the cmdlet operation to complete #> [CmdletBinding(DefaultParameterSetName = 'Name')] param ( [Parameter(Mandatory = $true, ParameterSetName = 'Name')] [ArgumentCompleter({ $possibleValues = Get-ChildItem -Path "$PSScriptRoot\ActionXml" | Select-Object -ExpandProperty BaseName return $possibleValues | ForEach-Object { $_ } })] [System.String]$Name, [Parameter(Mandatory = $true, ParameterSetName = 'FilePath')] [ValidateScript({ if($_ -notmatch "(\.xml)"){ throw "The leaf name specified must be a .xml file type" } return $true })] [System.IO.FileInfo]$FilePath, [Parameter(Mandatory = $false, ParameterSetName = 'Name')] [Parameter(Mandatory = $false, ParameterSetName = 'FilePath')] [Switch]$WaitForResult ) Confirm-AzsSupportOSVersion -MinimumVersion 23H2 try { switch($PSCmdlet.ParameterSetName) { 'Name' { $eceActionPlanXML = Get-ChildItem -Path "$PSScriptRoot\ActionXml" | Where-Object {$_.BaseName -ieq $Name} -ErrorAction Stop } 'FilePath' { $eceActionPlanXML = Get-Item -Path $FilePath.FullName -ErrorAction Continue } default { throw New-Object System.Exception("Invalid ParameterSetName") } } if ($eceActionPlanXML) { # get the description of the ECE action plan [xml]$content = Get-Content -Path $eceActionPlanXML.FullName $content.Action.Description | Trace-Output # invoke the ECE action plan Invoke-ActionPlanInstance -ActionPlanPath $eceActionPlanXML.FullName -WaitForResult:($WaitForResult) } } catch { $_ | Trace-Exception $_ | Write-Error } } function Get-AzsSupportEceDeploymentDetails { # TODO: Deprecated function - remove in 2026.01 release # has been replaced with Show-AzsSupportEceDeploymentDetail to align with PowerShell naming conventions $msg.AzsSupportEceDeploymentDetailsDeprecated | Write-Information -InformationAction Continue } # SIG # Begin signature block # MIIoUgYJKoZIhvcNAQcCoIIoQzCCKD8CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBTVLOqOGUyxgL2 # DVILMXDHi3A5Y+fv3QGJLMm1rweJlqCCDYUwggYDMIID66ADAgECAhMzAAAEhJji # EuB4ozFdAAAAAASEMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjUwNjE5MTgyMTM1WhcNMjYwNjE3MTgyMTM1WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDtekqMKDnzfsyc1T1QpHfFtr+rkir8ldzLPKmMXbRDouVXAsvBfd6E82tPj4Yz # aSluGDQoX3NpMKooKeVFjjNRq37yyT/h1QTLMB8dpmsZ/70UM+U/sYxvt1PWWxLj # MNIXqzB8PjG6i7H2YFgk4YOhfGSekvnzW13dLAtfjD0wiwREPvCNlilRz7XoFde5 # KO01eFiWeteh48qUOqUaAkIznC4XB3sFd1LWUmupXHK05QfJSmnei9qZJBYTt8Zh # ArGDh7nQn+Y1jOA3oBiCUJ4n1CMaWdDhrgdMuu026oWAbfC3prqkUn8LWp28H+2S # LetNG5KQZZwvy3Zcn7+PQGl5AgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUBN/0b6Fh6nMdE4FAxYG9kWCpbYUw # VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh # dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzUwNTM2MjAfBgNVHSMEGDAW # gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw # MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx # XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB # AGLQps1XU4RTcoDIDLP6QG3NnRE3p/WSMp61Cs8Z+JUv3xJWGtBzYmCINmHVFv6i # 8pYF/e79FNK6P1oKjduxqHSicBdg8Mj0k8kDFA/0eU26bPBRQUIaiWrhsDOrXWdL # m7Zmu516oQoUWcINs4jBfjDEVV4bmgQYfe+4/MUJwQJ9h6mfE+kcCP4HlP4ChIQB # UHoSymakcTBvZw+Qst7sbdt5KnQKkSEN01CzPG1awClCI6zLKf/vKIwnqHw/+Wvc # Ar7gwKlWNmLwTNi807r9rWsXQep1Q8YMkIuGmZ0a1qCd3GuOkSRznz2/0ojeZVYh # ZyohCQi1Bs+xfRkv/fy0HfV3mNyO22dFUvHzBZgqE5FbGjmUnrSr1x8lCrK+s4A+ # bOGp2IejOphWoZEPGOco/HEznZ5Lk6w6W+E2Jy3PHoFE0Y8TtkSE4/80Y2lBJhLj # 27d8ueJ8IdQhSpL/WzTjjnuYH7Dx5o9pWdIGSaFNYuSqOYxrVW7N4AEQVRDZeqDc # fqPG3O6r5SNsxXbd71DCIQURtUKss53ON+vrlV0rjiKBIdwvMNLQ9zK0jy77owDy # XXoYkQxakN2uFIBO1UNAvCYXjs4rw3SRmBX9qiZ5ENxcn/pLMkiyb68QdwHUXz+1 # fI6ea3/jjpNPz6Dlc/RMcXIWeMMkhup/XEbwu73U+uz/MIIHejCCBWKgAwIBAgIK # YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm # aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw # OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD # VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la # UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc # 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D # dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+ # lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk # kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6 # A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd # X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL # 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd # sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3 # T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS # 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI # bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL # BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD # uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv # c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF # BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h # cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA # YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn # 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7 # v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b # pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/ # KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy # CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp # mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi # hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb # BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS # oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL # gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX # cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGiMwghofAgEBMIGVMH4x # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p # Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAASEmOIS4HijMV0AAAAA # BIQwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEICAF # 30EgmsuPoG9qaSTiV2KmG/h03ZHAC+T4slNJTcnnMEIGCisGAQQBgjcCAQwxNDAy # oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20wDQYJKoZIhvcNAQEBBQAEggEAiH4VJY8+286Q+tM4JqNXZK9RKOewZR2poybp # xb9zL2b81lX9vhUvAL/m/pLNioYmGUvbtm/5kdmoFIJnJWCdw33eN46DcvijcSfF # qUbBlCSGxAIGnt+oveSEAcgSkU62mIdHtXPErYP6+D8/AHpXJ15/sSdaXReBDl1f # JRjwRgEN7JOAcN5OFUkiC+6GBsv+SZK4HrxdP1qdcjMJrt2dzAOxImXVmixZjVfm # e8Ps8J49ZIxRlDvt6mgUitI64okS7gJLKVwSBVhydcd3pA3o4F2vgF6/5B8UvDTP # KJcbqnFyS2MNWc2n9uhwhGSkUcegTD5GEYm9byDDU+K30RVxbaGCF60wghepBgor # BgEEAYI3AwMBMYIXmTCCF5UGCSqGSIb3DQEHAqCCF4YwgheCAgEDMQ8wDQYJYIZI # AWUDBAIBBQAwggFaBgsqhkiG9w0BCRABBKCCAUkEggFFMIIBQQIBAQYKKwYBBAGE # WQoDATAxMA0GCWCGSAFlAwQCAQUABCBg1JrW0wW2vi5aveXChbbBsLlhxgpfSeym # vyKYnNbmngIGaPG+juf1GBMyMDI1MTAyODIwNDEwNy4xNjVaMASAAgH0oIHZpIHW # MIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL # EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsT # Hm5TaGllbGQgVFNTIEVTTjoyRDFBLTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9z # b2Z0IFRpbWUtU3RhbXAgU2VydmljZaCCEfswggcoMIIFEKADAgECAhMzAAACEtEI # BjzKGE+qAAEAAAISMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w # IFBDQSAyMDEwMB4XDTI1MDgxNDE4NDgxNVoXDTI2MTExMzE4NDgxNVowgdMxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jv # c29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVs # ZCBUU1MgRVNOOjJEMUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGlt # ZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA # r0zToDkpWQtsZekS0cV0quDdKSTGkovvBaZH0OAIEi0O3CcO77JiX8c4Epq9uibH # VZZ1W/LoufE172vkRXO+QYNtWWorECJ2AcZQ10bpAltkhZNiXlVJ8L3QzhKgrXrm # Mkm2J+/g81U23JPcO4wXHEftonT3wpd//936rjmwxMm7NkbsygbJf+4AVBMNr4aM # PQhBd76od0KMB6WrvyEGOOU0893OFufS5EDey4n44WgaxJE0Vnv3/OOvuOw5Kp1K # PqjjYJ+L9ywLuBMtcDfLpNQO/h1eFEoMrbiEM67TOfNlXfxbDz4MlsYvLioxgd2X # zey1QxrV1+i+JyVDJMiSe9gKOuzpiQQFE19DUPgsidyjLTzXEhSVLBlRor0eCVf7 # gC6Rfk8NY3rO2sggOL79vU5FuDKTh/sIOtcUHeHC42jBGB+tfdKC1KOBR+UlN9aO # zg8mpUNI2FgqQvirVP9ppbeMUfvp2wA9voyTiRWvDgzCxo8xlJ1nscYTHIQrmkF9 # j/Ca0IDmt8fvOn64nnlJOGUYZYHMC1l0xtgkYTE1ESUqqkawKk7iqbxdnLyycS+d # R+zaxPudMDLrQFz8lgfy9obk0D8HC2dzhWpYNn5hdkoPEzgCqQUOp8v3Qj/sd4an # yupe5KoCkjABOP3yhSQ4W9Z+DrJnhM/rbsXC7oTv26cCAwEAAaOCAUkwggFFMB0G # A1UdDgQWBBRSBblSxb5cYKYOwvd/VfoXOfu33jAfBgNVHSMEGDAWgBSfpxVdAF5i # XYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jv # c29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENB # JTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRw # Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRp # bWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBYGA1Ud # JQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsF # AAOCAgEAXnSAkmX79Rc7lxS1wOozXJ7V0ou5DntVcOJplIkDjvEN8BIQph4U+gSO # LZuVReP/z9YdUiUkcPwL1PM245/kEX1EegpxNc8HDA6hKCHg0ALNEcuxnGOlgKLo # kXfUer1D5hiW8PABM9R+neiteTgPaaRlJFvGTYvotc0uqGiES5hMQhL8RNFhpS9R # cIWHtnQGEnrdOUvCAhs4FeViawcmLTKv+1870c/MeTHi0QDdeR+7/Wg4qhkJ2k1i # EHJdmYf8rIV0NRBZcdRTTdHee35SXP5neNCfAkjDIuZycRud6jzPLCNLiNYzGXBs # wzJygj4EeSORT7wMvaFuKeRAXoXC3wwYvgIsI1zn3DGY625Y+yZSi8UNSNHuri36 # Zv9a+Q4vJwDpYK36S0TB2pf7xLiiH32nk7YK73Rg98W6fZ2INuzYzZ7Ghgvfffkj # 4EUXg1E0EffY1pEqkbpDTP7h/DBqtzoPXsyw2MUh+7yvWcq2BGZSuca6CY6X4ioM # uc5PWpsmvOOli7ARNA7Ab8kKdCc2gNDLacglsweZEc9/VQB6hls/b6Kk32nkwuHE # xKlaeoSVrKB5U9xlp1+c8J/7GJj4Rw7AiQ8tcp+WmfyD8KxX2QlKbDi4SUjnglv4 # 617R8+a/cDWJyaMt8279Wn7f2yMedN7kfGIQ5SZj66RdhdlZOq8wggdxMIIFWaAD # AgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYD # VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe # MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv # ZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0yMTA5MzAxODIy # MjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y # cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw # MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5OGmTOe0ciELeaLL1yR5 # vQ7VgtP97pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/XE/HZveVU3Fa4n5KWv64 # NmeFRiMMtY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1hlDcwUTIcVxRMTegCjhu # je3XD9gmU3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7M62AW36MEBydUv626GIl # 3GoPz130/o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3KNi1wjjHINSi947SHJMPg # yY9+tVSP3PoFVZhtaDuaRr3tpK56KTesy+uDRedGbsoy1cCGMFxPLOJiss254o2I # 5JasAUq7vnGpF1tnYN74kpEeHT39IM9zfUGaRnXNxF803RKJ1v2lIH1+/NmeRd+2 # ci/bfV+AutuqfjbsNkz2K26oElHovwUDo9Fzpk03dJQcNIIP8BDyt0cY7afomXw/ # TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9ahhaYQFzymeiXtcodgLiMxhy # 16cg8ML6EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5UPkLiWHzNgY1GIRH29wb0f2y # 1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV2xo3xwgVGD94q0W29R6H # XtqPnhZyacaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIGCSsGAQQBgjcVAQQFAgMB # AAEwIwYJKwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUpzxD/LwTuMB0GA1UdDgQW # BBSfpxVdAF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBTMFEGDCsGAQQBgjdMg30B # ATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz # L0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJKwYB # BAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMB # Af8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYDVR0fBE8wTTBL # oEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMv # TWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggr # BgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNS # b29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcNAQELBQADggIBAJ1Vffwq # reEsH2cBMSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1OdfCcTY/2mRsfNB1OW27 # DzHkwo/7bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYAA7AFvonoaeC6Ce5732pv # vinLbtg/SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbzaN9l9qRWqveVtihVJ9Ak # vUCgvxm2EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6LGYnn8AtqgcKBGUIZUnWK # NsIdw2FzLixre24/LAl4FOmRsqlb30mjdAy87JGA0j3mSj5mO0+7hvoyGtmW9I/2 # kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0SCyxTkctwRQEcb9k+SS+ # c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmRaw2fpCjcZxkoJLo4S5pu+yFUa2pFEUep # 8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyhYWxz/gq77EFmPWn9y8FBSX5+k77L+Dvk # txW/tM4+pTFRhLy/AsGConsXHRWJjXD+57XQKBqJC4822rpM+Zv/Cuk0+CQ1Zyvg # DbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328y+l7vzhwRNGQ8cirOoo6CGJ/ # 2XBjU02N7oJtpQUQwXEGahC0HVUzWLOhcGbyoYIDVjCCAj4CAQEwggEBoYHZpIHW # MIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL # EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsT # Hm5TaGllbGQgVFNTIEVTTjoyRDFBLTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9z # b2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUA5VHBr4h00EN7 # jUdQ33SE+qbk/8CggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz # aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv # cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAx # MDANBgkqhkiG9w0BAQsFAAIFAOyrZTwwIhgPMjAyNTEwMjgxNTUyMjhaGA8yMDI1 # MTAyOTE1NTIyOFowdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA7KtlPAIBADAHAgEA # AgIufTAHAgEAAgIS5TAKAgUA7Ky2vAIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgor # BgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBCwUA # A4IBAQAoDSwy4FH2x1Fp6oANeZzMVaRMkbh5MBBZR+JAjhgvbCvp2W5qyKXPKmLU # wcBB5e4H3lM5Uqsb4sfauKeuqnKK2nEsss0LMb55dmtZqEr3Trol7ET4VbZtXN/U # rev/DPJTVlRw2n1U8zVSmGQ9DMiF2TY46zkDs1oYmzfQKuxUZiLVqHk1TZV3Obt6 # e9ptR1OOoNZrmKVXOWlr8n7UDJ5FYce+c/T3UN0KtrfhHIwgnn5iHUkiQHYxYnOv # Fs3Z4m+80BF+6fA6Y2ex0ketJ3wN6RVo+FFDn5fBs4Zgt+ykJO6LnDX5kthOr8e2 # pcYll29ld2kKwelNgN3XAAk68KuMMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp # bWUtU3RhbXAgUENBIDIwMTACEzMAAAIS0QgGPMoYT6oAAQAAAhIwDQYJYIZIAWUD # BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B # CQQxIgQgt4CRi4ltQf9zbnCeTr/J6qnY2h/tICxV+1QBcmcaCHcwgfoGCyqGSIb3 # DQEJEAIvMYHqMIHnMIHkMIG9BCBz+X5GvO7WngknH4BZeYU+BzBL1Jy5oJ8wVlTN # IxfYgzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAC # EtEIBjzKGE+qAAEAAAISMCIEILt8kTw+7ut0ySxqpAQeNssK4NV/55MTYdTKMChs # 1LLvMA0GCSqGSIb3DQEBCwUABIICAGhs8xcKlOQfOlZzriLa2kHfIaKhQfkgQbsq # g+HZNJ/5M5qZHgBeJEQfu5XPoSeYRtcjmZgVTb3PIxecClRjXNWo8EldRcTUSC6w # X5jYkQggDDQg0RWQvTm2DeEbZSmtY6vG+a8jzavTexTHa3oAfM6XGXE0XoGGAVsX # ZHqxqbzymoXVCDAO+OiAEc3irimXGItNAWlvZ7Qzf4wkDUVq9ALtZRcw46qla2/K # 0F6pLn7hsCsg4Pih9hdKTgD52BPa0TIRPq/Fuymxn1hy1cUMv0VeEDAvq/iw7HOn # yQMRksrNHDsJAdaA5HNkMbQIiV7wsxMjL7eCXSepS11lZeoS48mBG/StwKVHoN+W # edWBpWFAVgNs2eJKsp5j0f1grHcxhP+ag9y0h209ht7HPPkZwWX+C9SCT2wpNI0p # M0C3hz6dyE5bdq2bblKEJL4CSeKfFdL3U2bNq6K3jr/Snx5sVNA/KR3k9Rpwcn2D # XvvZBpdiFxQoq28+kKpV/VlyJ6UWsqohoI4AeFNJISFlueykHIO/sEKL90WQ/kjJ # dYwhbxhIDScNP7jI0Uzwrk26sQnpdYmyCNzApaCx3fbAmU8G9frHnWgKXAnJjwdp # 8i0nAxwJJs20GTs6GerhR4oI0pgi/98NJVCPBT1BQUxDniUCpxk5rOubGTXHMrZz # k5A4vDwH # SIG # End signature block |