PureStorage.CBS.AVS.psm1
. $PSScriptRoot/PureStorage.CommonUtil.ps1 . $PSScriptRoot/PureStorage.RunCommandLauncher.ps1 . $PSScriptRoot/PureStorage.CBS.AVS.VMFS.ps1 . $PSScriptRoot/PureStorage.CBS.AVS.Configuration.ps1 function Build-PCBSCluster { <# .SYNOPSIS Build or update settings for a cluster of ESXi servers .DESCRIPTION Build or update settings for a cluster of ESXi servers. Creates a hostgroup in Pure Cloud Block Store if it does not exists and updates iSCSI settings. Can be used when creating a new cluster or when adding hosts to a cluster. .PARAMETER ClusterName Cluster name .PARAMETER PureCloudBlockStoreConnection Pure Cloud Block Store Connection. The connection can be created using Connect-Pf2Array cmdlet .PARAMETER PureCloudBlockStoreCredential Pure Cloud Block Store Credentials .PARAMETER vCenterServer vCenter Server. If not provided, default vCenter server will be used .PARAMETER AVSCloudName AVS cloud name .PARAMETER AzureSubscriptionId Azure subscription Id. If not provided, default subscription will be used .PARAMETER AVSResourceGroup AVS ResourceGroup .EXAMPLE Build-PCBSCluster -ClusterName "mycluster" -PureCloudBlockStoreConnection $CBSConnection ` -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup #> [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [String]$ClusterName, [Parameter(Mandatory=$false)] $PureCloudBlockStoreConnection, [Parameter(Mandatory=$false)] $vCenterServer, [Parameter(Mandatory=$false)] [String]$AVSCloudName, [Parameter(Mandatory=$false)] [String]$AzureSubscriptionId, [Parameter(Mandatory=$false)] [String]$AVSResourceGroup ) Test-vCenterConnection -vCenterServer $vCenterServer $cluster = Get-Cluster -Name $ClusterName if (-not $cluster) { throw "Could not find cluster '$ClusterName'..." } $fa = Connect-PureCloudBlockStore -PureCloudBlockStoreConnection $PureCloudBlockStoreConnection $updated_hosts = New-PCBSHostGroupfromVcCluster -FlashArray $fa -Cluster $cluster ` -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup Remove-PCBSUnusedHosts -FlashArray $fa -Cluster $cluster | Out-Null $ethList = (Get-Pfa2NetworkInterface -Array $FlashArray | Where-Object {$_.services -eq "iscsi"} | Where-Object {$_.enabled -eq $true} | Where-Object {$null -ne $_.Eth.address}).Eth $ISCSIAddressList = @() foreach ($eth in $ethList) { $ISCSIAddressList += $eth.address } $params = @{ ClusterName = $ClusterName # Need to join the list as string as RunCommand does not support array type ISCSIAddress = $ISCSIAddressList -join "," } Invoke-RunScript -CmdletName "Remove-VMHostStaticiSCSITargets" -Parameters $params ` -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup } function New-PCBSVmfsDatastore { <# .SYNOPSIS Creates a new VMFS datastore and mounts to a VMware cluster .DESCRIPTION Creates a new VMFS datastore and mounts to a VMware cluster .PARAMETER ClusterName Cluster name .PARAMETER DatastoreName Datastore name .PARAMETER Size Datastore capacity size in bytes .PARAMETER PureCloudBlockStoreConnection Pure Cloud Block Store Connection. The connection can be created using Connect-Pf2Array cmdlet .PARAMETER vCenterServer vCenter Server. If not provided, default vCenter server will be used .PARAMETER AVSCloudName AVS cloud name .PARAMETER AzureSubscriptionId Azure subscription Id. If not provided, default subscription will be used .PARAMETER AVSResourceGroup AVS ResourceGroup .EXAMPLE New-PCBSVmfsDatastore -ClusterName myClusterName -PureCloudBlockStoreConnection $CBSConnection -DatastoreName MyVMFSStore -Size 4GB ` -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup Create a datastore "MyVMFS" #> [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [String]$ClusterName, [Parameter(Mandatory=$true)] [String]$DatastoreName, [Parameter(Mandatory=$true)] [UInt64]$Size, [Parameter(Mandatory=$false)] $PureCloudBlockStoreConnection, [Parameter(Mandatory=$false)] $vCenterServer, [Parameter(Mandatory=$false)] [String]$AVSCloudName, [Parameter(Mandatory=$false)] [String]$AzureSubscriptionId, [Parameter(Mandatory=$false)] [String]$AVSResourceGroup ) Test-vCenterConnection -vCenterServer $vCenterServer $Cluster = Get-Cluster -Name $ClusterName -ErrorAction Ignore if (-not $Cluster) { throw "Cluster $ClusterName does not exist." } $fa = Connect-PureCloudBlockStore -PureCloudBlockStoreConnection $PureCloudBlockStoreConnection New-PfaVmfs -Cluster $Cluster -Flasharray $fa -Name $DatastoreName -Size $Size ` -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup } function Restore-PCBSVmfsDatastore { <# .SYNOPSIS Mounts a copy of a VMFS datastore to a VMware cluster from a Pure Cloud Block Store snapshot. .DESCRIPTION Takes in a snapshot name, the corresponding Pure Cloud Block Store, and a cluster. The VMFS copy will be resignatured and mounted. .PARAMETER ClusterName Cluster name .PARAMETER VolumeSnapshotName Volume snapshot name .PARAMETER VolumeName Volume name .PARAMETER PureCloudBlockStoreConnection Pure Cloud Block Store Connection. The connection can be created using Connect-Pf2Array cmdlet .PARAMETER DatastoreName Datastore name .PARAMETER vCenterServer vCenter Server. If not provided, default vCenter server will be used .PARAMETER AVSCloudName AVS cloud name .PARAMETER AzureSubscriptionId Azure subscription Id. If not provided, default subscription will be used .PARAMETER AVSResourceGroup AVS ResourceGroup .EXAMPLE Restore-PCBSVmfsDatastore -ClusterName myClusterName -VolumeSnapshotName mySnapshotName -PureCloudBlockStoreConnection $CBSConnection ` -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup Takes in a snapshot name, the corresponding Pure Cloud Block Store, and a cluster. The VMFS copy will be resignatured and mounted. .EXAMPLE Restore-PCBSVmfsDatastore -ClusterName myClusterName -VolumeName myVolumeName -PureCloudBlockStoreConnection $CBSConnection ` -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup Takes in a volume name, the corresponding Pure Cloud Block Store, and a cluster. The VMFS copy will be resignatured and mounted. #> [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [String]$ClusterName, [Parameter(Mandatory = $true, ParameterSetName = 'VolumeSnapshot')] [String]$VolumeSnapshotName, [Parameter(Mandatory = $true, ParameterSetName = 'Volume')] [String]$VolumeName, [Parameter(Mandatory=$false)] $PureCloudBlockStoreConnection, [Parameter(Mandatory=$false)] $vCenterServer, [Parameter(Mandatory=$false)] [String]$AVSCloudName, [Parameter(Mandatory=$false)] [String]$AzureSubscriptionId, [Parameter(Mandatory=$false)] [String]$AVSResourceGroup ) Test-vCenterConnection -vCenterServer $vCenterServer $fa = Connect-PureCloudBlockStore -PureCloudBlockStoreConnection $PureCloudBlockStoreConnection $VolumesForRestore = @() switch ($PSCmdlet.ParameterSetName) { 'Volume' { Write-Host "Creating datastore from volume..." $VolumesForRestore += Get-Pfa2Volume -Array $fa -Name $VolumeName $NewDatastoreName = Restore-PfaVmfs -FlashArray $fa -ClusterName $ClusterName -Volumes $VolumesForRestore ` -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup break } 'VolumeSnapshot' { Write-Host "Creating datastore from volume snapshot..." $VolumesForRestore += New-VolumeFromSnaspshot -FlashArray $fa -SnapshotName $VolumeSnapshotName try { $NewDatastoreName = Restore-PfaVmfs -FlashArray $fa -ClusterName $ClusterName -Volumes $VolumesForRestore ` -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup } catch { foreach ($Volume in $VolumesForRestore) { Remove-Pfa2Connection -Array $FlashArray -HostgroupNames $hostGroup.name -VolumeNames $Volume.name -ErrorAction SilentlyContinue Remove-Pfa2Volume -Array $FlashArray -Name $Volume.name -Confirm:$false -ErrorAction SilentlyContinue Remove-Pfa2Volume -Array $FlashArray -Name $Volume.name -Eradicate -Confirm:$false -ErrorAction SilentlyContinue throw } } break } } return $NewDatastoreName } function Remove-PCBSVmfsDatastore { <# .SYNOPSIS Detaches and unmount a VMFS datastore from a cluster. Remove the datastore from the host group .DESCRIPTION Detaches and unmount a VMFS datastore from a cluster. Remove the datastore from the host group. The connection configured for the volume and cluster host/host group will be removed from Pure Cloud Block Store. The volume will be destroyed if there is no other connection left. .PARAMETER ClusterName Cluster name .PARAMETER DatastoreName Datastore name .PARAMETER PureCloudBlockStoreConnection Pure Cloud Block Store Connection. The connection can be created using Connect-Pf2Array cmdlet .PARAMETER vCenterServer vCenter Server. If not provided, default vCenter server will be used .PARAMETER AVSCloudName AVS cloud name .PARAMETER AzureSubscriptionId Azure subscription Id. If not provided, default subscription will be used .PARAMETER AVSResourceGroup AVS ResourceGroup .EXAMPLE Remove-PCBSVmfsDatastore -ClusterName "mycluster" -DatastoreName "myDatastore" PureCloudBlockStoreConnection $CBSConnection ` -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup Takes in a datastore name, datastore would be removed. #> [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [String]$ClusterName, [Parameter(Mandatory=$true)] [String]$DatastoreName, [Parameter(Mandatory=$false)] $PureCloudBlockStoreConnection, [Parameter(Mandatory=$false)] $vCenterServer, [Parameter(Mandatory=$false)] [String]$AVSCloudName, [Parameter(Mandatory=$false)] [String]$AzureSubscriptionId, [Parameter(Mandatory=$false)] [String]$AVSResourceGroup ) Test-vCenterConnection -vCenterServer $vCenterServer $FlashArray = Connect-PureCloudBlockStore -PureCloudBlockStoreConnection $PureCloudBlockStoreConnection Remove-PfaVmfsDatastore -ClusterName $ClusterName -DatastoreName $DataStoreName -FlashArray $FlashArray ` -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup } function Set-PCBSVmfsCapacity { <# .SYNOPSIS Increase the size of a Pure Cloud Block Store-based VMFS datastore. .DESCRIPTION Takes in a datastore, the corresponding Pure Cloud Block Store, and a new size. Both the volume and the VMFS will be grown. .PARAMETER ClusterName Cluster name .PARAMETER DatastoreName Datastore name .PARAMETER Size New datastore capacity size in bytes .PARAMETER PureCloudBlockStoreConnection Pure Cloud Block Store Connection. The connection can be created using Connect-Pf2Array cmdlet .PARAMETER vCenterServer vCenter Server. If not provided, default vCenter server will be used .PARAMETER AVSCloudName AVS cloud name .PARAMETER AzureSubscriptionId Azure subscription Id. If not provided, default subscription will be used .PARAMETER AVSResourceGroup AVS ResourceGroup .EXAMPLE Set-PCBSVmfsCapacity -ClusterName "mycluster" -DatastoreName myDatastore -Size 3GB -PureCloudBlockStoreConnection $CBSConnection ` -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup Expand size of the datastore myDatastore to 3GB. #> [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [String]$ClusterName, [Parameter(Mandatory=$true)] [string]$DatastoreName, [Parameter(Mandatory=$true)] [UInt64]$Size, [Parameter(Mandatory=$false)] $PureCloudBlockStoreConnection, [Parameter(Mandatory=$false)] $vCenterServer, [Parameter(Mandatory=$false)] [String]$AVSCloudName, [Parameter(Mandatory=$false)] [String]$AzureSubscriptionId, [Parameter(Mandatory=$false)] [String]$AVSResourceGroup ) Test-vCenterConnection -vCenterServer $vCenterServer $FlashArray = Connect-PureCloudBlockStore -PureCloudBlockStoreConnection $PureCloudBlockStoreConnection $Cluster = Get-Cluster -Name $ClusterName -ErrorAction Ignore if (-not $Cluster) { throw "Cluster $ClusterName does not exist." } Set-PfaVmfsCapacity -ClusterName $ClusterName -FlashArray $FlashArray -DatastoreName $DatastoreName -SizeInByte $Size ` -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup } Export-ModuleMember -Function Build-PCBSCluster Export-ModuleMember -Function New-PCBSVmfsDatastore Export-ModuleMember -Function Restore-PCBSVmfsDatastore Export-ModuleMember -Function Remove-PCBSVmfsDatastore Export-ModuleMember -Function Set-PCBSVmfsCapacity # SIG # Begin signature block # MIIjUAYJKoZIhvcNAQcCoIIjQTCCIz0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUCZrbQfugYf6PZ4+x2CLi7eXX # Om2ggh12MIIFMDCCBBigAwIBAgIQBAkYG1/Vu2Z1U0O1b5VQCDANBgkqhkiG9w0B # AQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAwWhcNMjgxMDIyMTIwMDAwWjByMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQg # Q29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA # +NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/5aid2zLXcep2nQUut4/6kkPApfmJ # 1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH03sjlOSRI5aQd4L5oYQjZhJUM1B0 # sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxKhwjfDPXiTWAYvqrEsq5wMWYzcT6s # cKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr/mzLfnQ5Ng2Q7+S1TqSp6moKq4Tz # rGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi6CxR93O8vYWxYoNzQYIH5DiLanMg # 0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCCAckwEgYDVR0TAQH/BAgwBgEB/wIB # ADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMweQYIKwYBBQUH # AQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYI # KwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFz # c3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmw0 # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaG # NGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RD # QS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0 # dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYIYIZIAYb9bAMwHQYDVR0OBBYE # FFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6en # IZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+7A1aJLPzItEVyCx8JSl2qB1dHC06 # GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbRknUPUbRupY5a4l4kgU4QpO4/cY5j # DhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7uq+1UcKNJK4kxscnKqEpKBo6cSgC # PC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7qPjFEmifz0DLQESlE/DmZAwlCEIy # sjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPas7CM1ekN3fYBIM6ZMWM9CBoYs4Gb # T8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR6mhsRDKyZqHnGKSaZFHvMIIFNzCC # BB+gAwIBAgIQC4jZOitkx57ksuMgsWXX0jANBgkqhkiG9w0BAQsFADByMQswCQYD # VQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGln # aWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgQ29k # ZSBTaWduaW5nIENBMB4XDTIwMDczMDAwMDAwMFoXDTIzMTAwNDEyMDAwMFowdDEL # MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50 # YWluIFZpZXcxGzAZBgNVBAoTElB1cmUgU3RvcmFnZSwgSW5jLjEbMBkGA1UEAxMS # UHVyZSBTdG9yYWdlLCBJbmMuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC # AQEA6nefE6+A0nNMY82xtkQb+akwI0oxLqEbRY65bE4re+CVQV2xP89/7FIAXooq # jxNOvrtWicWTGOZjBdAFEXXAUEyu9CkWFOXGLV3/QkcEfY3e3Z3jypa6h1EznSEp # 3wSQEIVbigi6jR2s7NDnDoSDAKnzcGcSZ8Nz7akXFrN8PAmg3gy8a/rwm2Ko7ClR # ZUHj1C/OMPXUqiN0Q4FyAsaeFmvg2PX2twxo192WRdNro1dkKNfmDvym2ss6MXcq # gFEjBcZtHDv3e/i0BjT24Jm1C27IVYZzVf28dqmVfPo7l8bLEHsVKgrRf0VzS2wI # R08gXiMrohf9tv3AbvtPk7ZaawIDAQABo4IBxTCCAcEwHwYDVR0jBBgwFoAUWsS5 # eyoKo6XqcQPAYPkt9mV1DlgwHQYDVR0OBBYEFJOwFn7S4Lj6QdNnH6tpm3FMFWJI # MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzB3BgNVHR8EcDBu # MDWgM6Axhi9odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNz # LWcxLmNybDA1oDOgMYYvaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNz # dXJlZC1jcy1nMS5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAwEwKjAoBggrBgEF # BQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBBAEwgYQG # CCsGAQUFBwEBBHgwdjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQu # Y29tME4GCCsGAQUFBzAChkJodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGln # aUNlcnRTSEEyQXNzdXJlZElEQ29kZVNpZ25pbmdDQS5jcnQwDAYDVR0TAQH/BAIw # ADANBgkqhkiG9w0BAQsFAAOCAQEAMVAa7mXxhBHf0dTzf6LKDncN8KnzB59KBvd0 # KvXZc6FoLHGi2Wg6XBSP+9mdDMMYOkohqstSk7RD+reT8xiptrIkSMcVcTog1Z3e # JjYTK8B7QsSpuu2lo0RWA5rdvqMJ+lVzbbjteTq+uicP4T/EDwv2q+iPAgpXQD8y # r084ExDWJtMfhvy0cxh555xx88rvFWOhJnXYiFtjaO9dp7f2TnZRJ44rmB98jc9E # BR/8GLOi/BhyPiiU4nBv8JIHVP1E5zIt8/9PhfpenmiWBbuuP0YLnzrqRhswtJaq # jJirYNLYojmINrbvdcpEKGK1AitsnuOjFadLI7bc696Y35lUATCCBY0wggR1oAMC # AQICEA6bGI750C3n79tQ4ghAGFowDQYJKoZIhvcNAQEMBQAwZTELMAkGA1UEBhMC # VVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0 # LmNvbTEkMCIGA1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTIy # MDgwMTAwMDAwMFoXDTMxMTEwOTIzNTk1OVowYjELMAkGA1UEBhMCVVMxFTATBgNV # BAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8G # A1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MIICIjANBgkqhkiG9w0BAQEF # AAOCAg8AMIICCgKCAgEAv+aQc2jeu+RdSjwwIjBpM+zCpyUuySE98orYWcLhKac9 # WKt2ms2uexuEDcQwH/MbpDgW61bGl20dq7J58soR0uRf1gU8Ug9SH8aeFaV+vp+p # VxZZVXKvaJNwwrK6dZlqczKU0RBEEC7fgvMHhOZ0O21x4i0MG+4g1ckgHWMpLc7s # Xk7Ik/ghYZs06wXGXuxbGrzryc/NrDRAX7F6Zu53yEioZldXn1RYjgwrt0+nMNlW # 7sp7XeOtyU9e5TXnMcvak17cjo+A2raRmECQecN4x7axxLVqGDgDEI3Y1DekLgV9 # iPWCPhCRcKtVgkEy19sEcypukQF8IUzUvK4bA3VdeGbZOjFEmjNAvwjXWkmkwuap # oGfdpCe8oU85tRFYF/ckXEaPZPfBaYh2mHY9WV1CdoeJl2l6SPDgohIbZpp0yt5L # HucOY67m1O+SkjqePdwA5EUlibaaRBkrfsCUtNJhbesz2cXfSwQAzH0clcOP9yGy # shG3u3/y1YxwLEFgqrFjGESVGnZifvaAsPvoZKYz0YkH4b235kOkGLimdwHhD5QM # IR2yVCkliWzlDlJRR3S+Jqy2QXXeeqxfjT/JvNNBERJb5RBQ6zHFynIWIgnffEx1 # P2PsIV/EIFFrb7GrhotPwtZFX50g/KEexcCPorF+CiaZ9eRpL5gdLfXZqbId5RsC # AwEAAaOCATowggE2MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOzX44LScV1k # TN8uZz/nupiuHA9PMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA4G # A1UdDwEB/wQEAwIBhjB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6 # Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMu # ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDBFBgNVHR8E # PjA8MDqgOKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1 # cmVkSURSb290Q0EuY3JsMBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQwF # AAOCAQEAcKC/Q1xV5zhfoKN0Gz22Ftf3v1cHvZqsoYcs7IVeqRq7IviHGmlUIu2k # iHdtvRoU9BNKei8ttzjv9P+Aufih9/Jy3iS8UgPITtAq3votVs/59PesMHqai7Je # 1M/RQ0SbQyHrlnKhSLSZy51PpwYDE3cnRNTnf+hZqPC/Lwum6fI0POz3A8eHqNJM # QBk1RmppVLC4oVaO7KTVPeix3P0c2PR3WlxUjG/voVA9/HYJaISfb8rbII01YBwC # A8sgsKxYoA5AY8WYIsGyWfVVa88nq2x2zm8jLfR+cWojayL/ErhULSd+2DrZ8LaH # lv1b0VysGMNNn3O3AamfV6peKOK5lDCCBq4wggSWoAMCAQICEAc2N7ckVHzYR6z9 # KGYqXlswDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERp # Z2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMY # RGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4XDTIyMDMyMzAwMDAwMFoXDTM3MDMy # MjIzNTk1OVowYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMu # MTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRp # bWVTdGFtcGluZyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMaG # NQZJs8E9cklRVcclA8TykTepl1Gh1tKD0Z5Mom2gsMyD+Vr2EaFEFUJfpIjzaPp9 # 85yJC3+dH54PMx9QEwsmc5Zt+FeoAn39Q7SE2hHxc7Gz7iuAhIoiGN/r2j3EF3+r # GSs+QtxnjupRPfDWVtTnKC3r07G1decfBmWNlCnT2exp39mQh0YAe9tEQYncfGpX # evA3eZ9drMvohGS0UvJ2R/dhgxndX7RUCyFobjchu0CsX7LeSn3O9TkSZ+8OpWNs # 5KbFHc02DVzV5huowWR0QKfAcsW6Th+xtVhNef7Xj3OTrCw54qVI1vCwMROpVymW # Jy71h6aPTnYVVSZwmCZ/oBpHIEPjQ2OAe3VuJyWQmDo4EbP29p7mO1vsgd4iFNmC # KseSv6De4z6ic/rnH1pslPJSlRErWHRAKKtzQ87fSqEcazjFKfPKqpZzQmiftkaz # nTqj1QPgv/CiPMpC3BhIfxQ0z9JMq++bPf4OuGQq+nUoJEHtQr8FnGZJUlD0UfM2 # SU2LINIsVzV5K6jzRWC8I41Y99xh3pP+OcD5sjClTNfpmEpYPtMDiP6zj9NeS3YS # UZPJjAw7W4oiqMEmCPkUEBIDfV8ju2TjY+Cm4T72wnSyPx4JduyrXUZ14mCjWAkB # KAAOhFTuzuldyF4wEr1GnrXTdrnSDmuZDNIztM2xAgMBAAGjggFdMIIBWTASBgNV # HRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBS6FtltTYUvcyl2mi91jGogj57IbzAf # BgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8EBAMCAYYw # EwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUFBzAB # hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9j # YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3J0MEMG # A1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2Vy # dFRydXN0ZWRSb290RzQuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG # /WwHATANBgkqhkiG9w0BAQsFAAOCAgEAfVmOwJO2b5ipRCIBfmbW2CFC4bAYLhBN # E88wU86/GPvHUF3iSyn7cIoNqilp/GnBzx0H6T5gyNgL5Vxb122H+oQgJTQxZ822 # EpZvxFBMYh0MCIKoFr2pVs8Vc40BIiXOlWk/R3f7cnQU1/+rT4osequFzUNf7WC2 # qk+RZp4snuCKrOX9jLxkJodskr2dfNBwCnzvqLx1T7pa96kQsl3p/yhUifDVinF2 # ZdrM8HKjI/rAJ4JErpknG6skHibBt94q6/aesXmZgaNWhqsKRcnfxI2g55j7+6ad # cq/Ex8HBanHZxhOACcS2n82HhyS7T6NJuXdmkfFynOlLAlKnN36TU6w7HQhJD5TN # OXrd/yVjmScsPT9rp/Fmw0HNT7ZAmyEhQNC3EyTN3B14OuSereU0cZLXJmvkOHOr # pgFPvT87eK1MrfvElXvtCl8zOYdBeHo46Zzh3SP9HSjTx/no8Zhf+yvYfvJGnXUs # HicsJttvFXseGYs2uJPU5vIXmVnKcPA3v5gA3yAWTyf7YGcWoWa63VXAOimGsJig # K+2VQbc61RWYMbRiCQ8KvYHZE/6/pNHzV9m8BPqC3jLfBInwAM1dwvnQI38AC+R2 # AibZ8GV2QqYphwlHK+Z/GqSFD/yYlvZVVCsfgPrA8g4r5db7qS9EFUrnEw4d2zc4 # GqEr9u3WfPwwggbAMIIEqKADAgECAhAMTWlyS5T6PCpKPSkHgD1aMA0GCSqGSIb3 # DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7 # MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1l # U3RhbXBpbmcgQ0EwHhcNMjIwOTIxMDAwMDAwWhcNMzMxMTIxMjM1OTU5WjBGMQsw # CQYDVQQGEwJVUzERMA8GA1UEChMIRGlnaUNlcnQxJDAiBgNVBAMTG0RpZ2lDZXJ0 # IFRpbWVzdGFtcCAyMDIyIC0gMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC # ggIBAM/spSY6xqnya7uNwQ2a26HoFIV0MxomrNAcVR4eNm28klUMYfSdCXc9FZYI # L2tkpP0GgxbXkZI4HDEClvtysZc6Va8z7GGK6aYo25BjXL2JU+A6LYyHQq4mpOS7 # eHi5ehbhVsbAumRTuyoW51BIu4hpDIjG8b7gL307scpTjUCDHufLckkoHkyAHoVW # 54Xt8mG8qjoHffarbuVm3eJc9S/tjdRNlYRo44DLannR0hCRRinrPibytIzNTLlm # yLuqUDgN5YyUXRlav/V7QG5vFqianJVHhoV5PgxeZowaCiS+nKrSnLb3T254xCg/ # oxwPUAY3ugjZNaa1Htp4WB056PhMkRCWfk3h3cKtpX74LRsf7CtGGKMZ9jn39cFP # cS6JAxGiS7uYv/pP5Hs27wZE5FX/NurlfDHn88JSxOYWe1p+pSVz28BqmSEtY+VZ # 9U0vkB8nt9KrFOU4ZodRCGv7U0M50GT6Vs/g9ArmFG1keLuY/ZTDcyHzL8IuINeB # rNPxB9ThvdldS24xlCmL5kGkZZTAWOXlLimQprdhZPrZIGwYUWC6poEPCSVT8b87 # 6asHDmoHOWIZydaFfxPZjXnPYsXs4Xu5zGcTB5rBeO3GiMiwbjJ5xwtZg43G7vUs # fHuOy2SJ8bHEuOdTXl9V0n0ZKVkDTvpd6kVzHIR+187i1Dp3AgMBAAGjggGLMIIB # hzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggr # BgEFBQcDCDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwHwYDVR0j # BBgwFoAUuhbZbU2FL3MpdpovdYxqII+eyG8wHQYDVR0OBBYEFGKK3tBh/I8xFO2X # C809KpQU31KcMFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdD # QS5jcmwwgZAGCCsGAQUFBwEBBIGDMIGAMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz # cC5kaWdpY2VydC5jb20wWAYIKwYBBQUHMAKGTGh0dHA6Ly9jYWNlcnRzLmRpZ2lj # ZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZUaW1lU3RhbXBp # bmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggIBAFWqKhrzRvN4Vzcw/HXjT9aFI/H8 # +ZU5myXm93KKmMN31GT8Ffs2wklRLHiIY1UJRjkA/GnUypsp+6M/wMkAmxMdsJiJ # 3HjyzXyFzVOdr2LiYWajFCpFh0qYQitQ/Bu1nggwCfrkLdcJiXn5CeaIzn0buGqi # m8FTYAnoo7id160fHLjsmEHw9g6A++T/350Qp+sAul9Kjxo6UrTqvwlJFTU2WZoP # VNKyG39+XgmtdlSKdG3K0gVnK3br/5iyJpU4GYhEFOUKWaJr5yI+RCHSPxzAm+18 # SLLYkgyRTzxmlK9dAlPrnuKe5NMfhgFknADC6Vp0dQ094XmIvxwBl8kZI4DXNlpf # lhaxYwzGRkA7zl011Fk+Q5oYrsPJy8P7mxNfarXH4PMFw1nfJ2Ir3kHJU7n/NBBn # 9iYymHv+XEKUgZSCnawKi8ZLFUrTmJBFYDOA4CPe+AOk9kVH5c64A0JH6EE2cXet # /aLol3ROLtoeHYxayB6a1cLwxiKoT5u92ByaUcQvmvZfpyeXupYuhVfAYOd4Vn9q # 78KVmksRAsiCnMkaBXy6cbVOepls9Oie1FqYyJ+/jbsYXEP10Cro4mLueATbvdH7 # WwqocH7wl4R44wgDXUcsY6glOJcB0j862uXl9uab3H4szP8XTE0AotjWAQ64i+7m # 4HJViSwnGWH2dwGMMYIFRDCCBUACAQEwgYYwcjELMAkGA1UEBhMCVVMxFTATBgNV # BAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8G # A1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBDQQIQ # C4jZOitkx57ksuMgsWXX0jAJBgUrDgMCGgUAoHAwEAYKKwYBBAGCNwIBDDECMAAw # GQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisG # AQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFBImk8QJcQGDXWyWVHYi5Kj+OV5fMA0G # CSqGSIb3DQEBAQUABIIBAB9W8jT1wqV2/wGmhkSRzxNFSXh73vhoxGX/FLyn/Dq7 # tR9d1Ez2QRr+Bo61g8TF/CnAvhfi3y2qDbM5+SntUfpL/QJ7QkIz18zvolLzsv8l # lI/LAGb8xQk0AP3pfhwYT24Pj47k18nDNNl7JDPdGEFZZB2hBbFZB0KLa6oIsiO0 # gcQa7LceFtDFyyCGPxQDQZ4+L9y3bh/0L2dk2EjZFJdyfCLsFzhGYvnXejEIMkDL # OeE0Qg+e9SOt0E9DCFe6TbC+FjbTpedXqh3nPbhhvTZPaqp1bDPQ5LCIwlotp52f # 6xRoqYQRh6BBMV0DyAnr1e56tmudJeBTKC0+VUiDe+2hggMgMIIDHAYJKoZIhvcN # AQkGMYIDDTCCAwkCAQEwdzBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNl # cnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBT # SEEyNTYgVGltZVN0YW1waW5nIENBAhAMTWlyS5T6PCpKPSkHgD1aMA0GCWCGSAFl # AwQCAQUAoGkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUx # DxcNMjMwNDI1MDIzMDQxWjAvBgkqhkiG9w0BCQQxIgQgcs2XpyMVROX4OUyXBcDR # 1EtpPPk0K1rFvjl6X2NKWYUwDQYJKoZIhvcNAQEBBQAEggIAtb4UE+zUCp0tKQD5 # VWLNiQHpqDIBSdSQn5a4jSMAEK44yfbhyBr52fqmHjGqXlf++iNmjyp/gPdPDSDE # HzInyU21By0fqZvpVeGjOCkCMOjy4Dpr2XyuF6egscnzW4yQTYoBJKTuW3Js06rr # 65tR8NUTyLVgdmc/tZbuH6mBw0xGM6ZOqHX5n0MVS8mYJWDhsBBlTJp62hO2tdJX # fLDrjhaMrcXiUK0kh1V2KrDFEkhDPOT367eC4Fww60w0CSoeEmuvxyPQ1hTGVgZe # ppk7OcIOQAUzf4ik1J+E+8KjUY2JEe3E77CooW0LjtabCxMkW7pvyukte3og7ROG # shbQAhZWT+zzLKcWlvWTiJK/opsIwIm8gu1b3tyJlTUej24ZZm33CFqBe1aaGKv6 # ezDCOlJD9tw3pPJRQ20ownwocChp4XiE1E2OSejJCGTfKr6+IzJEm7EdPTfCCvF4 # C3RuDZgY7QXv4dLpRNuC69Eoob6pmo/64Mfln1evTAIYsav9pfYfEYU5CXrZ6wDT # pV2m5WMRxXxG3GqcpqZTqwJ2ZG+sBCro/SkhGjUltCUxVBk4yOyDyd5pgdn3pvUI # t40hkw6FW5sbU6RMId7ktyZpm15wg1CUiZpdW+SUkMfhf11dcsFXwNdHMz3QXiT3 # izfaKwh2KlEpkmbe615t3I74fjY= # SIG # End signature block |