Microsoft.AzureStack.HCI.CSSTools.psm1
|
################################################################# # # # Copyright (C) Microsoft Corporation. All rights reserved. # # # ################################################################# [CmdletBinding()] param ( [Parameter(Mandatory = $false, Position = 0)] [Bool]$SkipStartupActions = $false ) $skipExplicitlySet = $PSBoundParameters.ContainsKey('SkipStartupActions') [void]$PSBoundParameters.Remove('SkipStartupActions') # check if we are within a PSSession or runspace # if we are and SkipStartupActions wasn't explicitly set, we skip the startup actions if ($PSSenderInfo -and -not $skipExplicitlySet) { $SkipStartupActions = $true } ################################################################# # # # STARTUP ACTIONS ON IMPORT # # # ################################################################# Import-LocalizedData -BindingVariable 'msg' -BaseDirectory "$PSScriptRoot\locale" -UICulture (Get-Culture) -WarningAction SilentlyContinue New-Variable -Name 'CSSTools_AzsSupport' -Scope 'Global' -Force -Value @{ Cache = @{} EnvironmentInfo = @{ WindowsProductName = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name 'ProductName' -ErrorAction Ignore).ProductName OSDisplayVersion = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name 'DisplayVersion' -ErrorAction Ignore).DisplayVersion CloudName = [string]::Empty # this is set later } ModuleVersion = $null } ################################################################# # # # ENUMS AND CLASSES # # # ################################################################# enum Component { OS AzureArcResourceBridge } ################################################################# # # # FUNCTIONS # # # ################################################################# function Get-AzsSupportStampInformation { <# .SYNOPSIS Gets common stamp information .DESCRIPTION Queries for common stamp information properties such as DeplymentID, OEMVersion and CloudID .EXAMPLE PS> Get-AzsSupportStampInformation .OUTPUTS Outputs the Stamp Information #> [CmdletBinding()] param() try { $stampInfo = Get-StampInformation -ErrorAction Stop $stampInformation = [Ordered]@{ DeploymentID = $stampInfo.DeploymentID OemVersion = $stampInfo.OemVersion StampVersion = $stampInfo.StampVersion ServicesVersion = $stampInfo.ServicesVersion PlatformVersion = $stampInfo.PlatformVersion InitialDeployedVersion = $stampInfo.InitialDeployedVersion NetworkSchemaVersion = $stampInfo.NetworkSchemaVersion Prefix = $stampInfo.Prefix CompanyName = $stampInfo.CompanyName ServerSku = $stampInfo.ServerSku Topology = $stampInfo.Topology TimeZone = $stampInfo.TimeZone HardwareOEM = $stampInfo.HardwareOEM RegionName = $stampInfo.RegionName DomainNetBIOSName = $stampInfo.DomainNetBIOSName DomainFQDN = $stampInfo.DomainFQDN TimeServer = $stampInfo.TimeServer NumberOfNodes = $stampInfo.NumberOfNodes CloudID = $stampInfo.CloudID RingName = $stampInfo.RingName InstallationMethod = $stampInfo.InstallationMethod HardwareClass = $stampInfo.HardwareClass } } catch { $_ | Write-Error } return $stampInformation } function Get-ModuleVersion { $manifest = Test-ModuleManifest -Path "$PSScriptRoot\Microsoft.AzureStack.HCI.CSSTools.psd1" $Global:CSSTools_AzsSupport.ModuleVersion = $manifest.Version.ToString() return $manifest.Version.ToString() } function Get-EntryText { @' ################################################################################# _ _ _ / \ _____ _ _ __ ___ | | ___ ___ __ _| | / _ \ |_ / | | | '__/ _ \ | | / _ \ / __/ _` | | / ___ \ / /| |_| | | | __/ | |__| (_) | (_| (_| | | /_/ \_\/___|\__,_|_| \___| |_____\___/ \___\__,_|_| ################################################################################# Provide feedback or suggestions to azscssdiag@microsoft.com Tool Tips: List CSSTools commands: Get-Command -Module Microsoft.AzureStack.HCI.CSSTools Get help with examples: Get-Help 'Verb-Command' -Full Check for common issues: Invoke-AzsSupportInsight Check for new updates: Find-Module -Name Microsoft.AzureStack.HCI.CSSTools Install latest version: Update-Module -Name Microsoft.AzureStack.HCI.CSSTools -Force Clean up the working directory after you are done to reclaim disk space: Clear-AzsSupportDirectory '@ | Write-Host -ForegroundColor:Green # display primary stamp info properties $stampInfo = Get-AzsSupportStampInformation if ($stampInfo) { $stampInfo += @{ CSSToolsVersion = $Global:CSSTools_AzsSupport.ModuleVersion CloudName = $Global:CSSTools_AzsSupport.EnvironmentInfo.CloudName } $maxKeyLength = ($stampInfo.Keys | Measure-Object -Property Length -Maximum).Maximum $stampInfo.Keys | ForEach-Object { $key = $_.PadRight($maxKeyLength) $value = "N/A" if (![string]::IsNullOrEmpty($stampInfo[$_])) { $value = $stampInfo[$_] } # Print aligned output "{0} --> {1}" -f $key, $value | Write-Host -ForegroundColor:Gray } } else { $msg.stampInfoNotAvailable | Write-Warning } "" | Write-Host } function New-AzsSupportDataBundle () { param ( # AUTOMATIC DATA COLLECTION SPECS [Parameter(ParameterSetName = 'DataCollectAuto')] [Component] $Component, # MANUAL DATA COLLECTION SPECS [Parameter(ParameterSetName = 'DataCollectManual')] [array] $ClusterCommands, [Parameter(ParameterSetName = 'DataCollectManual')] [array] $NodeCommands, [Parameter(ParameterSetName = 'DataCollectManual')] [array] $NodeEvents, [Parameter(ParameterSetName = 'DataCollectManual')] [array] $NodeRegistry, [Parameter(ParameterSetName = 'DataCollectManual')] [array] $NodeFolders, [Parameter(ParameterSetName = 'DataCollectManual')] [array] $ComputerName ) Trace-Output -Level:Information -Message $msg.startingNewDataBundle $runtime = Register-CommandRuntime switch ($PSCmdlet.ParameterSetName.ToLower()) { "datacollectmanual" { if(($NodeCommands -or $NodeEvents -or $NodeRegistry -or $NodeFolders) -and (-Not $ComputerName)) { Trace-Output -Level:Error -Message $msg.errComputerNameNotSupplied } else { Invoke-DataCollection ` -runtime $runtime ` -clusterCommands $ClusterCommands ` -nodeCommands $NodeCommands ` -nodeEvents $NodeEvents ` -nodeRegistry $NodeRegistry ` -nodeFolders $NodeFolders ` -ComputerName $ComputerName } } "datacollectauto" { Trace-Output -Level:Information -Message $msg.startingAutomaticCollection Invoke-AutoDataCollection -runtime $runtime -Component $Component } Default {} } } function Invoke-DataCollection() { param( [string] $runtime, [array] $ClusterCommands, [array] $NodeCommands, [array] $NodeEvents, [array] $NodeRegistry, [array] $NodeFolders, [array] $ComputerName ) Trace-Output -Level:Information -Message $msg.startingDataCollection $name = "SupportDataBundle" # important default information we want to always collect. $NodeCommands = $NodeCommands + @("Get-ChildItem env:*", "gpresult /h STORAGE_DEST/gpresultoutput.html") # manually collecting data Collect-SupportData ` -runtime $runtime ` -clusterCommands $ClusterCommands ` -nodeCommands $NodeCommands ` -nodeEvents $NodeEvents ` -nodeRegistry $NodeRegistry ` -nodeFolders $NodeFolders ` -ComputerName $ComputerName ` -customName $name } function Invoke-AutoDataCollection() { param( [string] $runtime, [Component] $Component ) $storage = Get-WorkingDirectory $storageTemp = ('{0}\temp' -f $storage) if((Test-Path -path $storageTemp) -eq $false) { New-Item -Type:Directory -Path $storageTemp | Out-Null } Trace-Output -Level:Verbose -Message $Component switch ($Component) { ([Component]::OS) { # Automatic OS log collection $cmd = Get-Command -Name "Send-DiagnosticData" -ErrorAction Ignore if($cmd) { Collect-SupportData ` -nodeCommands @('Send-DiagnosticData -SaveToPath STORAGE_DEST -FromDate ((Get-Date).AddDays(-1)) -ToDate (Get-Date) -CollectSddc:$true') ` -ComputerName (Get-ClusterNode) } else { Trace-Output -Level:Error -Message $msg.errSendDiagDataNotAvailable } } ([Component]::AzureArcResourceBridge) { Trace-Output -Level:Verbose -Message "Starting Resource Bridge Data Collection" Trace-Output -Level:Information -Message $msg.arcApplianceLogStart $destPath = ("{0}\SupportDataBundle-{1}" -f $storage, (Get-Date -Format "HH-mm_dd-MM-yyyy")) $azTenant = Read-Host -Prompt $msg.questionTenantLogin Trace-Output -Level:Information -Message $msg.arcApplianceLogConfig # get environment information $azStackInfo = Get-AzureStackHCI $azStackUri = $azStackInfo.AzureResourceUri.split("/") $azSub = $azStackUri[2] # xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx $azReg = $azStackUri[4] # sample-rg $arcHciConfigObject = Get-ArcHciConfig $arcHciConfigPath = ("{0}/hci-resource.yaml" -f $arcHciConfigObject.workingDir) $arcHciConfig = Get-Content -Path $arcHciConfigPath $arcHciConfig = $arcHciConfig.trim() $arcHciConfigApplianceName = "" foreach($arcHciConfigEntry in $arcHciConfig) { if($arcHciConfigEntry.indexOf("name:") -ne -1){ $arcHciConfigApplianceName = $arcHciConfigEntry.split(":")[1].trim() } } Trace-Output -Level:Information -Message $msg.arcApplianceLogLogin az login --tenant $azTenant --use-device-code az account set --subscription $azSub Trace-Output -Level:Information -Message $msg.arcApplianceLogCollectionStart az arcappliance get-credentials -g $azReg -n $arcHciConfigApplianceName --overwrite-existing --credentials-dir $storageTemp Get-ChildItem -path $storageTemp | ForEach-Object { Icacls $storageTemp /c /t /Inheritance:d | Out-Null Icacls $storageTemp /c /t /Grant ${env:UserName}:F | Out-Null TakeOwn /F $storageTemp | Out-Null Icacls $storageTemp /c /t /Grant:r ${env:UserName}:F | Out-Null Icacls $storageTemp /c /t /Remove:g Administrator "Authenticated Users" BUILTIN\Administrators BUILTIN Everyone System Users | Out-Null } | Out-Null az arcappliance logs hci ` --cloudagent $arcHciConfigObject.cloudFqdn ` --credentials-dir $storageTemp ` --ip $arcHciConfigObject.controlPlaneIP ` --kubeconfig ("{0}\kubeconfig" -f $arcHciConfigObject.workingDir) ` --loginconfigfile ("{0}\kvatoken.tok" -f $arcHciConfigObject.workingDir) ` --out-dir $destPath if($destPath) { $destZipPath = ("{0}.zip" -f $destPath) Compress-Archive -Path $destPath -DestinationPath ("{0}.zip" -f $destZipPath) Remove-Item -Path $destPath -Recurse -Force Trace-Output -Level:Success -Message ($msg.CollectionDataEnd -f $destZipPath) } else { Trace-Output -Level:Error -Message $msg.arcApplianceLogCollectionError } Remove-Item -Path $storageTemp -Recurse -Force } Default { Trace-Output -Level:Error -Message $msg.errComponentNotFound } } } function Confirm-AzsSupportOSVersion { <# .SYNOPSIS Validates the OS version against a specified version or minimum version. .DESCRIPTION This function checks the current OS version against a specified version or minimum version. It throws an error if the current OS version does not match the specified version or is below the minimum version. .PARAMETER Version The exact OS version to confirm against the current OS version. .PARAMETER MinimumVersion The minimum OS version that the current OS version must meet or exceed. .EXAMPLE Confirm-AzsSupportOSVersion -Version "23H2" # This will throw a terminating exception if the current OS version is not "23H2". .EXAMPLE Confirm-AzsSupportOSVersion -MinimumVersion "22H2" # This will throw a terminating exception if the current OS version is below "22H2". #> param( [Parameter(Mandatory = $true, ParameterSetName = 'ConfirmOSVersion')] [ValidateSet("22H2", "23H2", "24H2", "25H2")] [string]$Version, [Parameter(Mandatory = $true, ParameterSetName = 'ConfirmMinimumOSVersion')] [ValidateSet("22H2", "23H2", "24H2", "25H2")] [string]$MinimumVersion ) $osOrder = @("22H2", "23H2", "24H2", "25H2") $currentVersion = $Global:CSSTools_AzsSupport.EnvironmentInfo.OSDisplayVersion switch ($PSCmdlet.ParameterSetName) { 'ConfirmOSVersion' { if ($currentVersion -ne $Version) { throw ($msg.osNotSupported -f $Version) } } 'ConfirmMinimumOSVersion' { $minIndex = $osOrder.IndexOf($MinimumVersion) $curIndex = $osOrder.IndexOf($currentVersion) if ($curIndex -lt 0) { throw ($msg.osNotSupportedGeneric) } if ($curIndex -lt $minIndex) { throw ($msg.osNotSupported -f $MinimumVersion) } } } } ################################################################# # # # SECONDARY STARTUP ACTIONS ON IMPORT # # # ################################################################# $null = Get-ModuleVersion try { $cloudData = az cloud Show | ConvertFrom-Json if ($cloudData) { $Global:CSSTools_AzsSupport.EnvironmentInfo.CloudName = $cloudData.Name } } catch { $_.Exception.Message | Write-Warning } # print the entry text if we are not skipping the startup actions if (!$SkipStartupActions) { Get-EntryText Write-Host "" # just a spacer line Write-Information -MessageData "Microsoft.AzureStack.HCI.CSSTools is being deprecated. For future releases, please use the new Microsoft.AzLocal.CSSTools module." -InformationAction:Continue Write-Host "" # just a spacer line } Set-Location -Path (Get-AzsSupportWorkingDirectory) # Remove any existing PSSessions that were created by this module # This is to ensure that we do not have any stale sessions that could cause issues # when running commands in the module. Remove-AzsSupportPSSession # SIG # Begin signature block # MIIoUgYJKoZIhvcNAQcCoIIoQzCCKD8CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAYrFZkNHVFZ09A # 9jIrfJLcoi6VkWyPqBPVf7UVrBunAaCCDYUwggYDMIID66ADAgECAhMzAAAEhJji # 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 # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEINaf # v2fgZ8uSmG7y08Vjhj4WqSo+9mWuJ9kk9PvcLtuhMEIGCisGAQQBgjcCAQwxNDAy # oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20wDQYJKoZIhvcNAQEBBQAEggEAJ339DGMq+d/4+/J3Jj4tteYBcCHMhMcsM0Oo # 6s9aGDuFJHYIDtsPOdt2/5qj8P59WwNP6EOFx0ZkLhkRznaF2qif6S8DoDhbtGMT # /g5RD2Z5WR99ufb+TM1RGGR+AQUTKMlVVBVja6XkYhNbADvYLRTSAEuB+vK1aHJ8 # 77QSzs1YWYQFCwpBElFME3S+q4NjQ0DcOZIE00DES09d5Cbvw48nzHR9Z6sYK8Fi # bvlMzF+ufgVBNGnY9LNpeUOPzWY8ZBKCqFq3Mv7A2EXnLwVmn2kn+caEEm+cRy9I # lvfFAiWHQIsJ9MhOyABpTFC4O7lIwTN5drIERjWWcUn3jTz8PKGCF60wghepBgor # BgEEAYI3AwMBMYIXmTCCF5UGCSqGSIb3DQEHAqCCF4YwgheCAgEDMQ8wDQYJYIZI # AWUDBAIBBQAwggFaBgsqhkiG9w0BCRABBKCCAUkEggFFMIIBQQIBAQYKKwYBBAGE # WQoDATAxMA0GCWCGSAFlAwQCAQUABCDN55x7wdpiugBD2nEZV2RIGr5FTSbp5PKX # ADW0qRwVugIGaPedHbHiGBMyMDI1MTAyODIwNDEwMy4xMjlaMASAAgH0oIHZpIHW # MIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL # EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsT # Hm5TaGllbGQgVFNTIEVTTjo1MjFBLTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9z # b2Z0IFRpbWUtU3RhbXAgU2VydmljZaCCEfswggcoMIIFEKADAgECAhMzAAACF3H7 # LqWvAR3qAAEAAAIXMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w # IFBDQSAyMDEwMB4XDTI1MDgxNDE4NDgyM1oXDTI2MTExMzE4NDgyM1owgdMxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jv # c29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVs # ZCBUU1MgRVNOOjUyMUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGlt # ZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA # wM82sEw+39vYR7iGCIFDnYNhRM+BzF2AYiq5dUpZpJFPRjCcipQ6RUbI+RAYNRAp # Exx5ygrXbaWtuwvqsqAVSWbU/W6fecujjILkPqn9pngtWRkfQgbYgvaXALl6PY2y # OH9f72MD+6AyxQenSpAMdUzY/Qk/jtjsHdFXVBe+tshlIkSJ3GZw8VVKqTg3GZEl # ztwbJWNtrhBEvhf6anxMegQMJP7tO8/BJ7ITs4/AV3D2bv8eHk81Y+fOmQ8mQ61W # Lq2wItvlzIT5bzelK9LvEycf5x1lXxAwEw5a7dpS+CKTanhtv+Q2mwebAybjf9io # 4k48stTaq1rtcrOiDwddqVm1S9e8h1TszXFzjLLvE9EmjnNfIewsY+RChUaHnY4F # FwwJEnEv/JS76oHT0oGdy7+J60fGOl7A1UoUyAkhpb2Bja+SwSIiHbQ4FDyJiLlZ # 6drZZ84MoJ852JSxM0hBjGO6FZlPO8iuNyk680Di8VnbSNpIdJN+DhlepeTUMBDH # qCmd0mVWRWZPm1pvgty93asNt/Ng6o4m2dnooWOdM3yKsJaWjyHqic9gfTrZBM+P # CXqeTaO1oEiaQ+h4w0nHVdV+XSvI2m1yN4iibqjm5HPaAO3OJ+OmNLftNVmr4Z6U # 2T6pIcLBysoKcDUvCqycXj4C/+n1KFBpDGdDMw9gmu8CAwEAAaOCAUkwggFFMB0G # A1UdDgQWBBRQrN9jlwNOoeE5ZQqnF5x8S1bJQzAfBgNVHSMEGDAWgBSfpxVdAF5i # XYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jv # c29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENB # JTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRw # Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRp # bWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBYGA1Ud # JQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsF # AAOCAgEARmgFdhB7xIAIHEEg5I/5S+gx67aR6RiW8ZAwtE3mz8o0dyn+pIP+lidN # R1IKQQ0r+RjYgI9cZ6mbvAyvh3e2q/BV8rjHE3ud9PyYyq32euFgdZ3vX4b5QXeP # WlpBAYrdziR27rHz6WwpH5dZsSypbXDBbQkWkNl6g82yTy3AbBbKDXBdzxZsEaua # OplatK7Er4dhglKBex8JQ2dMSkSZweCNDXqd9r/9W2VdRZsDJKP/Xc4UyQlVsboB # otKtYESXFkjwR1HVsH+Q0C69/N5CP/Tq3YgI1ub4b9+3MJFKWhJXCcJGFZkcLwUm # YwoFg1XLo7DLJdGjrIH1jsI2NFXJFQHef6AdRe1ERvYQeqtyrBvxIvR+P/83FNYy # zx04inUT9TF2AwTOuqCC6Z67oNwR4pEEJyAIEREvkdhjjfWcgsk/nGTlfahvNY/S # OHrNRKo49KDlccNzRCJQyQ+D59r7/qebNSyQPTfwI9++jEY0Q/UWKVNLhio55GYB # seJ99s7NzkdxOr9Uftp597HEovbA69qGlZ3OpUE3H1RBGDVp/FvM2uXTum8LrMkP # Xx5Ap/kbPASsC9ju9oMCe2IEXO2SeD1aD3IqvAOdHFKHg1vpbPUQSWb6g2xfBV30 # wFcqaPYgzcbxPWPyZqK+S8l7zw64aO5hmJ7eQwoMfTu0Vay6r48wggdxMIIFWaAD # 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 # Hm5TaGllbGQgVFNTIEVTTjo1MjFBLTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9z # b2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAabKAFaKt2haU # dqkHfFYzAzfgSMuggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz # aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv # cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAx # MDANBgkqhkiG9w0BAQsFAAIFAOyrVXowIhgPMjAyNTEwMjgxNDQ1MTRaGA8yMDI1 # MTAyOTE0NDUxNFowdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA7KtVegIBADAHAgEA # AgICJjAHAgEAAgISOjAKAgUA7Kym+gIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgor # BgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBCwUA # A4IBAQCFqHNBTRfP+zUwUnQKUc8QFsWkUD893J6uL0HNJq4Gsu0PhSrXW6/oDN2p # IdPT5zVvgcRa9rnTu8zAAoV7v/sU3AAInJrSYvTXCvRyrfNqe/rDGJRyiE3m2GN/ # HvoiRQpdIZ9KsLDAvZ2nl2Tsm3FaUT+WV4HhgAzZ8V2tNHBIoRlY4Pkv3QusquiZ # eGip2m/oSxVvGPUVNP9e9XVeVa5Kh/csPC7RKxL3boy9uSAHUsq45qLXk7TVU0w8 # 54NB3nPpRZJKV9pmV1UoAoKxV+g8KSlAS0ceyDBwpdQJbapKMF+AiEeWUldyAOSn # 7E2/DXl4QlTGrvS6y4RcuYN9M3sUMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp # bWUtU3RhbXAgUENBIDIwMTACEzMAAAIXcfsupa8BHeoAAQAAAhcwDQYJYIZIAWUD # BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B # CQQxIgQg0JJcz6CEbXYLCrQ3BO15uZQbUbSPUEFyf2eHYAtOsxAwgfoGCyqGSIb3 # DQEJEAIvMYHqMIHnMIHkMIG9BCDQ8lBgPl23yZ0SzUSt5phOIegHPywrkNwevxe2 # k+RaWzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAC # F3H7LqWvAR3qAAEAAAIXMCIEIIP42c6AjaR2eEAWNp2RinULnCtTAy329lRNrmIu # 71RXMA0GCSqGSIb3DQEBCwUABIICAHR3SP8OJV2nJEqM6FT1sIQhGVxUasw+Gj5R # 8/Vrh6q8QGbzK2rcCHo5cl+z8TVmCWGWimEEZqQCvVszIt/1Kc/aRkkmrY2tDRfc # vQsEaFl+2jhLgimd7dajm9zqOBQ1v4W1Nein0OmsaC5Z7PrH+sZ9v6oiVlzKa+g0 # 0Ldwj0KLlXqRLC4fhWutudxMqT4fYv/Cxlc9RcXUlRyFHcblZGaT6cAi//6taARh # DsrSX6t4DI7GqudrkTLJBlwgUyi55OYgD8uSS8oUNtg2bV+Jb7PJZ2K8ZmY+TsH9 # TNstK9NqZq/ML3waiAFrRK82qJ03dvTKFyhCpDGXXsYrgvkJrKtLeHnMqGIF8pi1 # swaRgylKudVg7YG9YXk5W4GyE5x/DhGnNDhCRUrZfdsdWnjBoFLbSTp37AO/hypf # mBCjVvh0u7Jy0lgKGaq5mutyKG9rC8w5lqQsA7R0FoI+th8himU7K7Pfwj6ij26K # C2JgatHTb5uFZWapopvUWs8lXmULKM2u3HyQLEF+1jGhJJ7S2gRsJanFluMErpj4 # A3/b3CtCpstG/fAUK3arFlcvAxk+IdN0rollsiBf9HP8mARrvKYf3HhCGRv6gIHV # VuyjN1onavWCnjzT4XvnQ8zO2HWuIC9IzyXmbBgAUo0LveFla1bqfdH0jTXhXTkM # xv+U7PwX # SIG # End signature block |