jetdr_avs_lib.ps1
trap { Write-Host "$_" exit 1 } function download_jetdr_bundle{ param( $url, $download_file_path #"f:\tools\" + $zip_filename ) Write-Host "$url, $download_file_path" $download_path = Split-Path $download_file_path if(!(Test-Path -path $download_path)) { write-error "`n[ERROR] The path $download_path doesn't exist. Please create the folder and try again`n" -ErrorAction Stop } if(Test-Path -path $download_file_path) { Write-Host "File already exists. Skipping download." } else { Write-Host "### $($MyInvocation.MyCommand) ###" $start_time = Get-Date Invoke-WebRequest $url -OutFile $download_file_path -Resume if (!$?) { write-error "Downloading jetdr bundle failed, rc=$?" -ErrorAction Stop } Write-Host "Time taken: $((Get-Date).Subtract($start_time).TotalSeconds) second(s)" } } function unzip_ova { param( $zip_filename, #JSDR-GA.2.7.zip $destination_folder ) Write-Host "### $($MyInvocation.MyCommand) ###" # delete the extract directory if it exists if(Test-Path -path $destination_folder) { Write-Host "Destination directory $destination_folder already exists, deleting." Remove-Item $destination_folder -Recurse } try { Expand-Archive -Path $zip_filename -DestinationPath $destination_folder } catch { write-host "Unzip failed. The downloaded file may be corrupt. Deleting. Please run the script again." Remove-Item $zip_filename write-error "Unzip jetdr bundle failed, rc=$?" -ErrorAction Stop } $checksumfile = Get-ChildItem -Path $destination_folder -Filter "*checksum*txt" -Recurse | %{$_.FullName} $ovafile = Get-ChildItem -Path $destination_folder -Filter "*jetstream*ova" -Recurse | %{$_.FullName} $filehash = Get-FileHash $ovafile -Algorithm SHA256 $checksum = Select-String -Path $checksumfile -Pattern $filehash.hash if ($checksum -ne $null) { write-host "Ova checksum validated successfully" } else{ write-host "Checksum validation failed. The downloaded file may be corrupt. Deleting. Please run the script again." Remove-Item $zip_filename write-error "Ova checksum validation failed." -ErrorAction Stop } } function ms_rest_state { param( $ms_ip, $ms_user, $ms_pwd, $timeout = 600 ) Write-Host "### $($MyInvocation.MyCommand) ###" $rlt = 0 while ($timeout -gt 0) { $resp_obj = get_ms_state $ms_ip $ms_user $ms_pwd if($resp_obj -eq $null){ Write-Host "Unable to get MSA state, sleep for 10 seconds.." start-sleep 10 } else { Write-Host "MSA REST server is up and running" $rlt = 1 break } $timeout -= 10 } return $rlt } function deploy_ova { param( $ovf_path, $ms_network, $ms_hostname, $ms_pwd, $ms_gateway, $ms_dns, $ms_ip, $ms_netmask, $ms_cluster_name, $ms_vm_name, $ms_datastore, $disk_format="Thin", $disable_ssh=$true ) Write-Host "### $($MyInvocation.MyCommand) ###" $ovfConfig = Get-OvfConfiguration -Ovf $ovf_path $ovfConfig.NetworkMapping.Network_1.Value = $ms_network $ovfConfig.Common.hostname.Value = $ms_hostname $ovfConfig.Common.password.Value = $ms_pwd $ovfConfig.Common.disablessh.Value = $disable_ssh $ovfConfig.vami.JetStream_Software_Disaster_Recovery_Management_Server.gateway.Value = $ms_gateway $ovfConfig.vami.JetStream_Software_Disaster_Recovery_Management_Server.DNS.Value = $ms_dns $ovfConfig.vami.JetStream_Software_Disaster_Recovery_Management_Server.ip0.Value = $ms_ip $ovfConfig.vami.JetStream_Software_Disaster_Recovery_Management_Server.netmask0.Value = $ms_netmask $cluster = Get-Cluster -Name $ms_cluster_name $disk_format = "Thin" $vm_name = $ms_vm_name $datastore = Get-Datastore -Name $ms_datastore $vmhost = Get-Cluster $ms_cluster_name | Get-VMHost | Select -first 1 try { Import-VApp -Source $ovf_path -OvfConfiguration $ovfConfig -Name $vm_name -vmHost $vmhost -Location $cluster -Datastore $datastore -DiskStorageFormat $disk_format -Confirm:$false > $null } catch { write-error "Import MS ova failed, rc=$?" -ErrorAction Stop } start-vm $ms_vm_name -confirm:$false > $null if (!$?) { write-error "Starting VM $ms_vm_name failed" -ErrorAction Stop } $vm_ip=get_vm_ip $ms_vm_name 600 $rc=ms_rest_state $vm_ip "root" $ms_pwd 600 if (!$rc) { write-error "MSA $vm_ip is not ready after 600 seconds" -ErrorAction Stop } Write-Host "Sleep for 2 more minute after Manamgement server REST server is running" start-sleep 120 return $vm_ip } function ping_vm { param( $vm_ip = $( throw "specify vm ip" ), $timeout = 600 ) Write-Host "### $($MyInvocation.MyCommand) ###" $rlt = 0 while ($timeout -gt 0) { $rc = test-connection -computername $vm_ip -quiet if (!$rc) { Write-Host "$vm_ip is not reachable, sleep for 5 seconds.." start-sleep 5 } else { Write-Host "$vm_ip is pingable now." $rlt = 1 break } $timeout -= 5 } return $rlt } function get_vm_ip { param( $vm_name = $(throw "vmName is required"), $timeout = 600 ) Write-Host "### $($MyInvocation.MyCommand) ###" while ($timeout -gt 0) { $vm_ip = (Get-VM $vm_name).Guest.IPAddress[0] if (($vm_ip -ne $null) -and ($vm_ip -match "\d+\.\d+\.\d+\.\d+")) { $timeout = 0 } else { $timeout -= 30 Write-Host "couldn't get ip of $vm_name. Sleep for 30 seconds" Start-Sleep 30 } } if (($vm_ip -eq $null) -or ($vm_ip -notmatch "\d+\.\d+\.\d+\.\d+")) { write-error "Failed in getting ip of vm $vm_name" -ErrorAction Stop } return $vm_ip } function create_user { param( [String]$user, # e.g "testuser" [String]$pwd ) Write-Host "### $($MyInvocation.MyCommand) ###" $user=New-SsoPersonUser -UserName $user -Password $pwd if(!$user) { write-error "Failed to create user $user" -ErrorAction Stop } } function delete_user { param( [String]$user ) Write-Host "### $($MyInvocation.MyCommand) ###" $domain = $user.split("\")[0] $username = $user.split("\")[1] $ssouser = Get-SsoPersonUser -Name $username -Domain $domain Remove-SsoPersonUser -User $ssouser[0] } function assign_new_role_to_user { param( [String]$new_role_name, [String]$sso_user_name, # e.g "vsphere.local\testuser" [String[]]$new_privileges # e.g "Maintenance", "Query patch", "CIM interaction", "Profile-driven storage update" ) Write-Host "### $($MyInvocation.MyCommand) ###" $existing_role = "CloudAdmin" # chk if Cloudadmin role exists $cloudadmin_role = Get-VIRole | Where-Object {$_.Name -eq $existing_role} $cloudadmin_privileges = Get-VIPrivilege -Role $existing_role # check if new role already exists $new_role = Get-VIRole | Where-Object {$_.Name -eq $new_role_name} if ($new_role -ne $null) { #remove_role $new_role_name Write-Host "Role $new_role_name already exists in vCenter. Skipping creation" } else{ # create a new role with cloudadmin privileges $my_role = New-VIRole -Privilege $cloudadmin_privileges -Name $new_role_name if (!$?) { write-error "Failed to create new role ${new_role_name}, rc=$?" -ErrorAction Stop } } $my_role = Get-VIRole | Where-Object {$_.Name -eq $new_role_name} # add new privileges to this new role $priv = @() Foreach ($cust_priv in $new_privileges){ $priv += Get-VIPrivilege | Where-Object {$_.Name -eq $cust_priv} } Set-VIRole -Role $my_role -AddPrivilege $priv if (!$?) { write-error "Failed to add new privileges ${priv} to role ${my_role}, rc=$?" -ErrorAction Stop } # get root folder and then grant $sso_user_name access to the role on rootfolder level Write-Host "assign permissions" $rootfolder = Get-Folder -NoRecursion $new_permission = New-VIPermission -Role $new_role_name -Principal $sso_user_name -Entity $rootfolder if (!$?) { write-error "Failed to grant user ${sso_user_name} to role ${new_role_name}, rc=$?" -ErrorAction Stop } Write-Host "new permissions type: " + $new_permission return $new_permission } function remove_role { param( $role_name ) Write-Host "### $($MyInvocation.MyCommand) ###" Write-Host "Removing role $role_name" # remove a role Remove-VIRole $role_name -confirm:$false -Force if (!$?) { write-error "Failed to remove role ${role_name}, rc=$?" -ErrorAction Stop } return } function remove_permissions { param($permissions) Write-Host "### $($MyInvocation.MyCommand) ###" Remove-VIPermission $permissions -confirm:$false if (!$?) { write-error "Failed to remove permissions ${permissions}, rc=$?" -ErrorAction Stop } } function generate_password { param( [ValidateRange(8, 20)] [int] $length = 14 ) $symbols = '!@#$%^&*'.ToCharArray() $characterList = 'a'..'z' + 'A'..'Z' + '0'..'9' + $symbols do { $password = -join (0..$length | % { $characterList | Get-Random }) [int]$hasLowerChar = $password -cmatch '[a-z]' [int]$hasUpperChar = $password -cmatch '[A-Z]' [int]$hasDigit = $password -match '[0-9]' [int]$hasSymbol = $password.IndexOfAny($symbols) -ne -1 } until (($hasLowerChar + $hasUpperChar + $hasDigit + $hasSymbol) -ge 4) return $password } function get_request { param( $endpoint, $header, $outfile="get_request_output.csv" ) Write-Host "### $($MyInvocation.MyCommand) ###" try { $resp_obj = Invoke-RestMethod -Method 'Get' -Uri $endpoint -Headers $header -skipCertificateCheck } catch { # Dig into the exception to get the Response details. # Note that value__ is not a typo. $_.Exception |format-list -force } return $resp_obj } function get_dr_header { param($fios_session_id) Write-Host "### $($MyInvocation.MyCommand) ###" $header = @{ 'Accept' = "application/json" 'content-type' = 'application/json' 'fios-session' = $fios_session_id } return $header } function post_request { param( $endpoint, $header, $body, $outfile="post_request_output.csv" ) try { $resp_obj = Invoke-RestMethod -Method 'Post' -Uri $endpoint -Headers $header -Body $body -skipCertificateCheck } catch { $_.Exception | format-list -force } return $resp_obj } function get_encoded_auth { param($user, $pwd) $plain_str = "${user}:${pwd}" $bytes = [System.Text.Encoding]::UTF8.GetBytes($plain_str) $encoded_text =[Convert]::ToBase64String($bytes) $encoded_text } function get_vcenter_session { param($ms_ip, $vcenter_fqdn, $base64_cred) # https://<MS hostname>:8443/jss/domains $endpoint = 'https://' + $ms_ip + ':8443/jss/vmplatform/' + $vcenter_fqdn + "/loginByAddress" $header = @{ 'Accept' = "application/json" 'Authorization' = 'Basic ' + $base64_cred } $resp_obj = get_request $endpoint $header #$resp_obj | Out-String | Write-Host if ($resp_obj -match '=\"(.*?)\"') { $fios_session = $matches[1] } else { write-error "Failed to get vcenter session id. Please check if MSA is registered to vCenter and credentials are correct." -ErrorAction Stop } return $fios_session } function refresh_vc_session { param($ms_ip, $vc_hostname, $vc_user, $vc_pwd) $vc_base64 = get_encoded_auth $vc_user $vc_pwd $fios_session_id = get_vcenter_session $ms_ip $vc_hostname $vc_base64 return $fios_session_id } function login_ms_portal { param($ms_ip, $ms_user, $ms_pwd) $timeout = 600 $ms_base64 = get_encoded_auth $ms_user $ms_pwd $request_url = 'https://' + $ms_ip + ':8443/jss/ms/login' $header = @{ "Authorization" = "Basic " + $ms_base64 } Write-Host $request_url while ($timeout -gt 0) { try { $resp_obj = get_request $request_url $header $session_id = $resp_obj.loginResponse.sessionId } catch { $_.Exception |format-list -force } if ($session_id -ne $null) { return $session_id } else { Write-host "Waiting get MSA session id. Sleep for 1 minute and retry" $timeout -= 60 start-sleep 60 } } if ($session_id -eq $null) { Write-Error "Failed to get MSA session id after 10 minutes. Please check your MSA" -ErrorAction Stop } } function register_ms_with_vc { param($ms_ip, $ms_user, $ms_pwd, $vc_hostname, $vc_user, $vc_pwd, $ms_mode, $register_with_ip) Write-Host "### $($MyInvocation.MyCommand) ###" Write-Host "Registering vCenter $vc_hostname to MS $ms_ip with user $vc_user" $endpoint = 'https://' + $ms_ip + ':8443/jss/vmplatform' $vc_base64 = get_encoded_auth $vc_user $vc_pwd $header = @{ "Accept" = "application/json" 'content-type' = 'application/json' 'ms-session' = login_ms_portal $ms_ip $ms_user $ms_pwd } $body = @{ "address" = $vc_hostname "credential" = $vc_base64 "msMode" = $ms_mode "registerWithMsIp" = $register_with_ip } $json = $body | Convertto-JSON $resp_obj = post_request $endpoint $header $json } function unregister_vcenter_from_ms { param($ms_ip, $vc_hostname, $vc_user, $vc_pwd, $fios_session_id) Write-Host "### $($MyInvocation.MyCommand) ###" Write-Host "Unregistering vCenter $vc_hostname from MS $ms_ip" $endpoint = 'https://' + $ms_ip + ':8443/jss/vmplatform/' + $vc_hostname + "/unregisterByAddress" $vc_base64 = get_encoded_auth $vc_user $vc_pwd $body = @{ "credential" = $vc_base64 } $json = $body | Convertto-JSON $header = get_dr_header($fios_session_id) $resp_obj = post_request $endpoint $header $json } function get_drvas { param($ms_ip, $fios_session_id) Write-Host "### $($MyInvocation.MyCommand) ###" $endpoint = 'https://' + $ms_ip + ':8443/jss/drvas' $header = get_dr_header($fios_session_id) $resp_obj = get_request $endpoint $header $resp_obj if ($resp_obj -eq $null) { Write-Host "No DRVA is configured." } else { Write-Error "DRVA(s) are still configured. Please unconfigure and try again" -ErrorAction Stop } } function get_site_dc_state { param( $ms_ip, $fios_session_id ) $endpoint = 'https://' + $ms_ip + ":8443/jss/datacenters" $header = get_dr_header($fios_session_id) $primary_site_registered_vc = get_request $endpoint $header Write-Host "request_url: $endpoint" return $primary_site_registered_vc } function get_cluster_state { param( $ms_ip, $fios_session_id, $cluster_name ) $primary_site_dcs = get_site_dc_state $ms_ip $fios_session_id foreach ($dc in $primary_site_dcs) { foreach ($cluster in $dc.clusters) { if ($cluster.clusterName.ToLower() -eq $cluster_name.ToLower()) { $cluster_id = $cluster.id } } } $endpoint = 'https://' + $ms_ip + ":8443/jss/clusters/" + $cluster_id $header = get_dr_header($fios_session_id) $cluster_state = get_request $endpoint $header Write-Host "request_url: $endpoint" return $cluster_state } function get_dr_task_by_id { param($ms_ip, $fios_session_id, $task_id) $endpoint = 'https://' + $ms_ip + ":8443/jss/tasks/" + $task_id $header = get_dr_header($fios_session_id) $response = get_request $endpoint $header return $response } function wait_for_dr_task_finish { param($ms_ip, $fios_session_id, $task_id) Write-Host "Task id: $task_id" $dr_task = get_dr_task_by_id $ms_ip $fios_session_id $task_id $task_state = $dr_task.state $task_progress = $dr_task.progress $task_description = $dr_task.description while ($task_progress -ne "100") { Write-Host "State: $task_state" Write-Host "Progress: $task_progress" Write-Host "Sleep for 30 seconds and wait for task $task_description to finish" start-sleep 30 $dr_task = get_dr_task_by_id $ms_ip $fios_session_id $task_id $task_state = $dr_task.state $task_progress = $dr_task.progress } $err_code = $dr_task.errorCode if ($err_code -eq 0) { Write-Host "Task $task_description finished successfully: $task_state" return 0 } else { write-warning "Task $task_description finished w/ error: $err_code $dr_task.errorMessage" return 1 } } function configure_cluster { param($ms_ip, $cluster_name, $fios_session_id) Write-Host "### $($MyInvocation.MyCommand) ###" $retry_count=0 $cluster_params = @() $endpoint = 'https://' + $ms_ip + ":8443/jss/clusters/configure" $primary_site_dcs = get_site_dc_state $ms_ip $fios_session_id foreach ($dc in $primary_site_dcs) { foreach ($cluster in $dc.clusters) { if ($cluster.clusterName.ToLower() -eq $cluster_name.ToLower()) { $params = @{ "clusterId" = $cluster.id "packageType" = "DR" } $cluster_params += $params } } } $header = get_dr_header($fios_session_id) $body = @{ "clustersConfigureParams" = $cluster_params } $json = $body | Convertto-JSON do{ $task = post_request $endpoint $header $json # wait for cluster configuration finish before we can remove the elevated privileges $status = wait_for_dr_task_finish $ms_ip $fios_session_id $task.id $retry_count++ }while(($retry_count -lt 3) -and ($status -ne 0)) if (($retry_count -eq 3) -and ($status -ne 0)){ Write-Error "ERROR: Configure Cluster failed. Please check MS task logs, resolve the issues and run again." -ErrorAction Stop } return $status } function unconfigure_cluster { param($ms_ip, $cluster_name, $fios_session_id) Write-Host "### $($MyInvocation.MyCommand) ###" $retry_count=0 $cluster_params = @() $endpoint = 'https://' + $ms_ip + ":8443/jss/clusters/unconfigure" $primary_site_dcs = get_site_dc_state $ms_ip $fios_session_id $cluster_state=get_cluster_state $ms_ip $fios_session_id $cluster_name if ($cluster_state.software.name -eq 'jetdr') { Write-Host "Cluster $cluster_name has JetStream iofilter installed. Checking if there are 4 hosts in the custer in order to proceed with uninstall" $HostCount=Get-Cluster -Name $cluster_name -ErrorAction SilentlyContinue | Get-VMHost if ($HostCount.count -lt 4) { Write-Error "Cluster to be unconfigured has less than 4 hosts. Please make sure to have at least 4 hosts in protected cluster" -ErrorAction Stop } else { Write-Host "SUCCESS: Protected cluster satisfies the number of host requirement" } foreach ($dc in $primary_site_dcs) { foreach ($cluster in $dc.clusters) { if ($cluster.clusterName.ToLower() -eq $cluster_name.ToLower()) { if ($cluster.domainCnt -ne 0) { Write-Error "ERROR: Cannot unconfigure cluster as it is used by a Protected Domain" -ErrorAction Stop } $params = @{ "clusterId" = $cluster.id } $cluster_params += $params } } } $header = get_dr_header($fios_session_id) $body = @{ "clustersUnconfigureParams" = $cluster_params } $json = $body | Convertto-JSON do{ $task = post_request $endpoint $header $json # wait for cluster unconfiguration finish before we can remove the elevated privileges $status = wait_for_dr_task_finish $ms_ip $fios_session_id $task.id $retry_count++ }while(($retry_count -lt 3) -and ($status -ne 0)) if (($retry_count -eq 3) -and ($status -ne 0)){ Write-Error "ERROR: Unconfigure Cluster failed. Please check MS task logs, resolve the issues and run again." -ErrorAction Stop } return $status } else { Write-Host "Cluster doesn't have jetdr iofilter installed. Skipping unconfigure cluster" } } function get_ms_state { param($ms_ip, $ms_user, $ms_pwd) Write-Host "### $($MyInvocation.MyCommand) ###" $header = @{ "Accept" = "application/json" 'content-type' = 'application/json' 'ms-session' = login_ms_portal $ms_ip $ms_user $ms_pwd } $endpoint = 'https://' + $ms_ip + ":8443/jss/ms" $response = get_request $endpoint $header if (!$response) { Write-Host "MSA state api didn't return anything." } else { if($response.configured -eq $False) { Write-Host "MSA is not registered to any vCenter server" } else { Write-Host "MSA is registered" } } return $response } function get_system_state { param($ms_ip, $ms_user, $ms_pwd, $hostname, $dns) Write-Host "### $($MyInvocation.MyCommand) ###" $ms_up = ping_vm $ms_ip 5 if (!$ms_up) { Write-Host "MSA ip $ms_ip not pingable." return } else { Write-Host "MSA is pingable." get_ms_state $ms_ip $ms_user $ms_pwd } $rc = ping_vm $dns 5 if (!$rc) { Write-Host "ERROR: Dns server $dns not pingable." return } else { Write-Host "Dns server $dns is pingable" } $check_hostname=test-connection $hostname $var=$check_hostname[0].Address $var | Out-String | Write-Host Write-Host "DNS IP address for your Management Server appliance $hostname is $var" if ($check_hostname[0].Address.IPAddressToString -eq $ms_ip) { Write-Host "DNS IP address $var resolves to hostname $hostname" } else{ Write-Host "ERROR: DNS IP address $var doesn't resolve to hostname $hostname" } } function get_system_state_install { param($msvm_name, $msa_cluster, $protected_cluster, $datastore, $network) Write-Host "### $($MyInvocation.MyCommand) ###" $error=$False $rc=Get-Cluster -Name $protected_cluster -ErrorAction SilentlyContinue if (!$rc) { Write-Error "Specified cluster '$protected_cluster' does not exist in the Datacenter. Please provide correct details." $error=$True } else { Write-Host "SUCCESS: Cluster '$protected_cluster' provided for protection exists in the Datacenter" $HostCount=Get-Cluster -Name $protected_cluster -ErrorAction SilentlyContinue | Get-VMHost if ($HostCount.count -lt 3) { Write-Error "Cluster to be protected has less than 3 hosts. Please make sure to have at least 3 hosts in protected cluster" $error=$True } else { Write-Host "SUCCESS: Protected cluster satisfies the number of host requirement" } } $rc = getVasaProvider $protected_cluster if ($rc -eq 1) { $error=$True } $rc=Get-Cluster -Name $msa_cluster -ErrorAction SilentlyContinue if (!$rc) { Write-Error "Specified cluster '$msa_cluster' for deploying MSA does not exist in the Datacenter. Please provide correct details." $error=$True } else { Write-Host "SUCCESS: Cluster '$msa_cluster' provided for deploying MSA exists in the Datacenter" } $rc=Get-VM $msvm_name -ErrorAction SilentlyContinue if ($rc) { Write-Error "VM with name '$msvm_name' already exists in datacenter. Please remove the VM before proceeding" $error=$True } else{ Write-Host "SUCCESS: MSA vm doesn't exist in datacenter." } # Check if provided datastore exists in the datacenter $ds_obj=Get-DataStore $datastore -ErrorAction SilentlyContinue if ($ds_obj -eq $null) { Write-Error "Specified datastore $datastore not found in the datacenter. Please provide a correct datastore name." $error = $True } else { $ds_space_gb=$ds_obj.FreeSpaceGB if ($ds_space_gb -lt 60) { Write-Error "Datastore provided for MS deployment doesn't have enough free space for the deployment. Minimum required 60GB" $error = $True } else { Write-Host "SUCCESS: Datastore has enough free space for JetDR ova deployment." } } # Check if provided network exists in the datacenter $nw_obj = Get-VirtualNetwork $network -ErrorAction SilentlyContinue if ($nw_obj -eq $null) { Write-Error "Specified network name $network not found in the datacenter. Please provide a correct network name" $error = $True } else { $AVSModule = Get-Module -Name Microsoft.AVS.Management $AVSProtectedNWS = & $AVSModule {Get-ProtectedNetworks} if ($AVSProtectedNWS.Name.ToLower() -Contains $network.ToLower()) { Write-Error "Network $network is one of AVS protected networks. Please provide a different network for MSA deployment" $error = $True } else { Write-Host "SUCCESS: Network provided for MSA is not an AVS protected network." } } $extMgr = Get-View ExtensionManager $jsdrplugin=$extMgr.ExtensionList | select Key if ($jsdrplugin.Key -contains "com.jetstream.primary.jetdrplugin") { Write-Error "VCenter already has JetDR plugin. Please unregister vCenter or cleanup any stale plugins before continuing." $error=$True } else { Write-Host "SUCCESS: VCenter doesn't have JetDR plugin." } if ($error -eq $true) { Write-Error "There were errors in the preflight check. Please resolve the errors and try again" -ErrorAction Stop } else { Write-Host "SUCCESS: Preflight checks succeeded." } } function get_system_state_configure { param($protected_cluster) $rc=Get-Cluster -Name $protected_cluster -ErrorAction SilentlyContinue if (!$rc) { Write-Error "Specified cluster '$protected_cluster' does not exist in the Datacenter. Please provide correct details." $error=$True } else { Write-Host "SUCCESS: Cluster '$protected_cluster' provided for protection exists in the Datacenter" $HostCount=Get-Cluster -Name $protected_cluster -ErrorAction SilentlyContinue | Get-VMHost if ($HostCount.count -lt 3) { Write-Error "Cluster to be protected has less than 3 hosts. Please make sure to have at least 3 hosts in protected cluster" $error=$True } else { Write-Host "SUCCESS: Protected cluster satisfies the number of host requirement" } } $rc = getVasaProvider $protected_cluster if ($rc -eq 1) { $error=$True } $extMgr = Get-View ExtensionManager $jsdrplugin=$extMgr.ExtensionList | select Key if ($jsdrplugin.Key -contains "com.jetstream.primary.jetdrplugin") { Write-Host "SUCCESS: VCenter is registered to JetDR MSA." } else { Write-Host "ERROR: VCenter is not registered to any JetDR MSA. Please make sure VCenter is registered before trying configure" $error=$True } if ($error -eq $true) { Write-Error "There were errors in the preflight check. Please resolve the errors and try again" -ErrorAction Stop } else { Write-Host "SUCCESS: Preflight checks succeeded." } } function get_system_state_uninstall { param($ms_ip, $protected_cluster, $ms_user, $ms_pwd) Write-Host "### $($MyInvocation.MyCommand) ###" $error=$False $rc=Get-Cluster -Name $protected_cluster -ErrorAction SilentlyContinue if (!$rc) { Write-Error "Specified cluster '$protected_cluster' does not exist in the Datacenter. Please provide correct details." $error=$True } else { Write-Host "SUCCESS: Cluster '$protected_cluster' provided for unconfiguration exists in the Datacenter" } $ms_up=ms_rest_state $ms_ip $ms_user $ms_pwd 60 if ($ms_up) { Write-Host "JetStream MSA is up and running" $response=get_ms_state $ms_ip $ms_user $ms_pwd if($response.configured -eq $True) { Write-Host "SUCCESS: VCenter is registered to MSA $ms_ip." } else { Write-Error "VCenter is not registered to any MSA. Cannot proceed with uninstall" $error=$true } } else { Write-Error "JetStream MSA is not accessible. Please make sure it is running and try Uninstall again" $error=$true } if ($error -eq $true) { Write-Error "There were errors in the preflight check. Please resolve the errors and try again" -ErrorAction Stop } else { Write-Host "SUCCESS: Preflight check succeeded. Proceeding with uninstallation." } } function restart_cim { param($cluster) Write-Host "### $($MyInvocation.MyCommand) ###" $hosts=Get-Cluster $cluster | Get-VMHost foreach ($ESXhost in $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 } } function checkPSVersion { # This function checks whether Powershell version in the system is greatear than 7 or not $PowerShellVersion = $PSVersionTable.PSVersion.Major if($PowerShellVersion -lt 7) { write-error "Powershell version is less than 7. Please install powershell version 7.x and run again." -ErrorAction Stop } else { Write-Host "SUCCESS: Check for powershell version passed" } } function checkRole { # Checks for the presence of a role in the vCenter param( [String]$role ) $role_exists = Get-VIRole | Where-Object {$_.Name -eq $role} if ($role_exists) { Write-Host "SUCCESS: Check for $role role in vCenter passed" } else { write-error "$role role does not exist in the VCenter. Please make sure it exists before we can proceed with the configuration" -ErrorAction Stop } } function checkModule { param( [String]$module ) $module_exists=Get-Module -Name $module if($module_exists) { Write-Host "SUCCESS: Check for module $module passed" } else { write-error "Module $module not available. Please make sure the module is imported and try again." -ErrorAction Stop } } function checkVcaddress { if (-Not $VC_ADDRESS) { Write-Error "VC_ADDRESS is not set as a powershell variable. Please set it and run the script again" -ErrorAction Stop } else { Write-Host "SUCCESS: VCenter Address is set." } } function getVasaProvider { param( [String]$cluster ) $vasacount=0 $error=0 $vasaprovider = Get-VasaProvider -Server $VC_ADDRESS $hosts=Get-Cluster -Name $cluster -ErrorAction SilentlyContinue | Get-VMHost $hostcount = $hosts.count # Checking if storage provider is available for each host ForEach ($vasa in $vasaprovider) { ForEach ($hostname in $hosts.name) { if ($vasa.name.split() -Contains $hostname -And $vasa.namespace -eq "iofilters") { $vasacount++ if ($vasa.status -eq "online") { write-host "SUCCESS: Storage Provider for $hostname is Online" } else { write-error "Iofilter Storage Provider for $hostname is not Online. Please synchronize storage providers and make sure they are online before trying again" $error=1 } } } } if ($vasacount -ne $hostcount){ write-error "Iofilter Storage providers for all hosts in the cluster to be protected is not available. Please synchronize and make sure they are present and online before trying again." $error=1 } return $error } |