PureStorage.CBS.AVS.VMFS.ps1

function Get-PCBSVolumeFromVMFSDataStore {
    Param(
        [Parameter(mandatory=$true)]
        $FlashArray,

        [Parameter(mandatory=$true)]
        $DataStore
    )
    $Lun = $Datastore.ExtensionData.Info.Vmfs.Extent.DiskName |select-object -unique
    if ($Lun -like 'naa.624a9370*')
    {
        $VolSerial = ($lun.ToUpper()).substring(12)
        $PureVol = Get-Pfa2Volume -Array $FlashArray -Filter "Serial='$VolSerial'"
    }
    else
    {
        throw "This VMFS is not hosted on Pure Cloud Block Store."
    }

    return $PureVol
}

function Remove-PfaVmfsDatastore {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        $Cluster,

        [Parameter(Mandatory=$true)]
        $Datastore,

        [Parameter(ValueFromPipeline=$True)]
        $FlashArray,

        [Parameter(Mandatory=$false)]
        [String]$AVSCloudName,

        [Parameter(Mandatory=$false)]
        [String]$AzureSubscriptionId,

        [Parameter(Mandatory=$false)]
        [String]$AVSResourceGroup
    )


    $PureVol = Get-PCBSVolumeFromVMFSDataStore -FlashArray $FlashArray -Datastore $Datastore

    Write-Progress -Activity "Dismounting datastore" -Status "25% Complete:" -PercentComplete 25
    $params = @{
        ClusterName = $Cluster.Name;
        DatastoreName = $Datastore.Name
    }
    # Question: We just do unmount/detach at VMWare side. Do we need to run Remove-Datastore to clean the datastore?
    Invoke-RunScript -CmdletName "Dismount-VmfsDatastore" -Parameters $params `
        -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup

    Write-Progress -Activity "Removing volume" -Status "50% Complete:" -PercentComplete 50
    # Remove volume from array hostgroup if available
    $FaHg = Get-PCBSHostGroupfromVcCluster -Flasharray $Flasharray -Cluster $Cluster
    $HgConnection = Get-Pfa2Connection -Array $FlashArray -VolumeNames $PureVol.Name -HostGroupNames $FaHg.Name -ErrorAction SilentlyContinue
    if ($HgConnection -ne $null) {
        Write-Host "Removing volume $($PureVol.Name) from host group $($FaHg.Name)..."
        Remove-Pfa2Connection -Array $FlashArray -VolumeNames $PureVol.Name -HostGroupNames $FaHg.Name
    }

    # Destroy volume if there is no host/hg connections for the volume
    $Connections = Get-Pfa2Connection -Array $FlashArray -VolumeNames $PureVol.Name
    if ($Connections -eq $null) {
        Write-Host "Destroying volume $($PureVol.Name)..."
        Remove-Pfa2Volume -Array $FlashArray -Name $PureVol.Name
    }

    Write-Progress -Activity "Rescanning storage" -Status "75% Complete:" -PercentComplete 75
    $params = @{
        ClusterName = $Cluster.Name;
    }
    Invoke-RunScript -CmdletName "Sync-ClusterVMHostStorage" -Parameters $params `
        -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup
}

function New-VolumeFromSnaspshot {
    [CmdletBinding()]
    Param(
        [Parameter(ValueFromPipeline=$True)]
        $FlashArray,

        [Parameter(Mandatory=$true)]
        [String]$SnapshotName
    )

    $VolumeSnapshot = Get-Pfa2VolumeSnapshot -Array $FlashArray -Name $SnapshotName -ErrorAction Ignore
    if (-not $VolumeSnapshot) {
        throw "Could not find snapshot '$SnapshotName'."
    }

    if ($VolumeSnapshot.Source.Name) {
        # If the original volume still exist
        $VolumeName = $volumeSnapshot.Source.Name + "-"+ (Get-Random -Minimum 10000000 -Maximum 99999999)
    } else {
        # If the original volume is missing, get volume name from snapshot name
        # Get Alphanumeric string from snapshot
        $FilteredSnapshotName = $SnapshotName -replace "[^a-zA-Z0-9]"
        $VolumeName = $FilteredSnapshotName + "-volcopy-"+ (Get-Random -Minimum 10000000 -Maximum 99999999)
    }
    $newVol = New-PfaVolumeByPrefix -FlashArray $FlashArray -Name $VolumeName -SourceName $SnapshotName

    return $newVol
}

