Samples/ComposerApplianceConfig_Sample.ps1

##############################################################################
# ComposerApplianceConfig_Sample.ps1
# - Example scripts for configuring an HPE OneView appliance (networking, NTP,
# etc.).
#
# VERSION 3.0
#
# (C) Copyright 2013-2021 Hewlett Packard Enterprise Development LP
##############################################################################
<#
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
#>

##############################################################################

[CmdletBinding()]
param
(

    [Parameter (Mandatory, HelpMessage = "Provide the Appliances DHCP Address.")]
    [Alias('vm_ipaddr')]
    [ValidateNotNullorEmpty()]
    [IPAddress]$DhcpAddress,

    [Parameter (Mandatory, HelpMessage = "Provide the Appliances NEW Hostname or FQDN.")]
    [String]$Hostname,

    [Parameter (Mandatory, HelpMessage = "Provide a [SecureString] pr [String] object representing the new appliance Administrator password.")]
    [ValidateNotNullorEmpty()]
    [Object]$NewPassword,

    [Parameter (Mandatory, HelpMessage = "Provide the Composer Primary Virtual IP.")]
    [ValidateNotNullorEmpty()]
    [IPAddress]$IPv4Address,

    [Parameter (Mandatory, HelpMessage = "Provide the Appliances NEW IPv4 Subnet.")]
    [ValidateNotNullorEmpty()]
    [String]$IPv4SubnetMask,

    [Parameter (Mandatory, HelpMessage = "Provide the Appliances NEW IPv4 Default Gateway.")]
    [ValidateNotNullorEmpty()]
    [IPAddress]$IPv4Gateway,

    [Parameter (Mandatory, HelpMessage = "Provide the Appliances NEW IPv4 DNS Servers.")]
    [ValidateNotNullorEmpty()]
    [Array]$IPv4DnsServers,

    [Parameter (Mandatory, HelpMessage = "Provide the Appliances NEW DNS Domain Name.")]
    [ValidateNotNullorEmpty()]
    [String]$DnsDomainName,

    [Parameter (Mandatory, HelpMessage = "Provide the Appliances NEW DNS Domain Name.")]
    [ValidateNotNullorEmpty()]
    [IPAddress]$ServiceIPv4Node1,

    [Parameter (Mandatory, HelpMessage = "Provide the Appliances NEW DNS Domain Name.")]
    [ValidateNotNullorEmpty()]
    [IPAddress]$ServiceIPv4Node2,

    [Parameter (Mandatory = $false, HelpMessage = "Provide the Appliances NEW IPv4 NTP Servers.")]
    [ValidateNotNullorEmpty()]
    [Array]$IPv4NtpServers,

    [Parameter (Mandatory = $False, HelpMessage = "Provide the Appliances NEW IPv6 Static Address.")]
    [ValidateNotNullorEmpty()]
    [IPAddress]$IPv6Address,

    [Parameter (Mandatory = $False, HelpMessage = "Provide the Appliances NEW IPv6 Static Address.")]
    [ValidateNotNullorEmpty()]
    [Int]$IPv6CidrMask,

    [Parameter (Mandatory = $False, HelpMessage = "Provide the Service IP for Node 1 NEW IPv6 Static Address.")]
    [ValidateNotNullorEmpty()]
    [IPAddress]$ServiceIPv6Node1,

    [Parameter (Mandatory = $False, HelpMessage = "Provide the Service IP for Node 2 NEW IPv6 Static Address.")]
    [ValidateNotNullorEmpty()]
    [IPAddress]$ServiceIPv6Node2

)

if (-not (Get-Module HPEOneView.530))
{

    Import-Module HPEOneView.530

}

