AzStackHciStandaloneObservability/package/scripts/ExtensionHelper.psm1
##------------------------------------------------------------------ ## <copyright file="ExtensionHelper.psm1" company="Microsoft"> ## Copyright (C) Microsoft. All rights reserved. ## </copyright> ##------------------------------------------------------------------ #region Functions function Get-ExtensionRootLocation { Split-Path -Parent $PSScriptRoot } function Get-GmaPackageContentPath { Join-Path -Path $(Get-ExtensionRootLocation) -ChildPath 'bin\GMA' } ##--------------------------------------------------------------------------------------------------------------------- ## NOTE: Purposefully importing this module after the above function definitions. ##--------------------------------------------------------------------------------------------------------------------- Import-Module (Join-Path -Path (Get-GmaPackageContentPath) -ChildPath 'GMATenantJsonHelper.psm1') ` -DisableNameChecking ` -Verbose:$false #region Pre-installation validation functions function Assert-SufficientMemoryAvailableForGMACache { $driveLetter = Get-SystemDriveLetter $availableMemoryOnStamp = ((Get-Volume -DriveLetter $driveLetter).SizeRemaining) / 1GB if ($availableMemoryOnStamp -lt $MiscConstants.AvailableMemoryLimitInGB) { return $ErrorConstants.InsufficientMemoryForGMACache.Name } return $true } function Invoke-PreInstallationValidation { param ( [Parameter(Mandatory)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name $validationFunctionNames = ( $MiscConstants.ValidationFunctionNames.AssertSufficientMemoryAvailableForGMACache ) Write-Log ` -Message "$functionName : Performing pre-installation validation." ` -LogFile $logFile foreach($validationFunction in $validationFunctionNames) { $validationResult = (Invoke-Expression $validationFunction) if ($validationResult -ne $true) { Write-Log ` -Message "$validationFunction : $($ErrorConstants.$validationResult.Message)" ` -LogFile $LogFile ` -Level $MiscConstants.Level.Error throw $validationResult } Write-Log ` -Message "$validationFunction : $validationResult" ` -LogFile $LogFile ` } Write-Log ` -Message "$functionName : Pre-installation validation completed successfully." ` -LogFile $logFile } #endregion Pre-installation validation functions #region GCS functions function Get-CloudName { Param ( [Parameter(Mandatory)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name Write-Log ` -Message "$functionName : Entering..." ` -LogFile $LogFile $publicSettings = Get-HandlerConfigSettings -LogFile $LogFile $cloudName = "" ## Check if any cloud value is passed through Config settings, if yes than use that if (-not ([System.String]::IsNullOrEmpty($publicSettings.cloudName)) -and ` -not ([System.String]::IsNullOrWhiteSpace($publicSettings.cloudName))) { Write-Log ` -Message "$functionName : CloudName from publicSetting = $($publicSettings.cloudName)" ` -LogFile $LogFile $cloudName = $publicSettings.cloudName } Write-Log ` -Message "$functionName : Exiting. CloudName: $cloudName" ` -LogFile $LogFile return $cloudName } function Get-GcsEnvironmentName { Param ( [Parameter(Mandatory)] [System.String] $CloudName, [Parameter(Mandatory)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name Write-Log ` -Message "$functionName : CloudName = $CloudName" ` -LogFile $LogFile $gcsEnvironmentName = $MiscConstants.GCSEnvironment.Prod ## Check whether cloud name is Canary or TIP or reg key created for CI exists or not, if yes then change the GCSEnvironment to point to PPE instead. if ($CloudName -in $MiscConstants.CloudNames.AzureCanary -or ` $CloudName -in $MiscConstants.CloudNames.AzurePPE -or ` (Test-RegKeyExists -Path $MiscConstants.CIRegKey.Path -Name $MiscConstants.CIRegKey.Name) -eq $true) { $gcsEnvironmentName = $MiscConstants.GCSEnvironment.Ppe } elseif ($CloudName -in $MiscConstants.CloudNames.AzureUSGovernmentCloud) { $gcsEnvironmentName = $MiscConstants.GCSEnvironment.Fairfax } elseif ($CloudName -in $MiscConstants.CloudNames.AzureChinaCloud) { $gcsEnvironmentName = $MiscConstants.GCSEnvironment.Mooncake } Write-Log ` -Message "$functionName : GcsEnvironmentName based on CloudName ($CloudName) = $gcsEnvironmentName" ` -LogFile $LogFile return $gcsEnvironmentName } function Get-GcsRegionName { Param ( [Parameter(Mandatory)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name Write-Log ` -Message "$functionName : Entering..." ` -LogFile $LogFile ## Check if any region value is passed through Config settings, if yes than use that $publicSettings = Get-HandlerConfigSettings -LogFile $LogFile if (-not ([System.String]::IsNullOrEmpty($publicSettings.region)) -and ` -not ([System.String]::IsNullOrWhiteSpace($publicSettings.region))) { Write-Log ` -Message "$functionName : RegionName from publicSetting = $($publicSettings.region)" ` -LogFile $LogFile $gcsRegionName = $publicSettings.region } Write-Log ` -Message "$functionName : Exiting. GCSRegionName: $gcsRegionName" ` -LogFile $LogFile return $gcsRegionName } function Wait-ForGcsConfigSync() { [CmdletBinding()] Param ( [Parameter(Mandatory)] [System.String] $LogFile, [Parameter(Mandatory = $false)] [int] $TimeInSeconds = 60 ) $functionName = $MyInvocation.MyCommand.Name Write-Log ` -Message "$functionName : Entering. TimeOut: $TimeInSeconds" ` -LogFile $LogFile Write-Host "Going to wait for GCSConfig sync $TimeInSeconds" Start-Sleep -Seconds $TimeInSeconds $cacheDir = Get-GmaCacheDirectories $gcsConfigFiles = Get-ChildItem -Path $cacheDir.GMACache -Filter GcsConfig -Recurse if($gcsConfigFiles.Count -eq 0) { Write-Log ` -Message "$functionName : $($ErrorConstants.GcsConfigFilesNotFound.Message)" ` -LogFile $LogFile ` -Level $MiscConstants.Level.Error } Write-Log ` -Message "$functionName : Exiting. GCSCongfile count: $($gcsConfigFiles.Count)" ` -LogFile $LogFile } #endregion GCS functions #region Handler/Extension functions ## Get sequence number from env variable provided by Agent function Get-ConfigSequenceNumber {if ($null -eq $env:ConfigSequenceNumber) { 0 } else { $env:ConfigSequenceNumber }} function Get-HandlerConfigSettings { param ( [Parameter(Mandatory)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name $handlerEnvInfo = Get-HandlerEnvInfo -LogFile $LogFile if (-not (Test-Path $handlerEnvInfo.configFolder -PathType Container)) { Write-Log ` -Message "$functionName : $($ErrorConstants.ConfigFolderDoesNotExist.Message)" ` -LogFile $LogFile ` -Level $MiscConstants.Level.Error throw $ErrorConstants.ConfigFolderDoesNotExist.Name } $configFile = Get-ChildItem -Path $handlerEnvInfo.configFolder | Sort-Object CreationTime -Descending | Select-Object -First 1 # Parse config file to read parameters $configJson = Get-Content -Path $configFile.FullName -Raw | ConvertFrom-Json return $configJson.runtimeSettings[0].handlerSettings.publicSettings } function Get-HandlerEnvInfo { <# Sample HandlerEnvironment.json content: [ { "handlerEnvironment": { "configFolder": "C:\\Packages\\Plugins\\Microsoft.AzureStack.Observability.Observability\\0.0.0.4\\RuntimeSettings", "deploymentid": "", "heartbeatFile": "C:\\Packages\\Plugins\\Microsoft.AzureStack.Observability.Observability\\0.0.0.4\\status\\HeartBeat.Json", "hostResolverAddress": "", "instance": "", "logFolder": "C:\\ProgramData\\GuestConfig\\extension_logs\\Microsoft.AzureStack.Observability.Observability", "rolename": "", "statusFolder": "C:\\Packages\\Plugins\\Microsoft.AzureStack.Observability.Observability\\0.0.0.4\\status" }, "name": "Microsoft.RecoveryServices.Test.AzureSiteRecovery", "version": "1" } ] #> $envFile = "$(Get-ExtensionRootLocation)\HandlerEnvironment.json" if (-not (Test-Path $envFile -PathType Leaf)) { throw $ErrorConstants.HandlerEnvJsonDoesNotExist.Name } # Read handler config $envJson = Get-Content -Path $envFile -Raw | ConvertFrom-Json if ($envJson -is [System.Array]) { $envJson = $envJson[0] } return $envJson.handlerEnvironment } function Get-HandlerHeartBeatFile { $handlerEnvInfo = Get-HandlerEnvInfo -LogFile $LogFile return $handlerEnvInfo.heartbeatFile } function Get-HandlerLogFile { Join-Path $(Get-LogFolderPath) -ChildPath $MiscConstants.HandlerLogFileName } function Get-LogFolderPath { $handlerEnvInfo = Get-HandlerEnvInfo -LogFile $LogFile if (-not (Test-Path $handlerEnvInfo.logFolder -PathType Container)) { throw $ErrorConstants.LogFolderDoesNotExist.Name } return $handlerEnvInfo.logFolder } function Get-StatusFolderPath { $handlerEnvInfo = Get-HandlerEnvInfo -LogFile $LogFile if (-not (Test-Path $handlerEnvInfo.statusFolder -PathType Container)) { throw $ErrorConstants.StatusFolderDoesNotExist.Name } return $handlerEnvInfo.statusFolder } #endregion Handler/Extension functions #region Misc functions function Get-GmaCacheDirectories { $logFolderPath = Get-LogFolderPath return [ordered] @{ GMACache = "$logFolderPath\GMACache" DiagnosticsCache = "$logFolderPath\GMACache\DiagnosticsCache" HealthCache = "$logFolderPath\GMACache\HealthCache" JsonDropLocation = "$logFolderPath\GMACache\JsonDropLocation" MonAgentHostCache = "$logFolderPath\GMACache\MonAgentHostCache" TelemetryCache = "$logFolderPath\GMACache\TelemetryCache" MetricsCache = "$logFolderPath\GMACache\MetricsCache" } } function Set-GmaCacheDirectories { param ( [Parameter(Mandatory)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name $gmaCacheDirectories = Get-GmaCacheDirectories foreach ($directory in $gmaCacheDirectories.Values) { if (Test-Path $directory -PathType Container) { Write-Log ` -Message "$functionName : $directory exists already." ` -LogFile $LogFile } else { New-Item ` -Path $directory ` -ItemType Directory ` -Force ` | Out-Null } } return $gmaCacheDirectories } function Set-CacheDirectories { ## NOTE: Remove the above function when adding Diagnostics cache locations as this is supposed to be generic function to create cache dirs. param ( [Parameter(Mandatory = $true)] [System.String] $LogFile ) $gmaCacheDirectories = Get-GmaCacheDirectories foreach ($directory in $gmaCacheDirectories.Values) { Set-Directory ` -Path $directory ` -LogFile $logFile } return $gmaCacheDirectories } function Set-Directory { param ( [Parameter(Mandatory = $true)] [System.String] $Path, [Parameter(Mandatory = $true)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name if (-not (Test-Path $Path -PathType Container)) { New-Item ` -Path $Path ` -ItemType Directory ` -Force ` | Out-Null Write-Log ` -Message "$functionName : Directory path ($Path) created." ` -LogFile $LogFile } else { Write-Log ` -Message "$functionName : Directory path ($Path) exists already." ` -LogFile $LogFile } } function Get-UtcExporterPackageContentPath { Join-Path -Path $(Get-ExtensionRootLocation) -ChildPath "\bin\UtcExporter" } function Get-WatchdogPackageContentPath { Join-Path -Path $(Get-ExtensionRootLocation) -ChildPath "\bin\MAWatchdog" } function Get-SystemDriveLetter { ($env:SystemDrive).split(':')[0] } function Set-Status { Param ( [Parameter(Mandatory)] [System.String] $Name, [Parameter(Mandatory)] [System.String] $Operation, [Parameter(Mandatory)] [System.String] $Message, [Parameter(Mandatory)] [ValidateSet("transitioning", "error", "success", "warning")] [System.String] $Status, [Parameter(Mandatory)] [System.Int16] $Code ) & "$PSScriptRoot\ReportStatus.ps1" ` -Name $Name ` -Operation $Operation ` -Status $Status ` -Code $Code ` -Message $Message } #endregion Misc functions #region UTC setup functions Function Initialize-UTCSetup { [CmdletBinding()] Param ( [Parameter(Mandatory = $False)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name try { Write-Log ` -Message "$functionName : Initializing UTC setup." ` -LogFile $logFile #region Stop diagtrack service Stop-ServiceForObservability ` -ServiceName $MiscConstants.ObsServiceDetails.DiagTrack.Name ` -LogFile $logFile #endregion Stop diagtrack service ## Create the UTC exporter destination folder (if not present) and copy the UtcGenevaExporter dll in it. Write-Log ` -Message "$functionName : Create folder for UTCExporterdll and place the respective binary in it." ` -LogFile $logFile $utcExporterDllName = $MiscConstants.UtcxporterDllName $utcExporterSourcePath = Join-Path -Path (Get-UtcExporterPackageContentPath) -ChildPath $utcExporterDllName $utcExporterDestinationDirectory = $MiscConstants.UtcExporterDestinationDirectory Set-Directory ` -Path $utcExporterDestinationDirectory ` -LogFile $logFile Copy-Item ` -Path $utcExporterSourcePath ` -Destination $utcExporterDestinationDirectory ` -Force ` | Out-Null $utcExporterDestinationPath = Join-Path -Path $utcExporterDestinationDirectory -ChildPath $utcExporterDllName if (Test-Path $utcExporterDestinationPath) { Write-Log ` -Message "$functionName : Successfully copied '$utcExporterDllName' to '$utcExporterDestinationPath'." ` -LogFile $logFile } else { Write-Log ` -Message "$functionName : Failed to copy '$utcExporterDllName' to '$utcExporterDestinationPath'." ` -LogFile $logFile ` -Level $MiscConstans.Status.Error throw $ErrorConstants.CannotCopyUtcExporterDll.Name } #region Create reg keys Set-RegKey ` -Path $MiscConstants.DiagTrackExportersRegKeyPath ` -LogFile $logFile ` -CreatePathOnly Set-RegKey ` -Path $MiscConstants.GenevaExporterRegKey.Path ` -LogFile $logFile ` -CreatePathOnly Set-RegKey ` -Path $MiscConstants.DiagTrackRegKey.Path ` -Name $MiscConstants.DiagTrackRegKey.Name ` -PropertyType $MiscConstants.DiagTrackRegKey.PropertyType ` -Value $MiscConstants.DiagTrackRegKey.Value ` -LogFile $logFile Set-RegKey ` -Path $MiscConstants.GenevaExporterRegKey.Path ` -Name $MiscConstants.GenevaExporterRegKey.Name ` -PropertyType $MiscConstants.GenevaExporterRegKey.PropertyType ` -Value $utcExporterDestinationPath ` -LogFile $logFile Set-RegKey ` -Path $MiscConstants.TestHooksRegKey.Path ` -Name $MiscConstants.TestHooksRegKey.Name ` -PropertyType $MiscConstants.TestHooksRegKey.PropertyType ` -Value $MiscConstants.TestHooksRegKey.Value ` -LogFile $logFile Set-RegKey ` -Path $MiscConstants.GenevaExporterRegKey.Path ` -Name $MiscConstants.GenevaNamespaceRegKey.Name ` -PropertyType $MiscConstants.GenevaNamespaceRegKey.PropertyType ` -Value $MiscConstants.GenevaNamespaceRegKey.Value ` -LogFile $logFile #endregion Create reg keys #region Start diagtrack service Start-ServiceForObservability ` -ServiceName $MiscConstants.ObsServiceDetails.DiagTrack.Name ` -LogFile $logFile #endregion Start diagtrack service Write-Log ` -Message "$functionName : Successfully initialized UTC setup." ` -LogFile $logFile } finally { if ((Get-Service $MiscConstants.ObsServiceDetails.DiagTrack.Name).Status -eq "Stopped") { Write-Log ` -Message "$functionName : Starting $($MiscConstants.ObsServiceDetails.DiagTrack.Name) service after it was stopped." ` -LogFile $LogFile Start-Service ` -Name $MiscConstants.ObsServiceDetails.DiagTrack.Name ` -ErrorAction SilentlyContinue ` -Verbose:$false ` | Out-Null } } } Function Clear-UTCSetup { [CmdletBinding()] Param ( [Parameter(Mandatory = $False)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name try { Write-Log ` -Message "$functionName : Cleaning up UTC related artifacts." ` -LogFile $logFile #region Stop diagtrack service Stop-ServiceForObservability ` -ServiceName $MiscConstants.ObsServiceDetails.DiagTrack.Name ` -LogFile $LogFile #endregion Stop diagtrack service #region Remove UtcExporter dll Write-Log ` -Message "$functionName : Removing UTCExporterdll file and its folder." ` -LogFile $logFile $utcExporterDestinationPath = Join-Path -Path $MiscConstants.UtcExporterDestinationDirectory -ChildPath $MiscConstants.UtcxporterDllName if (Test-Path -Path $utcExporterDestinationPath) { Remove-Item ` -Path $utcExporterDestinationPath ` -Force ` -Verbose:$false ` | Out-Null Write-Log ` -Message "$functionName : Removed file '$utcExporterDestinationPath'." ` -LogFile $logFile if ((Get-ChildItem -Path $MiscConstants.UtcExporterDestinationDirectory | Measure-Object).Count -eq 0) { Remove-Item ` -Path $MiscConstants.UtcExporterDestinationDirectory ` -Force ` -Verbose:$false ` | Out-Null Write-Log ` -Message "$functionName : Removed directory '$($MiscConstants.UtcExporterDestinationDirectory)'." ` -LogFile $logFile } Write-Log ` -Message "$functionName : Removed UTCExporterdll file '$utcExporterDestinationPath' and its folder path '$($MiscConstants.UtcExporterDestinationDirectory)'." ` -LogFile $logFile } else { Write-Log ` -Message "$functionName : UTCExporter dll does not exists at path '$utcExporterDestinationPath'. Nothing to remove." ` -LogFile $logFile } #endregion Remove UtcExporter dll #region Remove reg keys Remove-RegKey ` -Path $MiscConstants.DiagTrackRegKey.Path ` -Name $MiscConstants.DiagTrackRegKey.Name ` -LogFile $logFile Remove-RegKey ` -Path $MiscConstants.TestHooksRegKey.Path ` -Name $MiscConstants.TestHooksRegKey.Name ` -LogFile $logFile Remove-RegKey ` -Path $MiscConstants.GenevaExporterRegKey.Path ` -Name $MiscConstants.GenevaExporterRegKey.Name ` -LogFile $logFile Remove-RegKey ` -Path $MiscConstants.GenevaExporterRegKey.Path ` -Name $MiscConstants.GenevaNamespaceRegKey.Name ` -LogFile $logFile Remove-RegKey ` -Path $MiscConstants.GenevaExporterRegKey.Path ` -LogFile $logFile ` -RemovePathOnly #endregion Remove reg keys #region Start diagtrack service Start-ServiceForObservability ` -ServiceName $MiscConstants.ObsServiceDetails.DiagTrack.Name ` -LogFile $LogFile #endregion Start diagtrack service Write-Log ` -Message "$functionName : Cleaned up artifacts related to UTC setup." ` -Logfile $logFile } finally { if ((Get-Service $MiscConstants.ObsServiceDetails.DiagTrack.Name).Status -eq "Stopped") { Write-Log ` -Message "$functionName : Starting $($MiscConstants.ObsServiceDetails.DiagTrack.Name) service after it was stopped." ` -LogFile $LogFile Start-Service ` -Name $MiscConstants.ObsServiceDetails.DiagTrack.Name ` -ErrorAction SilentlyContinue ` -Verbose:$false ` | Out-Null } } } #endregion UTC setup functions #region Registry functions function Set-RegKey { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $Path, [Parameter(Mandatory = $false)] [System.String] $Name, [Parameter(Mandatory = $false)] [System.String] $PropertyType, [Parameter(Mandatory = $false)] [System.String] $Value, [Parameter(Mandatory = $true)] [System.String] $LogFile, [Parameter(Mandatory=$false)] [System.Management.Automation.SwitchParameter] $CreatePathOnly ) $functionName = $MyInvocation.MyCommand.Name if ($CreatePathOnly) { if (-not (Test-Path -Path $Path)) { New-Item ` -Path $Path ` -Force ` -Verbose:$false ` | Out-Null Write-Log ` -Message "$functionName : Created RegKey path ($Path)." ` -LogFile $LogFile } else { Write-Log ` -Message "$functionName : RegKey path ($Path) exists already." ` -LogFile $LogFile } } else { if (-not (Test-RegKeyExists -Path $Path -Name $Name)) { New-ItemProperty ` -Path $Path ` -Name $Name ` -PropertyType $PropertyType ` -Value $Value ` -Force ` | Out-Null Write-Log ` -Message "$functionName : Created registry key with path ($Path), name ($Name) and value ($Value)." ` -LogFile $LogFile } else { Write-Log ` -Message "$functionName : RegKey path ($Path) and name ($Name) exists already." ` -LogFile $LogFile } } } Function Remove-RegKey { [CmdletBinding()] Param ( [Parameter(Mandatory = $True)] [System.String] $Path, [Parameter(Mandatory = $False)] [System.String] $Name, [Parameter(Mandatory = $False)] [System.String] $LogFile, [Parameter(Mandatory=$False)] [System.Management.Automation.SwitchParameter] $RemovePathOnly ) $functionName = $MyInvocation.MyCommand.Name if ($RemovePathOnly) { if (Test-Path -Path $Path) { Remove-Item ` -Path $Path ` -Force ` -Verbose:$false ` | Out-Null Write-Log ` -Message "$functionName : Path ($Path) removed successfully." ` -LogFile $LogFile } else { Write-Log ` -Message "$functionName : Path ($Path) does not exists. Nothing to remove" ` -LogFile $LogFile } } else { if (Test-RegKeyExists -Path $Path -Name $Name) { Remove-ItemProperty ` -Path $Path ` -Name $Name ` -Force ` -Verbose:$false ` | Out-Null Write-Log ` -Message "$functionName : RegKey path ($Path) and name ($Name) removed successfully." ` -LogFile $LogFile } else { Write-Log ` -Message "$functionName : RegKey path ($Path) and name ($Name) does not exists. Nothing to remove" ` -LogFile $LogFile } } } #endregion Registry functions #region Scheduled task functions function Enable-ObsScheduledTask { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name Write-Log ` -Message "$functionName : Enabling ObsScheduledTask ($($MiscConstants.ObsScheduledTaskDetails.TaskName))." ` -LogFile $LogFile Write-Log ` -Message "$functionName : $(Enable-ScheduledTask ` -TaskPath $MiscConstants.ObsScheduledTaskDetails.TaskPath ` -TaskName $MiscConstants.ObsScheduledTaskDetails.TaskName ` -ErrorAction Stop)" ` -LogFile $LogFile Write-Log ` -Message "$functionName : Successfully enabled obs scheduled task with name $($MiscConstants.ObsScheduledTaskDetails.TaskName)." ` -LogFile $LogFile } function Disable-ObsScheduledTask { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name Write-Log ` -Message "$functionName : Disabling ObsScheduledTask ($($MiscConstants.ObsScheduledTaskDetails.TaskName))." ` -LogFile $LogFile Write-Log ` -Message "$functionName : $(Disable-ScheduledTask ` -TaskPath $MiscConstants.ObsScheduledTaskDetails.TaskPath ` -TaskName $MiscConstants.ObsScheduledTaskDetails.TaskName ` -ErrorAction Stop)" ` -LogFile $LogFile Write-Log ` -Message "$functionName : Successfully disabled obs scheduled task with name $($MiscConstants.ObsScheduledTaskDetails.TaskName)." ` -LogFile $LogFile } function Remove-ObsScheduledTaskAndPath { param ( [Parameter(Mandatory)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name $trimmedTaskPath = $MiscConstants.ObsScheduledTaskDetails.TaskPath.TrimEnd('\') $tasks = Get-ScheduledTask -TaskPath "$trimmedTaskPath\*" if ($tasks) { foreach($task in $tasks) { if($task.TaskName -eq $MiscConstants.ObsScheduledTaskDetails.TaskName) { Unregister-ScheduledTask -TaskName $task.TaskName -TaskPath $task.TaskPath -Confirm:$false | Out-Null Write-Log ` -Message "$functionName : Successfully removed scheduled task $($task.TaskName) from path $($task.TaskPath)." ` -LogFile $LogFile } } } else { Write-Log ` -Message "$functionName : No scheduled tasks at task path $trimmedTaskPath found to delete." ` -LogFile $LogFile } } #endregion Scheduled task functions #region Windows service functions function Register-ServiceForObservability { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $ServiceName, [Parameter(Mandatory = $true)] [System.String] $ServiceDisplayName, [Parameter(Mandatory = $true)] [System.String] $ServiceBinaryFilePath, [Parameter(Mandatory = $false)] [System.String] $ServiceStartupType = 'Manual', [Parameter(Mandatory = $false)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name try { Write-Log ` -Message "$functionName : Starting registration of service '$ServiceName'." ` -LogFile $logFile Write-Log ` -Message "$functionName : Configuring service '$ServiceName' from path '$ServiceBinaryFilePath'" ` -LogFile $LogFile if (Get-Service $ServiceName -ErrorAction SilentlyContinue) { Write-Log ` -Message "$functionName : Service '$ServiceName' already registered." ` -LogFile $LogFile } else { New-Service ` -Name $ServiceName ` -BinaryPathName $ServiceBinaryFilePath ` -DisplayName $ServiceDisplayName ` -StartupType $ServiceStartupType ` -ErrorAction Stop ` -Verbose:$false ` | Out-Null } Write-Log ` -Message "$functionName : Registration of service '$ServiceName' with display name '$ServiceDisplayName' completed." ` -LogFile $logFile } catch { Write-Log ` -Message "$functionName : $($ErrorConstants.CannotRegisterService.Message) Service Name: '$ServiceName. Exception: $_" ` -LogFile $LogFile ` -Level $MiscConstants.Level.Error throw $ErrorConstants.CannotRegisterService.Name } } function Start-ServiceForObservability { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $ServiceName, [Parameter(Mandatory = $false)] [System.String] $LogFile, [Parameter(Mandatory = $false)] [int] $Retries = $MiscConstants.Retries ) $functionName = $MyInvocation.MyCommand.Name Write-Log ` -Message "$functionName : Starting service '$ServiceName'." ` -LogFile $logFile # Start MA Watchdog Agent Service $retryCount = $Retries $serviceStatus = (Get-Service $ServiceName).Status if ($serviceStatus -eq "Running") { Write-Log ` -Message "$functionName : Service '$ServiceName' running already." ` -LogFile $LogFile return } while(($serviceStatus -ne "Running") -and ($retryCount -gt 0)) { Start-Service $ServiceName ` -WarningAction SilentlyContinue ` -WarningVariable $startSvcWarn if ($null -ne $startSvcWarn) { Write-Log ` -Message "$functionName : $startSvcWarn" ` -Level $MiscConstants.Level.Warning ` -LogFile $LogFile } Write-Log ` -Message "$functionName : Waiting for service '$ServiceName' to start..." ` -LogFile $LogFile Start-Sleep -Seconds 5 $serviceStatus = (Get-Service $ServiceName).Status $retryCount-- } if ($serviceStatus -ne "Running") { Write-Log ` -Message "$functionName : $($ErrorConstants.CannotStartService.Message) Service Name: '$ServiceName'" ` -LogFile $LogFile ` -Level $MiscConstants.Level.Error throw $ErrorConstants.CannotStartService.Name } Write-Log ` -Message "$functionName : Successfully started service '$ServiceName'." ` -LogFile $LogFile } function Stop-ServiceForObservability { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $ServiceName, [Parameter(Mandatory = $false)] [System.String] $LogFile, [Parameter(Mandatory = $false)] [int] $Retries = $MiscConstants.Retries ) $functionName = $MyInvocation.MyCommand.Name Write-Log ` -Message "$functionName : Stopping service '$ServiceName'." ` -LogFile $logFile # Stop MA Watchdog Agent Service $retryCount = $Retries $serviceStatus = (Get-Service $ServiceName).Status if ($serviceStatus -eq "Stopped") { Write-Log ` -Message "$functionName : Service '$ServiceName' stopped already." ` -LogFile $LogFile return } while (($serviceStatus -ne "Stopped") -and ($retryCount -gt 0)) { Stop-Service $ServiceName ` -WarningAction SilentlyContinue ` -WarningVariable $stopSvcWarn if ($null -ne $stopSvcWarn) { Write-Log ` -Message "$functionName : $stopSvcWarn" ` -Level $MiscConstants.Level.Warning ` -LogFile $LogFile } Write-Log ` -Message "$functionName : Waiting for service '$ServiceName' to stop..." ` -LogFile $LogFile Start-Sleep -Seconds 5 $serviceStatus = (Get-Service $ServiceName).Status $retryCount-- } if ($serviceStatus -ne "Stopped") { Write-Log ` -Message "$functionName : $($ErrorConstants.CannotStopService.Message) Service Name: '$ServiceName'" ` -LogFile $LogFile ` -Level $MiscConstants.Level.Error throw $ErrorConstants.CannotStopService.Name } Write-Log ` -Message "$functionName : Successfully stopped service '$ServiceName'." ` -LogFile $LogFile } Function Unregister-ServiceForObservability { [CmdletBinding()] Param ( [Parameter(Mandatory = $true)] [System.String] $ServiceName, [Parameter(Mandatory = $true)] [System.String] $LogFile ) $functionName = $MyInvocation.MyCommand.Name Write-Log ` -Message "$functionName : Unregistering service '$ServiceName'." ` -LogFile $LogFile if (Get-Service $ServiceName -ErrorAction SilentlyContinue) { Stop-ServiceForObservability -ServiceName $ServiceName -LogFile $LogFile } Write-Log ` -Message "$functionName : $(sc.exe delete $ServiceName -Verbose)" ` -LogFile $LogFile Write-Log ` -Message "$functionName : Successfully unregisteried service '$ServiceName'." ` -LogFile $LogFile } function Set-StandaloneScenarioRegistry { [CmdletBinding()] Param ( [Parameter(Mandatory = $true)] [System.String] $LogFile ) Set-RegKey ` -Path $MiscConstants.GMAScenarioRegKey.Path ` -Name $MiscConstants.GMAScenarioRegKey.Name ` -PropertyType $MiscConstants.GMAScenarioRegKey.PropertyType ` -Value $MiscConstants.GMAScenarioRegKey.OneP ` -CreatePathOnly ` -LogFile $LogFile Set-RegKey ` -Path $MiscConstants.GMAScenarioRegKey.Path ` -Name $MiscConstants.GMAScenarioRegKey.Name ` -PropertyType $MiscConstants.GMAScenarioRegKey.PropertyType ` -Value $MiscConstants.GMAScenarioRegKey.OneP ` -LogFile $LogFile } #endregion #region GMA Utility functions #endregion #endregion Functions #region Exports Export-ModuleMember -Function Get-ExtensionRootLocation Export-ModuleMember -Function Get-GmaPackageContentPath # Pre-installation validation functions Export-ModuleMember -Function Invoke-PreInstallationValidation # GCS functions Export-ModuleMember -Function Get-CloudName Export-ModuleMember -Function Get-GcsEnvironmentName Export-ModuleMember -Function Get-GcsRegionName Export-ModuleMember -Function Wait-ForGcsConfigSync # Handler/Extension functions Export-ModuleMember -Function Get-ConfigSequenceNumber Export-ModuleMember -Function Get-HandlerConfigSettings Export-ModuleMember -Function Get-HandlerEnvInfo Export-ModuleMember -Function Get-HandlerHeartBeatFile Export-ModuleMember -Function Get-HandlerLogFile Export-ModuleMember -Function Get-LogFolderPath Export-ModuleMember -Function Get-StatusFolderPath # Misc functions Export-ModuleMember -Function Get-GmaCacheDirectories Export-ModuleMember -Function Set-GmaCacheDirectories Export-ModuleMember -Function Set-Directory Export-ModuleMember -Function Get-UtcExporterPackageContentPath Export-ModuleMember -Function Get-WatchdogPackageContentPath Export-ModuleMember -Function Get-SystemDriveLetter Export-ModuleMember -Function Set-Status Export-ModuleMember -Function Set-StandaloneScenarioRegistry # UTC setup functions Export-ModuleMember -Function Initialize-UTCSetup Export-ModuleMember -Function Clear-UTCSetup # Registry functions Export-ModuleMember -Function Set-RegKey Export-ModuleMember -Function Remove-RegKey # Scheduled task functions Export-ModuleMember -Function Enable-ObsScheduledTask Export-ModuleMember -Function Disable-ObsScheduledTask Export-ModuleMember -Function Remove-ObsScheduledTaskAndPath # Windows service functions Export-ModuleMember -Function Register-ServiceForObservability Export-ModuleMember -Function Start-ServiceForObservability Export-ModuleMember -Function Stop-ServiceForObservability Export-ModuleMember -Function Unregister-ServiceForObservability #endregion Exports # SIG # Begin signature block # MIInwgYJKoZIhvcNAQcCoIInszCCJ68CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBdkXq+guNBXJd9 # J8gwIwzJfbUFe2A4mVTRLKP1jQzbqKCCDXYwggX0MIID3KADAgECAhMzAAADTrU8 # esGEb+srAAAAAANOMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjMwMzE2MTg0MzI5WhcNMjQwMzE0MTg0MzI5WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDdCKiNI6IBFWuvJUmf6WdOJqZmIwYs5G7AJD5UbcL6tsC+EBPDbr36pFGo1bsU # p53nRyFYnncoMg8FK0d8jLlw0lgexDDr7gicf2zOBFWqfv/nSLwzJFNP5W03DF/1 # 1oZ12rSFqGlm+O46cRjTDFBpMRCZZGddZlRBjivby0eI1VgTD1TvAdfBYQe82fhm # WQkYR/lWmAK+vW/1+bO7jHaxXTNCxLIBW07F8PBjUcwFxxyfbe2mHB4h1L4U0Ofa # +HX/aREQ7SqYZz59sXM2ySOfvYyIjnqSO80NGBaz5DvzIG88J0+BNhOu2jl6Dfcq # jYQs1H/PMSQIK6E7lXDXSpXzAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUnMc7Zn/ukKBsBiWkwdNfsN5pdwAw # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW # MBQGA1UEBRMNMjMwMDEyKzUwMDUxNjAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAD21v9pHoLdBSNlFAjmk # mx4XxOZAPsVxxXbDyQv1+kGDe9XpgBnT1lXnx7JDpFMKBwAyIwdInmvhK9pGBa31 # TyeL3p7R2s0L8SABPPRJHAEk4NHpBXxHjm4TKjezAbSqqbgsy10Y7KApy+9UrKa2 # kGmsuASsk95PVm5vem7OmTs42vm0BJUU+JPQLg8Y/sdj3TtSfLYYZAaJwTAIgi7d # hzn5hatLo7Dhz+4T+MrFd+6LUa2U3zr97QwzDthx+RP9/RZnur4inzSQsG5DCVIM # pA1l2NWEA3KAca0tI2l6hQNYsaKL1kefdfHCrPxEry8onJjyGGv9YKoLv6AOO7Oh # JEmbQlz/xksYG2N/JSOJ+QqYpGTEuYFYVWain7He6jgb41JbpOGKDdE/b+V2q/gX # UgFe2gdwTpCDsvh8SMRoq1/BNXcr7iTAU38Vgr83iVtPYmFhZOVM0ULp/kKTVoir # IpP2KCxT4OekOctt8grYnhJ16QMjmMv5o53hjNFXOxigkQWYzUO+6w50g0FAeFa8 # 5ugCCB6lXEk21FFB1FdIHpjSQf+LP/W2OV/HfhC3uTPgKbRtXo83TZYEudooyZ/A # Vu08sibZ3MkGOJORLERNwKm2G7oqdOv4Qj8Z0JrGgMzj46NFKAxkLSpE5oHQYP1H # tPx1lPfD7iNSbJsP6LiUHXH1MIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq # 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 # /Xmfwb1tbWrJUnMTDXpQzTGCGaIwghmeAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAANOtTx6wYRv6ysAAAAAA04wDQYJYIZIAWUDBAIB # BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIEjws4OIo+nso8vP8M0bdkxv # bpddyxBaxNSPaXxgMSr5MEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A # cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB # BQAEggEAQSHcTQEj7KnJvZJ5XdAX9yX3c84XNRWhpbPz0GEjZEdrD4Hsf5Lz/B1y # fWX6x57DeZyPiDAGXClQGv8Y1gqxqKt8oypELcLyGAekvoPbEfOkBPh0IUqLv/XA # rXmS0vea5G5cgDwbO5pqtMsyi2+ajNMGMrf/NWxDO0RHsir+5oU65vTGd2VyY9Aq # kAgz+YjYLVLJKhyyEimurh2bTLMABFEc4lPVS5v+wY4/B2upLOWpSkgHPpvmWR7L # XqKPod5ySgVQww//GdeVvgee3OJPjTJbt8FnyhgVPGRuL59RTRmi9TCRhF00cFFe # 63KX46IdPsRsbjyyUm90fqaoxuPCQaGCFywwghcoBgorBgEEAYI3AwMBMYIXGDCC # FxQGCSqGSIb3DQEHAqCCFwUwghcBAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFZBgsq # hkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl # AwQCAQUABCDDL+HWc+Je7jEYtkj02QsGLUeY6R7D8krcfAzH8uUSLgIGZD/Uapni # GBMyMDIzMDUxMDE3MDExNS45NzNaMASAAgH0oIHYpIHVMIHSMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl # bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO # OjNCRDQtNEI4MC02OUMzMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT # ZXJ2aWNloIIRezCCBycwggUPoAMCAQICEzMAAAG0+4AIRAXSLfoAAQAAAbQwDQYJ # KoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjIw # OTIwMjAyMjA5WhcNMjMxMjE0MjAyMjA5WjCB0jELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3Bl # cmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozQkQ0LTRC # ODAtNjlDMzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCC # AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALRHpp5lBzJCH7zortuyvOmW # 8FoZLBsFe9g5dbhnaq9qSpvpn86E/mJ4JKvWixH/lw7QA8gPtiiGVNIjvFhu/XiY # 889vX5WaQSmyoPMZdj9zvXa5XrkMN05zXzTePkCIIzF6RN7cTxezOyESymTIjrdx # X5BVlZolyQAOxNziMCYKYYNPbYd0786fDE/PhzrRt23a0Xf8trvFa0LEEy2YlcE2 # eqg2CjU/D0GZe8Ra0kjt0M12vdS4qWZ2Dpd7IhiQwnntQWu19Ytd3UBR8SpeRX+C # cw3bjgWfOXtla6chctWt2shlMwayMOfY4TG4yMPWFXELfZFFp7cgpjZNeVsmwkvo # V6RAwy1Y9V+VvbJ5qFtartN/rp6a0I1kGlbjuwX3L0HTVXcikqgHistXk9h3HOZ9 # WgFXlxZurG1SZmcz0BEEdya+1vGHE45KguYU9qq2LiHGBjn9z4+DqnV5tUKobsLb # JMb4r+8st2fj8SacSsftnusxkWqEJiJS34P2uNlzVR03+ls6+ZO0NcO79LgP7BbI # MipiOx8yh19PMQw0piaKFwOW7Q+gdJcfy6rOkG+CrYZwOzdiBHSebIzCIch2cAa+ # 38w7JFP/koKdlJ36qzdVXWv4G/qZpWycIvDKYbxJWM40+z2Stg5uHqK3I8e09kFX # txCHpS7hm8c8m25WaEU5AgMBAAGjggFJMIIBRTAdBgNVHQ4EFgQUy0SF5fGUuDqc # uxIot07eOMwy2X4wHwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYD # VR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j # cmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwG # CCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIw # MjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcD # CDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBABLRDwWMKbeCYqEq # tI6Bs8KmF+kqDR+2G6qYAK3ZZ63bert7pCkRJbihFaktl2o18cdFJFxnOF4vXadm # 0sabskJ05KviEMJIO6dXSq8AGtr3Zmjc895q0mnlBLuNMgk4R8KrkJMHqBuHqkUW # XtfTrVUpgwzQt2UOiINKs+/b4r14MuXRVpOJ6cQOS8UhkeMAWl2iLlYaBGtOr3f/ # f9mLEPfWwoke0sSUbdV60OZCRh1ItBYYM9efKr14H5qu6jan6n00prEEa7W3uGb/ # 1/qj6P5emnvkqy5HI0X69DjVdLxVbjSsegm/dA+S4DaXPcfFf6iBxK/iV21l1upg # EVVajUApl5VR40wY4XF8EpmnUdTqLXDf7CqdhDjPST2K/OjvWPyQGQvc7oPapYyk # 66GU32AOyyHXJj6+vbtRUg/+ory+h0R2Xf5NhC+xbWcMzXEUXRRf1YKZDsRyH6r4 # 12pm8KDKE/r7Rk7aoKK7oYUpNGzNRf6QaYv5z2bVTSxkzWivFrepLHGwvRun9PYM # /8AQSTgZr0yzzjk/97WghkqCaAwAVpyvg3uaYnuCl/AccSkGyb8c+70bFSeUephs # fgb2r+QI7Mb2WcOnkJpCNLz0XJMS/UwlQn1ktLsiCpsqOk3aLJ2wTv6LK3u69I0v # QB/LKRKlZYRXKUDXzoPwr3UtsTVTMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJ # mQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT # Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh # dGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1 # WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEB # BQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxOdcjK # NVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQGOhg # fWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq/XJp # rx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVWTe/d # vI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7mka9 # 7aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De+JKR # Hh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv231fgLrbqn427DZM9itu # qBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEzOUyO # ArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYctenIPDC+hIK12NvDMk2ZItb # oKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6 # bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17aj54WcmnGrnu3tz5q4i6t # AgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQW # BBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacb # UzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYz # aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnku # aHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIA # QwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2 # VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwu # bWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEw # LTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93 # d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYt # MjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3hLB9nATEkW+Geckv8qW/q # XBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6 # U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74py27YP0h1AdkY3m2CDPVt # I1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1AoL8ZthISEV09J+BAljis # 9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTp # kbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0 # sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNtyo4JvbMBV0lUZNlz138e # W0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJ # sWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7 # Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0 # dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lwY1NNje6CbaUFEMFxBmoQ # tB1VM1izoXBm8qGCAtcwggJAAgEBMIIBAKGB2KSB1TCB0jELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxh # bmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjoz # QkQ0LTRCODAtNjlDMzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy # dmljZaIjCgEBMAcGBSsOAwIaAxUAZZzYkPObl/ZzeCkSbf4B5CceCQiggYMwgYCk # fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF # AOgGAIAwIhgPMjAyMzA1MTAxOTM3MzZaGA8yMDIzMDUxMTE5MzczNlowdzA9Bgor # BgEEAYRZCgQBMS8wLTAKAgUA6AYAgAIBADAKAgEAAgIPMgIB/zAHAgEAAgIVPDAK # AgUA6AdSAAIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB # AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAFZq4SXruRd45Yt+ # ofSN7Ol0nzequTa3Jd0g1YYMb7bqLlMeXeC52Ex6OXYPCE5u2JzpsUQ+Ux6BqaZZ # z2MPUaybQP75hnOWobgSBb9VHJ+RCVGzdiZ1PdOEMEdmOMItiz6yZe+tNMECZ3AQ # axhNIVqA5bgu30+WyXBzrAy0MQqLMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp # bWUtU3RhbXAgUENBIDIwMTACEzMAAAG0+4AIRAXSLfoAAQAAAbQwDQYJYIZIAWUD # BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B # CQQxIgQg0iCJtCJmHE0W5Uk1TyghXnuWNzoi9kdaBBhu5ayM54IwgfoGCyqGSIb3 # DQEJEAIvMYHqMIHnMIHkMIG9BCDTyPd75qMwcAZRcb36/6xJa3hT0eLse71ysdp4 # twH3BjCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB # tPuACEQF0i36AAEAAAG0MCIEIHSA/VKCqpY+ZWe8BgcfhCO8stlh60b/CiexrRlN # d/isMA0GCSqGSIb3DQEBCwUABIICADs1Zg4Zz097TDQw4w7nc+Aunz4IPR3V5Ra+ # ZopJvcfyKcsujn6GvXP0JlP6g4XRjDBuyAXh7SBHKO8MY++OH6jlsgA7g+4JSh36 # +goTmEGyX++7mk5K68PFvZZxHEIfJsKEKmTgyqf3UatECqQ+xs2m4+KQ1hEwhCXC # kCj6gtrt91w9AyA3Np1stf/muAHTv1DTOS0ikFl4mrGRzYVxj6fMgox9LgYBobdS # KzR4DyLe/qhqJTaivS26icxGebK8jj8jYLMFVDkvotiVqldy6SSqIasPrqt9rr+u # ppTccV9y0dIP34KLJAEKRzkg6FQgGykKJ2S0RgpNiFWpJsMTz/w05msQpXb1g/Of # OwCq2mIjGkqBTpToSbqwe2kJ0WNh33s8+NpFtvEuf7pOhWPQ4gW43+gaWOYFQDSe # Bd0TEJ63bFRivAaSomUtMxMKArmSfZssUKdjHZcUlsFzYJF2QMLJq09sCMPW5NFD # 4gRfmuQ2+nei3ckAzzX7T0Lr9HX/TuXXiHwyLL0UQjpg48pFTf65/Xz6zpibiadd # lIyx9VjfhcBB3Wo9ajAJw4wmC5XZlkl/uMGGPXYSpDOBBEwoocV1cgwBlfTtCYLW # 7izX4pBwfmjHENmr0oqbYQT4b9AfQJ/mUjiuNvvr6vxiSpkTJckduDHxdBBQgMBi # 34/FoB2W # SIG # End signature block |