JSDR.Configuration.psm1
<# Prerequisite: ============= 1. Module VMware.vSphere.SsoAdmin should be present 2. CloudAdmin role is present within vcenter 3. powershell version > 6 #> function Get-JetDR { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION This function downloads JetStream DR software from MMS .PARAMETER Url Url of the bundle to download .PARAMETER DownloadPath Path where the bundle has to be downloaded .EXAMPLE Get-JetDR -Url https://example.com/file.zip -DownloadPath /home/user/downloads #> [CmdletBinding()] param( [Parameter(Mandatory=$true, HelpMessage="Url of the bundle to download")] [string]$Url, [Parameter(Mandatory=$true, HelpMessage="Download location")] [string]$DownloadPath ) Process { $Filename = Split-Path $Url -Leaf $download_file_path = $DownloadPath + '/' + $Filename download_jetdr_bundle $Url $download_file_path } } function Expand-JetDR { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION This function unzips JetStream DR software .PARAMETER Filename Name of the bundle .PARAMETER FilePath Path where the bundle is located .PARAMETER UnzipPath Path where bundle will be unzipped .EXAMPLE Expand-JetDR -FileName file.zip -FilePath /home/user/downloads/ -UnzipPath /home/user/downloads/jsdr/ #> [CmdletBinding()] param( [Parameter(Mandatory=$true, HelpMessage="Name of the bundle")] [string]$Filename, [Parameter(Mandatory=$true, HelpMessage="Bundle location")] [string]$FilePath, [Parameter(Mandatory=$true, HelpMessage="Unzip location")] [string]$UnzipPath ) Process { $js_download_path = $FilePath + '/' + $Filename unzip_ova $js_download_path $UnzipPath } } function Deploy-JetDRMSA { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION This function deploys JetStream DR Management Server Appliance(MSA), powers it on and waits for all services to be running .PARAMETER OvfPath Full path of the ova file .PARAMETER Network Network for the MSA, e.g "VM Network" .PARAMETER Hostname Hostname of the MSA .PARAMETER MSACredential MSACredential of root user .PARAMETER Gateway Gateway of MSA .PARAMETER Dns DNS IP that MSA should use .PARAMETER Ip IP of MSA .PARAMETER Netmask Netmask of MSA .PARAMETER VlanId VLAN Tag ID for MSA to be deployed (Leave blank if NA) .PARAMETER Cluster Cluster name where MSA needs to be deployed .PARAMETER VmName Name of the MSA VM .PARAMETER Datastore Datastore where the MSA has to be deployed .EXAMPLE Deploy-JetDRMSA -OvfPath /home/user/downloads/jsdr.ova -Network "VM Network" -Hostname msavm.example.com -MSACredential <root/PSCredential object> -Gateway xxx.xxx.xxx.xxx -Dns xxx.xxx.xxx.xxx -Ip xxx.xxx.xxx.xxx -Netmask xxx.xxx.xxx.xxx -VlanId 101 -Cluster Test-Cluster -VmName JS-MSA -Datastore md3817 #> [CmdletBinding()] param( [Parameter(Mandatory=$true, HelpMessage="Location of the ova")] [string]$OvfPath, [Parameter(Mandatory=$true, HelpMessage="Location of the ova signature")] [string]$SignaturePath, [Parameter(Mandatory=$true, HelpMessage="Network device for MSA")] [string]$Network, [Parameter(Mandatory=$false, HelpMessage="Hostname of MSA")] [string]$Hostname, [Parameter(Mandatory=$true, HelpMessage="MSA Credentials of root user")] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential, [Parameter(Mandatory=$false, HelpMessage="Gateway for MSA")] [string]$Gateway, [Parameter(Mandatory=$false, HelpMessage="DNS IP that MSA should use")] [string]$Dns, [Parameter(Mandatory=$false, HelpMessage="IP for MSA")] [string]$Ip, [Parameter(Mandatory=$false, HelpMessage="Netmask for MSA")] [string]$Netmask, [Parameter(Mandatory=$false, HelpMessage="VLAN Tag ID for MSA VM to be deployed. (Leave blank if NA)")] [String]$VlanId, [Parameter(Mandatory=$true, HelpMessage="Cluster name where MSA will be deployed")] [string]$Cluster, [Parameter(Mandatory=$true, HelpMessage="Vm name for MSA")] [string]$VmName, [Parameter(Mandatory=$true, HelpMessage="Datastore where MSA will be deployed")] [string]$Datastore ) Process { $SecureFolder = [AVSSecureFolder]::GetOrCreate("js-appliance") if ($null -eq $SecureFolder) { Write-Error "Could not create secure folder to deploy MSA. Contact JetStream support for help." -ErrorAction Stop } $Password=$MSACredential.GetNetworkCredential().Password $mycluster=Get-Cluster -Name $Cluster $msa=Get-VM -Name $VmName -Location $mycluster -ErrorAction SilentlyContinue if ($null -ne $msa) { write-host "MSA VM with the same name already exists in the Cluster $Cluster. Skipping creation" if($msa.PowerState -eq 'PoweredOff') { write-host "MSA VM is powered off, powering it on" start-vm $msa -confirm:$false | Out-Null if (!$?) { write-host "Starting MSA VM failed" break } } $vm_ip=get_vm_ip $VmName 600 $rc=ms_rest_state $vm_ip "root" $Password 600 if (!$rc) { write-host "Failed to ping $vm_ip after 600 seconds" break } write-host "Sleep for 2 more minute after Manamgement server becomes pingable" start-sleep 120 } else { # Deploy the Management server appliance from the ova $vm_ip=deploy_ova $OvfPath $SignaturePath $Network $Hostname $Password $Gateway $Dns $Ip $Netmask $VlanId $Cluster $VmName $Datastore $SecureFolder } [AVSSecureFolder]::Secure($SecureFolder) return $vm_ip } } function Add-User { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION This function creates a new sso user .PARAMETER Username Username of the new sso user .PARAMETER Password Password of the new sso user .EXAMPLE Add-User -Username vsphere.local\tmpuser -Password *** #> [CmdletBinding()] param( [Parameter(Mandatory=$true, HelpMessage="New sso username")] [string]$Username, [Parameter(Mandatory=$true, HelpMessage="Password of new sso user")] [string]$Password ) Process { $domain = $Username.split("\")[0] $user = $Username.split("\")[1] $ssouser = Get-SsoPersonUser -Name $user -Domain $domain if($ssouser) { write-host "User $Username already exists. Deleting before creating again." delete_user $Username start-sleep 5 } create_user $user $Password } } function Remove-User { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION This function deletes an sso user .PARAMETER Username Username of the sso user .EXAMPLE Remove-User -Username vsphere.local\tmpuser #> [CmdletBinding()] param( [Parameter(Mandatory=$true, HelpMessage="sso username")] [string]$Username ) Process { delete_user $Username Write-Host "Script execution has completed. Please check status of the task for success/failure" } } function New-Role { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION This function creates a new role JSDR-elevated and assigns that role to the user created by Add-User .PARAMETER Username Username of the new sso user .PARAMETER Role Type of role to be created, elevated or operations .EXAMPLE New-Role -Username vsphere.local\tmpuser -Role elevated New-Role -Username vsphere.local\tmpuser -Role operations #> [CmdletBinding()] param( [Parameter(Mandatory=$true, HelpMessage="New sso username")] [string]$Username, [Parameter(Mandatory=$true, HelpMessage="Type of role. Either elevated or operations")] [string]$Role ) Begin { $extra_full_privilleges = "Maintenance", "Query patch", "CIM interaction", "Profile-driven storage update", "Register extension", "Unregister extension", "Update extension", "Security Profile and Firewall" $op_privilleges = "Register extension", "Unregister extension", "Update extension", "CIM interaction" } Process { if($Role -eq 'elevated') { $role = "JSDR-elevated" $privilleges = $extra_full_privilleges } elseif($Role -eq 'operations') { $role = "JSDR-operations" $privilleges = $op_privilleges } else { write-host "Invalid role specified. Must be one of 'elevated' or 'operations'" break } assign_new_role_to_user $role $Username $privilleges } } function Register-MS { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION This function registers JetStream MSA with vCenter .PARAMETER MS Management server ip/fqdn .PARAMETER MsaUser Management server user, e.g root .PARAMETER MsaPassword Management server password for MsaUser .PARAMETER VC vCenter ip/fqdn .PARAMETER Username Username of the new sso user, e.g vsphere.local\tmpuser .PARAMETER Password Password of the new sso user .PARAMETER RegisterWithIp Register MSA with IP instead of hostname .PARAMETER Mode Mode in which MSA has to be registered, e.g 'C2C' .EXAMPLE Register-MS -MS xxx.xxx.xxx.xxx -MsaUser root -MsaPassword *** -VC xxx.xxx.xxx.xxx -Username vsphere.local\tmpuser -Password *** -Mode C2C -RegisterWithIp $true #> [CmdletBinding()] param( [Parameter(Mandatory=$true, HelpMessage="ip/fqdn of MSA")] [string]$MS, [Parameter(Mandatory=$true, HelpMessage="MSA user")] [string]$MsaUser, [Parameter(Mandatory=$true, HelpMessage="MSA password")] [string]$MsaPassword, [Parameter(Mandatory=$true, HelpMessage="ip/fqdn of vCenter")] [string]$VC, [Parameter(Mandatory=$true, HelpMessage="sso username with which vCenter will be registered")] [string]$Username, [Parameter(Mandatory=$true, HelpMessage="sso user password")] [string]$Password, [Parameter(Mandatory=$true, HelpMessage="Register MSA with IP instead of hostname")] [bool]$RegisterWithIp, [Parameter(Mandatory=$true, HelpMessage="Mode in which MSA will be registered C2C")] [string]$Mode="C2C" ) Process { $response = get_ms_state $MS $MsaUser $MsaPassword if ($response.configured -eq $True) { write-host "MSA $MS already registered to vCenter. Skipping registration" } else { register_ms_with_vc $MS $MsaUser $MsaPassword $VC $Username $Password $Mode $RegisterWithIp start-sleep 10 } } } function Unregister-MS { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION This function unregisters JetStream MSA from vCenter .PARAMETER MS Management server ip/fqdn .PARAMETER VC vCenter ip/fqdn .PARAMETER Username Username of the new sso user, e.g vsphere.local\tmpuser .PARAMETER Password Password of the new sso user .EXAMPLE Unregister-MS -MS xxx.xxx.xxx.xxx -VC xxx.xxx.xxx.xxx -Username vsphere.local\tmpuser -Password *** #> [CmdletBinding()] param( [Parameter(Mandatory=$true, HelpMessage="ip/fqdn of MSA")] [string]$MS, [Parameter(Mandatory=$true, HelpMessage="ip/fqdn of vCenter")] [string]$VC, [Parameter(Mandatory=$true, HelpMessage="sso username with which vCenter will be registered")] [string]$Username, [Parameter(Mandatory=$true, HelpMessage="sso user password")] [string]$Password ) Process { $fios_session_id = refresh_vc_session $MS $VC $Username $Password unregister_vcenter_from_ms $MS $VC $Username $Password $fios_session_id start-sleep 10 } } function Install-Cluster { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION This function installs JetDR software to all hosts in the Cluster .PARAMETER MS Management server ip/fqdn .PARAMETER VC vCenter ip/fqdn .PARAMETER Username Username of the new sso user, e.g vsphere.local\tmpuser .PARAMETER Password Password of the new sso user .PARAMETER Cluster Cluster name which has to be configured .EXAMPLE Install-Cluster -MS xxx.xxx.xxx.xxx -VC xxx.xxx.xxx.xxx -Username vsphere.local\tmpuser -Password *** -Cluster prod-cluster #> [CmdletBinding()] param( [Parameter(Mandatory=$true, HelpMessage="ip/fqdn of MSA")] [string]$MS, [Parameter(Mandatory=$true, HelpMessage="ip/fqdn of vCenter")] [string]$VC, [Parameter(Mandatory=$true, HelpMessage="sso username with which vCenter will be registered")] [string]$Username, [Parameter(Mandatory=$true, HelpMessage="sso user password")] [string]$Password, [Parameter(Mandatory=$true, HelpMessage="Name of the cluster to be configured")] [string]$Cluster ) Process { $fios_session_id = refresh_vc_session $MS $VC $Username $Password configure_cluster $MS $Cluster $fios_session_id } } function Uninstall-Cluster { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION This function uninstalls JetStream software from the cluster .PARAMETER MS Management server ip/fqdn .PARAMETER VC vCenter ip/fqdn .PARAMETER Username Username of the new sso user, e.g vsphere.local\tmpuser .PARAMETER Password Password of the new sso user .PARAMETER Cluster Cluster name which has to be unconfigured .EXAMPLE Uninstall-Cluster -MS xxx.xxx.xxx.xxx -VC xxx.xxx.xxx.xxx -Username vsphere.local\tmpuser -Password *** -Cluster prod-cluster #> [CmdletBinding()] param( [Parameter(Mandatory=$true, HelpMessage="ip/fqdn of MSA")] [string]$MS, [Parameter(Mandatory=$true, HelpMessage="ip/fqdn of vCenter")] [string]$VC, [Parameter(Mandatory=$true, HelpMessage="sso username with which vCenter will be unregistered")] [string]$Username, [Parameter(Mandatory=$true, HelpMessage="sso user password")] [string]$Password, [Parameter(Mandatory=$true, HelpMessage="Name of the cluster to be unconfigured")] [string]$Cluster ) Process { $fios_session_id = refresh_vc_session $MS $VC $Username $Password unconfigure_cluster $MS $Cluster $fios_session_id } } function Remove-Role { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION This function deletes a role from the vCenter and the elevated permissions from the sso user .PARAMETER Username Username of the new sso user .PARAMETER Role Type of role to be created, elevated or operations .EXAMPLE Remove-Role -Username vsphere.local\tmpuser -Role elevated Remove-Role -Username vsphere.local\tmpuser -Role operations #> [CmdletBinding()] param( [Parameter(Mandatory=$true, HelpMessage="sso username")] [string]$Username, [Parameter(Mandatory=$true, HelpMessage="Type of role. Either elevated or operations")] [string]$Role ) Process { $user = $Domain + "\" + $Username if($Role -eq 'elevated') { $role = "JSDR-elevated" } elseif($Role -eq 'operations') { $role = "JSDR-operations" } else { write-host "Invalid role specified. Must be one of 'elevated' or 'operations'" break } $rootfolder = Get-Folder -NoRecursion $newly_added_permissions = Get-VIPermission -Entity $rootfolder -Principal $Username remove_permissions $newly_added_permissions remove_role $role } } function Restart-CIM { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION This function restarts CIM service on ESX hosts in the Cluster .PARAMETER Cluster Name of the cluster .EXAMPLE Restart-CIM -Cluster prod-cluster #> [CmdletBinding()] param( [Parameter(Mandatory=$true, HelpMessage="Name of the cluster")] [string]$Cluster ) Process { restart_cim $Cluster } } function Install-JetDRWithStaticIP { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Deploys JetDr Management Server Appliance(MSA) with Static network IP configuration and configures one cluster .PARAMETER Network Network mapping for the MSA to be deployed, e.g 'VM Network'" .PARAMETER HostName Hostname of the MSA to be deployed .PARAMETER MSACredential root user credential of the MSA to be deployed .PARAMETER Gateway Gateway of the MSA to be deployed .PARAMETER Dns DNS IP that MSA should use .PARAMETER MSAIp Ip of the MSA to be deployed .PARAMETER Netmask Netmask of the MSA to be deployed .PARAMETER VlanId VLAN Tag ID for MSA to be deployed (Leave blank if NA) .PARAMETER Cluster Cluster where the MSA will be deployed .PARAMETER VMName Name of the MSA VM .PARAMETER Datastore Datastore where MSA will be deployed .PARAMETER ProtectedCluster Cluster to be protected .PARAMETER RegisterWithIp Register MSA with IP instead of hostname .EXAMPLE Install-JetDRWithStaticIP -Network "VM Network" -HostName "jsdr-msa.example.com" -MSACredential <root/PSCredential Object> -Gateway xxx.xxx.xxx.xxx -Dns xxx.xxx.xxx.xxx -MSAIp xxx.xxx.xxx.xxx -Netmask xxx.xxx.xxx.xxx -VlanId 101 -Cluster MSA-Cluster -VMName jsdr-msa -Datastore shared-ds -ProtectedCluster Src-Cluster -RegisterWithIp $true .EXAMPLE Install-JetDRWithStaticIP -Network "VM Network" -HostName "jsdr-msa.example.com" -MSACredential <root/PSCredential Object> -Gateway xxx.xxx.xxx.xxx -Dns xxx.xxx.xxx.xxx -MSAIp xxx.xxx.xxx.xxx -Netmask xxx.xxx.xxx.xxx -VlanId 101 -Cluster MSA-Cluster -VMName jsdr-msa -Datastore shared-ds -ProtectedCluster Src-Cluster #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $True)] param( [Parameter(Mandatory=$true, HelpMessage="Network mapping for the MSA to be deployed, e.g 'VM Network'")] [String]$Network, [Parameter(Mandatory=$false, HelpMessage="Hostname(fqdn) of the MSA to be deployed")] [String]$HostName, [Parameter(Mandatory=$true, HelpMessage="Credentials of root user of the MSA to be deployed")] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential, [Parameter(Mandatory=$true, HelpMessage="Gateway of the MSA to be deployed.")] [String]$Gateway, [Parameter(Mandatory=$true, HelpMessage="DNS IP that MSA should use.")] [String]$Dns, [Parameter(Mandatory=$true, HelpMessage="Ip of the MSA to be deployed.")] [String]$MSAIp, [Parameter(Mandatory=$true, HelpMessage="Netmask of the MSA to be deployed.")] [String]$Netmask, [Parameter(Mandatory=$false, HelpMessage="VLAN Tag ID for MSA VM to be deployed. (Leave blank if NA)")] [String]$VlanId=$null, [Parameter(Mandatory=$true, HelpMessage="Cluster where MSA will be deployed")] [String]$Cluster, [Parameter(Mandatory=$false, HelpMessage="Name of the MSA VM")] [String]$VMName="msa@4.2.0+jetdr", [Parameter(Mandatory=$true, HelpMessage="Datastore where MSA will be deployed")] [String]$Datastore, [Parameter(Mandatory=$true, HelpMessage="Cluster to be protected")] [String]$ProtectedCluster, [Parameter(Mandatory=$false, HelpMessage="Register MSA with Ip instead of hostname.")] [Bool]$RegisterWithIp=$true ) Begin { $Mode = "C2C" # Script assumes that directory it is executed in is temporary $DownloadPath = "." $sso_user_name = "vsphere.local\jetdrusr" $sso_user_pwd=generate_password $js_download_path = $DownloadPath $js_destination_folder = $js_download_path + "/js_unzipped/" $UserName = $MSACredential.UserName.trim() $Password = $MSACredential.GetNetworkCredential().Password.trim() $VCIp = $VC_ADDRESS #Trimming string parameters for any leading and trailing spaces foreach ($key in $($PSBoundParameters.keys)) { if ($PSBoundParameters[$key].GetType().Name -eq 'String') { $PSBoundParameters[$key] = $($PSBoundParameters[$key].trim()) Set-Variable -Name $key -Value $($PSBoundParameters[$key].trim()) } } } Process { # Run Preflight before install Invoke-PreflightJetDRInstall -ProtectedCluster $ProtectedCluster -Cluster $Cluster -VMName $VMName -Datastore $Datastore -Network $Network # Download JetDR bundle from MMS $js_url = "https://jsmms.blob.core.windows.net/jsdrmms/JSDR-GA-4.2.6.582-240506.zip" $js_zip = Split-Path $js_url -Leaf Get-JetDR -Url $js_url -DownloadPath $js_download_path # Unzip JetDR bundle to specified location Expand-JetDR -FileName $js_zip -FilePath $js_download_path -UnzipPath $js_destination_folder $ovf_path = Get-ChildItem -Path $js_destination_folder -Filter "jetstream*ova" -Recurse | %{$_.FullName} $signature_path = Get-ChildItem -Path $js_destination_folder -Filter "signature" -Recurse | %{$_.FullName} try { # Create a new sso user Add-User -Username $sso_user_name -Password $sso_user_pwd try { # Create JSDR-elevated role and assign it to the newly created sso user New-Role -Username $sso_user_name -Role elevated # Deploy JetStream MSA $MSAIp=Deploy-JetDRMSA -OvfPath $ovf_path -SignaturePath $signature_path -Network $Network -Hostname $HostName -MSACredential $MSACredential -Gateway $Gateway -Dns $Dns -Ip $MSAIp -Netmask $Netmask -VlanId $VlanId -Cluster $Cluster -VmName $VMName -Datastore $Datastore # Register JetStream MSA with vCenter Register-MS -MS $MSAIp -MsaUser $UserName -MsaPassword $Password -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd -Mode $Mode -RegisterWithIp $RegisterWithIp # Configure cluster with JetStream software Install-Cluster -MS $MSAIp -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd -Cluster $ProtectedCluster # Restart CIM service on hosts Restart-CIM $ProtectedCluster # Unregister JetStream MSA from vCenter Unregister-MS -MS $MSAIp -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd } finally { # Delete permissions of JSDR-elevated role from sso user and delete the role from vCenter Remove-Role -Username $sso_user_name -Role elevated } try { # Create JSDR-operations role and assign it to the newly created sso user New-Role -Username $sso_user_name -Role operations # Register JetStream MSA with vCenter Register-MS -MS $MSAIp -MsaUser $UserName -MsaPassword $Password -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd -Mode $Mode -RegisterWithIp $RegisterWithIp } finally { # Delete permissions of JSDR-operations role from sso user and delete the role from vCenter Remove-Role -Username $sso_user_name -Role operations } } finally { # Delete the sso user created for this task Remove-User -Username $sso_user_name } } } function Install-JetDRWithDHCP { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Deploys JetDr Management Server Appliance(MSA) with Dynamic network IP configurations and configures one cluster .PARAMETER Network Network mapping for the MSA to be deployed, e.g 'VM Network'" .PARAMETER HostName Hostname of the MSA to be deployed .PARAMETER MSACredential root user credential of the MSA to be deployed .PARAMETER VlanId VLAN Tag ID for MSA to be deployed (Leave blank if NA) .PARAMETER Cluster Cluster where the MSA will be deployed .PARAMETER VMName Name of the MSA VM .PARAMETER Datastore Datastore where MSA will be deployed .PARAMETER ProtectedCluster Cluster to be protected .PARAMETER RegisterWithIp Register MSA with IP instead of hostname .EXAMPLE Install-JetDRWithDHCP -Network "VM Network" -HostName "jsdr-msa.example.com" -MSACredential <root/PSCredential Object> -VlanId 101 -Cluster MSA-Cluster -VMName jsdr-msa -Datastore shared-ds -ProtectedCluster Src-Cluster #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $True)] param( [Parameter(Mandatory=$true, HelpMessage="Network mapping for the MSA to be deployed, e.g 'VM Network'")] [String]$Network, [Parameter(Mandatory=$false, HelpMessage="Hostname(fqdn) of the MSA to be deployed")] [String]$HostName, [Parameter(Mandatory=$true, HelpMessage="Credentials of root user of the MSA to be deployed")] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential, [Parameter(Mandatory=$false, HelpMessage="VLAN Tag ID for MSA VM to be deployed. (Leave blank if NA)")] [String]$VlanId=$null, [Parameter(Mandatory=$true, HelpMessage="Cluster where MSA will be deployed")] [String]$Cluster, [Parameter(Mandatory=$false, HelpMessage="Name of the MSA VM")] [String]$VMName="msa@4.2.0+jetdr", [Parameter(Mandatory=$true, HelpMessage="Datastore where MSA will be deployed")] [String]$Datastore, [Parameter(Mandatory=$true, HelpMessage="Cluster to be protected")] [String]$ProtectedCluster, [Parameter(Mandatory=$false, HelpMessage="Register MSA with Ip instead of hostname.")] [Bool]$RegisterWithIp=$true ) Begin { $Mode = "C2C" # Script assumes that directory it is executed in is temporary $DownloadPath = "." $sso_user_name = "vsphere.local\jetdrusr" $sso_user_pwd=generate_password $js_download_path = $DownloadPath $js_destination_folder = $js_download_path + "/js_unzipped/" $UserName = $MSACredential.UserName.trim() $Password = $MSACredential.GetNetworkCredential().Password.trim() $VCIp = $VC_ADDRESS $Gateway = '' $Dns = '' $MSAIp = '' $Netmask = '' #Trimming string parameters for any leading and trailing spaces foreach ($key in $($PSBoundParameters.keys)) { if ($PSBoundParameters[$key].GetType().Name -eq 'String') { $PSBoundParameters[$key] = $($PSBoundParameters[$key].trim()) Set-Variable -Name $key -Value $($PSBoundParameters[$key].trim()) } } } Process { # Run Preflight before install Invoke-PreflightJetDRInstall -ProtectedCluster $ProtectedCluster -Cluster $Cluster -VMName $VMName -Datastore $Datastore -Network $Network # Download JetDR bundle from MMS $js_url = "https://jsmms.blob.core.windows.net/jsdrmms/JSDR-GA-4.2.6.582-240506.zip" $js_zip = Split-Path $js_url -Leaf Get-JetDR -Url $js_url -DownloadPath $js_download_path # Unzip JetDR bundle to specified location Expand-JetDR -FileName $js_zip -FilePath $js_download_path -UnzipPath $js_destination_folder $ovf_path = Get-ChildItem -Path $js_destination_folder -Filter "jetstream*ova" -Recurse | %{$_.FullName} $signature_path = Get-ChildItem -Path $js_destination_folder -Filter "signature" -Recurse | %{$_.FullName} try { # Create a new sso user Add-User -Username $sso_user_name -Password $sso_user_pwd try { # Create JSDR-elevated role and assign it to the newly created sso user New-Role -Username $sso_user_name -Role elevated # Deploy JetStream MSA $MSAIp=Deploy-JetDRMSA -OvfPath $ovf_path -SignaturePath $signature_path -Network $Network -Hostname $HostName -MSACredential $MSACredential -Gateway $Gateway -Dns $Dns -Ip $MSAIp -Netmask $Netmask -VlanId $VlanId -Cluster $Cluster -VmName $VMName -Datastore $Datastore # Commenting these as they may not be required any more. #Invoke-VMScript -VM $VMName -ScriptText 'echo "jss.dr.vc.forceUnregister=true" >> /var/lib/vme2/conf/server.properties' -GuestUser $UserName -GuestPassword $Password | Out-Null #Invoke-VMScript -VM $VMName -ScriptText '/etc/init.d/vme2 restart' -GuestUser $UserName -GuestPassword $Password | Out-Null # Register JetStream MSA with vCenter Register-MS -MS $MSAIp -MsaUser $UserName -MsaPassword $Password -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd -Mode $Mode -RegisterWithIp $RegisterWithIp # Configure cluster with JetStream software Install-Cluster -MS $MSAIp -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd -Cluster $ProtectedCluster # Restart CIM service on hosts Restart-CIM $ProtectedCluster # Unregister JetStream MSA from vCenter Unregister-MS -MS $MSAIp -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd } finally { # Delete permissions of JSDR-elevated role from sso user and delete the role from vCenter Remove-Role -Username $sso_user_name -Role elevated } try { # Create JSDR-operations role and assign it to the newly created sso user New-Role -Username $sso_user_name -Role operations # Register JetStream MSA with vCenter Register-MS -MS $MSAIp -MsaUser $UserName -MsaPassword $Password -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd -Mode $Mode -RegisterWithIp $RegisterWithIp } finally { # Delete permissions of JSDR-operations role from sso user and delete the role from vCenter Remove-Role -Username $sso_user_name -Role operations } } finally { # Delete the sso user created for this task Remove-User -Username $sso_user_name } } } function Uninstall-JetDR { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Unconfigures cluster, unregisters vCenter from the JetDr MSA .PARAMETER MSAIp MSA IP .PARAMETER MSACredential Credential of root user of MSA(root or PSCredential Object) .PARAMETER ProtectedCluster Cluster to be unconfigured .PARAMETER VMName Name of the MSA VM .EXAMPLE Uninstall-JetDR -MSAIp xxx.xxx.xxx.xxx -MSACredential <root/PSCredential Object> -ProtectedCluster Src-Cluster -VMName jsdr-msa #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $True)] param( [Parameter(Mandatory=$true, HelpMessage="Ip of the MSA")] [String]$MSAIp, [Parameter(Mandatory=$true, HelpMessage="Credential of the root user of MSA")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential, [Parameter(Mandatory=$true, HelpMessage="Cluster to be unconfigured")] [String]$ProtectedCluster, [Parameter(Mandatory=$false, HelpMessage="Name of the MSA VM")] [String]$VMName ) Begin { $sso_user_name = "vsphere.local\jetdrusr" $sso_user_pwd=generate_password $VCIp = $VC_ADDRESS #Trimming string parameters for any leading and trailing spaces foreach ($key in $($PSBoundParameters.keys)) { if ($PSBoundParameters[$key].GetType().Name -eq 'String') { $PSBoundParameters[$key] = $($PSBoundParameters[$key].trim()) Set-Variable -Name $key -Value $($PSBoundParameters[$key].trim()) } } $SecureFolder = [AVSSecureFolder]::GetOrCreate("js-appliance") if ('' -eq $VMName) { $msa_vms = Get-VM -Location $SecureFolder -Name msa@*+jetdr* } else { $msa_vms = Get-VM -Location $SecureFolder -Name $VMName -ErrorAction SilentlyContinue if ($null -eq $msa_vms) { $msa_vms = Get-VM $VMName -ErrorAction SilentlyContinue } } if ($null -eq $msa_vms) { Write-Error "Could not find MSA VM. Please rerun providing the correct VM name." -ErrorAction Stop } $msa_exists = $false foreach ($msa_vm in $msa_vms) { $vm_ip = (Get-VMGuest -VM (Get-VM -Name $msa_vm)).IPAddress if ($vm_ip -Contains $MSAIp) { Write-Host "IP of $msa_vm matches with provided $MSAIp" $msa_exists = $true break } } if ($msa_exists -eq $false) { Write-Error "The MSA Ip $MSAIp provided doesn't match with the ip of MSA VM" -ErrorAction Stop } } Process { # Run Preflight before uninstall Invoke-PreflightJetDRUninstall -MSAIp $MSAIp -MSACredential $MSACredential -ProtectedCluster $ProtectedCluster try { # Create a new sso user Add-User -Username $sso_user_name -Password $sso_user_pwd # Create JSDR-elevated role and assign it to the newly created sso user New-Role -Username $sso_user_name -Role elevated # Check for presence of DR Virtual appliance before unregistering $fios_session_id = refresh_vc_session $MSAIp $VCIp $sso_user_name $sso_user_pwd get_drvas $MSAIp $fios_session_id # Unconfigure JetStream software from cluster Uninstall-Cluster -MS $MSAIp -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd -Cluster $ProtectedCluster # Unregister JetStream MSA from vCenter Unregister-MS -MS $MSAIp -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd # Poweroff and delete MSA VM Write-Host "Powering off MSA VM $msa_vm" Stop-VM -VM $msa_vm -Confirm:$false Start-Sleep 5 if ((Get-VM -Name $msa_vm).PowerState -eq "PoweredOff") { Write-Host "$msa_vm powered off successfully" Write-Host "Deleting MSA VM $msa_vm" Remove-VM -VM $msa_vm -Confirm:$false -DeletePermanently Start-Sleep 5 $vm_exists = Get-VM -Name $msa_vm -ErrorAction SilentlyContinue if ($null -eq $vm_exists) { Write-Host "$msa_vm deleted successfully" } else { Write-Error "Failed to delete $msa_vm" -ErrorAction Stop } } else { Write-Error "Could not power off $msa_vm" -ErrorAction Stop } } finally { # Delete permissions of JSDR-elevated role from sso user and delete the role from vCenter Remove-Role -Username $sso_user_name -Role elevated # Delete the sso user created for this task Remove-User -Username $sso_user_name } } } function Invoke-PreflightJetDRInstall { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Checks to display current state of the system and minimum requirement are met before deploying JeDR. It also checks for minimum of 3 hosts in a cluster, jetdr plugin if already present in vcenter and if a vm exists with same name as MSA .PARAMETER VMName Name of the MSA VM .PARAMETER Cluster Cluster where the MSA will be deployed .PARAMETER ProtectedCluster Cluster to be protected .PARAMETER Datastore Datastore where MSA will be deployed .PARAMETER Network Network mapping for the MSA to be deployed, e.g 'VM Network' .EXAMPLE Invoke-PreflightJetDRInstall -VMName jsdr-msa -Cluster MSA-Cluster -ProtectedCluster Src-Cluster -Datastore datastore-name -Network network-name #> [CmdletBinding()] [AVSAttribute(5, UpdatesSDDC = $false)] param( [Parameter(Mandatory=$false, HelpMessage="Name of MSA VM")] [String]$VMName="msa@4.2.0+jetdr", [Parameter(Mandatory=$true, HelpMessage="Cluster Name where MSA will be deployed")] [String]$Cluster, [Parameter(Mandatory=$true, HelpMessage="Cluster to be protected")] [String]$ProtectedCluster, [Parameter(Mandatory=$true, HelpMessage="Datastore where MSA will be deployed")] [String]$Datastore, [Parameter(Mandatory=$true, HelpMessage="Network mapping for the MSA to be deployed, e.g 'VM Network'")] [String]$Network ) #Trimming string parameters for any leading and trailing spaces foreach ($key in $($PSBoundParameters.keys)) { if ($PSBoundParameters[$key].GetType().Name -eq 'String') { $PSBoundParameters[$key] = $($PSBoundParameters[$key].trim()) Set-Variable -Name $key -Value $($PSBoundParameters[$key].trim()) } } get_system_state_install $VMName $Cluster $ProtectedCluster $Datastore $Network } function Invoke-PreflightJetDRUninstall { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Checks to display current state of the system and minimum requirement are met before uninstalling JeDR. It also checks for minimum of 4 hosts in a cluster .PARAMETER MSAIp Ip of the MSA .PARAMETER MSACredential root credentials of MSA .PARAMETER ProtectedCluster Cluster to be protected .EXAMPLE Invoke-PreflightJetDRUninstall -MSAIp xxx.xxx.xxx.xxx -MSACredential <root/PSCredential Object> -ProtectedCluster Src-Cluster #> [CmdletBinding()] [AVSAttribute(5, UpdatesSDDC = $false)] param( [Parameter(Mandatory=$true, HelpMessage="IP of MSA VM")] [String]$MSAIp, [Parameter(Mandatory=$true, HelpMessage="Credential of the root user of MSA")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential, [Parameter(Mandatory=$true, HelpMessage="Protected Cluster")] [String]$ProtectedCluster ) if (!$MSACredential) { write-error "Please provide MSA credential, -MSACredential <root/PS Credential Object>" -ErrorAction Stop } else { $MSaUser = $MSACredential.UserName.trim() $MSaPassword = $MSACredential.GetNetworkCredential().Password.trim() } #Trimming string parameters for any leading and trailing spaces foreach ($key in $($PSBoundParameters.keys)) { if ($PSBoundParameters[$key].GetType().Name -eq 'String') { $PSBoundParameters[$key] = $($PSBoundParameters[$key].trim()) Set-Variable -Name $key -Value $($PSBoundParameters[$key].trim()) } } get_system_state_uninstall $MSAIp $ProtectedCluster $MSaUser $MSaPassword } function Invoke-PreflightJetDRSystemCheck { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION This Cmdlet checks and displays current state of the system It checks whether the minimal requirements for the script to run are met. .EXAMPLE Invoke-PreflightJetDRSystemCheck #> [CmdletBinding()] param() Begin { $role = "CloudAdmin" } Process { checkPSVersion checkVcaddress checkRole $role checkModule "VMware.vSphere.SsoAdmin" checkModule "VMware.VimAutomation.Core" Write-Host "Invoke-PreflightJetDRSystemCheck option only checks required configuration in the system to execute other Cmdlets. For more detailed check, try running Invoke-PreflightJetDRInstall/Invoke-PreflightJetDRUninstall." } } function Enable-JetDRForCluster { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Configures an additional cluster for protection. installs vib to all hosts in the cluster and creates storage policies. .PARAMETER MSAIp Ip of the MSA .PARAMETER MSACredential root credentials of MSA .PARAMETER ProtectedCluster Cluster to be protected .EXAMPLE Enable-JetDRForCluster -MSAIp xxx.xxx.xxx.xxx -MSACredential <root/PSCredential Object> -ProtectedCluster Src-Cluster #> [CmdletBinding()] [AVSAttribute(20, UpdatesSDDC = $True)] param( [Parameter(Mandatory=$true, HelpMessage="Ip of the MSA")] [String]$MSAIp, [Parameter(Mandatory=$true, HelpMessage="Credentials of root user of the MSA to be deployed")] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential, [Parameter(Mandatory=$true, HelpMessage="Cluster to be protected")] [String]$ProtectedCluster ) Begin { $Mode = "C2C" $VCIp = $VC_ADDRESS $sso_user_name="vsphere.local\jetdrelevatedusr" $sso_user_pwd=generate_password $UserName = $MSACredential.UserName.trim() $Password = $MSACredential.GetNetworkCredential().Password.trim() #Trimming string parameters for any leading and trailing spaces foreach ($key in $($PSBoundParameters.keys)) { if ($PSBoundParameters[$key].GetType().Name -eq 'String') { $PSBoundParameters[$key] = $($PSBoundParameters[$key].trim()) Set-Variable -Name $key -Value $($PSBoundParameters[$key].trim()) } } } Process { # Preflight checks for cluster configure get_system_state_configure $ProtectedCluster try { # Create a new sso user Add-User -Username $sso_user_name -Password $sso_user_pwd # Create JSDR-elevated role and assign it to the newly created sso user New-Role -Username $sso_user_name -Role elevated # Configure cluster with JetStream software Install-Cluster -MS $MSAIp -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd -Cluster $ProtectedCluster # Restart CIM service on hosts Restart-CIM $ProtectedCluster } finally { # Delete permissions of JSDR-elevated role from sso user and delete the role from vCenter Remove-Role -Username $sso_user_name -Role elevated # Delete the sso user created for this task Remove-User -Username $sso_user_name } } } function Disable-JetDRForCluster { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Unconfigures a cluster, uninstalls vibs from all hosts in the cluster and removes storage policies. It will not uninstall JetDR completely .PARAMETER MSAIp Ip of the MSA .PARAMETER MSACredential root credentials of MSA .PARAMETER ProtectedCluster Cluster to be unconfigured .EXAMPLE Disable-JetDRForCluster -MSAIp xxx.xxx.xxx.xxx -MSACredential <root/PSCredential Object> -ProtectedCluster Src-Cluster #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $True)] param( [Parameter(Mandatory=$true, HelpMessage="Ip of the MSA")] [String]$MSAIp, [Parameter(Mandatory=$true, HelpMessage="Credential of the root user of MSA")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential, [Parameter(Mandatory=$true, HelpMessage="Cluster to be unconfigured")] [String]$ProtectedCluster ) Begin { $sso_user_name = "vsphere.local\jetdrelevatedusr" $sso_user_pwd=generate_password $Mode = "C2C" $VCIp = $VC_ADDRESS $UserName = $MSACredential.UserName.trim() $Password = $MSACredential.GetNetworkCredential().Password.trim() #Trimming string parameters for any leading and trailing spaces foreach ($key in $($PSBoundParameters.keys)) { if ($PSBoundParameters[$key].GetType().Name -eq 'String') { $PSBoundParameters[$key] = $($PSBoundParameters[$key].trim()) Set-Variable -Name $key -Value $($PSBoundParameters[$key].trim()) } } } Process { # Preflight check for cluster unconfigure Invoke-PreflightJetDRUninstall -MSAIp $MSAIp -MSACredential $MSACredential -ProtectedCluster $ProtectedCluster try { # Create a new sso user Add-User -Username $sso_user_name -Password $sso_user_pwd # Create JSDR-elevated role and assign it to the newly created sso user New-Role -Username $sso_user_name -Role elevated # Unconfigure JetStream software from cluster Uninstall-Cluster -MS $MSAIp -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd -Cluster $ProtectedCluster } finally { # Delete permissions of JSDR-elevated role from sso user and delete the role from vCenter Remove-Role -Username $sso_user_name -Role elevated # Delete the sso user created for this task Remove-User -Username $sso_user_name } } } function Update-JetDRMSA { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Upgrades JetDR MSA and plugin to latest available update. .PARAMETER MSAIp Ip of the MSA .PARAMETER MSACredential root credentials of MSA .PARAMETER Datacenter Datacenter which manages the clusters .PARAMETER Datastore Datastore where upgrade iso will be copied .PARAMETER VMName MSA VM name where upgrade iso will be mounted .EXAMPLE Update-JetDRMSA -MSAIp xxx.xxx.xxx.xxx -MSACredential <root/PSCredential Object> -Datacenter Datacenter -Datastore shared-ds -VMName js-dr #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $False)] param( [Parameter(Mandatory=$true, HelpMessage="Ip of the MSA")] [String]$MSAIp, [Parameter(Mandatory=$true, HelpMessage="Credential of the root user of MSA")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential, [Parameter(Mandatory=$true, HelpMessage="Datacenter name")] [String]$Datacenter, [Parameter(Mandatory=$true, HelpMessage="Datastore where upgrade iso will be copied")] [String]$Datastore, [Parameter(Mandatory=$true, HelpMessage="MSA VM name where upgrade iso will be mounted")] [String]$VMName ) Begin { # Script assumes that directory it is executed in is temporary $DownloadPath = "." $js_download_path = $DownloadPath $js_destination_folder = $js_download_path + "/js_unzipped/" $UserName = $MSACredential.UserName.trim() $Password = $MSACredential.GetNetworkCredential().Password.trim() $VCIp = $VC_ADDRESS #Trimming string parameters for any leading and trailing spaces foreach ($key in $($PSBoundParameters.keys)) { if ($PSBoundParameters[$key].GetType().Name -eq 'String') { $PSBoundParameters[$key] = $($PSBoundParameters[$key].trim()) Set-Variable -Name $key -Value $($PSBoundParameters[$key].trim()) } } } Process { # Download JetDR bundle from MMS $js_url = "https://jsmms.blob.core.windows.net/jsdrmms/JSDR-GA-4.2.6.582-240506.zip" $js_zip = Split-Path $js_url -Leaf Get-JetDR -Url $js_url -DownloadPath $js_download_path # Unzip JetDR bundle to specified location Expand-JetDR -FileName $js_zip -FilePath $js_download_path -UnzipPath $js_destination_folder $iso_path = Get-ChildItem -Path $js_destination_folder -Filter "jetstream*iso" -Recurse | %{$_.FullName} $signature_path = Get-ChildItem -Path $js_destination_folder -Filter "signature_iso" -Recurse | %{$_.FullName} updateMSA $MSAIp $UserName $Password $Datacenter $Datastore $VMName $iso_path $signature_path $VCIp } } function Update-DRVAs { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Upgrades JetDR DRVAs to latest available update. .PARAMETER MSAIp Ip of the MSA .PARAMETER VC vCenter ip/fqdn .PARAMETER Username Username of the new sso user, e.g vsphere.local\tmpuser .PARAMETER Password Password of the new sso user .EXAMPLE Update-DRVAs -MSAIp xxx.xxx.xxx.xxx -VC xxx.xxx.xxx.xxx -Username vsphere.local\tmpuser -Password *** #> [CmdletBinding()] [AVSAttribute(60, UpdatesSDDC = $False)] param( [Parameter(Mandatory=$true, HelpMessage="Ip of the MSA")] [String]$MSAIp, [Parameter(Mandatory=$true, HelpMessage="ip/fqdn of vCenter")] [string]$VC, [Parameter(Mandatory=$true, HelpMessage="sso username with which vCenter will be registered")] [string]$Username, [Parameter(Mandatory=$true, HelpMessage="sso user password")] [string]$Password ) Process { $fios_session_id = refresh_vc_session $MSAIp $VC $Username $Password upgrade_drvas $MSAIp $fios_session_id } } function Update-RECOVERYVAs { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Upgrades JetDR RECOVERY VAs to latest available update. .PARAMETER MSAIp Ip of the MSA .PARAMETER VC vCenter ip/fqdn .PARAMETER Username Username of the new sso user, e.g vsphere.local\tmpuser .PARAMETER Password Password of the new sso user .EXAMPLE Update-RECOVERYVAs -MSAIp xxx.xxx.xxx.xxx -VC xxx.xxx.xxx.xxx -Username vsphere.local\tmpuser -Password *** #> [CmdletBinding()] [AVSAttribute(60, UpdatesSDDC = $False)] param( [Parameter(Mandatory=$true, HelpMessage="Ip of the MSA")] [String]$MSAIp, [Parameter(Mandatory=$true, HelpMessage="ip/fqdn of vCenter")] [string]$VC, [Parameter(Mandatory=$true, HelpMessage="sso username with which vCenter will be registered")] [string]$Username, [Parameter(Mandatory=$true, HelpMessage="sso user password")] [string]$Password ) Process { $fios_session_id = refresh_vc_session $MSAIp $VC $Username $Password upgrade_recovery_vas $MSAIp $fios_session_id } } function Update-JetDRCluster { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Upgrades JetDR iofilter to latest available update. .PARAMETER MSAIp Ip of the MSA .PARAMETER MSACredential Credentials of root user of MSA .PARAMETER VMName MSA VM Name .PARAMETER VC vCenter ip/fqdn .PARAMETER Username Username of the new sso user, e.g vsphere.local\tmpuser .PARAMETER Password Password of the new sso user .EXAMPLE Update-JetDRCluster -MSAIp xxx.xxx.xxx.xxx -VC xxx.xxx.xxx.xxx -Username vsphere.local\tmpuser -Password *** -MSAUser root -MSAPassword *** -VMName js-dr #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $True)] param( [Parameter(Mandatory=$true, HelpMessage="Ip of the MSA")] [String]$MSAIp, [Parameter(Mandatory=$true, HelpMessage="Credential of the root user of MSA")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential, [Parameter(Mandatory=$true, HelpMessage="MSA VM name")] [String]$VMName, [Parameter(Mandatory=$true, HelpMessage="ip/fqdn of vCenter")] [string]$VC, [Parameter(Mandatory=$true, HelpMessage="sso username with which vCenter will be registered")] [string]$Username, [Parameter(Mandatory=$true, HelpMessage="sso user password")] [string]$Password ) Begin { $UserName = $MSACredential.UserName.trim() $Password = $MSACredential.GetNetworkCredential().Password.trim() } Process { $fios_session_id = refresh_vc_session $MSAIp $VC $sso_user_name $sso_user_pwd update_clusters $MSAIp $fios_session_id $UserName $Password $VMName } } function Update-JetDR { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Upgrades JetDR components to latest available update. .PARAMETER Resume Resume upgrade .PARAMETER MSAIp Ip of the MSA .PARAMETER MSACredential root credentials of MSA .PARAMETER Datacenter Datacenter which manages the clusters .PARAMETER Datastore Datastore where upgrade iso will be copied .PARAMETER MSAVMName MSA VM name where upgrade iso will be mounted .EXAMPLE Update-JetDR -MSAIp xxx.xxx.xxx.xxx -MSACredential <root/PSCredential Object> -Datacenter Datacenter -Datastore shared-ds -MSAVMName js-dr #> [CmdletBinding()] [AVSAttribute(60, UpdatesSDDC = $False)] param( [Parameter(Mandatory=$false, HelpMessage="Resume upgrade if it failed at some point after upgrading MSA")] [Bool]$Resume, [Parameter(Mandatory=$true, HelpMessage="Ip of the MSA")] [String]$MSAIp, [Parameter(Mandatory=$true, HelpMessage="Credential of the root user of MSA")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential, [Parameter(Mandatory=$true, HelpMessage="Datacenter name")] [String]$Datacenter, [Parameter(Mandatory=$true, HelpMessage="Datastore where upgrade iso will be copied")] [String]$Datastore, [Parameter(Mandatory=$false, HelpMessage="MSA VM name where upgrade iso will be mounted")] [String]$MSAVMName ) Begin { $sso_user_name = "vsphere.local\jetdrelevatedusr" $sso_user_pwd=generate_password $VCIp = $VC_ADDRESS #Trimming string parameters for any leading and trailing spaces foreach ($key in $($PSBoundParameters.keys)) { if ($PSBoundParameters[$key].GetType().Name -eq 'String') { $PSBoundParameters[$key] = $($PSBoundParameters[$key].trim()) Set-Variable -Name $key -Value $($PSBoundParameters[$key].trim()) } } # Check if provided datacenter exists $dc_obj=Get-DataCenter $Datacenter -ErrorAction SilentlyContinue if ($dc_obj -eq $null) { Write-Error "Specified datacenter $Datacenter not found. Please provide a correct name." -ErrorAction Stop } # Check if provided datastore exists in the datacenter $ds_obj=Get-DataStore $Datastore -Location $dc_obj -ErrorAction SilentlyContinue if ($ds_obj -eq $null) { Write-Error "Specified datastore $Datastore not found in the datacenter. Please provide a correct datastore name." -ErrorAction Stop } $SecureFolder = [AVSSecureFolder]::GetOrCreate("js-appliance") if ('' -eq $MSAVMName) { $MSAVMName = 'msa@*+jetdr*' $msa_vms = Get-VM -Location $SecureFolder -Name $MSAVMName } else { $msa_vms = Get-VM -Location $SecureFolder -Name $MSAVMName -ErrorAction SilentlyContinue if ($null -eq $msa_vms) { $msa_vms = Get-VM $MSAVMName -ErrorAction SilentlyContinue } } if ($null -eq $msa_vms) { Write-Error "Could not find MSA VM. Please rerun providing the correct VM name." -ErrorAction Stop } $msa_exists = $false foreach ($msa_vm in $msa_vms) { $vm_ip = (Get-VMGuest -VM (Get-VM -Name $msa_vm)).IPAddress if ($vm_ip -Contains $MSAIp) { Write-Host "IP of $msa_vm matches with provided $MSAIp" $msa_exists = $true $MSAVMName = $msa_vm break } } if ($msa_exists -eq $false) { Write-Error "The MSA Ip $MSAIp provided doesn't match with the ip of MSA VM" -ErrorAction Stop } } Process { try { # Create a new sso user Add-User -Username $sso_user_name -Password $sso_user_pwd # Create JSDR-elevated role and assign it to the newly created sso user New-Role -Username $sso_user_name -Role elevated if ($Resume -eq $False) { Update-JetDRMSA -MSAIp $MSAIp -MSACredential $MSACredential -Datacenter $Datacenter -Datastore $Datastore -VMName $MSAVMName } Update-DRVAs -MSAIp $MSAIp -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd Update-RECOVERYVAs -MSAIp $MSAIp -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd Update-JetDRCluster -MSAIp $MSAIp -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd -MSACredential $MSACredential -VMName $MSAVMName } finally { # Delete permissions of JSDR-elevated role from sso user and delete the role from vCenter Remove-Role -Username $sso_user_name -Role elevated # Delete the sso user created for this task Remove-User -Username $sso_user_name } } } function Resolve-HostIssue { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Resolves last failed vCenter task on the host. .PARAMETER MSAIp Ip of the MSA .PARAMETER MSACredential root credentials of MSA .PARAMETER ProtectedCluster Cluster where the host resides .PARAMETER ESXHost Host where resolve issue will be done .EXAMPLE Resolve-HostIssue -MSAIp xxx.xxx.xxx.xxx -MSACredential <root/PSCredential Object> -ProtectedCluster Src-Cluster -ESXHost esxi-host-name #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $True)] param( [Parameter(Mandatory=$true, HelpMessage="Ip of the MSA")] [String]$MSAIp, [Parameter(Mandatory=$true, HelpMessage="Credential of the root user of MSA")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential, [Parameter(Mandatory=$true, HelpMessage="Cluster where the host resides")] [String]$ProtectedCluster, [Parameter(Mandatory=$true, HelpMessage="Host where resolve issue will be done")] [String]$ESXHost ) Begin { $sso_user_name = "vsphere.local\jetdrelevatedusr" $sso_user_pwd=generate_password $Mode = "C2C" $VCIp = $VC_ADDRESS $UserName = $MSACredential.UserName.trim() $Password = $MSACredential.GetNetworkCredential().Password.trim() #Trimming string parameters for any leading and trailing spaces foreach ($key in $($PSBoundParameters.keys)) { if ($PSBoundParameters[$key].GetType().Name -eq 'String') { $PSBoundParameters[$key] = $($PSBoundParameters[$key].trim()) Set-Variable -Name $key -Value $($PSBoundParameters[$key].trim()) } } } Process { Invoke-PreflightJetDRUninstall -MSAIp $MSAIp -MSACredential $MSACredential -ProtectedCluster $ProtectedCluster try { # Create a new sso user Add-User -Username $sso_user_name -Password $sso_user_pwd # Create JSDR-elevated role and assign it to the newly created sso user New-Role -Username $sso_user_name -Role elevated $fios_session_id = refresh_vc_session $MSAIp $VCIp $sso_user_name $sso_user_pwd $status = resolveHostIssue $MSAIp $ProtectedCluster $ESXHost $fios_session_id if ($status -eq 0) { # Restart CIM service on hosts Get-VMHost -name $ESXhost | Get-VMHostService | where {$_.key -eq 'sfcbd-watchdog'} | Stop-VMHostService -Confirm:$false Get-VMHost -name $ESXhost | Get-VMHostService | where {$_.key -eq 'sfcbd-watchdog'} | Start-VMHostService -Confirm:$false } } finally { # Delete permissions of JSDR-elevated role from sso user and delete the role from vCenter Remove-Role -Username $sso_user_name -Role elevated # Delete the sso user created for this task Remove-User -Username $sso_user_name } } } function Resolve-ClusterIssue { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Resolves the errors occured during an install/uninstall/upgrade operation of an IO Filter on a cluster. .PARAMETER MSAIp Ip of the MSA .PARAMETER MSACredential root credentials of MSA .PARAMETER ProtectedCluster Cluster where resolve issue will be done .EXAMPLE Resolve-ClusterIssue -MSAIp xxx.xxx.xxx.xxx -MSACredential <root/PSCredential Object> -ProtectedCluster Src-Cluster #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $True)] param( [Parameter(Mandatory=$true, HelpMessage="Ip of the MSA")] [String]$MSAIp, [Parameter(Mandatory=$true, HelpMessage="Credential of the root user of MSA")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential, [Parameter(Mandatory=$true, HelpMessage="Cluster where resolve issue will be done")] [String]$ProtectedCluster ) Begin { $sso_user_name = "vsphere.local\jetdrelevatedusr" $sso_user_pwd=generate_password $Mode = "C2C" $VCIp = $VC_ADDRESS $UserName = $MSACredential.UserName.trim() $Password = $MSACredential.GetNetworkCredential().Password.trim() #Trimming string parameters for any leading and trailing spaces foreach ($key in $($PSBoundParameters.keys)) { if ($PSBoundParameters[$key].GetType().Name -eq 'String') { $PSBoundParameters[$key] = $($PSBoundParameters[$key].trim()) Set-Variable -Name $key -Value $($PSBoundParameters[$key].trim()) } } } Process { Invoke-PreflightJetDRUninstall -MSAIp $MSAIp -MSACredential $MSACredential -ProtectedCluster $ProtectedCluster try { # Create a new sso user Add-User -Username $sso_user_name -Password $sso_user_pwd # Create JSDR-elevated role and assign it to the newly created sso user New-Role -Username $sso_user_name -Role elevated $fios_session_id = refresh_vc_session $MSAIp $VCIp $sso_user_name $sso_user_pwd $status = resolveClusterIssue $MSAIp $ProtectedCluster $fios_session_id if ($status -eq 0) { # Restart CIM service on all hosts restart_cim $ProtectedCluster } } finally { # Delete permissions of JSDR-elevated role from sso user and delete the role from vCenter Remove-Role -Username $sso_user_name -Role elevated # Delete the sso user created for this task Remove-User -Username $sso_user_name } } } function Register-JetDRPlugin { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Registers JetDR plugin to vCenter .PARAMETER MSAIp Ip of the MSA .PARAMETER MSACredential root credentials of MSA .PARAMETER RegisterWithIp Register MSA with Ip instead of hostname .EXAMPLE Register-JetDRPlugin -MSAIp xxx.xxx.xxx.xxx -MSACredential <root/PSCredential Object> -RegisterWithIp:$true #> [CmdletBinding()] [AVSAttribute(5, UpdatesSDDC = $False)] param( [Parameter(Mandatory=$true, HelpMessage="Ip of the MSA")] [String]$MSAIp, [Parameter(Mandatory=$true, HelpMessage="Credential of the root user of MSA")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential, [Parameter(Mandatory=$false, HelpMessage="Register MSA with Ip instead of hostname.")] [Bool]$RegisterWithIp=$true ) Begin { $sso_user_name = "vsphere.local\jetdrusr" $sso_user_pwd=generate_password $Mode = "C2C" $VCIp = $VC_ADDRESS $UserName = $MSACredential.UserName.trim() $Password = $MSACredential.GetNetworkCredential().Password.trim() #Trimming string parameters for any leading and trailing spaces foreach ($key in $($PSBoundParameters.keys)) { if ($PSBoundParameters[$key].GetType().Name -eq 'String') { $PSBoundParameters[$key] = $($PSBoundParameters[$key].trim()) Set-Variable -Name $key -Value $($PSBoundParameters[$key].trim()) } } } Process { try { # Create a new sso user Add-User -Username $sso_user_name -Password $sso_user_pwd # Create JSDR-operations role and assign it to the newly created sso user New-Role -Username $sso_user_name -Role operations # Register JetStream MSA with vCenter Register-MS -MS $MSAIp -MsaUser $UserName -MsaPassword $Password -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd -Mode $Mode -RegisterWithIp $RegisterWithIp } finally { # Delete permissions of JSDR-operations role from sso user and delete the role from vCenter Remove-Role -Username $sso_user_name -Role operations # Delete the sso user created for this task Remove-User -Username $sso_user_name } } } function Unregister-JetDRPlugin { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Unregisters JetDR plugin from vCenter .PARAMETER MSAIp Ip of the MSA .EXAMPLE Unregister-JetDRPlugin -MSAIp xxx.xxx.xxx.xxx #> [CmdletBinding()] [AVSAttribute(5, UpdatesSDDC = $False)] param( [Parameter(Mandatory=$false, HelpMessage="Ip of the MSA. Leave blank if MSA is not available.")] [String]$MSAIp ) Begin { $sso_user_name = "vsphere.local\jetdrusr" $sso_user_pwd=generate_password $VCIp = $VC_ADDRESS #Trimming string parameters for any leading and trailing spaces foreach ($key in $($PSBoundParameters.keys)) { if ($PSBoundParameters[$key].GetType().Name -eq 'String') { $PSBoundParameters[$key] = $($PSBoundParameters[$key].trim()) Set-Variable -Name $key -Value $($PSBoundParameters[$key].trim()) } } } Process { try { # Create a new sso user Add-User -Username $sso_user_name -Password $sso_user_pwd # Create JSDR-operations role and assign it to the newly created sso user New-Role -Username $sso_user_name -Role operations if ( $MSAIp -ne "") { # Unregister JetStream MSA from vCenter Unregister-MS -MS $MSAIp -VC $VCIp -Username $sso_user_name -Password $sso_user_pwd } else { # Force unregister JetStream MSA from vCenter force_unregister_ms } } finally { # Delete permissions of JSDR-operations role from sso user and delete the role from vCenter Remove-Role -Username $sso_user_name -Role operations # Delete the sso user created for this task Remove-User -Username $sso_user_name } } } function Restart-JetDRDaemon { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Restarts JetDR daemon on every host in the cluster .PARAMETER ProtectedCluster Cluster where daemon should be restarted for all hosts .EXAMPLE Restart-JetDRDaemon -ProtectedCluster Src-Cluster #> [CmdletBinding()] [AVSAttribute(5, UpdatesSDDC = $False)] param( [Parameter(Mandatory=$true, HelpMessage="Cluster where daemon should be restarted for all hosts")] [String]$ProtectedCluster ) Process { restart_jetdr $ProtectedCluster } } function Test-JetDRApplianceConnection { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Checks connection from Run Cmd infra to JetSream MSA .PARAMETER MSAIp MSA Ip .EXAMPLE Test-JetDRApplianceConnection -MSAIp xxx.xxx.xxx.xxx #> [CmdletBinding()] [AVSAttribute(5, UpdatesSDDC = $False)] param( [Parameter(Mandatory=$true, HelpMessage="IP of the MSA")] [String]$MSAIp ) Process { test_jetdr_conn $MSAIp } } function Enable-JetDRSshd { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Starts sshd on JetSream MSA .PARAMETER VMName MSA VM Name .PARAMETER MSACredential MSACredential of root user .EXAMPLE Enable-JetDRSshd -VMName JS-MSA -MSACredential xxx #> [CmdletBinding()] [AVSAttribute(5, UpdatesSDDC = $False)] param( [Parameter(Mandatory=$False, HelpMessage="Name of the MSA VM")] [String]$VmName="msa@4.2.0+jetdr", [Parameter(Mandatory=$true, HelpMessage="MSA Credentials of root user")] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential ) Begin { $UserName = $MSACredential.UserName.trim() $Password = $MSACredential.GetNetworkCredential().Password.trim() } Process { $msa_vm = Get-VM $VMName -ErrorAction SilentlyContinue if ($null -eq $msa_vm) { Write-Error "Could not find MSA VM. Please rerun providing the correct VM name." -ErrorAction Stop } $status_out = Invoke-VMScript -VM $VMName -ScriptText 'service sshd status' -GuestUser $UserName -GuestPassword $Password if($status_out.ExitCode -ne 0) { Write-Host "sshd service is not running on $VMName. Starting the service..." $start_out = Invoke-VMScript -VM $VMName -ScriptText 'service sshd start' -GuestUser $UserName -GuestPassword $Password if($start_out.ExitCode -eq 0) { Write-Host "Successfully started sshd on $VMName. For security reasons, please make sure to stop it once you are done by calling Disable-JetDRSshd" } else { Write-Error "Could not start sshd on $VMName" -ErrorAction Stop } } else { Write-Host "sshd service is already running on $VMname. For security reasons, please make sure to stop it if it is not needed by calling Disable-JetDRSshd." } } } function Disable-JetDRSshd { <# .NOTES =========================================================================== Created by: JetStream Software Inc =========================================================================== .DESCRIPTION Stops sshd on JetSream MSA .PARAMETER VMName MSA VM Name .PARAMETER MSACredential MSACredential of root user .EXAMPLE Disable-JetDRSshd -VMName JS-MSA -MSACredential xxx #> [CmdletBinding()] [AVSAttribute(5, UpdatesSDDC = $False)] param( [Parameter(Mandatory=$False, HelpMessage="Name of the MSA VM")] [String]$VmName="msa@4.2.0+jetdr", [Parameter(Mandatory=$true, HelpMessage="MSA Credentials of root user")] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $MSACredential ) Begin { $UserName = $MSACredential.UserName.trim() $Password = $MSACredential.GetNetworkCredential().Password.trim() } Process { $msa_vm = Get-VM $VMName -ErrorAction SilentlyContinue if ($null -eq $msa_vm) { Write-Error "Could not find MSA VM. Please rerun providing the correct VM name." -ErrorAction Stop } $status_out = Invoke-VMScript -VM $VMName -ScriptText 'service sshd status' -GuestUser $UserName -GuestPassword $Password if($status_out.ExitCode -eq 0) { Write-Host "sshd service is running on $VMName. Stopping the service..." $stop_out = Invoke-VMScript -VM $VMName -ScriptText 'service sshd stop' -GuestUser $UserName -GuestPassword $Password if($stop_out.ExitCode -eq 0) { Write-Host "Successfully stopped sshd on $VMName." } else { Write-Error "Could not stop sshd on $VMName" -ErrorAction Stop } } else { Write-Host "sshd service is already stopped on $VMname." } } } # SIG # Begin signature block # MIIUoAYJKoZIhvcNAQcCoIIUkTCCFI0CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDw745QEx1F4vJc # /ak/CCVsXnz4eGc2FqK4EXs2yOrtDaCCEVswggVvMIIEV6ADAgECAhBI/JO0YFWU # jTanyYqJ1pQWMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI # DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM # EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy # dmljZXMwHhcNMjEwNTI1MDAwMDAwWhcNMjgxMjMxMjM1OTU5WjBWMQswCQYDVQQG # EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdv # IFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQCN55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+s # hJHjUoq14pbe0IdjJImK/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCD # J9qaDStQ6Utbs7hkNqR+Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7 # P2bSlDFp+m2zNKzBenjcklDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extme # me/G3h+pDHazJyCh1rr9gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUz # T2MuuC3hv2WnBGsY2HH6zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6q # RT5uWl+PoVvLnTCGMOgDs0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mcz # mrYI4IAFSEDu9oJkRqj1c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEc # QNYWFyn8XJwYK+pF9e+91WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2T # OglmmVhcKaO5DKYwODzQRjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/ # AZwQsRb8zG4Y3G9i/qZQp7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QID # AQABo4IBEjCCAQ4wHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYD # VR0OBBYEFDLrkpr/NZZILyhAQnAgNpFcF4XmMA4GA1UdDwEB/wQEAwIBhjAPBgNV # HRMBAf8EBTADAQH/MBMGA1UdJQQMMAoGCCsGAQUFBwMDMBsGA1UdIAQUMBIwBgYE # VR0gADAIBgZngQwBBAEwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21v # ZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUHAQEE # KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZI # hvcNAQEMBQADggEBABK/oe+LdJqYRLhpRrWrJAoMpIpnuDqBv0WKfVIHqI0fTiGF # OaNrXi0ghr8QuK55O1PNtPvYRL4G2VxjZ9RAFodEhnIq1jIV9RKDwvnhXRFAZ/ZC # J3LFI+ICOBpMIOLbAffNRk8monxmwFE2tokCVMf8WPtsAO7+mKYulaEMUykfb9gZ # pk+e96wJ6l2CxouvgKe9gUhShDHaMuwV5KZMPWw5c9QLhTkg4IUaaOGnSDip0TYl # d8GNGRbFiExmfS9jzpjoad+sPKhdnckcW67Y8y90z7h+9teDnRGWYpquRRPaf9xH # +9/DUp/mBlXpnYzyOmJRvOwkDynUWICE5EV7WtgwggXGMIIELqADAgECAhEAx5f+ # KBbVHZKKYsCngzhy/DANBgkqhkiG9w0BAQwFADBUMQswCQYDVQQGEwJHQjEYMBYG # A1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1YmxpYyBD # b2RlIFNpZ25pbmcgQ0EgUjM2MB4XDTIzMDUwMzAwMDAwMFoXDTI1MDUwMjIzNTk1 # OVowXDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExGzAZBgNVBAoM # EkpldFN0cmVhbSBTb2Z0d2FyZTEbMBkGA1UEAwwSSmV0U3RyZWFtIFNvZnR3YXJl # MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA303037LJy/ygxXhA/dpm # taFbP40OUibB16KHBG8MsH1RA3KyDNm8IATCm5b8F4YT4umB7osCUewzuHmMebba # iG4R7+0eJ4ks+RpNbx5XXQ85KnaYRHqyqxeokJzD24Hn154M6Fjmbfj1cG/QgqRX # +tGngozNVouAhVP7XjNFPeNpNo16aAQElyAkdbJ6phDhENKT8sINmzVxPT53GZZm # mZx3Kk5VSHamELY4uD3fivSKjxUXAQEUOsEs4nm1Bet7J2Zl+VG6jbSLwWbzbCf3 # Y9ue3MZR95LCASqaKGppMj5PDeYtUm8Ww4Kjc3tvPtJfDaYE8Xwr8T6C6AwGqacE # a9Vry7XKuL2nucqWvc5bZwHFrpoHphvLXeGqNucyKvT47/w7ASonz3D3u7HvZnHH # xFL2XljDntOvIGDUvf7q4+P6rmJrrF+8VDLwx6us56bxUi30Hl8hVdPYHwDCEZB8 # T6arb5dq1XhAgS+m3v8GbP5KYwh08bWSXH+HDtv35aK9AgMBAAGjggGJMIIBhTAf # BgNVHSMEGDAWgBQPKssghyi47G9IritUpimqF6TNDDAdBgNVHQ4EFgQUDjCOWzEl # bVPAwKfIjtElrJOezhUwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYD # VR0lBAwwCgYIKwYBBQUHAwMwSgYDVR0gBEMwQTA1BgwrBgEEAbIxAQIBAwIwJTAj # BggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQQBMEkG # A1UdHwRCMEAwPqA8oDqGOGh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1 # YmxpY0NvZGVTaWduaW5nQ0FSMzYuY3JsMHkGCCsGAQUFBwEBBG0wazBEBggrBgEF # BQcwAoY4aHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNp # Z25pbmdDQVIzNi5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28u # Y29tMA0GCSqGSIb3DQEBDAUAA4IBgQCEQuY+MjBvY7xvU4BU0+PAASEGVEJgVO6e # eu0IBb1d0HJCOgOhhg3T6vLAIGTfB5BRhpHOnI73/7t+4GaqAORJkAqQNhryfxtm # N9JqUDUx/KvCq0+5oHYaVCWvjap3U1/vc5TbdIVIRRh+EZ92fEafQLlIDVrHun1Z # TKEdeoRkCDnpexs0X3Lz2IwTPGXqz0OIlGwsyUI/nBuwa//APQPq+q9MS6e1D3RI # 2IpCd9VuSNiFCcispPaT/E0dwqDe8vYZX7sOdcJTp5whLKC8bFQL2Fpt1pHRzmSz # hLAJbrRcnmqcnJr7hR+hWsYycnlkvUUxIHPg27bsZwjNJbG0xNSepo8VN8/MdeFE # ghkRE1QYSryE8JoQjrbk4oXsRvviZAFSGCp9yqeqvmpDrDNCaLwJk0JZ2L5Cpz79 # NvHJ+15kcIFKipn/ExiMZ5Hbj8IehE2vOI0L2olQ5LsPvB8/PA4E/yMq4bgbGg23 # Tn9u11KQlnaeju+dZW3DBs2WVEZmpUkwggYaMIIEAqADAgECAhBiHW0MUgGeO5B5 # FSCJIRwKMA0GCSqGSIb3DQEBDAUAMFYxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9T # ZWN0aWdvIExpbWl0ZWQxLTArBgNVBAMTJFNlY3RpZ28gUHVibGljIENvZGUgU2ln # bmluZyBSb290IFI0NjAeFw0yMTAzMjIwMDAwMDBaFw0zNjAzMjEyMzU5NTlaMFQx # CzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzApBgNVBAMT # IlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYwggGiMA0GCSqGSIb3 # DQEBAQUAA4IBjwAwggGKAoIBgQCbK51T+jU/jmAGQ2rAz/V/9shTUxjIztNsfvxY # B5UXeWUzCxEeAEZGbEN4QMgCsJLZUKhWThj/yPqy0iSZhXkZ6Pg2A2NVDgFigOMY # zB2OKhdqfWGVoYW3haT29PSTahYkwmMv0b/83nbeECbiMXhSOtbam+/36F09fy1t # sB8je/RV0mIk8XL/tfCK6cPuYHE215wzrK0h1SWHTxPbPuYkRdkP05ZwmRmTnAO5 # /arnY83jeNzhP06ShdnRqtZlV59+8yv+KIhE5ILMqgOZYAENHNX9SJDm+qxp4Vqp # B3MV/h53yl41aHU5pledi9lCBbH9JeIkNFICiVHNkRmq4TpxtwfvjsUedyz8rNyf # QJy/aOs5b4s+ac7IH60B+Ja7TVM+EKv1WuTGwcLmoU3FpOFMbmPj8pz44MPZ1f9+ # YEQIQty/NQd/2yGgW+ufflcZ/ZE9o1M7a5Jnqf2i2/uMSWymR8r2oQBMdlyh2n5H # irY4jKnFH/9gRvd+QOfdRrJZb1sCAwEAAaOCAWQwggFgMB8GA1UdIwQYMBaAFDLr # kpr/NZZILyhAQnAgNpFcF4XmMB0GA1UdDgQWBBQPKssghyi47G9IritUpimqF6TN # DDAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNVHSUEDDAK # BggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEsGA1UdHwRE # MEIwQKA+oDyGOmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0Nv # ZGVTaWduaW5nUm9vdFI0Ni5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsGAQUFBzAC # hjpodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmlu # Z1Jvb3RSNDYucDdjMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNv # bTANBgkqhkiG9w0BAQwFAAOCAgEABv+C4XdjNm57oRUgmxP/BP6YdURhw1aVcdGR # P4Wh60BAscjW4HL9hcpkOTz5jUug2oeunbYAowbFC2AKK+cMcXIBD0ZdOaWTsyNy # BBsMLHqafvIhrCymlaS98+QpoBCyKppP0OcxYEdU0hpsaqBBIZOtBajjcw5+w/Ke # FvPYfLF/ldYpmlG+vd0xqlqd099iChnyIMvY5HexjO2AmtsbpVn0OhNcWbWDRF/3 # sBp6fWXhz7DcML4iTAWS+MVXeNLj1lJziVKEoroGs9Mlizg0bUMbOalOhOfCipnx # 8CaLZeVme5yELg09Jlo8BMe80jO37PU8ejfkP9/uPak7VLwELKxAMcJszkyeiaer # lphwoKx1uHRzNyE6bxuSKcutisqmKL5OTunAvtONEoteSiabkPVSZ2z76mKnzAfZ # xCl/3dq3dUNw4rg3sTCggkHSRqTqlLMS7gjrhTqBmzu1L90Y1KWN/Y5JKdGvspbO # rTfOXyXvmPL6E52z1NZJ6ctuMFBQZH3pwWvqURR8AgQdULUvrxjUYbHHj95Ejza6 # 3zdrEcxWLDX6xWls/GDnVNueKjWUH3fTv1Y8Wdho698YADR7TNx8X8z2Bev6SivB # BOHY+uqiirZtg0y9ShQoPzmCcn63Syatatvx157YK9hlcPmVoa1oDE5/L9Uo2bC5 # a4CH2RwxggKbMIIClwIBATBpMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0 # aWdvIExpbWl0ZWQxKzApBgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmlu # ZyBDQSBSMzYCEQDHl/4oFtUdkopiwKeDOHL8MA0GCWCGSAFlAwQCAQUAoIGEMBgG # CisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcC # AQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIE # IN0S9rom/psnVz0uOErNazV+QRgS8t6Un11dHrHDjo0HMA0GCSqGSIb3DQEBAQUA # BIIBgEhXGf7yenRmlYuYmCLlxU5wJXOoEjlPRETmRymsaNZzh58IiNRkOyhJppjv # CFiRlBu6BP05GYRfKsWVVC3JIanm67Avcgexgvh5PXpNxFWRLpjI4uCgrmlIOnNU # Saj4RXgz5WT7yqvTy4F3ya8v/VMlVKcn93S5VR3s94ad8x/z4j4mwKfLuSBS7xrW # 3L6yz8U598JWQGXMrkI7Ie476bB8u5CUTTrM34r+933yuqzFw8qK4ryKyeLIY2kX # DtLGD8BdnaNx7PRFeuwkeMvXKS0/B5IHF2ikDSUryrZZLDa75o9ZQHgHw5ST6B9m # PAiFcZu9ycpLwupxbuR8zro9K/KwGS4eJ6Y6QkPntzKZCkqe0bJ0FK69H2peBLQP # N9K2VoYaznWLfwS4eibA+xh7mEnjYtB7INCoNe3YctHB4UInSvc7FmgAAZ6SMQR4 # S4qoVCF0ukse+3vh4nt/HT+nj9bc7EFE2KCv6PzVavDTdu3sLQetB9GWPxcz495P # NU0ZTw== # SIG # End signature block |