Utils.Exported.ps1
<# .Synopsis Get the list of drive letters available for mounting a snapshot. .Description Query the specified ComputerAddress to get a list of available drive letters. This information can be used in the Mount-PsbSnapshotSet cmdlet to mount a snapshot set to those drive letters using the Path parameter. If an available drive letter is in use as a mapped network drive, the drive letter will have to be unmapped from the share before the mounted disk is accessible. .Parameter ComputerAddress The name of the VM. .Parameter ComputerSession The PSSession for the VM. .Example $session = new-pssession Get-PSBAvailableDrive -ComputerAddress $vmName -ComputerSession $session #> function Invoke-GetAvailableDriveOp { Param ( [Parameter(Mandatory = $true)] [string] $ComputerAddress, [Parameter(Mandatory = $true)] [System.Management.Automation.Runspaces.PSSession] $ComputerSession, [parameter(Mandatory = $true)] [string] $FunctionName ) $FreeDriveLetter = SafeInvokeRemote -Session $ComputerSession -ScriptBlock { $Drives = (Get-PSDrive).Name -match '^[a-z]$' $AvailableDrives = @([int][char]'D'..[int][char]'Z' | foreach { if ($Drives -notcontains [char]$_) { [char]$_ + ':' } }) return $AvailableDrives } Write-Log -Level INFO -FunctionName $FunctionName -Msg "Free drive letters: $FreeDriveLetter" return $FreeDriveLetter } <# .Synopsis Connects an imported Lun as Hard Disk to VM hosted on ESXi .Description Connects Lun which is imported using Import-PfaSqlSnap as Hard Disk to VM hosted on ESXi configured as RDM .Parameter VolumeSerials List of Volume serial number of the Lun on Flash Array which is imported. .Parameter VCenterAddress The friendly name of the controlling VCenter previously configured with Add-PfaBackupCred .Parameter VCenterCredential vCenter credentials .Parameter VMName The name of the VM, if the SQL server host is a VM. .Parameter FlashArrayAddress The FlashArray address .Parameter VMPersistentId The PersistentId (also referred to as the InstanceUuid or MoRef) of the VM. .Example Connect-PfaVMHardDisk -VolumeSerials @(AC02BDF1FF541479000122CD) -VMName $VMName -VCenterAddress $VCenterAddress #> function Connect-PfaVMHardDisk { Param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string[]] $VolumeSerials, [Parameter(Mandatory = $true, ParameterSetName= 'VMName')] [ValidateNotNullOrEmpty()] [string] $VMName, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $VCenterAddress, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [pscredential] $VCenterCredential, [Parameter(Mandatory = $true)] $RestClient, [Parameter(Mandatory = $true, ParameterSetName='VMPersistentId')] [Parameter(Mandatory = $false, ParameterSetName='VMName')] [AllowEmptyString()] [string] $VMPersistentId, [Parameter(Mandatory = $false)] [string] $DatastoreName ) $FunctionName = $MyInvocation.MyCommand Write-Log -Level INFO -FunctionName $FunctionName -Msg "Entering with parameter: $(Get-Parameter $MyInvocation)" $EsxiDetails = Get-ESXiDetails -VCenterAddress $VCenterAddress -VCenterCredential $VCenterCredential -VMName $VMName -VMPersistentId $VMPersistentId $ESXiName = $EsxiDetails.ESXiName # Get the current name and Id from the VM we found. # Handles the case where the user supplied just the name or id, # or if they gave both, but the name doesn't coorespond to the Id. if (!$ESXiName) { ThrowErrorCode -ErrorCode $ErrorCode_IdentifyEsxiError -params @($EsxiDetails.VMNameString,$VCenterAddress) } # this function can take a while to rescan storage, we need it so the recently connected volume shows up on the vcenter Get-VMHostStorage -VMHost $ESXiName -RescanAllHba foreach($VolumeSerial in $volumeSerials){ $naaPage83 = Get-NaaPage83 -VolumeSerial $VolumeSerial $ScsiLun = Get-ScsiLun -VmHost $ESXiName | where CanonicalName -eq $naaPage83 #-eq is case insensitive by default if ($null -eq $ScsiLun -or [String]::IsNullOrWhiteSpace($ScsiLun)) { ThrowErrorCode -ErrorCode $ErrorCode_ScsiLunNotFound -params @($ESXiName,$naaPage83) } Write-Log -Level INFO -FunctionName $FunctionName -Msg "ESXi $ESXiName ScssiLun is $($ScsiLun)" $RDMHD = Get-HardDisk -VM $EsxiDetails.VM | where { ($_.PSObject.Properties['ScsiCanonicalName']) -and ($_.ScsiCanonicalName -eq $naaPage83) } if ($RDMHD) { Write-Log -Level WARN -FunctionName $FunctionName -Msg "RDM connection already exists on VM '$($EsxiDetails.VMNameString)' for volume serial $VolumeSerial" } else { Write-Log -Level INFO -FunctionName $FunctionName -Msg "Creating new RDM HD on VM '$($EsxiDetails.VMNameString)' for volume serial $VolumeSerial" if ($DatastoreName) { $Datastore = Get-Datastore $DatastoreName -Server $EsxiDetails.Server -ErrorAction SilentlyContinue # Replication DataStore appear twice if ($DataStore -is [array]) { if ($DataStore.Length -ge 1) { $DataStore = $DataStore[0] } else { $DataStore = $null } } } else { $Datastore = Get-DataStoreFromVolumeCopy -VM $EsxiDetails.VM -VolumeSerial $VolumeSerial -RestClient $RestClient } if ($null -eq $Datastore) { # We failed to get a valid DataStore, throw an error ThrowErrorCode -ErrorCode $ErrorCode_FailedToDetermineDatastore } else { # Verify DatStore type if ($Datastore.Type -ne "VMFS") { ThrowErrorCode -ErrorCode $ErrorCode_WrongDatastoreType -params @($Datastore.name,$Datastore.Type) } $RDMHD = New-HardDisk -VM $EsxiDetails.VM -DiskType RawPhysical -DeviceName $ScsiLun.ConsoleDeviceName -Datastore $Datastore -ErrorAction Stop Write-Log -Level INFO -FunctionName $FunctionName -Msg "Creating new RDM HD on VM '$($EsxiDetails.VMNameString)' for volume serial $VolumeSerial - Done!" } } } } <# .Synopsis Removes a Hard Disk from VM hosted on ESXi .Description Removes a Hard Disk which was previously imported using Import-PfaSqlSnap from VM hosted on ESXi configured as RDM .Parameter VolumeSerial Volume serial number of the Lun on Flash Array which was previously imported. .Parameter VCenterAddress The friendly name of the controlling VCenter previously configured with Add-PfaBackupCred .Parameter VCenterCredential vCenterCredentials .Parameter VMName The name of the VM, if the SQL server host is a VM. .Parameter VMPersistentId The PersistentId (also referred to as the InstanceUuid or MoRef) of the VM. .Example Remove-PfaVMHardDisk -VolumeSerial AC02BDF1FF541479000122CD -VMName $VMName -VCenterAddress $VCenterAddress #> function Remove-PfaVMHardDisk { Param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $VolumeSerial, [Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $VMName, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $VCenterAddress, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [PSCredential] $VCenterCredential, [Parameter(Position=0,mandatory=$false)] [AllowEmptyString()] [string] $VMPersistentId ) $FunctionName = $MyInvocation.MyCommand Write-Log -Level INFO -FunctionName $FunctionName -Msg "Entering with parameter: $(Get-Parameter $MyInvocation)" $naaPage83 = Get-NaaPage83 -VolumeSerial $VolumeSerial $EsxiDetails = Get-ESXiDetails -VCenterAddress $VCenterAddress -VCenterCredential $VCenterCredential -VMName $VMName -VMPersistentId $VMPersistentId $ESXiName = $EsxiDetails.ESXiName $ScsiLun = Get-ScsiLun -VmHost $ESXiName | where CanonicalName -eq $naaPage83 #-eq is case insensitive by default if ($null -eq $ScsiLun -or [String]::IsNullOrWhiteSpace($ScsiLun)) { ThrowErrorCode -ErrorCode $ErrorCode_ScsiLunNotFound -params @($ESXiName,$naaPage83) } Write-Log -Level INFO -FunctionName $FunctionName -Msg "ESXi $ESXiName ScssiLun is $($ScsiLun)" $RDMHD = Get-HardDisk -VM $EsxiDetails.VM | where { ($_.PSObject.Properties['ScsiCanonicalName']) -and ($_.ScsiCanonicalName -eq $naaPage83) } if (-not $RDMHD) { Write-Log -Level INFO -FunctionName $FunctionName -Msg "RDM connection not found VM '$($EsxiDetails.VMNameString)'. for volume serial $VolumeSerial" } else { Write-Log -Level INFO -FunctionName $FunctionName -Msg "Removing RDM HD on VM '$($EsxiDetails.VMNameString)' for volume serial $VolumeSerial" $RDMHD = Remove-HardDisk -HardDisk $RDMHD -DeletePermanently -Confirm:$false Write-Log -Level INFO -FunctionName $FunctionName -Msg "Removing RDM HD on VM '$($EsxiDetails.VMNameString)' for volume serial $VolumeSerial - Done!" } } <# .Synopsis Get VM Persistent ID (or IDs if more than one VM has the same name) from vCenter. The VM friendly name in vCenter, the vCenter hostname, FQDN, or IP Address, and the vCenter credential are required parameters. .Description Get VM Persistent ID (or IDs if more than one VM has the same name) from vCenter. The VM Persistent ID is needed when creating a new volume set (New-PsbVolumeSet) and when invoking a snapshot (Invoke-PsbSnapshotJob) so that operations can succeed even if the VM is renamed in vCenter. .Parameter VCenterAddress The friendly name of the controlling VCenter previously configured with Add-PfaBackupCred .Parameter VCenterCredential The credential for the controlling VCenter previously configured with Add-PfaBackupCred .Parameter VMName VM name in vCenter .Example Get-PSBVMPersistentId -VMName $vmName -VCenterAddress $vCenterEndpoint -VCenterCredential $vCenterCredential #> function Invoke-GetVMPersistentIdOp { Param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $VCenterAddress, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [PSCredential] $VCenterCredential, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $VMName, [parameter(Mandatory = $true)] [string] $FunctionName ) $IDs = @() if (-not (Get-Module -ListAvailable -Name VMware.PowerCLI)) { ThrowErrorCode -ErrorCode $ErrorCode_PowerCLIMissing } Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -DefaultVIServerMode Multiple -Scope Session -Confirm:$false | Out-Null Connect-VIServer -Server $VCenterAddress -Credential $VCenterCredential -ErrorAction Stop | Out-Null $VMs = Get-VM -Server $VCenterAddress -Name $VMName $IDs = foreach ($VM in $VMs) { $VM.PersistentId } Write-Log -Level INFO -FunctionName $FunctionName -Msg "VM(s) Persistent ID: $($IDs -Join ',')" return $IDs } <# .Synopsis Enumerate information about a disk by specifying a drive letter or mount point. .Description Enumerate information about a disk by specifying a drive letter or mount point. Disks that are not supported for Pure Storage snapshots will return a value of Unsupported. VolumeType (physical, rdm, vvol) of a disk must be specified in the backup configuration. .Parameter ComputerAddress The name of the SQL server host machine. .Parameter Path Disk path .Parameter RestClient Client for FlashArray .Parameter VCenterAddress When specified limit searching vCenters to only $VCenterAddress .Parameter VCenterCredential vCenter credentials .Parameter VMName When specified limit searching VMs to only $VMName .Example Get-PfaVerboseDiskInfo -ComputerAddress mycomputer -Path E: Get disk information for drive E: #> function Get-PfaVerboseDiskInfo { param ( [Parameter(Mandatory = $true, ParameterSetName= 'Virtual')] [Parameter(Mandatory = $true, ParameterSetName= 'Physical')] [System.Management.Automation.Runspaces.PSSession] $Session, [Parameter(Mandatory = $true, ParameterSetName= 'Virtual')] [Parameter(Mandatory = $true, ParameterSetName= 'Physical')] [string] $Path, [Parameter(Mandatory = $true, ParameterSetName= 'Virtual')] [Parameter(Mandatory = $true, ParameterSetName= 'Physical')] $RestClient, [Parameter(Mandatory = $true, ParameterSetName= 'Virtual')] [string] $VCenterAddress, [Parameter(Mandatory = $true, ParameterSetName= 'Virtual')] [PSCredential] $VCenterCredential, [Parameter(Mandatory = $true, ParameterSetName= 'Virtual')] [string] $VMName ) $FunctionName = $MyInvocation.MyCommand Write-Log -Level INFO -FunctionName $FunctionName -Msg "Entering with parameter: $(Get-Parameter $MyInvocation)" $result = @{} $FlashArrayAddress = $RestClient.ArrayName $ArrayConnections = @{} if ($RestClient) { # An array name is provided $ArrayConnections[$FlashArrayAddress] = $RestClient } $PathList = $Path.Split(",") foreach ($CurrentPath in $PathList) { $DiskInfo = SafeInvokeRemote -Session $session -ArgumentList $CurrentPath -ScriptBlock { param ( $Path ) $DiskInfo = $null if ($Path.Length -eq 1) { # Drive Letter without : $partitionFromPath = get-partition -DriveLetter $Path -ErrorAction SilentlyContinue } elseif ($Path.Length -eq 2) { if($Path[1] -ne ':'){ ThrowErrorCode -ErrorCode $ErrorCode_InvalidPath -params @($Path) } # Drive Letter $DriveLetter = $Path.Substring(0, $Path.Length - 1) $partitionFromPath = get-partition -DriveLetter $DriveLetter -ErrorAction SilentlyContinue } elseif ($Path.Length -gt 2) { # Mount Point $ResolvedPath = (Resolve-Path -Path $Path).Path if ($ResolvedPath[$ResolvedPath.Length -1] -ne '\') { $ResolvedPath = $ResolvedPath + '\' } $WmiVol = Get-WmiObject win32_volume | Where-Object {$_.Name -eq $ResolvedPath} $CimVol = get-volume | Where-Object {$_.path -eq $WmiVol.DeviceID} $partitionFromPath = get-partition -Volume $CimVol -ErrorAction SilentlyContinue } else { ThrowErrorCode -ErrorCode $ErrorCode_UnsupportedPathFormat -params @($Path) } if(-not $partitionFromPath){ # drive letter/path did not exist ThrowErrorCode -ErrorCode $ErrorCode_InvalidPath -params @($Path) } $DiskInfo = $partitionFromPath | get-disk $partitionsInDisk = $DiskInfo | Get-Partition | where-object {$_.AccessPaths} if($partitionsInDisk.Count -gt 1){ ThrowErrorCode -ErrorCode $ErrorCode_MultiPartitions } return $DiskInfo } $result[$CurrentPath] = FillInDiskInfo -DiskInfo $DiskInfo -restClient $RestClient -VCenterAddress $VCenterAddress -VMName $VMName } return $result } function GetVerboseDiskInfoById { param ( [System.Management.Automation.Runspaces.PSSession] $Session, $RestClient, [string[]] $DiskIds, [string] $VCenterAddress, [PSCredential] $VCenterCredential, [string] $VMName ) $FunctionName = $MyInvocation.MyCommand Write-Log -Level INFO -FunctionName $FunctionName -Msg "Entering with parameter: $(Get-Parameter $MyInvocation)" $result = @{} $FlashArrayAddress = $RestClient.ArrayName $ArrayConnections = @{} if ($RestClient) { # An array name is provided $ArrayConnections[$FlashArrayAddress] = $RestClient } $DisksInfo = SafeInvokeRemote -Session $session -ArgumentList @(,$DiskIds) -ScriptBlock { param($DiskIds) # get disks with serial in diskIds and that have 0 or 1 partitions $DisksInfo = get-disk | Where-object {$DiskIds -contains $_.SerialNumber} return $DisksInfo } foreach ($DiskInfo in $DisksInfo) { $DiskUniqueID = $DiskInfo.UniqueId $result[$DiskUniqueID] = FillInDiskInfo -DiskInfo $DiskInfo -restClient $RestClient -VCenterAddress $VCenterAddress -VMName $VMName $Path = SafeInvokeRemote -Session $session -ArgumentList $DiskInfo -ScriptBlock { param($DiskInfo) $paths = ($DiskInfo | Get-Partition).AccessPaths return $paths | Where-Object {-not ($_ -like "\\?\*")} } if($Path){ $result[$DiskUniqueID]["Path"] = $Path } else{ $result[$DiskUniqueID]["Path"] = "" } } return $result } function CleanupMountByDiskId{ Param( [System.Management.Automation.Runspaces.PSSession] $ComputerSession, $RestClient, [string[]] $DiskIds, [string[]] $newVolumesSerials, [string] $VCenterAddress, [PSCredential] $VCenterCredential, [string] $VMName, [string] $FunctionName ) # unexpose disks on $diskIds $verboseDisk = GetVerboseDiskInfoById -Session $ComputerSession -RestClient $RestClient -DiskIds $diskIds -VCenterAddress $VCenterAddress -VCenterCredential $VCenterCredential -VMName $VMName foreach ($disk in $verboseDisk.Keys){ try{ if( -not ($verboseDisk[$disk]['ArrayVolumeInfo']["VolumeSerial"] -in $newVolumesSerials)){ #it's not one of the mounted volumes continue } if($verboseDisk[$disk]["Path"]){ # unexpose vvol from VM Write-Log -Level INFO -FunctionName $FunctionName -Msg "Unexposing $($verboseDisk[$disk]["Path"])" $success = $success -and (Unexpose-Disks -Session $ComputerSession -Paths $verboseDisk[$disk]["Path"] -VolumeSerialNumbers $diskIds) } if("vVol" -eq $disk["VolumeType"]){ # destroy vvol $disk.VMWareInfo.VMDisk | Remove-HardDisk -DeletePermanently -Confirm:$false } } catch{ Write-Log -Level WARN -FunctionName $FunctionName -Msg "Failed to cleanup $disk" } } } function CleanupMountByVolSerial { Param( $RestClient, [string[]] $newVolumesSerials, [string] $VolumeType, [string] $VCenterAddress, [PSCredential] $VCenterCredential, $MountVM, [string] $FunctionName ) # destroy volumes on $newvolumeSerials foreach ($serial in $newVolumesSerials){ try{ $volume = Get-Pfa2Volume -Array $RestClient -Filter "Serial='$($serial)'" -ErrorAction SilentlyContinue if($volume){ # remove RDM volumes from VM if ("RDM" -ieq $VolumeType) { Remove-PfaVMHardDisk -VolumeSerial $serial -VMName $($MountVM.Name) -VMPersistentId $($MountVM.PersistentId) -VCenterAddress $VCenterAddress -VCenterCredential $VCenterCredential -ErrorAction SilentlyContinue } if ("VVOL" -ieq $VolumeType) { # vvols should be cleaned by the unexpose cmdlet # if vvol still exists it failed the unexpose # we should not delete the vvol manually as it can put the datastore in a bad status # we will log a warning and proceed Write-Log -Level WARN -FunctionName $FunctionName -Msg "vVol [$serial] could not be removed. Please delete disk manually on the vCenter" continue } # remove all host/hostgroup connections Disconnect-VolHosts -volumeName $Volume.Name -RestClient $RestClient # destroy vol Remove-Pfa2Volume -Array $RestClient -Name $Volume.Name } } catch{ Write-Log -Level WARN -FunctionName $FunctionName -Msg "Failed to cleanup $serial" } } } function FillInDiskInfo{ param( $DiskInfo, $restClient, $VCenterAddress, $VMName ) $result = @{ "VolumeType" = "Unsupported"; "ArrayVolumeInfo" = @() ; "ComputerDiskInfo" = $null; "VMWareInfo" = @() } $result["ComputerDiskInfo"] = $DiskInfo $DiskName = $DiskInfo.FriendlyName $DiskUniqueID = $DiskInfo.UniqueId if ($DiskName -like "PURE FlashArray*") { $result["VolumeType"] = "Physical" # Might be Physical or RDM Disk # Search all arrays for Volume with serial nnumber that matches the Disk SerialNumber $volume = Get-Pfa2Volume -Array $RestClient -Filter "Serial='$($DiskInfo.SerialNumber)'" if ($null -ne $volume) { $result['ArrayVolumeInfo'] += @{VolumeName=$volume.Name; ArrayName=$RestClient.ArrayName; "VolumeSerial"=$volume.serial; "VolumeId"=$volume.Id} } else{ # if we didn't find the volume on the array, throw an error ThrowErrorCode -ErrorCode $ErrorCode_VolumesNotFoundOnFA -params @($DiskInfo.SerialNumber) } # Check if RDM. Find HardDisk from vCenter and see if the DiskType is RawPhysical $naaPage83 = "naa.$DiskUniqueID" if ($VCenterAddress) { $VMHardDisk = Get-HardDisk -VM $VMName | Where-Object {($_.PSObject.Properties['ScsiCanonicalName']) -and ($_.ScsiCanonicalName.ToUpper() -eq $naaPage83.ToUpper())} if ($null -ne $VMHardDisk) { $result["VolumeType"] = "RDM" $result["VMWareInfo"] += @{ "VCenterAddress"= $VCenterAddress; "VMName"=$VMName; "VMDisk"=$VMHardDisk } } } } elseif ($DiskName -like "VMWare*") { # Might be vVol or vmfs disk if(-not $VCenterAddress){ ThrowErrorCode -ErrorCode $ErrorCode_InvalidVolType -params @($path,'Physical') } $VMHardDisks = Get-HardDisk -VM $VMName foreach ($vmHardDisk in $vmHardDisks) { if ($null -eq $vmHardDisk.ExtensionData.Backing.uuid) { continue } $vmHardDiskUuid = $vmHardDisk.ExtensionData.Backing.uuid | ForEach-Object {$_.replace(' ','').replace('-','')} if ($vmHardDiskUuid -ieq $DiskUniqueID) { # Get related Array info try { $vvolUUID = Get-PfaVvolUuidFromVmdk -vmdk $vmHardDisk $result["VolumeType"] = "vVol" $result["VMWareInfo"] += @{ "VCenterAddress"= $VCenterAddress; "VMName"=$VMName; "VMDisk"=$VMHardDisk } # Get related Array information try { $volname = Get-PfaVolumeNameFromVvolUuid -vvolUUID $vvolUUID -restClient $restClient if ($null -ne $volname){ $EV = $null # gets the volume info from the array $vol = Get-Pfa2Volume -Name $volname -Array $restClient -ErrorAction SilentlyContinue -ErrorVariable EV # if volume not found on array throw error if ($EV) { ThrowErrorCode -ErrorCode $ErrorCode_VolumesNotFoundOnFA -params @($volname) -innerException $EV.Exception } # if volume found on array add info to the result $result['ArrayVolumeInfo'] += @{VolumeName=$vol.Name; ArrayName=$RestClient.ArrayName; "VolumeSerial"=$vol.Serial; "VolumeId"=$vol.Id} } } catch { $Msg = "Failed to check array $($RestClient.ArrayName)). $($_.Exception.Message)" Write-Log -Level WARN -FunctionName $FunctionName -Msg $Msg } } catch { # Either not a vvol or not a Pure Storage disk continue # Skip this disk } } } if ("Unknown" -eq $result) { # Could not find a matching disk then it must be a non-supported disk $result = "Unsupported" } } else { # Unsupported disk type $result = "Unsupported" } return $result } # SIG # Begin signature block # MIIn+AYJKoZIhvcNAQcCoIIn6TCCJ+UCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU84BIm8Jo0/z/erJvoPOMRINf # VRGggiEoMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B # AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz # 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS # 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7 # bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI # SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH # trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14 # Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2 # h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt # 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR # iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER # ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K # Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd # BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS # y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC # hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS # b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV # HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh # hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO # 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo # 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h # UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x # aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIGrjCCBJag # AwIBAgIQBzY3tyRUfNhHrP0oZipeWzANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQG # EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl # cnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjIw # MzIzMDAwMDAwWhcNMzcwMzIyMjM1OTU5WjBjMQswCQYDVQQGEwJVUzEXMBUGA1UE # ChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQg # UlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMIICIjANBgkqhkiG9w0BAQEF # AAOCAg8AMIICCgKCAgEAxoY1BkmzwT1ySVFVxyUDxPKRN6mXUaHW0oPRnkyibaCw # zIP5WvYRoUQVQl+kiPNo+n3znIkLf50fng8zH1ATCyZzlm34V6gCff1DtITaEfFz # sbPuK4CEiiIY3+vaPcQXf6sZKz5C3GeO6lE98NZW1OcoLevTsbV15x8GZY2UKdPZ # 7Gnf2ZCHRgB720RBidx8ald68Dd5n12sy+iEZLRS8nZH92GDGd1ftFQLIWhuNyG7 # QKxfst5Kfc71ORJn7w6lY2zkpsUdzTYNXNXmG6jBZHRAp8ByxbpOH7G1WE15/teP # c5OsLDnipUjW8LAxE6lXKZYnLvWHpo9OdhVVJnCYJn+gGkcgQ+NDY4B7dW4nJZCY # OjgRs/b2nuY7W+yB3iIU2YIqx5K/oN7jPqJz+ucfWmyU8lKVEStYdEAoq3NDzt9K # oRxrOMUp88qqlnNCaJ+2RrOdOqPVA+C/8KI8ykLcGEh/FDTP0kyr75s9/g64ZCr6 # dSgkQe1CvwWcZklSUPRR8zZJTYsg0ixXNXkrqPNFYLwjjVj33GHek/45wPmyMKVM # 1+mYSlg+0wOI/rOP015LdhJRk8mMDDtbiiKowSYI+RQQEgN9XyO7ZONj4KbhPvbC # dLI/Hgl27KtdRnXiYKNYCQEoAA6EVO7O6V3IXjASvUaetdN2udIOa5kM0jO0zbEC # AwEAAaOCAV0wggFZMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFLoW2W1N # hS9zKXaaL3WMaiCPnshvMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9P # MA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDCDB3BggrBgEFBQcB # AQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggr # BgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1 # c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwIAYDVR0gBBkwFzAI # BgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQB9WY7Ak7Zv # mKlEIgF+ZtbYIULhsBguEE0TzzBTzr8Y+8dQXeJLKftwig2qKWn8acHPHQfpPmDI # 2AvlXFvXbYf6hCAlNDFnzbYSlm/EUExiHQwIgqgWvalWzxVzjQEiJc6VaT9Hd/ty # dBTX/6tPiix6q4XNQ1/tYLaqT5Fmniye4Iqs5f2MvGQmh2ySvZ180HAKfO+ovHVP # ulr3qRCyXen/KFSJ8NWKcXZl2szwcqMj+sAngkSumScbqyQeJsG33irr9p6xeZmB # o1aGqwpFyd/EjaDnmPv7pp1yr8THwcFqcdnGE4AJxLafzYeHJLtPo0m5d2aR8XKc # 6UsCUqc3fpNTrDsdCEkPlM05et3/JWOZJyw9P2un8WbDQc1PtkCbISFA0LcTJM3c # HXg65J6t5TRxktcma+Q4c6umAU+9Pzt4rUyt+8SVe+0KXzM5h0F4ejjpnOHdI/0d # KNPH+ejxmF/7K9h+8kaddSweJywm228Vex4Ziza4k9Tm8heZWcpw8De/mADfIBZP # J/tgZxahZrrdVcA6KYawmKAr7ZVBtzrVFZgxtGIJDwq9gdkT/r+k0fNX2bwE+oLe # Mt8EifAAzV3C+dAjfwAL5HYCJtnwZXZCpimHCUcr5n8apIUP/JiW9lVUKx+A+sDy # Divl1vupL0QVSucTDh3bNzgaoSv27dZ8/DCCBrAwggSYoAMCAQICEAitQLJg0pxM # n17Nqb2TrtkwDQYJKoZIhvcNAQEMBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoT # DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UE # AxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4XDTIxMDQyOTAwMDAwMFoXDTM2 # MDQyODIzNTk1OVowaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ # bmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBS # U0E0MDk2IFNIQTM4NCAyMDIxIENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC # AgoCggIBANW0L0LQKK14t13VOVkbsYhC9TOM6z2Bl3DFu8SFJjCfpI5o2Fz16zQk # B+FLT9N4Q/QX1x7a+dLVZxpSTw6hV/yImcGRzIEDPk1wJGSzjeIIfTR9TIBXEmtD # mpnyxTsf8u/LR1oTpkyzASAl8xDTi7L7CPCK4J0JwGWn+piASTWHPVEZ6JAheEUu # oZ8s4RjCGszF7pNJcEIyj/vG6hzzZWiRok1MghFIUmjeEL0UV13oGBNlxX+yT4Us # SKRWhDXW+S6cqgAV0Tf+GgaUwnzI6hsy5srC9KejAw50pa85tqtgEuPo1rn3MeHc # reQYoNjBI0dHs6EPbqOrbZgGgxu3amct0r1EGpIQgY+wOwnXx5syWsL/amBUi0nB # k+3htFzgb+sm+YzVsvk4EObqzpH1vtP7b5NhNFy8k0UogzYqZihfsHPOiyYlBrKD # 1Fz2FRlM7WLgXjPy6OjsCqewAyuRsjZ5vvetCB51pmXMu+NIUPN3kRr+21CiRshh # WJj1fAIWPIMorTmG7NS3DVPQ+EfmdTCN7DCTdhSmW0tddGFNPxKRdt6/WMtyEClB # 8NXFbSZ2aBFBE1ia3CYrAfSJTVnbeM+BSj5AR1/JgVBzhRAjIVlgimRUwcwhGug4 # GXxmHM14OEUwmU//Y09Mu6oNCFNBfFg9R7P6tuyMMgkCzGw8DFYRAgMBAAGjggFZ # MIIBVTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBRoN+Drtjv4XxGG+/5h # ewiIZfROQjAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8B # Af8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYIKwYBBQUHAQEEazBpMCQG # CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKG # NWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290 # RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNv # bS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMBwGA1UdIAQVMBMwBwYFZ4EMAQMw # CAYGZ4EMAQQBMA0GCSqGSIb3DQEBDAUAA4ICAQA6I0Q9jQh27o+8OpnTVuACGqX4 # SDTzLLbmdGb3lHKxAMqvbDAnExKekESfS/2eo3wm1Te8Ol1IbZXVP0n0J7sWgUVQ # /Zy9toXgdn43ccsi91qqkM/1k2rj6yDR1VB5iJqKisG2vaFIGH7c2IAaERkYzWGZ # gVb2yeN258TkG19D+D6U/3Y5PZ7Umc9K3SjrXyahlVhI1Rr+1yc//ZDRdobdHLBg # XPMNqO7giaG9OeE4Ttpuuzad++UhU1rDyulq8aI+20O4M8hPOBSSmfXdzlRt2V0C # FB9AM3wD4pWywiF1c1LLRtjENByipUuNzW92NyyFPxrOJukYvpAHsEN/lYgggnDw # zMrv/Sk1XB+JOFX3N4qLCaHLC+kxGv8uGVw5ceG+nKcKBtYmZ7eS5k5f3nqsSc8u # pHSSrds8pJyGH+PBVhsrI/+PteqIe3Br5qC6/To/RabE6BaRUotBwEiES5ZNq0RA # 443wFSjO7fEYVgcqLxDEDAhkPDOPriiMPMuPiAsNvzv0zh57ju+168u38HcT5uco # P6wSrqUvImxB+YJcFWbMbA7KxYbD9iYzDAdLoNMHAmpqQDBISzSoUSC7rRuFCOJZ # DW3KBVAr6kocnqX9oKcfBnTn8tZSkP2vhUgh+Vc7tJwD7YZF9LRhbr9o4iZghurI # r6n+lB3nYxs6hlZ4TjCCBsIwggSqoAMCAQICEAVEr/OUnQg5pr/bP1/lYRYwDQYJ # KoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ # bmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2 # IFRpbWVTdGFtcGluZyBDQTAeFw0yMzA3MTQwMDAwMDBaFw0zNDEwMTMyMzU5NTla # MEgxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEgMB4GA1UE # AxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjMwggIiMA0GCSqGSIb3DQEBAQUAA4IC # DwAwggIKAoICAQCjU0WHHYOOW6w+VLMj4M+f1+XS512hDgncL0ijl3o7Kpxn3GIV # WMGpkxGnzaqyat0QKYoeYmNp01icNXG/OpfrlFCPHCDqx5o7L5Zm42nnaf5bw9Yr # IBzBl5S0pVCB8s/LB6YwaMqDQtr8fwkklKSCGtpqutg7yl3eGRiF+0XqDWFsnf5x # XsQGmjzwxS55DxtmUuPI1j5f2kPThPXQx/ZILV5FdZZ1/t0QoRuDwbjmUpW1R9d4 # KTlr4HhZl+NEK0rVlc7vCBfqgmRN/yPjyobutKQhZHDr1eWg2mOzLukF7qr2JPUd # vJscsrdf3/Dudn0xmWVHVZ1KJC+sK5e+n+T9e3M+Mu5SNPvUu+vUoCw0m+PebmQZ # BzcBkQ8ctVHNqkxmg4hoYru8QRt4GW3k2Q/gWEH72LEs4VGvtK0VBhTqYggT02ke # fGRNnQ/fztFejKqrUBXJs8q818Q7aESjpTtC/XN97t0K/3k0EH6mXApYTAA+hWl1 # x4Nk1nXNjxJ2VqUk+tfEayG66B80mC866msBsPf7Kobse1I4qZgJoXGybHGvPrhv # ltXhEBP+YUcKjP7wtsfVx95sJPC/QoLKoHE9nJKTBLRpcCcNT7e1NtHJXwikcKPs # CvERLmTgyyIryvEoEyFJUX4GZtM7vvrrkTjYUQfKlLfiUKHzOtOKg8tAewIDAQAB # o4IBizCCAYcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/ # BAwwCgYIKwYBBQUHAwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcB # MB8GA1UdIwQYMBaAFLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQWBBSltu8T # 5+/N0GSh1VapZTGj3tXjSTBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsMy5k # aWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0 # YW1waW5nQ0EuY3JsMIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcwAYYYaHR0 # cDovL29jc3AuZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8vY2FjZXJ0 # cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGlt # ZVN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCBGtbeoKm1mBe8cI1P # ijxonNgl/8ss5M3qXSKS7IwiAqm4z4Co2efjxe0mgopxLxjdTrbebNfhYJwr7e09 # SI64a7p8Xb3CYTdoSXej65CqEtcnhfOOHpLawkA4n13IoC4leCWdKgV6hCmYtld5 # j9smViuw86e9NwzYmHZPVrlSwradOKmB521BXIxp0bkrxMZ7z5z6eOKTGnaiaXXT # UOREEr4gDZ6pRND45Ul3CFohxbTPmJUaVLq5vMFpGbrPFvKDNzRusEEm3d5al08z # jdSNd311RaGlWCZqA0Xe2VC1UIyvVr1MxeFGxSjTredDAHDezJieGYkD6tSRN+9N # UvPJYCHEVkft2hFLjDLDiOZY4rbbPvlfsELWj+MXkdGqwFXjhr+sJyxB0JozSqg2 # 1Llyln6XeThIX8rC3D0y33XWNmdaifj2p8flTzU8AL2+nCpseQHc2kTmOt44Owde # OVj0fHMxVaCAEcsUDH6uvP6k63llqmjWIso765qCNVcoFstp8jKastLYOrixRoZr # uhf9xHdsFWyuq69zOuhJRrfVf8y2OMDY7Bz1tqG4QyzfTkx9HmhwwHcK1ALgXGC7 # KP845VJa1qwXIiNO9OzTF/tQa/8Hdx9xl0RBybhG02wyfFgvZ0dl5Rtztpn5aywG # Ru9BHvDwX+Db2a2QgESvgBBBijCCB2cwggVPoAMCAQICEATd+82EVAN2YngfhA+f # z/UwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lD # ZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2ln # bmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENBMTAeFw0yMzEwMDQwMDAwMDBaFw0y # NjExMTUyMzU5NTlaMG8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MREwDwYDVQQHEwhCZWxsZXZ1ZTEbMBkGA1UEChMSUHVyZSBTdG9yYWdlLCBJbmMu # MRswGQYDVQQDExJQdXJlIFN0b3JhZ2UsIEluYy4wggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQCdhXqOLFS3HR5KD2RtAOzGdwKU0mMGGHfU7qUo1YFvDCN8 # vF/X8LDhouGtsZPdIfd298orsXHfXYElTgBo91gba7SqKBWi9xdXTqMR5vpt41K/ # a554AgiQp02nfYwuspZoAGnt//mDJ6ErP1jUFiWuwHsYsxk0gFEayp5xIKzmj3q4 # 9g+AenKpktbDn6HPpXZPdvg+g+GR9lPpiJo7Z40SIqzaacJsVcl5MhPfbFdLeP1s # n0MBW3BiYLyz4CEUq8IA2vJ2557N0uB0UzWERE31brL0mBn5gB1g8Zij9VsI9J5+ # Q+THKYIgwknlnXFiSwQhQbJ3Cn7IVotei1M/D011XjUR66kNHm02VVDsbxX92xLf # qIX7BZ0e6shMsOFVakkdM00nXhfRscDkRqEQ+IwgC3vcyJgp/QRX0SfWaaD5G0fi # ECMBZtmq5hijTJ18MAW2KaFePW0PIn9IRnoXS3tx9coXVJMTFwnLYdIukelF4jIW # 779IP5lQH7IBNHS01BgysjWVaQhPYxWZYtsxyRUX3gVRjFChhOtBNCAy2S+YYjUS # TOM7CdUNTtCARX/HgcRYxxU7UTOYXPYyabdQu3mFF8yD5YNkarlgc4TQ+H1PWnIU # l7pq3P0ZSaE5Est24ApVi6wlZC/Q3jQRKPziRg8x7Zv1TZX8TfxPDmE0Nsd+BwID # AQABo4ICAzCCAf8wHwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHQYD # VR0OBBYEFCvH/lBQxrVtiuuihv+e6+2VgDPXMD4GA1UdIAQ3MDUwMwYGZ4EMAQQB # MCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAOBgNV # HQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwgbUGA1UdHwSBrTCBqjBT # oFGgT4ZNaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0 # Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcmwwU6BRoE+GTWh0dHA6 # Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5n # UlNBNDA5NlNIQTM4NDIwMjFDQTEuY3JsMIGUBggrBgEFBQcBAQSBhzCBhDAkBggr # BgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFwGCCsGAQUFBzAChlBo # dHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2Rl # U2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNydDAJBgNVHRMEAjAAMA0GCSqG # SIb3DQEBCwUAA4ICAQCrjkZxw1B2w/pYu4siB36x5J9Xate13IDt57bxZvc7OGgz # limeUq1/HObzW4Vej9tESBpT6a5FBuVSXQXvYQntQczEFBBksRXyad3tx5/xElHA # LaE6BCZUtPKu3/CSrgsvVi7OgWNybOFWF2Xk9K1djImG55J7jOY+8ZKegUSlHPjB # 8HF9G4VdS85L2SuFaRzOMTEIW+h0Ihkp6Js1rbe0YLZu/ad6VWFKoX++FDg3cbM8 # FLf482p+XCmuX/qZuFmySYDQQ4jvNiecEiyZ4m6HUryx9Fagc0NBADiOJc1R2p2I # QbBasyndhn8KWlGSudJ+uCfuzD6ukGVe4kOpYlqkzVeOscetaY0/5v+896yP4FA8 # NS68I2eMuKbis2ouOIrAVkNPdymBjaEW1U6q979upeEG22UjjrRkq5qSdO+nk2tK # NL1ZIc92bqIs132yuwVZ6A7Dvez03VSitT2UVBMz0BKNy1EnZ4hjqBrApU+Bbcwc # 7nPV9hKKbEFKCcCNLpkAP8SCVX6r7qMyqYhAl+XKSfCkMpxRD2LykRup5mz54cQP # RPoy86iVhFhWUez1O3t371sgYulMuxaff5mXK3xlzYZUHpJGkOYntQ2VlqUpl/VO # KcNTXWnuPOyuUZY0b9tWU0Ofs8Imp7+lULJ7XUbrJoY1bUa22ce912PVBsWOojGC # BjowggY2AgEBMH0waTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ # bmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBS # U0E0MDk2IFNIQTM4NCAyMDIxIENBMQIQBN37zYRUA3ZieB+ED5/P9TAJBgUrDgMC # GgUAoHAwEAYKKwYBBAGCNwIBDDECMAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcC # AQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYE # FJ6MilDlc6e6seYigtp6wO/V9EMbMA0GCSqGSIb3DQEBAQUABIICAHdLRr24qt4l # zw9PzzahHQhZTYuPqZKYvYnHz+8Zi463pW4fkNCQTFPa65mDOl1Euq8MgYHf2vH4 # 8/8L5uUn3d5C4tbBKu55afopKxdrRkpjN16/lvsEBu+BGILy8NBnCjh+msmUP0Wi # KqVRwFG0rKG9HrcV4sdkKLBtpOY+V2qlREjIL5KdtIcjrCPK+NuBhIsaLovV1V66 # e7bA8hQnFUYw9Is64F22BYh98fY6JMANKd4954Qe7wy+nj10gIk7fWKPS1TEVgGk # +J60DCVkKNfTfKHWY4yOife++yyPlxAvhnWrtvo7qgNaznHyyS9Sr9zEN44H105I # 4AveZE5Y0Vaad/ftQJk0/Xw/Bgb7rNPgziVRivpZGqUIDm7M1NOtyVtma+308y/t # Nkmg/sUa/vQ4PdyYwvwPPioTSzbCICddjChAwRTOHM2fjVV1yvLpDEDbVHW6xuQP # gAzukmJe44DliMsZQwBc39q7yFj45G6LWyRNg12N0v/Y4g1/xKlC1AghaH6RduiW # ynrIYoehCMRvPylk7YrwUAb7hA7B7c1SaUeP28w9/4aPTEdnYA5Pn3aIwpppQsy2 # anSlSfAdzZx8G9jr8VPEhaflhbuHFKAspTE2mQ85T6s5kWFokQTWIXGFkMhiMdgP # DI++5YrQFo/uAcoo0s+rYZApawWqqHZmoYIDIDCCAxwGCSqGSIb3DQEJBjGCAw0w # ggMJAgEBMHcwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMu # MTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRp # bWVTdGFtcGluZyBDQQIQBUSv85SdCDmmv9s/X+VhFjANBglghkgBZQMEAgEFAKBp # MBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTIzMTEx # MDAwMjY0OFowLwYJKoZIhvcNAQkEMSIEIHFF0bA5A1lh5CIML8h4ziqsTlAVKinT # mmxiAALmmu62MA0GCSqGSIb3DQEBAQUABIICAGS4ddJHBs6cciNBhrsqiJPPkn/s # NYJ3LaQXJjOlN2mkRM1T7ihkqyveHLPDM/h8FWL+qWWijKpD5F95oT4KrDQWOnPn # W84GPm8TkIObQmLkAtrTi5nyKl2LlovTQT/AkrPGQACqhWEXKzfcGL80KvDgiEGz # kOe0EGV/LWJxTPbNXQ5TgaytsTJuuJFleffuajin1/Fbdw4mhztCQXygWmBRp77D # Ji/VHF6uUy2adhuPAOc3UxIDQPIz8HkIRgQ5ntneLLEySioyVXtCyFI9S+tnl2hE # 8xU+lYm+BQjHfZYo0Kie4j0KlD1BSV3/+Fy3lGvXXeOx/21zm9lTDVmRnWwxT1zz # WogSVtLYEBo7/rBVB1wH6yh6P/XwBrrw8tILoqliRcAnJjGolZjUPuwwvHTh1+nZ # sz6VJ8TaWwyxAvGJIuau9KcJ1CiH3crEsp5B6p3Nc7LEadiRlQ+5HsCjRn4J5tfa # 3odxavsfeFL95dN6iqiaKTgQwmUyr36qPV/AERFEL55dDT4y3aKqybBJEL+XVmmx # i+k3yp37MVDSAAgP/09wgV3KNLUUUgYXJ4t8IQKJj1WANIf2KWPgK/FTD/1KcPwO # vIjZyetiFW0Z56AvKvVNDG/roNkbfI/0JwWDJrumeaB2whDUjaULcowAMPGb9P1l # WIqetBz8TWFnkFxU # SIG # End signature block |