#region

    Write-Host 'Waiting for appliance to respond to network test.' -NoNewline

    While (-not (Test-Connection -ComputerName $DhcpAddress.IPAddressToString -Quiet))
    {

        Write-Host '.' -NoNewline

    }

    Write-Host ""

    #Core Appliance Setup

    # Accept the EULA
    if (-not (Get-OVEulaStatus -Appliance $DhcpAddress.IPAddressToString).Accepted )
    {

        Write-Host "Accepting EULA..."

        Try
        {

            $ret = Set-OVEulaStatus -SupportAccess "yes" -Appliance $DhcpAddress.IPAddressToString

        }

        Catch
        {

            $PSCMdlet.ThrowTerminatingError($_)
        }

    }

    # For initial setup, connect first using "default" Administrator credentials:
    Try
    {

        Connect-OVMgmt -appliance $DhcpAddress.IPAddressToString -user "Administrator" -password "admin"

    }

    catch [HPEOneView.Appliance.PasswordChangeRequired]
    {

        Write-Host "Set initial password"

        Try
        {

            Set-OVInitialPassword -OldPassword "admin" -NewPassword $NewPassword -Appliance $DhcpAddress.IPAddressToString

        }

        Catch
        {

            $PSCMdlet.ThrowTerminatingError($_)

        }

    }

    catch [HPEOneView.Appliance.AuthSessionException]
    {

        Write-Host "Default password was already changed."

    }

    Catch
    {

        $PSCMdlet.ThrowTerminatingError($_)

    }

    Write-Host "Reconnect with new password"

    Try
    {

        $ApplianceConnection = Connect-OVMgmt -appliance $DhcpAddress.IPAddressToString -user Administrator -password $NewPassword

    }

    Catch
    {

        $PSCMdlet.ThrowTerminatingError($_)

    }

    Write-Host "Set appliance networking configuration"

    $params = @{

        Hostname         = $Hostname;
        IPv4Addr         = $IPv4Address.IPAddressToString;
        IPv4Subnet       = $IPv4SubnetMask;
        IPv4Gateway      = $IPv4Gateway.IPAddressToString;
        DomainName       = $DnsDomainName;
        IPv4NameServers  = $IPv4DnsServers;
        ServiceIPv4Node1 = $ServiceIPv4Node1;
        ServiceIPv4Node2 = $ServiceIPv4Node2

    }

    if ($IPv6Address)
    {

        $params.Add('IPv6Type','STATIC')
        $params.Add('IPv6Addr', $IPv6Address)
        $params.Add('IPv6Subnet', $IPv6CidrMask)
        $params.Add('ServiceIPv6Node1', $ServiceIPv6Node1)
        $params.Add('ServiceIPv6Node2', $ServiceIPv6Node2)

    }

    Try
    {

        $task = Set-OVApplianceNetworkConfig @params

    }

    Catch
    {

        $PSCMdlet.ThrowTerminatingError($_)

    }

    if (-not($Global:ConnectedSessions | ? Name -EQ $Hostname))
    {

        Try
        {

            $ApplianceConnection = Connect-OVMgmt -appliance $Hostname -user Administrator -password $NewPassword

        }

        Catch
        {

            $PSCMdlet.ThrowTerminatingError($_)

        }

    }

    try
    {

        Write-Host 'Setting Appliance NTP Servers'

        $Results = Set-OVApplianceDateTime -NtpServers $IPv4NtpServers

    }

    catch
    {

        $PSCmdlet.ThrowTerminatingError($_)

    }

    #Configuring appliance LDAP/AD Security
    $dc1 = New-OVLdapServer -Name dc1.domain.local
    $dc2 = New-OVLdapServer -Name dc2.domain.local

    $AuthParams = @{

        UserName = "ftoomey@domain.local"
        Password = convertto-securestring -asplaintext "HPinv3nt" -force

    }

    Try
    {

        $LdapAuthDirectory = New-OVLdapDirectory -Name 'domain.local' -AD -BaseDN 'dc=domain,dc=local' -servers $dc1,$dc2 @AuthParams
        $LdapGroups = $LdapAuthDirectory | Show-OVLdapGroups @AuthParams
        $InfrastructureAdminGroup = $LdapGroups | ? Name -match 'CI Manager Full'
        $ServerAdminGroup  = $LdapGroups | ? Name -match 'CI Manager Server'
        $StorageAdminGroup = $LdapGroups | ? Name -match 'CI Manager Storage'
        $NetworkAdminGroup = $LdapGroups | ? Name -match 'CI Manager Network'
        New-OVLdapGroup -d $LdapAuthDirectory -GroupName $InfrastructureAdminGroup -Roles "Infrastructure administrator" @AuthParams
        New-OVLdapGroup -d $LdapAuthDirectory -GroupName $NetworkAdminGroup -Roles "Network administrator"  @AuthParams
        New-OVLdapGroup -d $LdapAuthDirectory -GroupName $ServerAdminGroup  -Roles "Server administrator"  @AuthParams
        New-OVLdapGroup -d $LdapAuthDirectory -GroupName $StorageAdminGroup -Roles "Storage administrator"  @AuthParams

    }

    Catch
    {

        $PSCMdlet.ThrowTerminatingError($_)

    }

    Try
    {

        #Upload custom SPP Baseline
        gci \\Server\software\SPP\bp-2016-07-11-00.iso | Add-OVBaseline

    }

    Catch
    {

        $PSCMdlet.ThrowTerminatingError($_)

    }


    # Create the new users
    New-OVUser Nat   -fullName "Nat Network Admin"  -password hpinvent -roles "Network administrator"
    New-OVUser Sarah -fullName "Sarah Server Admin" -password hpinvent -roles "Server administrator"
    New-OVUser Sandy -fullName "Sandy SAN Admin"    -password hpinvent -roles "Storage administrator"
    New-OVUser Rheid -fullName "Rheid Read-Only"      -password hpinvent -roles "Read only"
    New-OVUser Bob   -fullName "Bob Backup"          -password hpinvent -roles "Backup administrator"
    New-OVUser admin -fullName "admin"              -password hpinvent -roles "Infrastructure administrator"