function Restore-PfaVmfsFromProtectionGroupSnapshot {
    <#
    .SYNOPSIS
      Mounts a copy of a VMFS datastore to a VMware cluster from a Pure Storage Block Store protection groupsnapshot.
    .DESCRIPTION
      Takes in a snapshot name, the corresponding Pure Storage Block Store, and a cluster. The VMFS copy will be resignatured and mounted.
    .INPUTS
      Pure Cloud Block Store connection, a VolumeSnapshot, and a cluster.
    .OUTPUTS
      Returns the new datastore.
    #>

    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$True)]
        $Cluster,

        [Parameter(ValueFromPipeline=$True)]
        $FlashArray,

        [Parameter(Mandatory=$true)]
        [String]$ProtectionGroupSnapshotName,

        [Parameter(Mandatory=$false)]
        [String]$AVSCloudName,

        [Parameter(Mandatory=$false)]
        [String]$AzureSubscriptionId,

        [Parameter(Mandatory=$false)]
        [String]$AVSResourceGroup
    )

    $NewDatastore = @()
    $VolumeSnapshots = Get-Pfa2VolumeSnapshot -Array $FlashArray -Filter "Name='$($ProtectionGroupSnapshotName)*'"
    foreach ($VolumeSnapshot in $VolumeSnapshots) {
        try {
            $NewDatastore += Restore-PfaVmfsFromVolumeSnapshot -FlashArray $FlashArray -Cluster $Cluster -VolumeSnapshotName $VolumeSnapshot.Name `
                                -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup
        } catch {
            Write-Error "Failed to restore datastore from protection group $ProtectionGroupSnapshotName using volume snapshot $($VolumeSnapshot.Name)"
            Write-Error $_.Exception.Message
        }
    }

    return $NewDatastore
}

function Restore-PfaVmfsFromPod {
    <#
    .SYNOPSIS
      Mounts a copy of a VMFS datastore to a VMware cluster from a Pure Storage Block Store protection groupsnapshot.
    .DESCRIPTION
      Takes in a snapshot name, the corresponding Pure Storage Block Store, and a cluster. The VMFS copy will be resignatured and mounted.
    .INPUTS
      Pure Cloud Block Store connection, a VolumeSnapshot, and a cluster.
    .OUTPUTS
      Returns the new datastore.
    #>

    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$True)]
        $Cluster,

        [Parameter(ValueFromPipeline=$True)]
        $FlashArray,

        [Parameter(Mandatory=$true)]
        [String]$PodName,

        [Parameter(Mandatory=$false)]
        [String]$AVSCloudName,

        [Parameter(Mandatory=$false)]
        [String]$AzureSubscriptionId,

        [Parameter(Mandatory=$false)]
        [String]$AVSResourceGroup
    )

    $NewDatastore = @()
    $Volumes = Get-Pfa2Volume -Array $FlashArray -Filter "Name='$($PodName)::*'"
    foreach ($Volume in $Volumes) {
        try {
            $NewDatastore += Restore-PfaVmfsFromVolume -FlashArray $FlashArray -Cluster $Cluster -VolumeName $Volume.Name `
                                -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup
        } catch {
            Write-Error "Failed to restore datastore from pod $PodName using volume $($Volume.Name)"
            Write-Error $_.Exception.Message
        }
    }

    return $NewDatastore
}

