modules/AzStack.Network/AzStack.Network.psm1
|
################################################################# # # # Copyright (C) Microsoft Corporation. All rights reserved. # # # ################################################################# ################################################################# # # # STARTUP ACTIONS ON IMPORT # # # ################################################################# Import-LocalizedData -BindingVariable 'msg' -BaseDirectory "$PSScriptRoot\locale" -UICulture (Get-Culture) Import-Module $PSScriptRoot\..\AzStack.Utilities\AzStack.Utilities.psm1 -WarningAction SilentlyContinue Import-Module $PSScriptRoot\..\AzStack.Common\AzStack.Common.psm1 -WarningAction SilentlyContinue # Import SdnDiagnostics module if not already imported if (-not (Get-Module -Name 'SdnDiagnostics')) { $sdnDiagModule = Get-Item -Path "$PSScriptRoot\..\..\packages\SdnDiagnostics.*\SdnDiagnostics.psd1" -ErrorAction SilentlyContinue if ($sdnDiagModule) { Import-Module $sdnDiagModule.FullName } else { Trace-Output -Level:Error -Message "SdnDiagnostics module not found at the specified path." } } ################################################################# # # # ENUMS AND CLASSES # # # ################################################################# ################################################################# # # # FUNCTIONS # # # ################################################################# function Set-AzsSupportNetworkATCIntentApplyWithTracing { <# .SYNOPSIS Applies a Network ATC intent with tracing enabled to capture diagnostic information. .DESCRIPTION This function enables Network ATC tracing, applies a retry state to a specified network intent, waits for the intent to complete, and then captures the trace data. If the intent fails to apply successfully, it optionally collects additional diagnostic data. .PARAMETER IntentName The name of the Network ATC intent to apply. This intent must already exist. .PARAMETER OutputDirectory Optional. The directory where trace files and diagnostic data will be saved. .EXAMPLE Set-AzsSupportNetworkATCIntentApplyWithTracing -IntentName "Compute_Management" Applies the "Compute_Management" intent with tracing enabled and saves output to default directory. .EXAMPLE Set-AzsSupportNetworkATCIntentApplyWithTracing -IntentName "Storage" -OutputDirectory "C:\Traces" Applies the "Storage" intent with tracing enabled and saves output to C:\Traces. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$IntentName, [Parameter(Mandatory = $false)] [string]$OutputDirectory = "$(Get-AzsSupportWorkingDirectory)\HostNetwork" ) $resultObject = [PSCustomObject]@{ IntentName = $IntentName IntentConfigStatus = $null IntentProvisioningStatus = $null OutputDirectory = $null TraceFilePath = $null AdditionalDiagnosticData = $null OccurrenceTimeUtc = (Get-Date).ToUniversalTime().ToString("o") Result = $null } $traceFilePath = "C:\Windows\NetworkATCTrace.etl" # NetworkATC always writes to this path # Validate that the intent exists $existingIntent = Get-NetIntent -Name $IntentName -ErrorAction SilentlyContinue if (-not $existingIntent) { Trace-Output -Level:Error -Message "NetIntent '$IntentName' not found." return } $OutputDirectory = Join-Path -Path $OutputDirectory -ChildPath "NetworkATC-IntentRetry_$($IntentName)" $null = Initialize-DataCollection -FilePath $OutputDirectory -MinimumMB 500 # Cleanup existing trace file, if it exists if (Test-Path -Path $traceFilePath) { $confirm = Confirm-UserInput -Message "Trace file already exists at $traceFilePath. Would you like to delete the existing trace file?" if ($confirm) { Trace-Output -Level:Information -Message "Deleting existing trace file at $traceFilePath" Remove-Item -Path $traceFilePath -Force } else { Trace-Output -Level:Information -Message "Keeping existing trace file at $traceFilePath" } } $null = Set-NetIntentTracing -ComputerName $env:COMPUTERNAME *>&1 Trace-Output -Level:Information -Message "Enabled network intent tracing" # Retry applying the intent Trace-Output -Level:Information -Message "Applying intent retry state for '$IntentName'" $null = Set-NetIntentRetryState -Name $IntentName -NodeName $env:COMPUTERNAME *>&1 # Wait for the intent to be applied $iter = 1 $maxIter = 12 $sleepTime = 15 Trace-Output -Level:Information -Message "Waiting for intent '$IntentName' to be applied. Maximum iterations: $maxIter, Sleep time between iterations: $sleepTime seconds." while ($iter -le $maxIter) { $status = Get-NetIntentStatus -Name $IntentName -ErrorAction SilentlyContinue | Where-Object { $_.Host -like $env:COMPUTERNAME } Trace-Output -Level:Information -Message "[$iter/$maxIter] Intent '$IntentName' ConfigurationStatus: $($status.ConfigurationStatus), ProvisioningStatus: $($status.ProvisioningStatus)" if ($status.ConfigurationStatus -eq "Success" -and $status.ProvisioningStatus -eq "Completed") { Trace-Output -Level:Information -Message "Intent '$IntentName' applied successfully." break } Start-Sleep -Seconds $sleepTime $iter++ } $null = Set-NetIntentTracing -StopTracing *>&1 Trace-Output -Level:Information -Message "Stopped network intent tracing" # Copy the trace file to output directory and convert to text if (Test-Path -Path $traceFilePath) { $destinationPath = Join-Path -Path $OutputDirectory -ChildPath "NetworkATC_Trace.etl" $txtOutputPath = Join-Path -Path $OutputDirectory -ChildPath "NetworkATC_Trace.txt" Trace-Output -Level:Verbose -Message "Copying trace file to output directory: $destinationPath" Copy-Item -Path $traceFilePath -Destination $destinationPath -Force Trace-Output -Level:Verbose -Message "Converting trace file to text format: $txtOutputPath" $null = netsh trace convert $destinationPath output=$txtOutputPath *>&1 } # Summarize results $intentStatus = Get-NetIntentStatus -Name $IntentName -ErrorAction Ignore | Where-Object { $_.Host -like $env:COMPUTERNAME } Trace-Output -Level:Information -Message "Intent '$IntentName' Retry Result" $statusLevel = if ($intentStatus.ConfigurationStatus -eq "Success" -and $intentStatus.ProvisioningStatus -eq "Completed") { "Success" } else { "Warning" } $resultObject.IntentConfigStatus = $intentStatus.ConfigurationStatus $resultObject.IntentProvisioningStatus = $intentStatus.ProvisioningStatus $resultObject.OutputDirectory = $OutputDirectory $resultObject.TraceFilePath = $txtOutputPath $resultObject.Result = $statusLevel # If the intent was not applied successfully, collect the additional support data if ($intentStatus.ConfigurationStatus -ne "Success" -or $intentStatus.ProvisioningStatus -ne "Completed") { $confirm = Confirm-UserInput -Message "Would you like to collect additional Network ATC Diagnostic Data for this node?" if ($confirm) { $null = Get-AzsSupportHostNetworkDiagnosticData -OutputDirectory $OutputDirectory -SkipCompression $compressedData = Compress-AzsSupportArchive -Path $OutputDirectory -Destination "$OutputDirectory.zip" Show-UploadInstruction -DataType 'Network ATC Diagnostic Data' -SourcePath $compressedData.FullName $resultObject.AdditionalDiagnosticData = $compressedData.FullName } } else { Trace-Output -Level:Success -Message "Intent '$IntentName' applied successfully. No additional diagnostic data is needed." } return $resultObject } function Get-AzsSupportHostNetworkDiagnosticData { <# .SYNOPSIS Collects comprehensive network diagnostic data from the local host. .DESCRIPTION This function gathers extensive network diagnostic information including Network ATC configuration, Windows Event Logs, cluster configuration, network adapter settings, and host configuration. The collected data is saved to JSON files and optionally compressed into a ZIP archive. .PARAMETER FilePrefix Optional. A prefix to add to the diagnostic data folder name for easier identification. .PARAMETER OutputDirectory Optional. The directory where diagnostic data will be saved. .PARAMETER SkipCompression Optional. If specified, the diagnostic data will not be compressed into a ZIP file. By default, a ZIP archive is created for easier transport. .EXAMPLE Get-AzsSupportHostNetworkDiagnosticData Collects diagnostic data to the default Network folder and creates a ZIP archive. .EXAMPLE Get-AzsSupportHostNetworkDiagnosticData -FilePrefix "Issue123" -OutputDirectory "C:\Diagnostics" Collects diagnostic data with "Issue123" prefix to C:\Diagnostics and creates a ZIP archive. .EXAMPLE Get-AzsSupportHostNetworkDiagnosticData -SkipCompression Collects diagnostic data without creating a ZIP archive. #> [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [string]$FilePrefix = $null, [Parameter(Mandatory = $false)] [string]$OutputDirectory = "$(Get-AzsSupportWorkingDirectory)\HostNetwork", [Parameter(Mandatory = $false)] [switch]$SkipCompression ) $winEventsToExport = @( "System", "Application", "Microsoft-Windows-Networking-NetworkAtc/Operational", "Microsoft-Windows-Networking-NetworkAtc/Admin", "Microsoft-Windows-FailoverClustering/Operational", "AzStackHciEnvironmentChecker" ) $diagPath = Join-Path -Path $OutputDirectory -ChildPath "DiagnosticData" $null = Initialize-DataCollection -FilePath $diagPath -MinimumMB 500 # Collect Network ATC Configuration Invoke-CommandToJSON -Command { Get-NetIntent } -OutputDirectory $diagPath -FileName "Get-NetIntent.json" Invoke-CommandToJSON -Command { Get-NetIntentStatus } -OutputDirectory $diagPath -FileName "Get-NetIntentStatus.json" Invoke-CommandToJSON -Command { Get-NetIntent -GlobalOverrides } -OutputDirectory $diagPath -FileName "Get-NetIntent-GlobalOverrides.json" Invoke-CommandToJSON -Command { Get-NetIntentAllGoalStates } -OutputDirectory $diagPath -FileName "Get-NetIntentAllGoalStates.json" # Collect Cluster Configuration Invoke-CommandToJSON -Command { Get-Cluster } -OutputDirectory $diagPath -FileName "Get-Cluster.json" Invoke-CommandToJSON -Command { Get-ClusterNode } -OutputDirectory $diagPath -FileName "Get-ClusterNode.json" Invoke-CommandToJSON -Command { Get-ClusterResource } -OutputDirectory $diagPath -FileName "Get-ClusterResource.json" Invoke-CommandToJSON -Command { Get-ClusterNetwork } -OutputDirectory $diagPath -FileName "Get-ClusterNetwork.json" Invoke-CommandToJSON -Command { Get-ClusterResourceType "Virtual Machine" | Get-ClusterParameter -Name "migration*" } -OutputDirectory $diagPath -FileName "Get-ClusterResourceType-Migration.json" # Collect Network Configuration Invoke-CommandToJSON -Command { Get-NetIPAddress } -OutputDirectory $diagPath -FileName "Get-NetIPAddress.json" Invoke-CommandToJSON -Command { Get-NetIPConfiguration 4>$null } -OutputDirectory $diagPath -FileName "Get-NetIPConfiguration.json" Invoke-CommandToJSON -Command { Get-NetAdapter } -OutputDirectory $diagPath -FileName "Get-NetAdapter.json" Invoke-CommandToJSON -Command { Get-NetAdapterAdvancedProperty } -OutputDirectory $diagPath -FileName "Get-NetAdapterAdvancedProperty.json" Invoke-CommandToJSON -Command { Get-VMSwitch } -OutputDirectory $diagPath -FileName "Get-VMSwitch.json" Invoke-CommandToJSON -Command { Get-VMSwitch | Get-VMSwitchTeam -ErrorAction SilentlyContinue } -OutputDirectory $diagPath -FileName "Get-VMSwitchTeam.json" Invoke-CommandToJSON -Command { Get-VMNetworkAdapter -ManagementOS } -OutputDirectory $diagPath -FileName "Get-VMNetworkAdapter-ManagementOS.json" Invoke-CommandToJSON -Command { Get-VMNetworkAdapterVlan -ManagementOS } -OutputDirectory $diagPath -FileName "Get-VMNetworkAdapterVlan-ManagementOS.json" Invoke-CommandToJSON -Command { Get-VMNetworkAdapterIsolation -ManagementOS } -OutputDirectory $diagPath -FileName "Get-VMNetworkAdapterIsolation-ManagementOS.json" # Collect Host Configuration Invoke-CommandToJSON -Command { Get-ComputerInfo } -OutputDirectory $diagPath -FileName "Get-ComputerInfo.json" Invoke-CommandToJSON -Command { Get-HotFix } -OutputDirectory $diagPath -FileName "Get-HotFix.json" # collect event logs $exportResults = Export-AzsSupportEventLog -LogName $winEventsToExport -Destination $diagPath $exportResults | Export-ObjectToFile -OutputDirectory $diagPath -FileName "Export-AzsSupportEventLog_Summary.json" # compress the results unless operator has request to skip compression if (!$SkipCompression) { $result = Compress-AzsSupportArchive -Path $diagPath -Destination "$diagPath.zip" } else { $result = Get-Item -Path $diagPath } return $result } # SIG # Begin signature block # MIIoUgYJKoZIhvcNAQcCoIIoQzCCKD8CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAWgFBtGzGHMRMw # dO91g/efmT6oon6bEiPlT3Lqs/ybsqCCDYUwggYDMIID66ADAgECAhMzAAAEhJji # 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 # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEICKD # 6HCBJPvn7jKsyZxJVHtYMB3nn1SOckMxNDBZXpOGMEIGCisGAQQBgjcCAQwxNDAy # oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20wDQYJKoZIhvcNAQEBBQAEggEANC/QkDJFJdJxNZ+MMi4UuyEu613p+zSgw5PN # nEaiku/mGKcUe4iFxi8ETcwAPW3ZPMcRVLvIEcqLJ+lAVqakgj/MB+GuC512jhpU # eKKCspS2GfQNZXWUhxkXDEoLnGgz4oR7yPzM0uEuAomwIvYSyYnCIB15gJPUAMfn # pE4CQwdfOcB9SpQmjE5Olu+P9/oyV/s707hgnyChGKFH7WGJgfjge0pYV+t5GTts # uQxP0B8kzItKfStX8XnR19QadD7yqO4xbojRcBLViU9gF3zKVPaMNaxvOLKZk0r0 # I5jLEh5OdXo686EFeeq5uJs6L/Zr8bJM8cvTMIHAkGSyk83oCaGCF60wghepBgor # BgEEAYI3AwMBMYIXmTCCF5UGCSqGSIb3DQEHAqCCF4YwgheCAgEDMQ8wDQYJYIZI # AWUDBAIBBQAwggFaBgsqhkiG9w0BCRABBKCCAUkEggFFMIIBQQIBAQYKKwYBBAGE # WQoDATAxMA0GCWCGSAFlAwQCAQUABCBKtXb9V2UI8HT8OXR2C5tfVqNZo39WHmBW # ZM3wnHxg3wIGaPedHa0kGBMyMDI1MTAyODIwNDAwMy43NzlaMASAAgH0oIHZpIHW # 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 # CQQxIgQgQeBkUBE8zmH8h0km8Cnu49+cOdqqZkDFuRxIg9+PXSowgfoGCyqGSIb3 # DQEJEAIvMYHqMIHnMIHkMIG9BCDQ8lBgPl23yZ0SzUSt5phOIegHPywrkNwevxe2 # k+RaWzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAC # F3H7LqWvAR3qAAEAAAIXMCIEIIP42c6AjaR2eEAWNp2RinULnCtTAy329lRNrmIu # 71RXMA0GCSqGSIb3DQEBCwUABIICAB/vad6RyNxDcxOBumo9ADVCamCpYbTJ5WbB # /kg3QfuQOOhEDEf0xDuLA56XF00yttcJKTQF45PMb/i54w+urSAy8LFdpwtajNEC # AkOrqvGgDKAEEwtfQqjxWNq3FQ0LtLgvgjXiLSphuwIlWLYJQEC4WFfteKEpQrC5 # MJy4XBSVXnNwfIzu8xaBAx4FfMJkkU63BZwGQvkD8+PnkAG3V8qB9swDiOI5I3fw # rpej9xxB/qFy1mgMj110jPxBn58DrQV695Fdsn//AZuVeL6YGDPF7ES+sTGPK6qY # tJ9ldHTEZOuL7N2qa4MueiVlpUVvFEm+VmXxglTo7SfQ2segoYBLz33Ih4eKthiU # MeYNHg+8JuDbjzE4bheGRQlx8MTcs1Ka+5Jo089O5PGiNQ/41xpEOsPChqe07SXw # NQB1Y2XkugcSW73AL51P8YmQxpkkfe65tLnLY+imkBD4erAh0pK0eKdtZl2W2+io # MlTy77wEOfNUK3PzhuFSI8bsdSPMtq79TzeF4mDw5VPZoIQSdxDRGRYgHwHT8xvc # 9vPTc8Cz3UtP4J+aL7DGX8AEAVIOq2ZYOBQqBszPhWUulk4pX53EfeCX4OsUQldz # /aXbxr6WtTtqLsBMFqX3eRk/V44WECaUpCVAVBJgz2LKUgSpG3OZlVJPsoGJk9yW # hTK4MrmA # SIG # End signature block |