#endregion

#region

    #Resource Configuration

    $params = @{

        hostname  = "172.18.15.1";
        type      = "BNA";
        username  = "administrator";
        password  = "pasword";
        UseSsl    = $True

    }

    write-host "Importing BNA SAN Manager"

    Try
    {

        Add-OVSanManager @params | Wait-OVTaskComplete

    }

    Catch
    {

        $PSCMdlet.ThrowTerminatingError($_)

    }

    Write-Host "Creating network resources"

    # Management networks
    Try
    {

        New-OVNetwork -Name "MLAG VLAN 10" -type "Ethernet" -vlanId 10 -smartlink $true -purpose Management

        # Internal Networks
        New-OVNetwork -Name "Internal Live Migration" -type "Ethernet" -vlanId 100 -smartlink $true -purpose VMMigration
        New-OVNetwork -Name "Internal Heartbeat" -type "Ethernet" -vlanId 101 -smartlink $true -purpose Management
        New-OVNetwork -Name "iSCSI Network" -type "Ethernet" -vlanId 3000 -smartlink $true -purpose ISCSI

        # VM Networks
        20,30,40,50 | % { New-OVNetwork -Name "MLAG Prod VLAN $_" -type "Ethernet" -vlanId $_ -smartlink $true -purpose General }
        101,102,103,104,105 | % { New-OVNetwork -Name "MLAG Dev VLAN $_" -type "Ethernet" -vlanId $_ -smartlink $true -purpose General }

        $AllMlagDevNetworks = Get-OVNetwork -Name "MLAG Dev VLAN"
        $AllMlagNetworks    = Get-OVNetwork -Name "MLAG VLAN*"
        $InternalNetworks   = Get-OVNetwork -Name Internal*

        # Create the network sets
        New-OVNetworkSet -Name "Prod NetSet" -networks $AllMlagNetworks -untaggedNetwork $AllMlagNetworks[0] -typicalBandwidth 2500 -maximumBandwidth 10000
        New-OVNetworkSet -Name "Dev Networks A" -networks $AllMlagDevNetworks -untaggedNetwork $AllMlagDevNetworks[0]  -typicalBandwidth 2500 -maximumBandwidth 10000

        # Create the FC networks:
        New-OVNetwork -Name "Fabric A" -type "FibreChannel" -typicalBandwidth 4000 -autoLoginRedistribution $true #-managedSan "SAN1_0"
        New-OVNetwork -Name "Fabric B" -type "FibreChannel" -typicalBandwidth 4000 -autoLoginRedistribution $true #-managedSan "SAN1_1"
        New-OVNetwork -Name "DirectAttach A" -type "FibreChannel" -typicalBandwidth 4000 -autoLoginRedistribution $true -fabricType DirectAttach
        New-OVNetwork -Name "DirectAttach B" -type "FibreChannel" -typicalBandwidth 4000 -autoLoginRedistribution $true -fabricType DirectAttach

    }

    Catch
    {

        $PSCMdlet.ThrowTerminatingError($_)

    }

    $params = @{

        username  = "3paradm";
        password  = "3pardata";
        hostname  = "172.18.11.11";
        domain    = "NO DOMAIN"

    }

    Write-Host "Importing storage array: $($params.hostname)"
    Try
    {

        $Results = Add-OVStorageSystem @params | Wait-OVTaskComplete

        $Results = Get-OVStorageSystem | Add-OVStoragePool -Pool 'FST_CPG1','FST_CPG2' | Wait-OVTaskComplete

    }

    Catch
    {

        $PSCMdlet.ThrowTerminatingError($_)

    }

    $SynergyLigParams = @{

        Name               = 'Default Synergy LIG';
        InterconnectBaySet = 3;
        FabricModuleType   = 'SEVC40F8';
        FrameCount         = 3;
        InternalNetworks   = $InternalNetworks;
        FabricRedundancy   = 'HighlyAvailable'
        Bays               = @{
                                Frame1 = @{Bay3 = 'SEVC40f8'; Bay6 = 'SE20ILM' };
                                Frame2 = @{Bay3 = 'SE20ILM'; Bay6 = 'SEVC40f8'};
                                Frame3 = @{Bay3 = 'SE20ILM'; Bay6 = 'SE20ILM'}
                                }

    }

    $CreatedLogicalInterconnectObject = New-OVLogicalInterconnectGroup @SynergyLigParams | Get-OVLogicalInterconnectGroup

    $UplinkSetParams = @{

        InputObject = $CreatedLogicalInterconnectObject;
        Name        = 'MLag UplinkSet';
        Type        = 'Ethernet';
        Networks    = $AllMlagNetworks;
        UplinkPorts = "Enclosure1:Bay3:Q1","Enclosure1:Bay3:Q2","Enclosure2:Bay6:Q1","Enclosure2:Bay6:Q2"

    }

    $CreateUplinkSetResults = New-OVUplinkSet @UplinkSetParams

    $LIG = Get-OVLogicalInterconnectGroup -Name 'Default Synergy LIG'

    $EgParams = @{

        Name                            = 'Synergy Default EG';
        EnclosureCount                  = 3;
        LogicalInterconnectGroupMapping = $LIG;
        IPv4AddressType                 = 'DHCP'

    }

    $CreateEGResults = New-OVEnclosureGroup @EgParams

    Disconnect-OVMgmt

    Remove-Module HPEOneView.530