function Restore-PfaVmfsFromVolumeSnapshot {
    <#
    .SYNOPSIS
      Mounts a copy of a VMFS datastore to a VMware cluster from a Pure Storage Block Store snapshot.
    .DESCRIPTION
      Takes in a snapshot name, the corresponding Pure Storage Block Store, and a cluster. The VMFS copy will be resignatured and mounted.
    .INPUTS
      Pure Cloud Block Store connection, a VolumeSnapshot, and a cluster.
    .OUTPUTS
      Returns the new datastore.
    #>

    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$True)]
        $Cluster,

        [Parameter(ValueFromPipeline=$True)]
        $FlashArray,

        [Parameter(Mandatory=$true)]
        [String]$VolumeSnapshotName,

        [Parameter(Mandatory=$false)]
        [String]$DatastoreName,

        [Parameter(Mandatory=$false)]
        [String]$AVSCloudName,

        [Parameter(Mandatory=$false)]
        [String]$AzureSubscriptionId,

        [Parameter(Mandatory=$false)]
        [String]$AVSResourceGroup
    )

    $hostGroup = Get-PCBSHostGroupfromVcCluster -cluster $cluster -FlashArray $FlashArray

    # Create volume from the volume snapshot
    $VolumesForRestore = New-VolumeFromSnaspshot -FlashArray $FlashArray -SnapshotName $VolumeSnapshotName

    try {
        $NewDatastore = Restore-PfaVmfsFromVolume -FlashArray $FlashArray -Cluster $Cluster -VolumeName $VolumesForRestore.Name ` -DatastoreName $DatastoreName `
                            -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup
    } catch {
        # Clean up created volume if restore failed
        Write-Host "Failed to restore datastore from the volume snapshot $($VolumeSnapshotName)..."
        Write-Host "Cleaning up the volume $($VolumesForRestore.name) created from $($VolumeSnapshotName)..."
        Remove-Pfa2Connection -Array $FlashArray -HostgroupNames $hostGroup.name -VolumeNames $VolumesForRestore.name -ErrorAction SilentlyContinue
        Remove-Pfa2Volume  -Array $FlashArray -Name $VolumesForRestore.name -Confirm:$false -ErrorAction SilentlyContinue
        Remove-Pfa2Volume  -Array $FlashArray -Name $VolumesForRestore.name -Eradicate -Confirm:$false -ErrorAction SilentlyContinue
        throw
    }

    return $NewDatastore
}

function Restore-PfaVmfsFromVolume {
    <#
    .SYNOPSIS
      Mounts a copy of a VMFS datastore to a VMware cluster from a Pure Storage Block Store volume.
    .DESCRIPTION
      Takes in a snapshot name, the corresponding Pure Storage Block Store, and a cluster. The VMFS copy will be resignatured and mounted.
    .INPUTS
      Pure Cloud Block Store connection, a VolumeSnapshot, and a cluster.
    .OUTPUTS
      Returns the new datastore.
    #>

    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$True)]
        $Cluster,

        [Parameter(ValueFromPipeline=$True)]
        $FlashArray,

        [Parameter(Mandatory=$true)]
        [String]$VolumeName,

        [Parameter(Mandatory=$false)]
        [String]$DatastoreName,

        [Parameter(Mandatory=$false)]
        [String]$AVSCloudName,

        [Parameter(Mandatory=$false)]
        [String]$AzureSubscriptionId,

        [Parameter(Mandatory=$false)]
        [String]$AVSResourceGroup
    )

    $Volume =  Get-Pfa2Volume -Array $FlashArray -Name $VolumeName -ErrorAction Ignore
    if (-not $Volume) {
        throw "Volume $VolumeName does not exist."
    }

    $hostGroup = Get-PCBSHostGroupfromVcCluster -cluster $cluster -FlashArray $FlashArray

    Write-Progress -Activity "Connecting volume" -Status "25% Complete:" -PercentComplete 25
    Write-Host "Connecting volume $($Volume.Name) to host group $($hostGroup.Name)..."
    $Connection = Get-Pfa2Connection -Array $FlashArray -VolumeName $($Volume.Name) -HostGroupName $hostGroup.name -ErrorAction Ignore

    if ($Connection) {
        Write-Host "Volume $($Volume.Name) is already connected to host group $($hostGroup.Name). Using the existing connection..."
    } else {
        New-Pfa2Connection -Array $FlashArray -VolumeName $($Volume.Name) -HostGroupName $hostGroup.name | Out-Null
    }

    $esxi = $cluster | Get-VMHost| where-object {($_.ConnectionState -eq 'Connected')} | Select-Object -last 1
    Write-Progress -Activity "Rescanning storage" -Status "50% Complete:" -PercentComplete 50
    Write-Host "Rescanning HBA..."
    $params = @{
        VMHostName = $esxi.Name;
    }
    Invoke-RunScript -CmdletName "Sync-VMHostStorage" -Parameters $params `
        -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup

    $newNAA =  "naa.624a9370" + $Volume.serial.toLower()

    Write-Progress -Activity "Restoring volume" -Status "75% Complete:" -PercentComplete 75
    $params = @{
            ClusterName = $Cluster.Name;
            DeviceNaaId = $newNAA
            DatastoreName = $DatastoreName
    }

    Write-Host "Restoring VMFS Datastore $($DatastoreName) from volume $($Volume.Name)..."

    Invoke-RunScript -CmdletName  "Restore-VmfsVolume" -Parameters $params `
        -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup

    $NewDatastore = Get-Datastore -ErrorAction stop | Where-Object {$_.ExtensionData.Info.Vmfs.Extent.DiskName -eq $newNAA}

    return $NewDatastore
}

