common_utils.ps1
$ZVM_VM_NAME = "ZVML" $VRA_VM_PATTERN = "Z-VRA*" function Start-ZVM { try { Write-Host "Starting $($MyInvocation.MyCommand)..." $ZVM = Get-VM -Name $ZVM_VM_NAME if ($null -eq $ZVM) { throw "$ZVM_VM_NAME VM does not exist" } else { if ($ZVM.PowerState -eq 'PoweredOff') { Write-Host "$ZVM_VM_NAME is powered off, going to power it on" Start-VM $ZVM -ErrorAction Stop | Out-Null } else { Write-Host "$ZVM_VM_NAME is up and running" } } } catch { throw "Failed to start $ZVM_VM_NAME. Problem: $_" } } function Stop-ZVM { try { Write-Host "Starting $($MyInvocation.MyCommand)..." $ZVM = Get-VM -Name $ZVM_VM_NAME if ($null -eq $ZVM) { Write-Error "$ZVM_VM_NAME does not exist" -ErrorAction Stop } else { if ($ZVM.PowerState -eq 'PoweredOn') { Write-Host "$ZVM_VM_NAME is powered on, going to power it off" Stop-VM -VM $ZVM -Confirm:$False -ErrorAction Stop | Out-Null } else { Write-Host "$ZVM_VM_NAME is off" } } } catch { Write-Error "Failed to stop $ZVM_VM_NAME. Problem: $_" -ErrorAction Stop #TODO:GK Remove -ErrorAction and review usages } } function New-RandomPassword { # Generate a password with at least 4 uppercase, 4 lowercase, 2 digits and 2 special characters from !@#%^*() # The first character must be a letter # The password length will vary between 12 and 14 symbols Write-Host "Starting $($MyInvocation.MyCommand)..." $extlen = { Get-SecureRandom(0, 1) } $firstRand = 'a'..'z' | Get-SecureRandom $lowerRand = 'a'..'z' | Get-SecureRandom -Count (3 + (& $extlen)) $upperRand = 'A'..'Z' | Get-SecureRandom -Count (4 + (& $extlen)) $numericRand = '0'..'9' | Get-SecureRandom -Count (2 + (& $extlen)) $specialRand = [char[]]'!@#%^*()' | Get-SecureRandom -Count (2 + (& $extlen)) $allRand = $upperRand + $lowerRand + $numericRand + $specialRand $shuffledRand = $allRand | Get-SecureRandom -Count $allRand.Length $password = $firstRand + ($shuffledRand -join '') return $password } function New-ZertoFolderOnHost { param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName ) process { Write-Host "Starting $($MyInvocation.MyCommand)..." $Command = "mkdir -p $ZERTO_FOLDER_ON_HOST" $Res = Invoke-SSHCommands -HostName $HostName -Commands $Command $ExitStatus = $Res["0_exitStatus"]; if ( $ExitStatus -ne '0' ) { throw "failed to create $ZERTO_FOLDER_ON_HOST on host $HostName. Exit status for ""$Command"" is $ExitStatus" } else { Write-Host "Zerto folder ($ZERTO_FOLDER_ON_HOST) was created on $HostName." } } } function Invoke-Retry { param ( [Parameter(Mandatory = $true)] [ScriptBlock]$Action, [Parameter(Mandatory = $true)] [string]$ActionName, [Parameter(Mandatory = $true)] [int]$RetryCount, [Parameter(Mandatory = $true)] [int]$RetryIntervalSeconds ) for ($i = 1; $i -le $RetryCount; $i++) { try { Write-Output "Attempt $i of $RetryCount executing $ActionName." & $Action Write-Output "$ActionName succeeded." return } catch { Write-Output "Attempt $i of $RetryCount on $ActionName wasn't successful." if ($i -ne $RetryCount) { Write-Output "Waiting for $RetryIntervalSeconds seconds before retrying $ActionName..." Start-Sleep -Seconds $RetryIntervalSeconds } else { Write-Output "Error: All attempts to execute $ActionName failed. Exiting." throw } } } } function Invoke-ZVMScriptWithTimeout { param ( [Parameter(Mandatory = $true)] [string]$ScriptText, [Parameter(Mandatory = $true)] [string]$ActionName, [int]$TimeoutMinutes = 30 ) $ZVM = Get-VM -Name $ZVM_VM_NAME Write-Output "Starting $ActionName execution." # Start the script asynchronously $task = Invoke-VMScript -VM $ZVM -ScriptText $ScriptText -GuestUser $ZAPPLIANCE_USER -GuestPassword $PersistentSecrets.ZappliancePassword -RunAsync # Calculate the timeout time $timeoutTime = (Get-Date).AddMinutes($TimeoutMinutes) while ((Get-Date) -lt $timeoutTime) { # Check the task status if ($task.State -eq 'Success') { # The 'Success' state indicates that the remote script was executed, but does not reflect the script's success or failure. Write-Output "$ActionName execution done." return $task.Result } elseif ($task.State -eq 'Error') { throw "$ActionName execution failed with error: $($task.ErrorMessage)" } # Wait for a short period before checking again Start-Sleep -Seconds 30 } # If the loop exits, it means the timeout was reached throw "$ActionName did not complete within the allotted time of $TimeoutMinutes minutes." } function Get-DatastoreUUID ($DatastoreName) { Write-Host "Starting $($MyInvocation.MyCommand)..." $datastore = Get-Datastore -Name $DatastoreName $uuid = ($datastore.ExtensionData.Info.Url -replace '.*volumes/', '').TrimEnd('/') # Url format is 'ds:///vmfs/volumes/vsan:529ecf79732d3104-202d349462b20b76/' Write-Host "Datastore '$DatastoreName' UUID: $uuid" return $uuid } function Invoke-SSHCommands { param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName, [Parameter(Mandatory = $true, HelpMessage = "Commands to execute")] [String[]]$Commands, [Parameter(Mandatory = $false, HelpMessage = "Action on exitStatus 1")] [string]$ExitStatusAction = "Stop" ) process { Write-Host "Starting $($MyInvocation.MyCommand)..." $NamedOutputs = @{} Set-Variable -Name NamedOutputs -Value $NamedOutputs -Scope Global $i = 0 foreach ($Command in $Commands) { $SSH = Invoke-SSHCommand -SSHSession $SSH_Sessions[$HostName].Value -Command $Command if (!$SSH) { throw "Failed to Invoke-SSHCommand '$Command' on host $HostName" } $ExitStatus = $SSH.ExitStatus $SshError = $SSH.Error $Output = ($SSH.Output -join ";") if ($ExitStatus -ne 0 -Or $SshError) { if (($ExitStatus -eq 1) -And (!$SshError) -And ($ExitStatusAction -eq "Skip")) { Write-Host "ExitStatus of '$Command' is 1, while ExitStatusAction = Skip. Skipping..." } else { throw "Failed to run '$Command' on host $HostName, ExitStatus: $ExitStatus, Output: $Output, Error: $SshError, ExitStatusAction: $ExitStatusAction" } } Write-Host "Command was completed successfully '$Command' on host $HostName, ExitStatus: $ExitStatus, Output: $Output, Error: $SshError" $NamedOutputs["$($i)_cmd"] = $Command $NamedOutputs["$($i)_exitStatus"] = $ExitStatus $NamedOutputs["$($i)_output"] = $Output $NamedOutputs["$($i)_error"] = $SshError $i++; } return $NamedOutputs } } |