#endregion
# SIG # Begin signature block
# MIIhJAYJKoZIhvcNAQcCoIIhFTCCIRECAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCz9BHF3bg1pUSS
# 9F8BlEaKVpgZ7j5mof6jYBZBS0VQx6CCEPYwggV0MIIEXKADAgECAhEA4uyQqa0b
# usW8CNcfQ2uSeDANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJHQjEbMBkGA1UE
# CBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRgwFgYDVQQK
# Ew9TZWN0aWdvIExpbWl0ZWQxJDAiBgNVBAMTG1NlY3RpZ28gUlNBIENvZGUgU2ln
# bmluZyBDQTAeFw0yMDEwMjEwMDAwMDBaFw0yMTEwMjEyMzU5NTlaMIHaMQswCQYD
# VQQGEwJVUzEOMAwGA1UEEQwFOTQzMDQxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQ
# BgNVBAcMCVBhbG8gQWx0bzEcMBoGA1UECQwTMzAwMCBIYW5vdmVyIFN0cmVldDEr
# MCkGA1UECgwiSGV3bGV0dCBQYWNrYXJkIEVudGVycHJpc2UgQ29tcGFueTEaMBgG
# A1UECwwRSFAgQ3liZXIgU2VjdXJpdHkxKzApBgNVBAMMIkhld2xldHQgUGFja2Fy
# ZCBFbnRlcnByaXNlIENvbXBhbnkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
# AoIBAQDqW2H8BiQozcKceSJau9tZAWp/YIjcOFBH7DT6DkS4tOAY/abriMVAPYiK
# oxJ8GEck3wWlYFm09+IrpeEDvXCZj0D8B7ls7AMUudCikqO5GJsgL3vzJqOmmUjp
# I3VsRvoJ5I4Ioq3N7jUINYSpHx3R0Sx8YMlKCRJLQO9DRveO1JSNMULIA2yatA9f
# lmZ/9jTf2UJCj6n7exfqobZCSzlRoiYED6fPmzJIzFXHkZdzmZ4XlNT19sxl3uIl
# BeT7DNipZ/VjnkPmddoEIn1gcsDzjuiE2+fxhkmWSwsWuDv3dDztYfoGZjbJi8bm
# OhfTRZiCQUDpjDyYbFzORnoK6tu9AgMBAAGjggGQMIIBjDAfBgNVHSMEGDAWgBQO
# 4TqoUzox1Yq+wbutZxoDha00DjAdBgNVHQ4EFgQUNeRTASY3ei1XaNNs+0/ZvUDs
# P2owDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYB
# BQUHAwMwEQYJYIZIAYb4QgEBBAQDAgQQMEoGA1UdIARDMEEwNQYMKwYBBAGyMQEC
# AQMCMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMAgGBmeB
# DAEEATBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsLnNlY3RpZ28uY29tL1Nl
# Y3RpZ29SU0FDb2RlU2lnbmluZ0NBLmNybDBzBggrBgEFBQcBAQRnMGUwPgYIKwYB
# BQUHMAKGMmh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1JTQUNvZGVTaWdu
# aW5nQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAN
# BgkqhkiG9w0BAQsFAAOCAQEAev9EUlTOTH7o28vQnCN+uelty9iliqJBID4NcwYQ
# BBruKhgheokkvMVW8PvGDLsELMRDCOCD6WJZB2e6mICkhglFrcVLVoWcVToBym/t
# ipBXsEyYle6qTNxY+5eBC40FRxlurIZXiPgtEXa8PbNI6OGCQpEEp9wtVitUnPF3
# Q6MD/k+tyC81PaqzCXfXLC/cyTRki+8EAiSIhKSNY5h6at/29gN6+QppRJRb7ghN
# zATfVwiiW2jgYb8sUzvO8dbE3WIa9dv58VZNEvnhAGbHwLz15Gf2ygQaS26AuJ3S
# y4P8pXDC+oGoPiDngeQm0f9rF9AlYhmm8oeq+HGGgsesNjCCBYEwggRpoAMCAQIC
# EDlyRDr5IrdR19NsEN0xNZUwDQYJKoZIhvcNAQEMBQAwezELMAkGA1UEBhMCR0Ix
# GzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEa
# MBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMMGEFBQSBDZXJ0aWZp
# Y2F0ZSBTZXJ2aWNlczAeFw0xOTAzMTIwMDAwMDBaFw0yODEyMzEyMzU5NTlaMIGI
# MQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVy
# c2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UE
# AxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJ
# KoZIhvcNAQEBBQADggIPADCCAgoCggIBAIASZRc2DsPbCLPQrFcNdu3NJ9NMrVCD
# YeKqIE0JLWQJ3M6Jn8w9qez2z8Hc8dOx1ns3KBErR9o5xrw6GbRfpr19naNjQrZ2
# 8qk7K5H44m/Q7BYgkAk+4uh0yRi0kdRiZNt/owbxiBhqkCI8vP4T8IcUe/bkH47U
# 5FHGEWdGCFHLhhRUP7wz/n5snP8WnRi9UY41pqdmyHJn2yFmsdSbeAPAUDrozPDc
# vJ5M/q8FljUfV1q3/875PbcstvZU3cjnEjpNrkyKt1yatLcgPcp/IjSufjtoZgFE
# 5wFORlObM2D3lL5TN5BzQ/Myw1Pv26r+dE5px2uMYJPexMcM3+EyrsyTO1F4lWeL
# 7j1W/gzQaQ8bD/MlJmszbfduR/pzQ+V+DqVmsSl8MoRjVYnEDcGTVDAZE6zTfTen
# 6106bDVc20HXEtqpSQvf2ICKCZNijrVmzyWIzYS4sT+kOQ/ZAp7rEkyVfPNrBale
# FoPMuGfi6BOdzFuC00yz7Vv/3uVzrCM7LQC/NVV0CUnYSVgaf5I25lGSDvMmfRxN
# F7zJ7EMm0L9BX0CpRET0medXh55QH1dUqD79dGMvsVBlCeZYQi5DGky08CVHWfoE
# HpPUJkZKUIGy3r54t/xnFeHJV4QeD2PW6WK61l9VLupcxigIBCU5uA4rqfJMlxwH
# Pw1S9e3vL4IPAgMBAAGjgfIwge8wHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Kl
# f9AwpLQwHQYDVR0OBBYEFFN5v1qqK0rPVIDh2JvAnfKyA2bLMA4GA1UdDwEB/wQE
# AwIBhjAPBgNVHRMBAf8EBTADAQH/MBEGA1UdIAQKMAgwBgYEVR0gADBDBgNVHR8E
# PDA6MDigNqA0hjJodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9BQUFDZXJ0aWZpY2F0
# ZVNlcnZpY2VzLmNybDA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6
# Ly9vY3NwLmNvbW9kb2NhLmNvbTANBgkqhkiG9w0BAQwFAAOCAQEAGIdR3HQhPZyK
# 4Ce3M9AuzOzw5steEd4ib5t1jp5y/uTW/qofnJYt7wNKfq70jW9yPEM7wD/ruN9c
# qqnGrvL82O6je0P2hjZ8FODN9Pc//t64tIrwkZb+/UNkfv3M0gGhfX34GRnJQisT
# v1iLuqSiZgR2iJFODIkUzqJNyTKzuugUGrxx8VvwQQuYAAoiAxDlDLH5zZI3Ge07
# 8eQ6tvlFEyZ1r7uq7z97dzvSxAKRPRkA0xdcOds/exgNRc2ThZYvXd9ZFk8/Ub3V
# RRg/7UqO6AZhdCMWtQ1QcydER38QXYkqa4UxFMToqWpMgLxqeM+4f452cpkMnf7X
# kQgWoaNflTCCBfUwggPdoAMCAQICEB2iSDBvmyYY0ILgln0z02owDQYJKoZIhvcN
# AQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYD
# VQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3Jr
# MS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
# MB4XDTE4MTEwMjAwMDAwMFoXDTMwMTIzMTIzNTk1OVowfDELMAkGA1UEBhMCR0Ix
# GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEY
# MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQwIgYDVQQDExtTZWN0aWdvIFJTQSBD
# b2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCG
# Io0yhXoYn0nwli9jCB4t3HyfFM/jJrYlZilAhlRGdDFixRDtsocnppnLlTDAVvWk
# dcapDlBipVGREGrgS2Ku/fD4GKyn/+4uMyD6DBmJqGx7rQDDYaHcaWVtH24nlteX
# UYam9CflfGqLlR5bYNV+1xaSnAAvaPeX7Wpyvjg7Y96Pv25MQV0SIAhZ6DnNj9LW
# zwa0VwW2TqE+V2sfmLzEYtYbC43HZhtKn52BxHJAteJf7wtF/6POF6YtVbC3sLxU
# ap28jVZTxvC6eVBJLPcDuf4vZTXyIuosB69G2flGHNyMfHEo8/6nxhTdVZFuihEN
# 3wYklX0Pp6F8OtqGNWHTAgMBAAGjggFkMIIBYDAfBgNVHSMEGDAWgBRTeb9aqitK
# z1SA4dibwJ3ysgNmyzAdBgNVHQ4EFgQUDuE6qFM6MdWKvsG7rWcaA4WtNA4wDgYD
# VR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYB
# BQUHAwMGCCsGAQUFBwMIMBEGA1UdIAQKMAgwBgYEVR0gADBQBgNVHR8ESTBHMEWg
# Q6BBhj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNBQ2VydGlm
# aWNhdGlvbkF1dGhvcml0eS5jcmwwdgYIKwYBBQUHAQEEajBoMD8GCCsGAQUFBzAC
# hjNodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNBQWRkVHJ1c3RD
# QS5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJ
# KoZIhvcNAQEMBQADggIBAE1jUO1HNEphpNveaiqMm/EAAB4dYns61zLC9rPgY7P7
# YQCImhttEAcET7646ol4IusPRuzzRl5ARokS9At3WpwqQTr81vTr5/cVlTPDoYMo
# t94v5JT3hTODLUpASL+awk9KsY8k9LOBN9O3ZLCmI2pZaFJCX/8E6+F0ZXkI9amT
# 3mtxQJmWunjxucjiwwgWsatjWsgVgG10Xkp1fqW4w2y1z99KeYdcx0BNYzX2MNPP
# tQoOCwR/oEuuu6Ol0IQAkz5TXTSlADVpbL6fICUQDRn7UJBhvjmPeo5N9p8OHv4H
# URJmgyYZSJXOSsnBf/M6BZv5b9+If8AjntIeQ3pFMcGcTanwWbJZGehqjSkEAnd8
# S0vNcL46slVaeD68u28DECV3FTSK+TbMQ5Lkuk/xYpMoJVcp+1EZx6ElQGqEV8ay
# nbG8HArafGd+fS7pKEwYfsR7MUFxmksp7As9V1DSyt39ngVR5UR43QHesXWYDVQk
# /fBO4+L4g71yuss9Ou7wXheSaG3IYfmm8SoKC6W59J7umDIFhZ7r+YMp08Ysfb06
# dy6LN0KgaoLtO0qqlBCk4Q34F8W2WnkzGJLjtXX4oemOCiUe5B7xn1qHI/+fpFGe
# +zmAEc3btcSnqIBv5VPU4OOiwtJbGvoyJi1qV3AcPKRYLqPzW0sH3DJZ84enGm1Y
# MYIPhDCCD4ACAQEwgZEwfDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIg
# TWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBM
# aW1pdGVkMSQwIgYDVQQDExtTZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcgQ0ECEQDi
# 7JCprRu6xbwI1x9Da5J4MA0GCWCGSAFlAwQCAQUAoHwwEAYKKwYBBAGCNwIBDDEC
# MAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwG
# CisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFqhH8XGUlx6qIYTL9hTS/bLoSYF
# zm+M8nxcHW/xuw+JMA0GCSqGSIb3DQEBAQUABIIBAB+8ci57Gnfokmw082mBNPXS
# KQAN5jontiHYXFqvj/GAIAiWxQ+/tCGnmlbXEOLLkBgC0sPHS6eAfEE7huaUz8lv
# m5k+HEkAGy0+mDUQ59CO1KlcbfanGZa3IRp0t9xhRjhAi8uGRQneATa/8yFAAF6H
# A2Lyicgi/MmIXIPZiJ09VJjVKr4q4uuhlit/18gH2fzI6X3oxrTV0ikuJuHrt8/s
# wwtLUEUdViNYjGkNjRR6ErCwMokOgypduvFHEolbkgK3BBxUMNnPdWB18fCyJPhY
# 6ag2ESTQG8Gqzptm1l5f9MNN+1PaeDVf1GVwiVoZKKbnfrC24uRfLBt+ASzwE7+h
# gg1FMIINQQYKKwYBBAGCNwMDATGCDTEwgg0tBgkqhkiG9w0BBwKggg0eMIINGgIB
# AzEPMA0GCWCGSAFlAwQCAQUAMHgGCyqGSIb3DQEJEAEEoGkEZzBlAgEBBglghkgB
# hv1sBwEwMTANBglghkgBZQMEAgEFAAQg5t6R8bhlmWcqXx6rhyfcU1AsgbIVJ9rj
# MeU5AHDBSKACEQDO699zSIKCD6NZzhaDWsN5GA8yMDIxMDMyMjIyMjI0OVqgggo3
# MIIE/jCCA+agAwIBAgIQDUJK4L46iP9gQCHOFADw3TANBgkqhkiG9w0BAQsFADBy
# MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
# d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQg
# SUQgVGltZXN0YW1waW5nIENBMB4XDTIxMDEwMTAwMDAwMFoXDTMxMDEwNjAwMDAw
# MFowSDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSAwHgYD
# VQQDExdEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMTCCASIwDQYJKoZIhvcNAQEBBQAD
# ggEPADCCAQoCggEBAMLmYYRnxYr1DQikRcpja1HXOhFCvQp1dU2UtAxQtSYQ/h3I
# b5FrDJbnGlxI70Tlv5thzRWRYlq4/2cLnGP9NmqB+in43Stwhd4CGPN4bbx9+cdt
# CT2+anaH6Yq9+IRdHnbJ5MZ2djpT0dHTWjaPxqPhLxs6t2HWc+xObTOKfF1FLUux
# UOZBOjdWhtyTI433UCXoZObd048vV7WHIOsOjizVI9r0TXhG4wODMSlKXAwxikqM
# iMX3MFr5FK8VX2xDSQn9JiNT9o1j6BqrW7EdMMKbaYK02/xWVLwfoYervnpbCiAv
# SwnJlaeNsvrWY4tOpXIc7p96AXP4Gdb+DUmEvQECAwEAAaOCAbgwggG0MA4GA1Ud
# DwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMI
# MEEGA1UdIAQ6MDgwNgYJYIZIAYb9bAcBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93
# d3cuZGlnaWNlcnQuY29tL0NQUzAfBgNVHSMEGDAWgBT0tuEgHf4prtLkYaWyoiWy
# yBc1bjAdBgNVHQ4EFgQUNkSGjqS6sGa+vCgtHUQ23eNqerwwcQYDVR0fBGowaDAy
# oDCgLoYsaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC10cy5j
# cmwwMqAwoC6GLGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQt
# dHMuY3JsMIGFBggrBgEFBQcBAQR5MHcwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3Nw
# LmRpZ2ljZXJ0LmNvbTBPBggrBgEFBQcwAoZDaHR0cDovL2NhY2VydHMuZGlnaWNl
# cnQuY29tL0RpZ2lDZXJ0U0hBMkFzc3VyZWRJRFRpbWVzdGFtcGluZ0NBLmNydDAN
# BgkqhkiG9w0BAQsFAAOCAQEASBzctemaI7znGucgDo5nRv1CclF0CiNHo6uS0iXE
# cFm+FKDlJ4GlTRQVGQd58NEEw4bZO73+RAJmTe1ppA/2uHDPYuj1UUp4eTZ6J7fz
# 51Kfk6ftQ55757TdQSKJ+4eiRgNO/PT+t2R3Y18jUmmDgvoaU+2QzI2hF3MN9PNl
# OXBL85zWenvaDLw9MtAby/Vh/HUIAHa8gQ74wOFcz8QRcucbZEnYIpp1FUL1LTI4
# gdr0YKK6tFL7XOBhJCVPst/JKahzQ1HavWPWH1ub9y4bTxMd90oNcX6Xt/Q/hOvB
# 46NJofrOp79Wz7pZdmGJX36ntI5nePk2mOHLKNpbh6aKLzCCBTEwggQZoAMCAQIC
# EAqhJdbWMht+QeQF2jaXwhUwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCVVMx
# FTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNv
# bTEkMCIGA1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTE2MDEw
# NzEyMDAwMFoXDTMxMDEwNzEyMDAwMFowcjELMAkGA1UEBhMCVVMxFTATBgNVBAoT
# DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UE
# AxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQTCCASIw
# DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3QMu5LzY9/3am6gpnFOVQoV7Yj
# SsQOB0UzURB90Pl9TWh+57ag9I2ziOSXv2MhkJi/E7xX08PhfgjWahQAOPcuHjvu
# zKb2Mln+X2U/4Jvr40ZHBhpVfgsnfsCi9aDg3iI/Dv9+lfvzo7oiPhisEeTwmQNt
# O4V8CdPuXciaC1TjqAlxa+DPIhAPdc9xck4Krd9AOly3UeGheRTGTSQjMF287Dxg
# aqwvB8z98OpH2YhQXv1mblZhJymJhFHmgudGUP2UKiyn5HU+upgPhH+fMRTWrdXy
# ZMt7HgXQhBlyF/EXBu89zdZN7wZC/aJTKk+FHcQdPK/P2qwQ9d2srOlW/5MCAwEA
# AaOCAc4wggHKMB0GA1UdDgQWBBT0tuEgHf4prtLkYaWyoiWyyBc1bjAfBgNVHSME
# GDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzASBgNVHRMBAf8ECDAGAQH/AgEAMA4G
# A1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDCDB5BggrBgEFBQcBAQRt
# MGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEF
# BQcwAoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJl
# ZElEUm9vdENBLmNydDCBgQYDVR0fBHoweDA6oDigNoY0aHR0cDovL2NybDQuZGln
# aWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0
# cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNy
# bDBQBgNVHSAESTBHMDgGCmCGSAGG/WwAAgQwKjAoBggrBgEFBQcCARYcaHR0cHM6
# Ly93d3cuZGlnaWNlcnQuY29tL0NQUzALBglghkgBhv1sBwEwDQYJKoZIhvcNAQEL
# BQADggEBAHGVEulRh1Zpze/d2nyqY3qzeM8GN0CE70uEv8rPAwL9xafDDiBCLK93
# 8ysfDCFaKrcFNB1qrpn4J6JmvwmqYN92pDqTD/iy0dh8GWLoXoIlHsS6HHssIeLW
# WywUNUMEaLLbdQLgcseY1jxk5R9IEBhfiThhTWJGJIdjjJFSLK8pieV4H9YLFKWA
# 1xJHcLN11ZOFk362kmf7U2GJqPVrlsD0WGkNfMgBsbkodbeZY4UijGHKeZR+WfyM
# D+NvtQEmtmyl7odRIeRYYJu6DC0rbaLEfrvEJStHAgh8Sa4TtuF8QkIoxhhWz0E0
# tmZdtnR79VYzIi8iNrJLokqV2PWmjlIxggJNMIICSQIBATCBhjByMQswCQYDVQQG
# EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
# cnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgVGltZXN0
# YW1waW5nIENBAhANQkrgvjqI/2BAIc4UAPDdMA0GCWCGSAFlAwQCAQUAoIGYMBoG
# CSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjEwMzIy
# MjIyMjQ5WjArBgsqhkiG9w0BCRACDDEcMBowGDAWBBTh14Ko4ZG+72vKFpG1qrSU
# piSb8zAvBgkqhkiG9w0BCQQxIgQgFU4YzJg/KwQJNq/qSEds5BSRpchgLWrb9sKn
# Ks0r3NowDQYJKoZIhvcNAQEBBQAEggEAdv6zWE+98kv50bP/Gv1d+b3oxCLjSyvq
# 9+v6S0NdpkIeI5puNcopQ2VB30dR1//xsmKQGFBctcy7B4W0RSlreYm2Ib2oy42Z
# fGARR+pXLI+zrVZndWH09npLFqwopSVAODezDCp3Q3wf9tNu63YsD85pHDyFfygm
# 6ilsD576PbnPitPumbITv1f+q+zJmgomtDzG6ImQqZlVh51JycorJhVPjP3Z84ni
# utLosBG5fK96fA1kUi44sWbX5kBD2oWwkwr1Z0GYN1/9E6nDpvBQHKuyhpdTf6l+
# jkgW+L4FAhPr97H13eoDHxUupNqsllvhC4YFshr+V8RvsGiMkbuVXA==
# SIG # End signature block