function New-PfaVolumeByPrefix {
    Param (
        [Parameter(Mandatory=$true)]
        [string] $Name,


        [ValidateRange(1073741824,68169720922112)] # 1 GB to 62 TB
        [Parameter(Mandatory=$false)]
        [UInt64] $Size,

        [Parameter(Mandatory=$True)]
        $Flasharray,

        [Parameter(Mandatory=$false)]
        [string] $SourceName
    )
    # Create a volume with the specified name. If the name already exists in the array, use it as a prefix
    $maxTries = 20
    $count = 0
    $existingVolume = $null
    # Get base volume name from source volume reflected in pure snapshot object
    # Source volume name possibility:
    # regular volume snapshot: testvol
    # pod volume snapshot: testpod::testacvol
    # array replicated volume snapshot: msconnect-ff-flasharray-1:testvol
    $BaseName = $Name.split(":")[-1]

    # Truncate the name if it is too large
    if ($BaseName.Length -gt 53) {
        $BaseName = $BaseName.Substring(0,53).TrimEnd("-")
    }
    $volName = $BaseName
    $existingVolume = Get-Pfa2Volume -Array $Flasharray  -Name $volName -ErrorAction SilentlyContinue
    while ($existingVolume -and $count -lt $maxTries) {
        $count = $count + 1
        $volName = "$BaseName-$count"
        $existingVolume = Get-Pfa2Volume -Array $Flasharray  -Name $volName -ErrorAction SilentlyContinue
    }
    if ($existingVolume) {
        # We exhausted the max number of tries
        throw "Could note create a volume based on the Name '$Name', please select a unique volume name"
    }
    Write-Host "Creating volume $volName..."
    if ($SourceName) {
        # Create a volume from a snapshot
        $vol = New-Pfa2Volume -Array $FlashArray -Name $volName -SourceName $SourceName -ErrorAction Stop
    }
    else {
        # Create a fresh volume
        $vol = New-Pfa2Volume -Array $FlashArray -Name $volName -Provisioned $Size -ErrorAction Stop
    }
    return $vol

}
function New-PfaVmfs {
    <#
    .SYNOPSIS
      Create a new VMFS on a new Pure Cloud Block Store volume
    .DESCRIPTION
      Creates a new VMFS on Pure Cloud Block Store and presents it to a cluster.
    .INPUTS
      FlashArray connection, a vCenter cluster, a volume size, and name.
    .OUTPUTS
      Returns a VMFS object.
    #>


    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]$Cluster,

        [Parameter(Mandatory=$True)]
        $Flasharray,

        [Parameter(Mandatory=$true)]
        [string]$Name,

        [Parameter(Mandatory=$true)]
        $vCenterServer,

        [ValidateRange(1073741824,68169720922112)] # 1 GB to 62 TB
        [Parameter(Mandatory=$true)]
        [UInt64]$Size,

        [Parameter(Mandatory=$false)]
        [String]$AVSCloudName,

        [Parameter(Mandatory=$false)]
        [String]$AzureSubscriptionId,

        [Parameter(Mandatory=$false)]
        [String]$AVSResourceGroup
    )
    Write-Progress -Activity "Creating volume" -Status "25% Complete:" -PercentComplete 25
    $datastore = Get-Datastore -Server $vCenterServer  -Name $Name -ErrorAction Ignore
    if ($datastore) {
        throw "Cannot create the datastore. Datastore '$Name' already exists!"
    }
    $hostGroup = Get-PCBSHostGroupfromVcCluster -cluster $cluster -FlashArray $FlashArray -ErrorAction Stop
    $newVol = New-PfaVolumeByPrefix -FlashArray $FlashArray -Name $Name -Size $Size -ErrorAction Stop
    New-Pfa2Connection -Array $FlashArray -HostGroupNames $hostGroup.Name -VolumeNames $newVol.Name | Out-Null
    Write-Progress -Activity "Rescanning storage" -Status "50% Complete:" -PercentComplete 50
    $newNAA = "naa.624a9370" + $newVol.serial.toLower()
    Write-Host "Rescanning storage..."
    $params = @{
        ClusterName = $Cluster.Name;
    }
    Invoke-RunScript -CmdletName "Sync-ClusterVMHostStorage" -Parameters $params `
        -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup

    Write-Debug -Message "NAA for datastore $Name is $newNAA"
    Write-Progress -Activity "Creating datastore" -Status "75% Complete:" -PercentComplete 75
    try {
        $params = @{
            ClusterName = $Cluster.Name;
            DatastoreName = $Name;
            DeviceNaaId = $newNAA;
            Size = $Size
        }
        Invoke-RunScript -CmdletName  "New-VmfsDatastore" -Parameters $params `
            -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup
    }
    catch {
        # Cleanup
        Remove-Pfa2Connection -Array $Flasharray -HostGroupNames $hostGroup.Name -VolumeNames $newVol.Name
        Remove-Pfa2Volume -Array $Flasharray -Name $newVol.Name | Out-Null
        Remove-Pfa2Volume -Array $Flasharray -Name $newVol.Name -Eradicate -Confirm:$false| Out-Null
        throw
    }
}


