CLI/SystemManager.psm1
#################################################################################### ## © 2020,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. ## ## File Name: SystemManager.psm1 ## Description: System Manager cmdlets ## ## Created: December 2019 ## Last Modified: December 2019 ## History: v3.0 - Created ##################################################################################### $Info = "INFO:" $Debug = "DEBUG:" $global:VSLibraries = Split-Path $MyInvocation.MyCommand.Path [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ############################################################################################################################################ ## FUNCTION Test-CLIObject ############################################################################################################################################ Function Test-CLIObject { Param( [string]$ObjectType, [string]$ObjectName , [string]$ObjectMsg = $ObjectType, $SANConnection = $global:SANConnection ) $IsObjectExisted = $True $ObjCmd = $ObjectType -replace ' ', '' $Cmds = "show$ObjCmd $ObjectName" $Result = Invoke-CLICommand -Connection $SANConnection -cmds $Cmds if ($Result -like "no $ObjectMsg listed") { $IsObjectExisted = $false } return $IsObjectExisted } # End FUNCTION Test-CLIObject ########################################################################## ######################### FUNCTION Get-Cert ######################### ########################################################################## Function Get-Cert() { <# .SYNOPSIS Get-Cert - Show information about SSL certificates of the Storage System. .DESCRIPTION The Get-Cert command has two forms. The first is a table with a high level overview of the certificates used by the SSL Services. This table is customizable with the -showcols option. The second form provides detailed certificate information in either human readable format or in PEM (Privacy Enhanced Mail) format. It can also save the certificates in a specified file. .EXAMPLE Get-Cert -Service unified-server -Pem .EXAMPLE Get-Cert -Service unified-server -Text .PARAMETER Listcols Displays the valid table columns. .PARAMETER Showcols Changes the columns displayed in the table. .PARAMETER Service Displays only the certificates used by the service(s). Multiple services must be delimited by a comma. Valid service names are cim, cli, ekm-client, ekm-server, ldap, syslog-gen-client, syslog-gen-server, syslog-sec-client, syslog-sec-server, wsapi, vasa, and unified-server. .PARAMETER Type Displays only certificates of the specified type, e.g., only root CA. Multiple types must be delimited by a comma. Valid types are csr, cert, intca, and rootca. .PARAMETER Pem Displays the certificates in PEM format. When a filename is specified the certificates are exported to the file. .PARAMETER Text Displays the certificates in human readable format. When a filename is specified the certificates are exported to the file. .PARAMETER File Specifies the export file of the -pem or -text option. .Notes NAME: Get-Cert LASTEDIT December 2019 KEYWORDS: Get-Cert .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$false)] [switch] $Listcols, [Parameter(Position=1, Mandatory=$false)] [System.String] $Showcols, [Parameter(Position=2, Mandatory=$false)] [System.String] $Service, [Parameter(Position=3, Mandatory=$false)] [System.String] $Type, [Parameter(Position=4, Mandatory=$false)] [switch] $Pem, [Parameter(Position=5, Mandatory=$false)] [switch] $Text, [Parameter(Position=6, Mandatory=$false)] [System.String] $File, [Parameter(Position=7, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In Get-Cert - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or the array address (FQDN/IP Address) or user credentials in the connection object are either null or incorrect. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" " ERR: " Write-DebugLog "Stop: Exiting Get-Cert since SAN connection object values are null/empty" $Debug Return "Unable to execute the cmdlet Get-Cert since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $plinkresult = Test-PARCli -SANConnection $SANConnection if($plinkresult -match "FAILURE :") { write-debuglog "$plinkresult" Return $plinkresult } $Cmd = " showcert " if($Listcols) { $Cmd += " -listcols " } if($Showcols) { $Cmd += " -showcols $Showcols " } if($Service) { $Cmd += " -service $Service " } if($Type) { $Cmd += " -type $Type " } if($Pem) { $Cmd += " -pem " } if($Text) { $Cmd += " -text " } if($File) { $Cmd += " -file $File " } if($Listcols -Or $Pem -Or $Text) { $Result = Invoke-CLICommand -Connection $SANConnection -cmds $Cmd Write-DebugLog "Executing Function : Get-Cert Command -->" INFO: Return $Result } else { $Result = Invoke-CLICommand -Connection $SANConnection -cmds $Cmd Write-DebugLog "Executing Function : Get-Cert Command -->" INFO: if($Result.count -gt 1) { $tempFile = [IO.Path]::GetTempFileName() $LastItem = $Result.Count foreach ($s in $Result[0..$LastItem] ) { $s= [regex]::Replace($s,"^ ","") $s= [regex]::Replace($s," +",",") $s= [regex]::Replace($s,"-","") $s= $s.Trim() $temp1 = $s -replace 'Enddate','Month,Date,Time,Year,Zone' $s = $temp1 ## added code to replace blanc Enddate $sTemp1=$s $sTemp = $sTemp1.Split(',') if ([string]::IsNullOrEmpty($sTemp[3])) { $sTemp[3] = "--,--,--,--,---" } $newTemp= [regex]::Replace($sTemp,"^ ","") $newTemp= [regex]::Replace($sTemp," ",",") $newTemp= $newTemp.Trim() $s=$newTemp Add-Content -Path $tempfile -Value $s } Import-Csv $tempFile del $tempFile } else { return $Result } if($Result.count -gt 1) { return " Success : Executing Get-Cert" } else { return $Result } } } ## End-of Get-Cert ########################################################################## ######################### FUNCTION Get-Encryption #################### ########################################################################## Function Get-Encryption() { <# .SYNOPSIS Get-Encryption - Show Data Encryption information. .DESCRIPTION The Get-Encryption command shows Data Encryption information. .EXAMPLE .PARAMETER D Provides details on the encryption status. .Notes NAME: Get-Encryption LASTEDIT December 2019 KEYWORDS: Get-Encryption .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$false)] [switch] $D, [Parameter(Position=1, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In Get-Encryption - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or the array address (FQDN/IP Address) or user credentials in the connection object are either null or incorrect. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" " ERR: " Write-DebugLog "Stop: Exiting Get-Encryption since SAN connection object values are null/empty" $Debug Return "Unable to execute the cmdlet Get-Encryption since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $plinkresult = Test-PARCli -SANConnection $SANConnection if($plinkresult -match "FAILURE :") { write-debuglog "$plinkresult" Return $plinkresult } $Cmd = " showencryption " if($D) { $Cmd += " -d " } $Result = Invoke-CLICommand -Connection $SANConnection -cmds $Cmd Write-DebugLog "Executing Function : Get-Encryption Command -->" INFO: if($Result.count -gt 1) { $LastItem = 0 $Fcnt = 0 if($D) { $Fcnt = 4 $LastItem = $Result.Count -2 } else { $LastItem = $Result.Count -0 } $tempFile = [IO.Path]::GetTempFileName foreach ($s in $Result[$Fcnt..$LastItem] ) { $s= [regex]::Replace($s,"^ ","") $s= [regex]::Replace($s," +",",") $s= [regex]::Replace($s,"-","") $s= $s.Trim() $temp1 = $s -replace 'AdmissionTime','Date,Time,Zone' $s = $temp1 Add-Content -Path $tempfile -Value $s } Import-Csv $tempFile del $tempFile } if($Result.count -gt 1) { return " Success : Executing Get-Encryption" } else { return $Result } } ## End-of Get-Encryption ########################################################################## ############################ FUNCTION Get-SR ############################# ########################################################################## Function Get-SR { <# .SYNOPSIS Displays the amount of space consumed by the various System Reporter databases on the System Reporter volume. .DESCRIPTION Displays the amount of space consumed by the various System Reporter databases on the System Reporter volume. .EXAMPLE Get-SR shows how to display the System Reporter status: .EXAMPLE Get-SR -Btsecs 10 .PARAMETER ldrg Displays which LD region statistic samples are available. This is used with the -btsecs and -etsecs options. .PARAMETER Btsecs Select the begin time in seconds for the report. The value can be specified as either - The absolute epoch time (for example 1351263600). - The absolute time as a text string in one of the following formats: - Full time string including time zone: "2012-10-26 11:00:00 PDT" - Full time string excluding time zone: "2012-10-26 11:00:00" - Date string: "2012-10-26" or 2012-10-26 - Time string: "11:00:00" or 11:00:00 - A negative number indicating the number of seconds before the current time. Instead of a number representing seconds, <secs> can be specified with a suffix of m, h or d to represent time in minutes (e.g. -30m), hours (e.g. -1.5h) or days (e.g. -7d). If it is not specified then the time at which the report begins depends on the sample category (-hires, -hourly, -daily): - For hires, the default begin time is 12 hours ago (-btsecs -12h). - For hourly, the default begin time is 7 days ago (-btsecs -7d). - For daily, the default begin time is 90 days ago (-btsecs -90d). If begin time and sample category are not specified then the time the report begins is 12 hours ago and the default sample category is hires. If -btsecs 0 is specified then the report begins at the earliest sample. .PARAMETER Etsecs Select the end time in seconds for the report. If -attime is specified, select the time for the report. The value can be specified as either - The absolute epoch time (for example 1351263600). - The absolute time as a text string in one of the following formats: - Full time string including time zone: "2012-10-26 11:00:00 PDT" - Full time string excluding time zone: "2012-10-26 11:00:00" - Date string: "2012-10-26" or 2012-10-26 - Time string: "11:00:00" or 11:00:00 - A negative number indicating the number of seconds before the current time. Instead of a number representing seconds, <secs> can be specified with a suffix of m, h or d to represent time in minutes (e.g. -30m), hours (e.g. -1.5h) or days (e.g. -7d). .PARAMETER SANConnection Specify the SAN Connection object created with New-CLIConnection or New-PoshSshConnection .Notes NAME: Get-SR LASTEDIT: December 2019 KEYWORDS: Get-SR .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$false)] [switch] $ldrg, [Parameter(Position=1, Mandatory=$false)] [System.String] $Btsecs, [Parameter(Position=2, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Etsecs, [Parameter(Position=3, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In Get-SR - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or the array address (FQDN/IP Address) or user credentials in the connection object are either null or incorrect. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" "ERR:" Write-DebugLog "Stop: Exiting Get-SR since SAN connection object values are null/empty" $Debug return "Unable to execute the cmdlet Get-SR since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $cliresult1 = Test-PARCli -SANConnection $SANConnection if(($cliresult1 -match "FAILURE :")) { write-debuglog "$cliresult1" "ERR:" return $cliresult1 } $srinfocmd = "showsr " if($ldrg) { $srinfocmd += "-ldrg " } if($Btsecs) { $srinfocmd += "-btsecs $Btsecs " } if($Etsecs) { $srinfocmd += "-etsecs $Etsecs " } $Result = Invoke-CLICommand -Connection $SANConnection -cmds $srinfocmd write-host "" return $Result } ## EndOf Get-SR ########################################################################## ########################### FUNCTION Import-Cert ######################### ########################################################################## Function Import-Cert() { <# .SYNOPSIS Import-Cert - imports a signed certificate and supporting certificate authorities (CAs) for the Storage System SSL services. .DESCRIPTION The Import-Cert command allows a user to import certificates for a given service. The user can import a CA bundle containing the intermediate and/or root CAs prior to importing the service certificate. The CA bundle can also be imported alongside the service certificate. .EXAMPLE Import-Cert -SSL_service wsapi -Service_cert wsapi-service.pem .PARAMETER SSL_service Valid service names are cim, cli, ekm-client, ekm-server, ldap, syslog-gen-client, syslog-gen-server, syslog-sec-client, syslog-sec-server, wsapi, vasa, and unified-server. .PARAMETER CA_bundle Allows the import of a CA bundle without importing a service certificate. Note the filename "stdin" can be used to paste the CA bundle into the CLI. .PARAMETER Ca Allows the import of a CA bundle without importing a service certificate. Note the filename "stdin" can be used to paste the CA bundle into the CLI. .Notes NAME: Import-Cert LASTEDIT December 2019 KEYWORDS: Import-Cert .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$true)] [System.String] $SSL_service, [Parameter(Position=1, Mandatory=$false)] [System.String] $Service_cert, [Parameter(Position=2, Mandatory=$false)] [System.String] $CA_bundle, [Parameter(Position=3, Mandatory=$false)] [System.String] $Ca, [Parameter(Position=4, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In Import-Cert - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or the array address (FQDN/IP Address) or user credentials in the connection object are either null or incorrect. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" " ERR: " Write-DebugLog "Stop: Exiting Import-Cert since SAN connection object values are null/empty" $Debug Return "Unable to execute the cmdlet Import-Cert since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $plinkresult = Test-PARCli -SANConnection $SANConnection if($plinkresult -match "FAILURE :") { write-debuglog "$plinkresult" Return $plinkresult } $Cmd = " importcert " if($SSL_service) { $Cmd += " $SSL_service -f " } if($Service_cert) { $Cmd += " $Service_cert " } if($CA_bundle) { $Cmd += " $CA_bundle " } if($Ca) { $Cmd += " -ca $Ca " } $Result = Invoke-CLICommand -Connection $SANConnection -cmds $Cmd Write-DebugLog "Executing Function : Import-Cert Command -->" INFO: Return $Result } ## End-of Import-Cert ########################################################################## ######################### FUNCTION New-Cert ####################### ########################################################################## Function New-Cert() { <# .SYNOPSIS New-Cert - Create self-signed SSL certificate or a certificate signing request (CSR) for the Storage System SSL services. .DESCRIPTION The New-Cert command creates a self-signed certificate or a certificate signing request for a specified service. .EXAMPLE New-Cert -SSL_service unified-server -Selfsigned -Keysize 2048 -Days 365 .EXAMPLE New-Cert -SSL_service wsapi -Selfsigned -Keysize 2048 -Days 365 .PARAMETER SSL_service Valid service names are cim, cli, ekm-client, ekm-server, ldap, syslog-gen-client, syslog-gen-server, syslog-sec-client, syslog-sec-server, wsapi, vasa, and unified-server. .PARAMETER Csr Creates a certificate signing request for the service. No certificates are modified and no services are restarted. .PARAMETER Selfsigned Creates a self-signed certificate for the service. The previous certificate is removed and the service restarted. The intermediate and/or root certificate authorities for a service are not removed. .PARAMETER Keysize Specifies the encryption key size in bits of the self-signed certificate. Valid values are 1024 and 2048. The default value is 2048. .PARAMETER Days Specifies the valid days of the self-signed certificate. Valid values are between 1 and 3650 days (10 years). The default value is 1095 days (3 years). .PARAMETER C Specifies the value of country (C) attribute of the subject of the certificate. .PARAMETER ST Specifies the value of state (ST) attribute of the subject of the certificate. .PARAMETER L Specifies the value of locality (L) attribute of the subject of the certificate. .PARAMETER O Specifies the value of organization (O) attribute of the subject of the certificate. .PARAMETER OU Specifies the value of organizational unit (OU) attribute of the subject of the certificate. .PARAMETER CN Specifies the value of common name (CN) attribute of the subject of the certificate. Over ssh, -CN must be specified. .PARAMETER SAN Subject alternative name is a X509 extension that allows other pieces of information to be associated with the certificate. Multiple SANs may delimited with a comma. .Notes NAME: New-Cert LASTEDIT December 2019 KEYWORDS: New-Cert .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [System.String] $SSL_service, [Parameter(Position=1, Mandatory=$false, ValueFromPipeline=$true)] [switch] $Csr, [Parameter(Position=2, Mandatory=$false, ValueFromPipeline=$true)] [switch] $Selfsigned, [Parameter(Position=3, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Keysize, [Parameter(Position=4, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Days, [Parameter(Position=5, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $C, [Parameter(Position=6, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $ST, [Parameter(Position=7, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $L, [Parameter(Position=8, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $O, [Parameter(Position=9, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $OU, [Parameter(Position=10, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $CN, [Parameter(Position=11, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $SAN, [Parameter(Position=13, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In New-Cert - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or the array address (FQDN/IP Address) or user credentials in the connection object are either null or incorrect. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" " ERR: " Write-DebugLog "Stop: Exiting New-Cert since SAN connection object values are null/empty" $Debug Return "Unable to execute the cmdlet New-Cert since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $plinkresult = Test-PARCli -SANConnection $SANConnection if($plinkresult -match "FAILURE :") { write-debuglog "$plinkresult" Return $plinkresult } $Cmd = " createcert " if($SSL_service) { $Cmd += " $SSL_service " } if($Csr) { $Cmd += " -csr -f" } Elseif($Selfsigned) { $Cmd += " -selfsigned -f" } else { Return "Select at least one from [Csr | Selfsigned]..." } if($Keysize) { $Cmd += " -keysize $Keysize " } if($Days) { $Cmd += " -days $Days " } if($C) { $Cmd += " -C $C " } if($ST) { $Cmd += " -ST $ST " } if($L) { $Cmd += " -L $L " } if($O) { $Cmd += " -O $O " } if($OU) { $Cmd += " -OU $OU " } if($CN) { $Cmd += " -CN $CN " } if($SAN) { $Cmd += " -SAN $SAN " } $Result = Invoke-CLICommand -Connection $SANConnection -cmds $Cmd Write-DebugLog "Executing Function : New-Cert Command -->" INFO: Return $Result } ## End-of New-Cert #################################################################################################################### ## FUNCTION New-RCopyGroup ################################################################################################################### Function New-RCopyGroup { <# .SYNOPSIS The New-RCopyGroup command creates a remote-copy volume group. .DESCRIPTION The New-RCopyGroup command creates a remote-copy volume group. .EXAMPLE New-RCopyGroup -GroupName AS_TEST -TargetName CHIMERA03 -Mode sync .EXAMPLE New-RCopyGroup -GroupName AS_TEST1 -TargetName CHIMERA03 -Mode async .EXAMPLE New-RCopyGroup -GroupName AS_TEST2 -TargetName CHIMERA03 -Mode periodic .EXAMPLE New-RCopyGroup -domain DEMO -GroupName AS_TEST3 -TargetName CHIMERA03 -Mode periodic .PARAMETER domain Creates the remote-copy group in the specified domain. .PARAMETER Usr_Cpg_Name Specify the local user CPG and target user CPG that will be used for volumes that are auto-created. .PARAMETER Target_TargetCPG Specify the local user CPG and target user CPG that will be used for volumes that are auto-created. .PARAMETER Snp_Cpg_Name Specify the local snap CPG and target snap CPG that will be used for volumes that are auto-created. .PARAMETER Target_TargetSNP Specify the local snap CPG and target snap CPG that will be used for volumes that are auto-created. .PARAMETER GroupName Specifies the name of the volume group, using up to 22 characters if the mirror_config policy is set, or up to 31 characters otherwise. This name is assigned with this command. .PARAMETER TargetName Specifies the target name associated with this group. .PARAMETER Mode sync—synchronous replication async—asynchronous streaming replication periodic—periodic asynchronous replication .PARAMETER SANConnection Specify the SAN Connection object created with New-CLIConnection or New-PoshSshConnection .Notes NAME: New-RCopyGroup LASTEDIT: December 2019 KEYWORDS: New-RCopyGroup .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $GroupName, [Parameter(Position=1, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $TargetName, [Parameter(Position=2, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Mode, [Parameter(Position=3, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $domain, [Parameter(Position=4, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Usr_Cpg_Name, [Parameter(Position=5, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Target_TargetCPG, [Parameter(Position=6, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Snp_Cpg_Name, [Parameter(Position=7, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Target_TargetSNP, [Parameter(Position=8, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In New-RCopyGroup - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or the array address (FQDN/IP Address) or user credentials in the connection object are either null or incorrect. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" "ERR:" Write-DebugLog "Stop: Exiting New-RCopyGroup since SAN connection object values are null/empty" $Debug return "Unable to execute the cmdlet New-RCopyGroup since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $plinkresult = Test-PARCli if($plinkresult -match "FAILURE :") { write-debuglog "$plinkresult" "ERR:" return $plinkresult } $cmd= "creatercopygroup" if ($domain) { $cmd+=" -domain $domain" } if ($Usr_Cpg_Name) { $cmd+=" -usr_cpg $Usr_Cpg_Name " if($Target_TargetCPG) { $cmd+= " $TargetName" $cmd+= ":$Target_TargetCPG " } else { return "Target_TargetCPG is required with Usr CPG option" } } if ($Snp_Cpg_Name) { $cmd+=" -snp_cpg $Snp_Cpg_Name " if($Target_TargetSNP) { $cmd+= " $TargetName" $cmd+= ":$Target_TargetSNP " } else { return "Target_TargetSNP is required with Usr CPG option" } } if ($GroupName) { $cmd+=" $GroupName" } else { Write-DebugLog "Stop: GroupName is mandatory" $Debug return "Error : -GroupName is mandatory. " } if ($TargetName) { $cmd+=" $TargetName" } else { Write-DebugLog "Stop: TargetName is mandatory" $Debug return "Error : -TargetName is mandatory. " } if ($Mode) { $a = "sync","async","periodic" $l=$Mode if($a -eq $l) { $cmd+=":$Mode " } else { Write-DebugLog "Stop: Exiting New-RCopyGroup since Mode $Mode in incorrect " Return "FAILURE : Mode :- $Mode is an Incorrect Mode [a] can be used only . " } } else { Write-DebugLog "Stop: Mode is mandatory" $Debug return "Error : -Mode is mandatory. " } $Result = Invoke-CLICommand -Connection $SANConnection -cmds $cmd write-debuglog " The command creates a remote-copy volume group.. " "INFO:" if([string]::IsNullOrEmpty($Result)) { return "Success : Executing New-RCopyGroup Command $Result" } else { return "FAILURE : While Executing New-RCopyGroup $Result " } } # End New-RCopyGroup #################################################################################################################### ## FUNCTION New-RCopyGroupCPG ################################################################################################################### Function New-RCopyGroupCPG { <# .SYNOPSIS The New-RCopyGroupCPG command creates a remote-copy volume group. .DESCRIPTION The New-RCopyGroupCPG command creates a remote-copy volume group. .EXAMPLE New-RCopyGroupCPG -GroupName ABC -TargetName XYZ -Mode Sync .EXAMPLE New-RCopyGroupCPG -UsrCpg -LocalUserCPG BB -UsrTargetName XYZ -TargetUserCPG CC -GroupName ABC -TargetName XYZ -Mode Sync .PARAMETER UsrCpg .PARAMETER SnpCpg .PARAMETER UsrTargetName .PARAMETER SnpTargetName .PARAMETER LocalUserCPG Specifies the local user CPG and target user CPG that will be used for volumes that are auto-created. .PARAMETER TargetUserCPG -TargetUserCPG target:Targetcpg The local CPG will only be used after fail-over and recovery. .PARAMETER LocalSnapCPG Specifies the local snap CPG and target snap CPG that will be used for volumes that are auto-created. .PARAMETER TargetSnapCPG -LocalSnapCPG target:Targetcpg .PARAMETER domain Creates the remote-copy group in the specified domain. .PARAMETER GroupName Specifies the name of the volume group, using up to 22 characters if the mirror_config policy is set, or up to 31 characters otherwise. This name is assigned with this command. .PARAMETER TargetName Specifies the target name associated with this group. .PARAMETER Mode sync—synchronous replication async—asynchronous streaming replication periodic—periodic asynchronous replication .PARAMETER SANConnection Specify the SAN Connection object created with New-PoshSshConnection Or New-CLIConnection .Notes NAME: New-RCopyGroupCPG LASTEDIT: December 2019 KEYWORDS: New-RCopyGroupCPG .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $GroupName, [Parameter(Position=1, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $TargetName, [Parameter(Position=2, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Mode, [Parameter(Position=3, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $domain, [Parameter(Position=4, Mandatory=$false, ValueFromPipeline=$true)] [Switch] $UsrCpg, [Parameter(Position=5, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $LocalUserCPG, [Parameter(Position=6, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $TargetUserCPG, [Parameter(Position=9, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $UsrTargetName, [Parameter(Position=7, Mandatory=$false, ValueFromPipeline=$true)] [Switch] $SnpCpg, [Parameter(Position=8, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $LocalSnapCPG, [Parameter(Position=9, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $TargetSnapCPG, [Parameter(Position=9, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $SnpTargetName, [Parameter(Position=10, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In New-RCopyGroupCPG - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or the array address (FQDN/IP Address) or user credentials in the connection object are either null or incorrect. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" "ERR:" Write-DebugLog "Stop: Exiting New-RCopyGroupCPG since SAN connection object values are null/empty" $Debug return "Unable to execute the cmdlet New-RCopyGroupCPG since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $plinkresult = Test-PARCli if($plinkresult -match "FAILURE :") { write-debuglog "$plinkresult" "ERR:" return $plinkresult } $cmd= "creatercopygroup" if ($domain) { $cmd+=" -domain $domain" } if($UsrCpg) { $cmd+=" -usr_cpg" if($LocalUserCPG) { $cmd+=" $LocalUserCPG" } if ($UsrTargetName) { $cmd+=" $UsrTargetName" } if($TargetUserCPG) { $cmd+=":$TargetUserCPG " } } if($SnpCpg) { $cmd+=" -snp_cpg" if($LocalSnapCPG) { $cmd+=" $LocalSnapCPG" } if ($SnpTargetName) { $cmd+=" $SnpTargetName" } if($TargetSnapCPG) { $cmd+=":$TargetSnapCPG " } } if ($GroupName) { $cmd+=" $GroupName" } else { Write-DebugLog "Stop: GroupName is mandatory" $Debug return "Error : -GroupName is mandatory. " } if ($TargetName) { $cmd+=" $TargetName" } else { Write-DebugLog "Stop: TargetName is mandatory" $Debug return "Error : -TargetName is mandatory. " } if ($Mode) { $a = "sync","async","periodic" $l=$Mode if($a -eq $l) { $cmd+=":$Mode " } else { Write-DebugLog "Stop: Exiting New-RCopyGroupCPG since Mode $Mode in incorrect " Return "FAILURE : Mode :- $Mode is an Incorrect Mode [sync | async | periodic] can be used only . " } } else { Write-DebugLog "Stop: Mode is mandatory" $Debug return "Error : -Mode is mandatory. " } $Result = Invoke-CLICommand -Connection $SANConnection -cmds $cmd write-debuglog " The command creates a remote-copy volume group.. " "INFO:" if([string]::IsNullOrEmpty($Result)) { return "Success : Executing New-RCopyGroupCPG Command $Result" } else { return "FAILURE : While Executing New-RCopyGroupCPG $Result " } } # End New-RCopyGroupCPG #################################################################################################################### ## FUNCTION New-RCopyTarget #################################################################################################################### Function New-RCopyTarget { <# .SYNOPSIS The New-RCopyTarget command creates a remote-copy target definition. .DESCRIPTION The New-RCopyTarget command creates a remote-copy target definition. .EXAMPLE New-RCopyTarget -TargetName demo1 -RCIP -NSP_IP 1:2:3:10.1.1.1 This Example creates a remote-copy target, with option N_S_P_IP Node ,Slot ,Port and IP address. as 1:2:3:10.1.1.1 for Target Name demo1 .EXAMPLE New-RCopyTarget -TargetName demo1 -RCIP -NSP_IP "1:2:3:10.1.1.1,1:2:3:10.20.30.40" This Example creates a remote-copy with multiple targets .EXAMPLE New-RCopyTarget -TargetName demo1 -RCFC -Node_WWN 1122112211221122 -NSP_WWN 1:2:3:1122112211221122 This Example creates a remote-copy target, with option NSP_WWN Node ,Slot ,Port and WWN as 1:2:3:1122112211221122 for Target Name demo1 .EXAMPLE New-RCopyTarget -TargetName demo1 -RCFC -Node_WWN 1122112211221122 -NSP_WWN "1:2:3:1122112211221122,1:2:3:2244224422442244" This Example creates a remote-copy of FC with multiple targets .PARAMETER TargetName The name of the target definition to be created, specified by using up to 23 characters. .PARAMETER RCIP : remote copy over IP (RCIP). .PARAMETER RCFC : remote copy over Fibre Channel (RCFC). .PARAMETER Node_WWN The node's World Wide Name (WWN) on the target system (Fibre Channel target only). .PARAMETER NSP_IP Node number:Slot number:Port Number:IP Address of the Target to be created. .PARAMETER NSP_WWN Node number:Slot number:Port Number:World Wide Name (WWN) address on the target system. .PARAMETER SANConnection Specify the SAN Connection object created with New-CLIConnection or New-PoshSshConnection .Notes NAME: New-RCopyTarget LASTEDIT: December 2019 KEYWORDS: New-RCopyTarget .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$false, ValueFromPipeline=$true)] [switch] $RCIP, [Parameter(Position=1, Mandatory=$false, ValueFromPipeline=$true)] [switch] $RCFC, [Parameter(Position=2, Mandatory=$false, ValueFromPipeline=$true)] [switch] $Disabled, [Parameter(Position=3, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $TargetName, [Parameter(Position=4, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Node_WWN, [Parameter(Position=5, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $NSP_IP, [Parameter(Position=6, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $NSP_WWN, [Parameter(Position=7, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In New-RCopyTarget - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or the array address (FQDN/IP Address) or user credentials in the connection object are either null or incorrect. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" "ERR:" Write-DebugLog "Stop: Exiting New-RCopyTarget since SAN connection object values are null/empty" $Debug return "Unable to execute the cmdlet New-RCopyTarget since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $plinkresult = Test-PARCli if($plinkresult -match "FAILURE :") { write-debuglog "$plinkresult" "ERR:" return $plinkresult } $cmd= "creatercopytarget" if ($Disabled) { $cmd+=" -disabled " } if ($TargetName) { $cmd+=" $TargetName " } else { Write-DebugLog "Stop: -TargetName is mandatory" $Debug return "Error : -TargetName is mandatory. " } if ($RCIP) { if($RCFC) { return "FAILURE : Use either RCIP or RCFC" } else { $cmd+=" IP " } } if ($RCFC) { if($RCIP) { return "FAILURE : Use either RCIP or RCFC" } else { $cmd+=" FC " } } if($NSP_IP) { if($RCFC) { return "Error : -NSP_IP $NSP_IP cannot be used, Along with $RCFC. " } $s = $NSP_IP $s= [regex]::Replace($s,","," ") $cmd+="$s" } if ($Node_WWN) { if($RCIP) { return "Error : -Node_WWN $Node_WWN cannot be used, Along with $RCIP. " } $cmd+=" $Node_WWN " if ($NSP_WWN) { $s = $NSP_WWN $s= [regex]::Replace($s,","," ") $cmd+="$s" } } if ($cmd -eq "creatercopytarget") { write-debuglog "Error: no parameters passed " return get-help New-RCopyTarget } $Result = Invoke-CLICommand -Connection $SANConnection -cmds $cmd write-debuglog " The New-RCopyTarget command creates a remote-copy target definition. " "INFO:" if([string]::IsNullOrEmpty($Result)) { return "Success : Executing New-RCopyTarget Command " } else { return "FAILURE : While Executing New-RCopyTarget $Result " } } # End New-RCopyTarget ########################################################################## ######################### FUNCTION Remove-Cert ####################### ########################################################################## Function Remove-Cert() { <# .SYNOPSIS Remove-Cert - Removes SSL certificates from the Storage System. .DESCRIPTION The Remove-Cert command is used to remove certificates that are no longer trusted. In most cases it is better to overwrite the offending certificate with importcert. The user specifies which service to have its certificates removed. The removal can be limited to a specific type. .EXAMPLE Remove-Cert -SSL_Service_Name "xyz" -Type "xyz" .EXAMPLE Remove-Cert -SSL_Service_Name "all" -Type "xyz" .PARAMETER SSL_Service_Name Valid service names are cim, cli, ekm-client, ekm-server, ldap, syslog-gen-client, syslog-gen-server, syslog-sec-client, syslog-sec-server, wsapi, vasa, and unified-server. The user may also specify all, which will remove certificates for all services. .PARAMETER F Skips the prompt warning the user of which certificates will be removed and which services will be restarted. .PARAMETER Type Allows the user to limit the removal to a specific type. Note that types are cascading. For example, intca will cause the service certificate to also be removed. Valid types are csr, cert, intca, and rootca. .Notes NAME: Remove-Cert LASTEDIT December 2019 KEYWORDS: Remove-Cert .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$true)] [System.String] $SSL_Service_Name, [Parameter(Position=1, Mandatory=$false)] [switch] $F, [Parameter(Position=2, Mandatory=$false)] [System.String] $Type, [Parameter(Position=3, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In Remove-Cert - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or the array address (FQDN/IP Address) or user credentials in the connection object are either null or incorrect. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" " ERR: " Write-DebugLog "Stop: Exiting Remove-Cert since SAN connection object values are null/empty" $Debug Return "Unable to execute the cmdlet Remove-Cert since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $plinkresult = Test-PARCli -SANConnection $SANConnection if($plinkresult -match "FAILURE :") { write-debuglog "$plinkresult" Return $plinkresult } $Cmd = " removecert " if($SSL_Service_Name) { $Cmd += " $SSL_Service_Name " } if($F) { $Cmd += " -f " } if($Type) { $Cmd += " -type $Type " } $Result = Invoke-CLICommand -Connection $SANConnection -cmds $Cmd Write-DebugLog "Executing Function : Remove-Cert Command -->" INFO: Return $Result } ## End-of Remove-Cert ########################################################################## ######################### FUNCTION Measure-Upgrade ##################### ########################################################################## Function Measure-Upgrade() { <# .SYNOPSIS Measure-Upgrade - Determine if a system can do an online upgrade. (HIDDEN) .EXAMPLE .PARAMETER Allow_singlepathhost Overrides the default behavior of preventing an online upgrade if a host is at risk of losing connectivity to the array due to only having a single access path to the StoreServ. Use of this option will result in a loss of connectivity for the host when the path to the array disconnects as the node reboots to the new version. This option should be used with extreme caution. .PARAMETER Debug Display debug level information from check scripts. .PARAMETER Extraverbose Display test output, even for passing or not applicable scripts. .PARAMETER Getpostabortresults Displays results of the latest set of postabort scripts. .PARAMETER Getresults Displays results of the latest set of scripts that have been run (except postabort scripts). .PARAMETER Getworkarounds Displays information about workarounds that apply to an upgrade. .PARAMETER Nopatch Do not check for any checkupgrade update packages. .PARAMETER Offline Checks that apply only to online upgrades will be skipped. .PARAMETER Phase <phasename> Set of scripts to run. phasename can be any one of the following: postabort, postcheck, postchecklist, postunpack, preboot, precheck, prechecklist, preswitch, preupgrade, preupgradelist .PARAMETER Revertnode Used to check when reverting nodes as part of aborting an upgrade. .PARAMETER Verbose Display output from the checkupgrade update package check. .Notes NAME: Measure-Upgrade LASTEDIT: March 2020 KEYWORDS: Measure-Upgrade .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$false)] [switch] $Allow_singlepathhost, [Parameter(Position=1, Mandatory=$false)] [switch] $Extraverbose, [Parameter(Position=2, Mandatory=$false)] [switch] $Getpostabortresults, [Parameter(Position=3, Mandatory=$false)] [switch] $Getresults, [Parameter(Position=4, Mandatory=$false)] [switch] $Getworkarounds, [Parameter(Position=5, Mandatory=$false)] [switch] $Nopatch, [Parameter(Position=6, Mandatory=$false)] [switch] $Offline, [Parameter(Position=7, Mandatory=$false)] [System.String] $Phase, [Parameter(Position=8, Mandatory=$false)] [switch] $Revertnode, [Parameter(Position=9, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In Measure-Upgrade - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or the array address (FQDN/IP Address) or user credentials in the connection object are either null or incorrect. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" " ERR: " Write-DebugLog "Stop: Exiting Measure-Upgrade since SAN connection object values are null/empty" $Debug Return "Unable to execute the cmdlet Measure-Upgrade since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $plinkresult = Test-PARCli -SANConnection $SANConnection if($plinkresult -match "FAILURE :") { write-debuglog "$plinkresult" Return $plinkresult } $Cmd = " checkupgrade " if($Allow_singlepathhost) { $Cmd += " -allow_singlepathhost " } if($Debug) { $Cmd += " -debug " } if($Extraverbose) { $Cmd += " -extraverbose " } if($Getpostabortresults) { $Cmd += " -getpostabortresults " } if($Getresults) { $Cmd += " -getresults " } if($Getworkarounds) { $Cmd += " -getworkarounds " } if($Nopatch) { $Cmd += " -nopatch " } if($Offline) { $Cmd += " -offline " } if($Phase) { $Cmd += " -phase $Phase " } if($Revertnode) { $Cmd += " -revertnode " } if($Verbose) { $Cmd += " -verbose " } $Result = Invoke-CLICommand -Connection $SANConnection -cmds $Cmd Write-DebugLog "Executing Function : Measure-Upgrade Command -->" INFO: Return $Result } ## End-of Measure-Upgrade ########################################################################## ######################### FUNCTION Optimize-LD ####################### ########################################################################## Function Optimize-LD() { <# .SYNOPSIS Optimize-LD - Change the layout of a logical disk. (HIDDEN) .DESCRIPTION (HIDDEN) The Optimize-LD command is used to make changes to a logical disk (LD) by creating a new LD and moving regions from the original LD to the new LD. The new LD will always have the same space type (SA, SD, USR) as the original LD. If the original LD belongs to a CPG, the new LD inherits the characteristics of that CPG. SA and SD space LDs have growth and allocations blocked so the original LD can be completely emptied during the tune. If the original LD does not belong to a CPG, a new LD will be created, inheriting the characteristics of the original LD. When a new LD is created it will spread to whatever PDs are available as determined by availability and pattern rules. The options detailed below can be used to control some aspects of the new LD. .EXAMPLE .PARAMETER LD_name Name of the LD to tune. .PARAMETER Waittask Wait for the command to complete before returning. .PARAMETER DR Specifies that the command is a dry run and that the logical disk will not be tuned. The command will return any error messages that would be displayed or a summary of the actions that would be performed. .PARAMETER Shared Where possible, share the destination LDs and do not create new LDs. .PARAMETER Regions Number of regions to move at a time. Range is 1-1024, default is 1024. .PARAMETER Tunesys Only to be used when called from tunesys. When present, tuneld will update task information in the calling tunesys task with progress information. Also, when present tuneld will exit the CLI if certain errors occur, otherwise only an error will be displayed. .PARAMETER Tunenodech Only to be used when called from tunenodech. When present tuneld will exit the CLI if certain errors occur, otherwise only an error will be displayed. .PARAMETER Preserved Only to be used when source LD is in a preserved state. This option will move all good regions from the source LD to a new LD. .Notes NAME: Optimize-LD LASTEDIT: March 2020 KEYWORDS: Optimize-LD .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$false, ValueFromPipeline=$true)] [switch] $Waittask, [Parameter(Position=1, Mandatory=$false, ValueFromPipeline=$true)] [switch] $DR, [Parameter(Position=2, Mandatory=$false, ValueFromPipeline=$true)] [switch] $Shared, [Parameter(Position=3, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Regions, [Parameter(Position=4, Mandatory=$false, ValueFromPipeline=$true)] [switch] $Tunesys, [Parameter(Position=5, Mandatory=$false, ValueFromPipeline=$true)] [switch] $Tunenodech, [Parameter(Position=6, Mandatory=$false, ValueFromPipeline=$true)] [switch] $Preserved, [Parameter(Position=7, Mandatory=$true)] [System.String] $LD_name, [Parameter(Position=8, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In Optimize-LD - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or the array address (FQDN/IP Address) or user credentials in the connection object are either null or incorrect. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" " ERR: " Write-DebugLog "Stop: Exiting Optimize-LD since SAN connection object values are null/empty" $Debug Return "Unable to execute the cmdlet Optimize-LD since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $plinkresult = Test-PARCli -SANConnection $SANConnection if($plinkresult -match "FAILURE :") { write-debuglog "$plinkresult" Return $plinkresult } $Cmd = " tuneld -f " if($Waittask) { $Cmd += " -waittask " } if($DR) { $Cmd += " -dr " } if($Shared) { $Cmd += " -shared " } if($Regions) { $Cmd += " -regions $Regions " } if($Tunesys) { $Cmd += " -tunesys " } if($Tunenodech) { $Cmd += " -tunenodech " } if($Preserved) { $Cmd += " -preserved " } if($LD_name) { $Cmd += " $LD_name " } $Result = Invoke-CLICommand -Connection $SANConnection -cmds $Cmd Write-DebugLog "Executing Function : Optimize-LD Command -->" INFO: Return $Result } ## End-of Optimize-LD ########################################################################## ######################### FUNCTION Optimize-Nodech ####################### ########################################################################## Function Optimize-Nodech() { <# .SYNOPSIS Optimize-Nodech - Rebalance PD utilization on a node after upgrades. (HIDDEN) .DESCRIPTION The tunenodech command is used to analyze and detect poor layout and disk utilization across PDs with a specified node owner. Rebalancing is achieved using a combination of chunklet movement and re-laying out LDs associated with the node. .EXAMPLE .PARAMETER Node The ID of the node to be tuned. <number> must be in the range 0-7. This parameter must be supplied. .PARAMETER Chunkpct Controls the detection of underutilized PDs associated with a node. The average utilization of all PDs of a devtype is calculated and any PD with a utilization of (average - <percentage>) will trigger node tuning for that devtype. For example, if the average is 70% and <percentage> is 10%, then the threshold will be 60%. <percentage> must be between 1 and 100. The default value is 10. .PARAMETER Maxchunk Controls how many chunklets are moved from each PD per move operation. <number> must be between 1 and 8. The default value is 8. .PARAMETER Fulldiskpct If a PD has more than <percentage> of its capacity utilized, chunklet movement is used to reduce its usage to <percentage> before LD tuning is used to complete the rebalance. e.g. if a PD is 98% utilized and <percentage> is 90, chunklets will be redistributed to other PDs until the utilization is less than 90%. If <percentage> is less than the devtype average then the calculated average will be used instead. <percentage> must be between 1 and 100. The default value is 90. .PARAMETER Devtype Specifies a comma separated list of one or more devtypes to be tuned. <devtype> can be one of SSD, FC or NL. Default is all devtypes. All named devtypes must be present on the node being tuned. .PARAMETER DR Perform a dry-run analysis of the system and report details on what tuning would be performed with the supplied settings. .Notes NAME: Optimize-Nodech LASTEDIT: March 2020 KEYWORDS: Optimize-Nodech .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Node, [Parameter(Position=1, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Chunkpct, [Parameter(Position=2, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Maxchunk, [Parameter(Position=3, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Fulldiskpct, [Parameter(Position=4, Mandatory=$false, ValueFromPipeline=$true)] [System.String] $Devtype, [Parameter(Position=5, Mandatory=$false, ValueFromPipeline=$true)] [switch] $DR, [Parameter(Position=6, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In Optimize-Nodech - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or the array address (FQDN/IP Address) or user credentials in the connection object are either null or incorrect. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" " ERR: " Write-DebugLog "Stop: Exiting Optimize-Nodech since SAN connection object values are null/empty" $Debug Return "Unable to execute the cmdlet Optimize-Nodech since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $plinkresult = Test-PARCli -SANConnection $SANConnection if($plinkresult -match "FAILURE :") { write-debuglog "$plinkresult" Return $plinkresult } $Cmd = " tunenodech -f " if($Node) { $Cmd += " -node $Node " } if($Chunkpct) { $Cmd += " -chunkpct $Chunkpct " } if($Maxchunk) { $Cmd += " -maxchunk $Maxchunk " } if($Fulldiskpct) { $Cmd += " -fulldiskpct $Fulldiskpct " } if($Devtype) { $Cmd += " -devtype $Devtype " } if($DR) { $Cmd += " -dr " } $Result = Invoke-CLICommand -Connection $SANConnection -cmds $Cmd Write-DebugLog "Executing Function : Optimize-Nodech Command -->" INFO: Return $Result } ## End-of Optimize-Nodech ################################################################################# ############################ Function Start-SR ################################## ################################################################################# Function Start-SR { <# .SYNOPSIS To start System reporter. .DESCRIPTION To start System reporter. .EXAMPLE Start-SR Starts System Reporter .PARAMETER SANConnection Specify the SAN Connection object created with New-CLIConnection or New-PoshSshConnection .Notes NAME: Start-SR LASTEDIT: March 2020 KEYWORDS: Start-SR .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In Start-SR - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or Connection object username, password, IPAaddress are null/empty. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" "ERR:" Write-DebugLog "Stop: Exiting Start-SR since SAN connection object values are null/empty" $Debug return "Unable to execute the cmdlet Start-SR since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $cliresult1 = Test-PARCli -SANConnection $SANConnection if(($cliresult1 -match "FAILURE :")) { write-debuglog "$cliresult1" "ERR:" return $cliresult1 } $srinfocmd = "startsr -f " write-debuglog "System reporter command => $srinfocmd" "INFO:" $3parosver = Get-Version -S -SANConnection $SANConnection if($3parosver -ge "3.1.2") { $Result = Invoke-CLICommand -Connection $SANConnection -cmds $srinfocmd if(-not $Result) { return "Success: Started System Reporter $Result" } elseif($Result -match "Cannot startsr, already started") { Return "Command Execute Successfully :- Cannot startsr, already started" } else { return $Result } } else { return "Current version $3parosver does not support these cmdlet" } } #### End Start-SR ################################################################################# ############################ Function Stop-SR ################################### ################################################################################# Function Stop-SR { <# .SYNOPSIS To stop System reporter. .DESCRIPTION To stop System reporter. .EXAMPLE Stop-SR Stop System Reporter .PARAMETER SANConnection Specify the SAN Connection object created with New-CLIConnection or New-PoshSshConnection .Notes NAME: Stop-SR LASTEDIT: March 2020 KEYWORDS: Stop-SR .Link http://www.hpe.com #Requires PS -Version 3.0 #> [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$false, ValueFromPipeline=$true)] $SANConnection = $global:SANConnection ) Write-DebugLog "Start: In Stop-SR - validating input values" $Debug #check if connection object contents are null/empty if(!$SANConnection) { #check if connection object contents are null/empty $Validate1 = Test-CLIConnection $SANConnection if($Validate1 -eq "Failed") { #check if global connection object contents are null/empty $Validate2 = Test-CLIConnection $global:SANConnection if($Validate2 -eq "Failed") { Write-DebugLog "Connection object is null/empty or Connection object username, password, IPAaddress are null/empty. Create a valid connection object using New-CLIConnection or New-PoshSshConnection" "ERR:" Write-DebugLog "Stop: Exiting Stop-SR since SAN connection object values are null/empty" $Debug return "Unable to execute the cmdlet Stop-SR since no active storage connection session exists. `nUse New-PoshSSHConnection or New-CLIConnection to start a new storage connection session." } } } $cliresult1 = Test-PARCli -SANConnection $SANConnection if(($cliresult1 -match "FAILURE :")) { write-debuglog "$cliresult1" "ERR:" return $cliresult1 } $srinfocmd = "stopsr -f " $3parosver = Get-Version -S -SANConnection $SANConnection write-debuglog "System reporter command => $srinfocmd" "INFO:" if($3parosver -ge "3.1.2") { $Result = Invoke-CLICommand -Connection $SANConnection -cmds $srinfocmd if(-not $Result) { return "Success: Stopped System Reporter $Result" } else { return $Result } } else { return "Current OS version $3parosver does not support these cmdlet" } } #### End Stop-SR Export-ModuleMember Get-Cert , Get-Encryption , Get-SR , Import-Cert , New-Cert , New-RCopyGroup , New-RCopyGroupCPG , New-RCopyTarget , Remove-Cert , Measure-Upgrade , Optimize-LD , Optimize-Nodech , Start-SR , Stop-SR # SIG # Begin signature block # MIIh0AYJKoZIhvcNAQcCoIIhwTCCIb0CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCm/R+he5BmF3yw # 6yPqiLXxw/CBuz4btUb1atgidRt3UKCCEKswggUpMIIEEaADAgECAhB4Lu4fcD9z # xUgD+jf1OoqlMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAkdCMRswGQYDVQQI # ExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoT # D1NlY3RpZ28gTGltaXRlZDEkMCIGA1UEAxMbU2VjdGlnbyBSU0EgQ29kZSBTaWdu # aW5nIENBMB4XDTIxMDUyODAwMDAwMFoXDTIyMDUyODIzNTk1OVowgZAxCzAJBgNV # BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlQYWxvIEFsdG8x # KzApBgNVBAoMIkhld2xldHQgUGFja2FyZCBFbnRlcnByaXNlIENvbXBhbnkxKzAp # BgNVBAMMIkhld2xldHQgUGFja2FyZCBFbnRlcnByaXNlIENvbXBhbnkwggEiMA0G # CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDmclZSXJBXA55ijwwFymuq+Y4F/quF # mm2vRdEmjFhzRvTpnGjIYtVcG11ka4JGCROmNVDZGAelnqcXn5DKO710j5SICTBC # 5gXOLwga7usifs21W+lVT0BsZTiUnFu4hEhuFTlahJIEvPGVgO1GBcuItD2QqB4q # 9j15GDI5nGBSzIyJKMctcIalxsTSPG1kiDbLkdfsIivhe9u9m8q6NRqDUaYYQTN+ # /qGCqVNannMapH8tNHqFb6VdzUFI04t7kFtSk00AkdD6qUvA4u8mL2bUXAYz8K5m # nrFs+ckx5Yqdxfx68EO26Bt2qbz/oTHxE6FiVzsDl90bcUAah2l976ebAgMBAAGj # ggGQMIIBjDAfBgNVHSMEGDAWgBQO4TqoUzox1Yq+wbutZxoDha00DjAdBgNVHQ4E # FgQUlC56g+JaYFsl5QWK2WDVOsG+pCEwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB # /wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEQYJYIZIAYb4QgEBBAQDAgQQMEoG # A1UdIARDMEEwNQYMKwYBBAGyMQECAQMCMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8v # c2VjdGlnby5jb20vQ1BTMAgGBmeBDAEEATBDBgNVHR8EPDA6MDigNqA0hjJodHRw # Oi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29SU0FDb2RlU2lnbmluZ0NBLmNybDBz # BggrBgEFBQcBAQRnMGUwPgYIKwYBBQUHMAKGMmh0dHA6Ly9jcnQuc2VjdGlnby5j # b20vU2VjdGlnb1JTQUNvZGVTaWduaW5nQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRw # Oi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAY+1n2UUlQU6Z # VoEVaZKqZf/zrM/d7Kbx+S/t8mR2E+uNXStAnwztElqrm3fSr+5LMRzBhrYiSmea # w9c/0c7qFO9mt8RR2q2uj0Huf+oAMh7TMuMKZU/XbT6tS1e15B8ZhtqOAhmCug6s # DuNvoxbMpokYevpa24pYn18ELGXOUKlqNUY2qOs61GVvhG2+V8Hl/pajE7yQ4diz # iP7QjMySms6BtZV5qmjIFEWKY+UTktUcvN4NVA2J0TV9uunDbHRt4xdY8TF/Clgz # Z/MQHJ/X5yX6kupgDeN2t3o+TrColetBnwk/SkJEsUit0JapAiFUx44j4w61Qanb # Zmi0tr8YGDCCBYEwggRpoAMCAQICEDlyRDr5IrdR19NsEN0xNZUwDQYJKoZIhvcN # AQEMBQAwezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3Rl # cjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQx # ITAfBgNVBAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0xOTAzMTIwMDAw # MDBaFw0yODEyMzEyMzU5NTlaMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3 # IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VS # VFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0 # aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIAS # ZRc2DsPbCLPQrFcNdu3NJ9NMrVCDYeKqIE0JLWQJ3M6Jn8w9qez2z8Hc8dOx1ns3 # KBErR9o5xrw6GbRfpr19naNjQrZ28qk7K5H44m/Q7BYgkAk+4uh0yRi0kdRiZNt/ # owbxiBhqkCI8vP4T8IcUe/bkH47U5FHGEWdGCFHLhhRUP7wz/n5snP8WnRi9UY41 # pqdmyHJn2yFmsdSbeAPAUDrozPDcvJ5M/q8FljUfV1q3/875PbcstvZU3cjnEjpN # rkyKt1yatLcgPcp/IjSufjtoZgFE5wFORlObM2D3lL5TN5BzQ/Myw1Pv26r+dE5p # x2uMYJPexMcM3+EyrsyTO1F4lWeL7j1W/gzQaQ8bD/MlJmszbfduR/pzQ+V+DqVm # sSl8MoRjVYnEDcGTVDAZE6zTfTen6106bDVc20HXEtqpSQvf2ICKCZNijrVmzyWI # zYS4sT+kOQ/ZAp7rEkyVfPNrBaleFoPMuGfi6BOdzFuC00yz7Vv/3uVzrCM7LQC/ # NVV0CUnYSVgaf5I25lGSDvMmfRxNF7zJ7EMm0L9BX0CpRET0medXh55QH1dUqD79 # dGMvsVBlCeZYQi5DGky08CVHWfoEHpPUJkZKUIGy3r54t/xnFeHJV4QeD2PW6WK6 # 1l9VLupcxigIBCU5uA4rqfJMlxwHPw1S9e3vL4IPAgMBAAGjgfIwge8wHwYDVR0j # BBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYDVR0OBBYEFFN5v1qqK0rPVIDh # 2JvAnfKyA2bLMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MBEGA1Ud # IAQKMAgwBgYEVR0gADBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsLmNvbW9k # b2NhLmNvbS9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDA0BggrBgEFBQcBAQQo # MCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTANBgkqhkiG # 9w0BAQwFAAOCAQEAGIdR3HQhPZyK4Ce3M9AuzOzw5steEd4ib5t1jp5y/uTW/qof # nJYt7wNKfq70jW9yPEM7wD/ruN9cqqnGrvL82O6je0P2hjZ8FODN9Pc//t64tIrw # kZb+/UNkfv3M0gGhfX34GRnJQisTv1iLuqSiZgR2iJFODIkUzqJNyTKzuugUGrxx # 8VvwQQuYAAoiAxDlDLH5zZI3Ge078eQ6tvlFEyZ1r7uq7z97dzvSxAKRPRkA0xdc # Ods/exgNRc2ThZYvXd9ZFk8/Ub3VRRg/7UqO6AZhdCMWtQ1QcydER38QXYkqa4Ux # FMToqWpMgLxqeM+4f452cpkMnf7XkQgWoaNflTCCBfUwggPdoAMCAQICEB2iSDBv # myYY0ILgln0z02owDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMV # VGhlIFVTRVJUUlVTVCBOZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENl # cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTE4MTEwMjAwMDAwMFoXDTMwMTIzMTIz # NTk1OVowfDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3Rl # cjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQw # IgYDVQQDExtTZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqGSIb3 # DQEBAQUAA4IBDwAwggEKAoIBAQCGIo0yhXoYn0nwli9jCB4t3HyfFM/jJrYlZilA # hlRGdDFixRDtsocnppnLlTDAVvWkdcapDlBipVGREGrgS2Ku/fD4GKyn/+4uMyD6 # DBmJqGx7rQDDYaHcaWVtH24nlteXUYam9CflfGqLlR5bYNV+1xaSnAAvaPeX7Wpy # vjg7Y96Pv25MQV0SIAhZ6DnNj9LWzwa0VwW2TqE+V2sfmLzEYtYbC43HZhtKn52B # xHJAteJf7wtF/6POF6YtVbC3sLxUap28jVZTxvC6eVBJLPcDuf4vZTXyIuosB69G # 2flGHNyMfHEo8/6nxhTdVZFuihEN3wYklX0Pp6F8OtqGNWHTAgMBAAGjggFkMIIB # YDAfBgNVHSMEGDAWgBRTeb9aqitKz1SA4dibwJ3ysgNmyzAdBgNVHQ4EFgQUDuE6 # qFM6MdWKvsG7rWcaA4WtNA4wDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYB # Af8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwMGCCsGAQUFBwMIMBEGA1UdIAQKMAgw # BgYEVR0gADBQBgNVHR8ESTBHMEWgQ6BBhj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5j # b20vVVNFUlRydXN0UlNBQ2VydGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwdgYIKwYB # BQUHAQEEajBoMD8GCCsGAQUFBzAChjNodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20v # VVNFUlRydXN0UlNBQWRkVHJ1c3RDQS5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9v # Y3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggIBAE1jUO1HNEphpNve # aiqMm/EAAB4dYns61zLC9rPgY7P7YQCImhttEAcET7646ol4IusPRuzzRl5ARokS # 9At3WpwqQTr81vTr5/cVlTPDoYMot94v5JT3hTODLUpASL+awk9KsY8k9LOBN9O3 # ZLCmI2pZaFJCX/8E6+F0ZXkI9amT3mtxQJmWunjxucjiwwgWsatjWsgVgG10Xkp1 # fqW4w2y1z99KeYdcx0BNYzX2MNPPtQoOCwR/oEuuu6Ol0IQAkz5TXTSlADVpbL6f # ICUQDRn7UJBhvjmPeo5N9p8OHv4HURJmgyYZSJXOSsnBf/M6BZv5b9+If8AjntIe # Q3pFMcGcTanwWbJZGehqjSkEAnd8S0vNcL46slVaeD68u28DECV3FTSK+TbMQ5Lk # uk/xYpMoJVcp+1EZx6ElQGqEV8aynbG8HArafGd+fS7pKEwYfsR7MUFxmksp7As9 # V1DSyt39ngVR5UR43QHesXWYDVQk/fBO4+L4g71yuss9Ou7wXheSaG3IYfmm8SoK # C6W59J7umDIFhZ7r+YMp08Ysfb06dy6LN0KgaoLtO0qqlBCk4Q34F8W2WnkzGJLj # tXX4oemOCiUe5B7xn1qHI/+fpFGe+zmAEc3btcSnqIBv5VPU4OOiwtJbGvoyJi1q # V3AcPKRYLqPzW0sH3DJZ84enGm1YMYIQezCCEHcCAQEwgZAwfDELMAkGA1UEBhMC # R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9y # ZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQwIgYDVQQDExtTZWN0aWdvIFJT # QSBDb2RlIFNpZ25pbmcgQ0ECEHgu7h9wP3PFSAP6N/U6iqUwDQYJYIZIAWUDBAIB # BQCgfDAQBgorBgEEAYI3AgEMMQIwADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIB # BDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg # y2Zq94KlWptcPMa2JayPQEh7wbT5NmZq6b8agkyxfggwDQYJKoZIhvcNAQEBBQAE # ggEAi+2lkaxtdO8KghrbDCBFr30V4va/ArKT04hl0r9wdHxMndd71+R7Ip9nZsqz # LZCI5/0NItznfkxPkDqW+Nw1BUHyvOGG9yKL1Zeka707CWVKAI/txcHE2PlwLeKT # zlF1mlHRP1Or0V1X+wXdUdMCT71If6ie4SS/zWFAlB+8m1iIY/zYIsFOzw0y/Amk # pCF2XpZMrzuQq4zM1cbv7d/MBNIg50xyxkN7QCHWdn2reuDnlxTfgSf11coIjqUY # n+ZZ7Y2j7os61lioRgrKEMy1vkDnHJww0bXnHGLrWJhrpzKmH0eBDxfmUscNPAVd # uiLoDTbfkKUBS2erR32YEOaL7aGCDj0wgg45BgorBgEEAYI3AwMBMYIOKTCCDiUG # CSqGSIb3DQEHAqCCDhYwgg4SAgEDMQ0wCwYJYIZIAWUDBAIBMIIBDwYLKoZIhvcN # AQkQAQSggf8EgfwwgfkCAQEGC2CGSAGG+EUBBxcDMDEwDQYJYIZIAWUDBAIBBQAE # IBVY4J9AvZRWqASoIDI8MaKvuJlvfRFR7lV1+dR1JsY0AhUAltqbLyMY8HR73OtO # L3k0asRWWloYDzIwMjEwNjE5MDQyNzIzWjADAgEeoIGGpIGDMIGAMQswCQYDVQQG # EwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5 # bWFudGVjIFRydXN0IE5ldHdvcmsxMTAvBgNVBAMTKFN5bWFudGVjIFNIQTI1NiBU # aW1lU3RhbXBpbmcgU2lnbmVyIC0gRzOgggqLMIIFODCCBCCgAwIBAgIQewWx1Elo # UUT3yYnSnBmdEjANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UEBhMCVVMxFzAVBgNV # BAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3 # b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo # b3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9v # dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNjAxMTIwMDAwMDBaFw0zMTAx # MTEyMzU5NTlaMHcxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jw # b3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEoMCYGA1UE # AxMfU3ltYW50ZWMgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTCCASIwDQYJKoZIhvcN # AQEBBQADggEPADCCAQoCggEBALtZnVlVT52Mcl0agaLrVfOwAa08cawyjwVrhpon # ADKXak3JZBRLKbvC2Sm5Luxjs+HPPwtWkPhiG37rpgfi3n9ebUA41JEG50F8eRzL # y60bv9iVkfPw7mz4rZY5Ln/BJ7h4OcWEpe3tr4eOzo3HberSmLU6Hx45ncP0mqj0 # hOHE0XxxxgYptD/kgw0mw3sIPk35CrczSf/KO9T1sptL4YiZGvXA6TMU1t/HgNuR # 7v68kldyd/TNqMz+CfWTN76ViGrF3PSxS9TO6AmRX7WEeTWKeKwZMo8jwTJBG1kO # qT6xzPnWK++32OTVHW0ROpL2k8mc40juu1MO1DaXhnjFoTcCAwEAAaOCAXcwggFz # MA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMGYGA1UdIARfMF0w # WwYLYIZIAYb4RQEHFwMwTDAjBggrBgEFBQcCARYXaHR0cHM6Ly9kLnN5bWNiLmNv # bS9jcHMwJQYIKwYBBQUHAgIwGRoXaHR0cHM6Ly9kLnN5bWNiLmNvbS9ycGEwLgYI # KwYBBQUHAQEEIjAgMB4GCCsGAQUFBzABhhJodHRwOi8vcy5zeW1jZC5jb20wNgYD # VR0fBC8wLTAroCmgJ4YlaHR0cDovL3Muc3ltY2IuY29tL3VuaXZlcnNhbC1yb290 # LmNybDATBgNVHSUEDDAKBggrBgEFBQcDCDAoBgNVHREEITAfpB0wGzEZMBcGA1UE # AxMQVGltZVN0YW1wLTIwNDgtMzAdBgNVHQ4EFgQUr2PWyqNOhXLgp7xB8ymiOH+A # dWIwHwYDVR0jBBgwFoAUtnf6aUhHn1MS1cLqBzJ2B9GXBxkwDQYJKoZIhvcNAQEL # BQADggEBAHXqsC3VNBlcMkX+DuHUT6Z4wW/X6t3cT/OhyIGI96ePFeZAKa3mXfSi # 2VZkhHEwKt0eYRdmIFYGmBmNXXHy+Je8Cf0ckUfJ4uiNA/vMkC/WCmxOM+zWtJPI # TJBjSDlAIcTd1m6JmDy1mJfoqQa3CcmPU1dBkC/hHk1O3MoQeGxCbvC2xfhhXFL1 # TvZrjfdKer7zzf0D19n2A6gP41P3CnXsxnUuqmaFBJm3+AZX4cYO9uiv2uybGB+q # ueM6AL/OipTLAduexzi7D1Kr0eOUA2AKTaD+J20UMvw/l0Dhv5mJ2+Q5FL3a5NPD # 6itas5VYVQR9x5rsIwONhSrS/66pYYEwggVLMIIEM6ADAgECAhB71OWvuswHP6EB # IwQiQU0SMA0GCSqGSIb3DQEBCwUAMHcxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRT # eW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0 # d29yazEoMCYGA1UEAxMfU3ltYW50ZWMgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTAe # Fw0xNzEyMjMwMDAwMDBaFw0yOTAzMjIyMzU5NTlaMIGAMQswCQYDVQQGEwJVUzEd # MBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVj # IFRydXN0IE5ldHdvcmsxMTAvBgNVBAMTKFN5bWFudGVjIFNIQTI1NiBUaW1lU3Rh # bXBpbmcgU2lnbmVyIC0gRzMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQCvDoqq+Ny/aXtUF3FHCb2NPIH4dBV3Z5Cc/d5OAp5LdvblNj5l1SQgbTD53R2D # 6T8nSjNObRaK5I1AjSKqvqcLG9IHtjy1GiQo+BtyUT3ICYgmCDr5+kMjdUdwDLNf # W48IHXJIV2VNrwI8QPf03TI4kz/lLKbzWSPLgN4TTfkQyaoKGGxVYVfR8QIsxLWr # 8mwj0p8NDxlsrYViaf1OhcGKUjGrW9jJdFLjV2wiv1V/b8oGqz9KtyJ2ZezsNvKW # lYEmLP27mKoBONOvJUCbCVPwKVeFWF7qhUhBIYfl3rTTJrJ7QFNYeY5SMQZNlANF # xM48A+y3API6IsW0b+XvsIqbAgMBAAGjggHHMIIBwzAMBgNVHRMBAf8EAjAAMGYG # A1UdIARfMF0wWwYLYIZIAYb4RQEHFwMwTDAjBggrBgEFBQcCARYXaHR0cHM6Ly9k # LnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUHAgIwGRoXaHR0cHM6Ly9kLnN5bWNiLmNv # bS9ycGEwQAYDVR0fBDkwNzA1oDOgMYYvaHR0cDovL3RzLWNybC53cy5zeW1hbnRl # Yy5jb20vc2hhMjU2LXRzcy1jYS5jcmwwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgw # DgYDVR0PAQH/BAQDAgeAMHcGCCsGAQUFBwEBBGswaTAqBggrBgEFBQcwAYYeaHR0 # cDovL3RzLW9jc3Aud3Muc3ltYW50ZWMuY29tMDsGCCsGAQUFBzAChi9odHRwOi8v # dHMtYWlhLndzLnN5bWFudGVjLmNvbS9zaGEyNTYtdHNzLWNhLmNlcjAoBgNVHREE # ITAfpB0wGzEZMBcGA1UEAxMQVGltZVN0YW1wLTIwNDgtNjAdBgNVHQ4EFgQUpRMB # qZ+FzBtuFh5fOzGqeTYAex0wHwYDVR0jBBgwFoAUr2PWyqNOhXLgp7xB8ymiOH+A # dWIwDQYJKoZIhvcNAQELBQADggEBAEaer/C4ol+imUjPqCdLIc2yuaZycGMv41Up # ezlGTud+ZQZYi7xXipINCNgQujYk+gp7+zvTYr9KlBXmgtuKVG3/KP5nz3E/5jMJ # 2aJZEPQeSv5lzN7Ua+NSKXUASiulzMub6KlN97QXWZJBw7c/hub2wH9EPEZcF1rj # pDvVaSbVIX3hgGd+Yqy3Ti4VmuWcI69bEepxqUH5DXk4qaENz7Sx2j6aescixXTN # 30cJhsT8kSWyG5bphQjo3ep0YG5gpVZ6DchEWNzm+UgUnuW/3gC9d7GYFHIUJN/H # ESwfAD/DSxTGZxzMHgajkF9cVIs+4zNbgg/Ft4YCTnGf6WZFP3YxggJaMIICVgIB # ATCBizB3MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRp # b24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMTH1N5 # bWFudGVjIFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0ECEHvU5a+6zAc/oQEjBCJBTRIw # CwYJYIZIAWUDBAIBoIGkMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkq # hkiG9w0BCQUxDxcNMjEwNjE5MDQyNzIzWjAvBgkqhkiG9w0BCQQxIgQg/GB29ymb # H/oBtVzxky/vC9HhWwF+UvmElHdeETCDwMcwNwYLKoZIhvcNAQkQAi8xKDAmMCQw # IgQgxHTOdgB9AjlODaXk3nwUxoD54oIBPP72U+9dtx/fYfgwCwYJKoZIhvcNAQEB # BIIBAIwi5NbGtV8V9PDr8vj2y/TZjxF5JVkGETms/FSWtlbKWaJf7YOqBqJpH43i # ZXE7I5SE2XnNWZJruXi5fWGDGL8QKr/mTQu/M10apM43I5NGy+w0jJK7A72aSxkZ # 164INn3mu6cCsaKbacESMTekdxFk/aDJBuv4z3h9LKY4DXRptpeaFQcp1yty21Dg # jN8b8qhtbWg2b3g3LydrOVux64Vzf0kyeBqrku66fxvOVwp1U1lw3W4MD+2pGsRU # 5+MjLWcIkex/BK0Eljx10ziDnKjLMJIqQhheBORMnKclzOH8bEr6PrAXDJeoUanf # imK0Y1O9YGDxNZcCTea0rREDdRk= # SIG # End signature block |