function Set-PfaVmfsCapacity {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        $Cluster,

        [Parameter(Position=0,ValueFromPipeline=$True)]
        $Flasharray,

        [Parameter(Position=1,mandatory=$true,ValueFromPipeline=$True)]
        $Datastore,

        [Parameter(mandatory=$false)]
        [UInt64]$SizeInByte,

        [Parameter(Mandatory=$false)]
        [String]$AVSCloudName,

        [Parameter(Mandatory=$false)]
        [String]$AzureSubscriptionId,

        [Parameter(Mandatory=$false)]
        [String]$AVSResourceGroup
    )

    Write-Progress -Activity "Resizing volume" -Status "25% Complete:" -PercentComplete 25


    $pureVol = Get-PCBSVolumeFromVMFSDataStore -Flasharray $FlashArray -Datastore $Datastore
    $Size = Get-FriendlySize -SizeInByte $SizeInByte
    $CurrentSize = Get-FriendlySize -SizeInByte $pureVol.Provisioned
    if ($SizeInByte -lt $pureVol.Provisioned)
    {
        throw "The new specified size '$Size' is not larger than the current size '$CurrentSize'. ESXi does not permit VMFS volumes to be shrunk--please specify a size larger than the existing."
    }
    elseif ($SizeInByte -eq $pureVol.Provisioned) {
        # Resize operation might not have been completed in the past, try again

        # Check if the datastore was already resizes
        $CapacityDiff = ($SizeInByte - $Datastore.CapacityGB * 1GB) / 1GB
        if ($CapacityDiff -lt 0) {
            throw "Cannot resize datastore to lower capacity than $($Datastore.CapacityGB)GB"
        }
        if ($CapacityDiff -le 1) {
            # Difference is negligible. Might be due to VMWare reserved capacity
            Write-Warning "Datastore '$Datastore.Name' is already set to requested capacity."
            return
        }
        Write-Warning "Volume $($pureVol.Name) is already set at the requested capacity. Refreshing datastore object on AVS.."
    }
    else {
        Write-Host "Increasing the size of the volume $($pureVol.Name) to $Size on Pure Cloud Block Store..."

        # FlashArray only accept byte that is multiple of 512. If not, we round up by 512
        $SizeInByte = [math]::ceiling($SizeInByte/512) * 512

        Update-Pfa2Volume -Array $FlashArray -Name $pureVol.Name -Provisioned $SizeInByte | Out-Null
    }

    Write-Progress -Activity "Resizing datastore" -Status "50% Complete:" -PercentComplete 50
    $params = @{
        ClusterName = $Cluster.Name;
        DeviceNaaId = $Datastore.ExtensionData.Info.Vmfs.Extent.DiskName
    }
    Invoke-RunScript -CmdletName "Resize-VmfsVolume" -Parameters $params `
        -AVSCloudName $AVSCloudName -AzureSubscriptionId $AzureSubscriptionId -AVSResourceGroup $AVSResourceGroup

}

function Get-FriendlySize {
    [CmdletBinding()]
    Param(
        [Parameter(mandatory=$false)]
        [UInt64]$SizeInByte
    )

    $SizeInGB = $SizeInByte / 1024 / 1024 / 1024

    if ($SizeInGB -ge 1024) {
        $SizeInTB = $SizeInGB/1024
        return "$([math]::Round($SizeInTB, 2)) TB"
    } else {
        return "$([math]::Round($SizeInGB, 2)) GB"
    }
}


# SIG # Begin signature block
# MIIjUgYJKoZIhvcNAQcCoIIjQzCCIz8CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUNiodRj1+AVXTFpsa/H+/DfWN
# GoCggh14MIIFMDCCBBigAwIBAgIQBAkYG1/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
# GqEr9u3WfPwwggbCMIIEqqADAgECAhAFRK/zlJ0IOaa/2z9f5WEWMA0GCSqGSIb3
# DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7
# MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1l
# U3RhbXBpbmcgQ0EwHhcNMjMwNzE0MDAwMDAwWhcNMzQxMDEzMjM1OTU5WjBIMQsw
# CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xIDAeBgNVBAMTF0Rp
# Z2lDZXJ0IFRpbWVzdGFtcCAyMDIzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
# CgKCAgEAo1NFhx2DjlusPlSzI+DPn9fl0uddoQ4J3C9Io5d6OyqcZ9xiFVjBqZMR
# p82qsmrdECmKHmJjadNYnDVxvzqX65RQjxwg6seaOy+WZuNp52n+W8PWKyAcwZeU
# tKVQgfLPywemMGjKg0La/H8JJJSkghraarrYO8pd3hkYhftF6g1hbJ3+cV7EBpo8
# 8MUueQ8bZlLjyNY+X9pD04T10Mf2SC1eRXWWdf7dEKEbg8G45lKVtUfXeCk5a+B4
# WZfjRCtK1ZXO7wgX6oJkTf8j48qG7rSkIWRw69XloNpjsy7pBe6q9iT1HbybHLK3
# X9/w7nZ9MZllR1WdSiQvrCuXvp/k/XtzPjLuUjT71Lvr1KAsNJvj3m5kGQc3AZEP
# HLVRzapMZoOIaGK7vEEbeBlt5NkP4FhB+9ixLOFRr7StFQYU6mIIE9NpHnxkTZ0P
# 387RXoyqq1AVybPKvNfEO2hEo6U7Qv1zfe7dCv95NBB+plwKWEwAPoVpdceDZNZ1
# zY8SdlalJPrXxGshuugfNJgvOuprAbD3+yqG7HtSOKmYCaFxsmxxrz64b5bV4RAT
# /mFHCoz+8LbH1cfebCTwv0KCyqBxPZySkwS0aXAnDU+3tTbRyV8IpHCj7ArxES5k
# 4MsiK8rxKBMhSVF+BmbTO77665E42FEHypS34lCh8zrTioPLQHsCAwEAAaOCAYsw
# ggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoG
# CCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATAfBgNV
# HSMEGDAWgBS6FtltTYUvcyl2mi91jGogj57IbzAdBgNVHQ4EFgQUpbbvE+fvzdBk
# odVWqWUxo97V40kwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDovL2NybDMuZGlnaWNl
# cnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNIQTI1NlRpbWVTdGFtcGlu
# Z0NBLmNybDCBkAYIKwYBBQUHAQEEgYMwgYAwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v
# Y3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEFBQcwAoZMaHR0cDovL2NhY2VydHMuZGln
# aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNIQTI1NlRpbWVTdGFt
# cGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAgRrW3qCptZgXvHCNT4o8aJzY
# Jf/LLOTN6l0ikuyMIgKpuM+AqNnn48XtJoKKcS8Y3U623mzX4WCcK+3tPUiOuGu6
# fF29wmE3aEl3o+uQqhLXJ4Xzjh6S2sJAOJ9dyKAuJXglnSoFeoQpmLZXeY/bJlYr
# sPOnvTcM2Jh2T1a5UsK2nTipgedtQVyMadG5K8TGe8+c+njikxp2oml101DkRBK+
# IA2eqUTQ+OVJdwhaIcW0z5iVGlS6ubzBaRm6zxbygzc0brBBJt3eWpdPM43UjXd9
# dUWhpVgmagNF3tlQtVCMr1a9TMXhRsUo063nQwBw3syYnhmJA+rUkTfvTVLzyWAh
# xFZH7doRS4wyw4jmWOK22z75X7BC1o/jF5HRqsBV44a/rCcsQdCaM0qoNtS5cpZ+
# l3k4SF/Kwtw9Mt911jZnWon49qfH5U81PAC9vpwqbHkB3NpE5jreODsHXjlY9Hxz
# MVWggBHLFAx+rrz+pOt5Zapo1iLKO+uagjVXKBbLafIymrLS2Dq4sUaGa7oX/cR3
# bBVsrquvczroSUa31X/MtjjA2Owc9bahuEMs305MfR5ocMB3CtQC4Fxguyj/OOVS
# WtasFyIjTvTs0xf7UGv/B3cfcZdEQcm4RtNsMnxYL2dHZeUbc7aZ+WssBkbvQR7w
# 8F/g29mtkIBEr4AQQYoxggVEMIIFQAIBATCBhjByMQswCQYDVQQGEwJVUzEVMBMG
# A1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEw
# LwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENB
# AhALiNk6K2THnuSy4yCxZdfSMAkGBSsOAwIaBQCgcDAQBgorBgEEAYI3AgEMMQIw
# ADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYK
# KwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUYveQ+FISj56tnjUpe8lhJOsKc6Aw
# DQYJKoZIhvcNAQEBBQAEggEAmj6hzBRr7HWeIcgaBa4KqmkcHd9kcwm0Sz2gjZQH
# paC/zA2zoJ+e3XW+mMR2+4VXi4d7yaJCKPP+5leNaT5kc8dGB3bUb6XpbUkCsLD2
# RxWGlc+riKn2U2zoI/ttToZKoNI9Vm/4lwAASSf3UJYGrWbZP+vGBK37q/zCa9Vj
# J8jmZg+potPCJysfTlpLskJ1v6cg71fKv1+F8pzriDuQ8k9fkF51gRAc/4ujJcKo
# VFu19RObCUbrWRAMsTmJ8nBlxCmDbodElJakZu91d4QCbf/xExjIlN/vi3pGVV/9
# +gqM9vLjBfANA0JHknTV2Be92av3eqzbG7dA7bscUaTb6KGCAyAwggMcBgkqhkiG
# 9w0BCQYxggMNMIIDCQIBATB3MGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdp
# Q2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2
# IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0ECEAVEr/OUnQg5pr/bP1/lYRYwDQYJYIZI
# AWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJ
# BTEPFw0yMzA5MDUyMjAxNDNaMC8GCSqGSIb3DQEJBDEiBCAlNmf7JgsR5FcydLRt
# RSr4C+vhYdHfpRRNr6ksfXEb8zANBgkqhkiG9w0BAQEFAASCAgA+YuihgYuYO7Kr
# rYKLux1ZpIRI5VzWG2WhyO0I726tuvfbxuf/eoVIhHAeqDm8u2AHcdy71r44z27W
# xkpzGbZGCwfhaxhyyzzjQs0nx9BzGcFaNCJoBUPwLyheD0VnH6ALnF59QtKOVyaQ
# tmHFZObx7LCzPnWMS4XqrLoqxwk5T5wVRNt/3HbI5XHELwplqjduDIR3qUfXmR7H
# HaO1aICsTAwe4nHWY+0MqOHWzUvCmbJCG8yvk0ymJNkez8tykQsDTHCPaLeInbUc
# K86eCzdAJZDC5NRmVZMdrcSeEX57P7WkutYy+D+68Mk+T6GjKJ/WqJWNL1e9UE/S
# taydkgbq2Hm04uGPCf8pu5G2IS4X2Z808/GXzdKiG4h1EGeL4bcFXZNL+MhGaebB
# XwDpCuOOyUi7vCKOdDhWLE32GMjGIICbZwkSnetI0vxWDXo+/kBElWDI1l1nH/5g
# o6swlzatCUl4jUwqsRZhKZfn7Vk5ZyQdR5+UmOPoz+zGJMKS+hDtEp4oGnyR9Hxp
# EPjk7rrAL225PTzsw0BNJDN2YNTuxKHfml3ih/k/aMqsqmv7Cs2miOUC/GBYG0BA
# vRn3ngDDhpUF+J5mRr/RntBILjV6XmyB3KvmCvP0qtEfBIlcOkHFPgzCXt+BQFtx
# 344JwBAxAJEx3qu99EVcQaqCvolX1A==
# SIG # End signature block