ZertoAVSModule.psm1
using module Microsoft.AVS.Management $PUBLIC_KEY = ('{0}/ZertoPublicKey.pem' -f $psScriptRoot) $ZERTO_FOLDER_ON_HOST = "/var/zerto" $LOCAL_TEMP_FOLDER_FOR_ZERTO_DRIVER_LOGS = ('{0}/zertoDriverLogs/' -f $psScriptRoot) $LOCAL_TEMP_FOLDER_FOR_DOWNLOADED_FILES = ('{0}/filesFromDatastore/' -f $psScriptRoot) #region Zerto Validations Function IsZertoUserExists { <# .DESCRIPTION Get a zertoUsername and a domain, and return whether or not the user exists in the domain. .PARAMETER zertoUsername Zerto user name (defaule value is ZertoDR) .PARAMETER domain Domain name (defaule value is vsphere.local) .EXAMPLE IsZertoUserExists -zertoUsername <Username> -domain <domain> #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $false)] param( [parameter(Mandatory=$false, HelpMessage = "Zerto user name for ZVM installation")] [string]$zertoUsername = "ZertoDR", [parameter(Mandatory=$false, HelpMessage = "Domain to search the user at")] [string]$domain = "vsphere.local" ) Process { Write-Host "Starting $($MyInvocation.MyCommand)..." if(Get-SsoPersonUser -Name $zertoUsername -Domain $domain -ErrorAction SilentlyContinue) { Write-Host "$zertoUsername already exists in $VC_ADDRESS, domain: $domain." return $true; } Write-Host "$zertoUsername doesn't exist in $VC_ADDRESS, domain: $domain." return $false; } } Function IsZertoRoleExists { <# .DESCRIPTION Return true if ZertoRole exists, otherwise return false. .PARAMETER zertoRole Zerto role name (defaule value is ZertoRole) .EXAMPLE IsZertoRoleExists -zertoRole <role> #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $false)] param( [parameter(Mandatory=$false, HelpMessage = "Zerto role name for ZVM installation")] [string]$zertoRole = "ZertoRole" ) Process { Write-Host "Starting $($MyInvocation.MyCommand)..." If (Get-VIRole -Name $zertoRole -ErrorAction SilentlyContinue) { Write-Host "$zertoRole already exists in $VC_ADDRESS" return $true } Write-Host "$zertoRole doesn't exist in $VC_ADDRESS" return $false; } } Function IsZertoDriverLoaded { <# .DESCRIPTION Return true if Zerto driver is loaded, otherwise return false. .PARAMETER HostName Host Name to connect with ssh .EXAMPLE IsZertoDriverLoaded -HostName <HostName> #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $false)] param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName ) Process { Write-Host "Starting $($MyInvocation.MyCommand)..." $vmkload = '/tmp/vmklod_output' $ZertoDriver = '/tmp/zertoDriver' $Command = ('vmkload_mod -l > {0}' -f $vmkload) $Res = RunSSHCommands -HostName $HostName -Commands $Command $Command = ('grep "zdriver" {0} > {1}' -f $vmkload, $ZertoDriver) $Res = RunSSHCommands -HostName $HostName -Commands $Command -ExitStatusAction "Skip" $ExitStatus = $Res["0_exitStatus"] if ($ExitStatus -eq '0') { Write-Host "Zerto driver is loaded" return $true; } if ($ExitStatus -eq '1') { Write-Host "Zerto driver is not loaded" return $false; } } } Function GetDriverLogsFromHost { <# .DESCRIPTION Copy Zerto driver logs from host to datastore .PARAMETER HostName Host Name to connect with ssh .PARAMETER DatastoreName Datastore Name .EXAMPLE GetDriverLogsFromHost -HostName <HostName> -DatastoreName <DatastoreName> #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $false)] param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName, [Parameter(Mandatory = $true, HelpMessage = "Datastore Name")] [string]$DatastoreName ) Write-Host "Starting $($MyInvocation.MyCommand)..." DownloadDriverLogFilesFromHostToPSEngine -HostName $HostName UploadDriverLogFilesFromPSEngineToDatastore -DatastoreName $DatastoreName -HostName $HostName } Function DownloadDriverLogFilesFromHostToPSEngine { param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName ) Write-Host "Starting $($MyInvocation.MyCommand)..." $sftpSessionId = ($SFTP_Sessions[$HostName]).Value.SessionId if (!(Test-Path -path $LOCAL_TEMP_FOLDER_FOR_ZERTO_DRIVER_LOGS)) { New-Item $LOCAL_TEMP_FOLDER_FOR_ZERTO_DRIVER_LOGS -Type Directory Write-Host "Create $LOCAL_TEMP_FOLDER_FOR_ZERTO_DRIVER_LOGS folder on powerShell engine" } $files = '/etc/vmware/zloadmod.txt', '/etc/vmware/zunloadmod.txt' foreach ($file in $files) { if (Test-SFTPPath -SessionId $sftpSessionId -Path $file) { Write-Host "Going to download $file from $HostName to powerShell engine ($LOCAL_TEMP_FOLDER_FOR_ZERTO_DRIVER_LOGS)" Get-SFTPItem -SessionId $sftpSessionId -Destination $LOCAL_TEMP_FOLDER_FOR_ZERTO_DRIVER_LOGS -Path $file -Force Write-Host "$file was copied from $HostName to powerShell engine" } else { Write-Host "File $file doesn't exist on $HostName" } } } Function UploadDriverLogFilesFromPSEngineToDatastore { param( [Parameter(Mandatory = $true, HelpMessage = "Datastore Name")] [string]$DatastoreName, [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName ) Write-Host "Starting $($MyInvocation.MyCommand)..." $psDriverName = "ds" $zertoDriverLogsDSPath = ('{0}:\zertoDriverLogsFromHost\{1}\' -f $psDriverName, $HostName) $zertoDriverLogsPSPath = ('{0}*' -f $LOCAL_TEMP_FOLDER_FOR_ZERTO_DRIVER_LOGS) $datastore = Get-Datastore $DatastoreName New-PSDrive -Location $datastore -Name $psDriverName -PSProvider VimDatastore -Root "\" -ErrorAction Stop Copy-DatastoreItem -Item $zertoDriverLogsPSPath -Destination $zertoDriverLogsDSPath -Force -ErrorAction Stop $files = (Get-ChildItem -Path $zertoDriverLogsDSPath -Name) -join ";" Write-Host "$MyInvocation.MyCommand - ZertoDriverFiles: {$files} were copied from powerShell engine ($zertoDriverLogsPSPath) to datastore ($zertoDriverLogsDSPath)" Remove-PSDrive -Name $psDriverName } Function GetZertoFilesListFromHost { <# .DESCRIPTION Return a list of all Zerto files on host under /var/zerto .PARAMETER HostName Host Name to connect with ssh .EXAMPLE GetZertoFilesListFromHost -HostName <HostName> #> [CmdletBinding()] [AVSAttribute(5, UpdatesSDDC = $false)] param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName ) process { Write-Host "Starting $($MyInvocation.MyCommand)..." $Command = ('ls -l {0}' -f $ZERTO_FOLDER_ON_HOST) return RunSSHCommands -HostName $HostName -Commands $Command } } #end Region Function TestConnection { return "TestConnection" } Function GenerateRandomPassword { #Generate a password with at least 2 uppercase, 4 lowercase, 4 digits & 2 special character (!@#$%^&*()) Write-Host "Starting $($MyInvocation.MyCommand)..." $upperChars =(65..90) $lowerChars = (97..122) $numerics = (48..57) $specialChars = @(33, 35, 36, 37, 38, 40, 41, 42, 45, 64, 94) $seedArray = ($upperChars | Get-Random -Count 2) $seedArray += ($lowerChars | Get-Random -Count 4) $seedArray += ($numerics | Get-Random -Count 4) $seedArray += ($specialChars | Get-Random -Count 2) Foreach ($a in $seedArray){ $passwordAscii += , [char][byte]$a } $password = $passwordAscii -join "" return $password } Function CreateZertoUser { <# .DESCRIPTION Create a ZertoDR user and a ZertoDR role which includes required privileges. The script creates a permission by assigning the ZertoDR role to the ZertoDR user. .PARAMETER zertoUsername Zerto user name (defaule value is ZertoDR) .PARAMETER zertoRole Zerto role name (defaule value is ZertoRole) .EXAMPLE CreateZertoUser -zertoUsername <Username> -zertoRole <Role> #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $false)] param( [parameter(Mandatory=$false, HelpMessage = "Zerto user name for ZVM installation")] [string]$zertoUsername = "ZertoDR", [parameter(Mandatory=$false, HelpMessage = "Zerto role name for ZVM installation")] [string]$zertoRole = "ZertoRole" ) Process{ Write-Host "Starting $($MyInvocation.MyCommand)..." $domain = "vsphere.local" $zertoPrincipal = $domain + "\" + $zertoUsername $zertoPrivileges = @( "Alarm.Create", "Alarm.Delete", "Authorization.ModifyPermissions", "Cryptographer.Access", "Datastore.AllocateSpace", "Datastore.Browse", "Datastore.Config", "Datastore.DeleteFile", "Datastore.FileManagement", "Datastore.UpdateVirtualMachineFiles", "StoragePod.Config", "Extension.Register", "Extension.Unregister", "Folder.Create", "Global.CancelTask", "Global.Diagnostics", "Global.DisableMethods", "Global.EnableMethods", "Global.LogEvent", "Host.Config.AdvancedConfig", "Host.Config.AutoStart", "Host.Config.Settings", "Host.Config.NetService", "Host.Config.Patch", "Host.Inventory.EditCluster", "Network.Assign", "Resource.AssignVAppToPool", "Resource.AssignVMToPool", "Resource.ColdMigrate", "Resource.HotMigrate", "Sessions.ValidateSession", "Task.Create", "Task.Update", "VApp.ApplicationConfig", "VApp.AssignResourcePool", "VApp.AssignVM", "VApp.Create", "VApp.Delete", "VApp.Import", "VApp.PowerOff", "VApp.PowerOn", "VirtualMachine.Config.AddExistingDisk", "VirtualMachine.Config.AddNewDisk", "VirtualMachine.Config.AddRemoveDevice", "VirtualMachine.Config.AdvancedConfig", "VirtualMachine.Config.CPUCount", "VirtualMachine.Config.DiskExtend", "VirtualMachine.Config.EditDevice", "VirtualMachine.Config.ManagedBy", "VirtualMachine.Config.Memory", "VirtualMachine.Config.RawDevice", "VirtualMachine.Config.RemoveDisk", "VirtualMachine.Config.Resource", "VirtualMachine.Config.Settings", "VirtualMachine.Config.SwapPlacement", "VirtualMachine.Config.UpgradeVirtualHardware", "VirtualMachine.Interact.PowerOff", "VirtualMachine.Interact.PowerOn", "VirtualMachine.Inventory.CreateFromExisting", "VirtualMachine.Inventory.Create", "VirtualMachine.Inventory.Register", "VirtualMachine.Inventory.Delete", "VirtualMachine.Inventory.Unregister", "VirtualMachine.State.RemoveSnapshot" ) #if the user already exists - do nothing if(IsZertoUserExists $zertoUsername) { Write-Host "$zertoUsername already exists in $VC_ADDRESS. Skip creation..." } else { #Create Zerto user $PersistentSecrets.ZertoPassword = GenerateRandomPassword New-SsoPersonUser -UserName $zertoUsername -Password $PersistentSecrets.ZertoPassword -Description "Zerto DR user" -EmailAddress "ZertoDR@zerto.com" -FirstName "Zerto" -LastName "DR" -ErrorAction Stop # Add user to CloudAdmins group $group = "CloudAdmins" $SsoGroup = Get-SsoGroup -Name $group -Domain $domain Get-SsoPersonUser -Name $zertoUsername -Domain $domain -ErrorAction Stop | Add-UserToSsoGroup -TargetGroup $SsoGroup -ErrorAction Stop } #If ZertoRole already exists - overwrite it with the new privilages If (IsZertoRoleExists $zertoRole) { $joinedPrivilgaes = ($zertoPrivileges -join ";") Write-Host "Role: $zertoRole already exists. Overwrite it with the following privilages: $joinedPrivilgaes" Remove-VIRole -Role (Get-VIRole -Name $zertoRole) -Force:$true -Confirm:$false New-VIRole -name $zertoRole -Privilege (Get-VIPrivilege -Server $VC_ADDRESS -id $zertoPrivileges) -Server $VC_ADDRESS } else { #Create a new role New-VIRole -name $zertoRole -Privilege (Get-VIPrivilege -Server $VC_ADDRESS -id $zertoPrivileges) -Server $VC_ADDRESS -ErrorAction Stop Write-Host "Role $zertoRole created on $VC_ADDRESS" } # Get the Root Folder $rootFolder = Get-Folder -NoRecursion # Create permission on vCenter object by assigning role to user New-VIPermission -Entity $rootFolder -Principal $zertoPrincipal -Role $zertoRole -Propagate:$true -ErrorAction Stop Write-Host "Finish to create ZertoUser ($zertoUsername) and assign ZertoRole ($zertoRole)" } } Function ResetZertoPassword { <# .DESCRIPTION Change password for Zerto user .PARAMETER zertoUsername Zerto user name (defaule value is ZertoDR) .EXAMPLE ResetZertoPassword -zertoUsername <Username> -domain <domain> #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $false)] param( [parameter(Mandatory=$false, HelpMessage = "Zerto user name for reset password")] [string]$zertoUsername = "ZertoDR", [parameter(Mandatory=$false, HelpMessage = "Domain to search the user at")] [string]$domain = "vsphere.local" ) process { Write-Host "Starting $($MyInvocation.MyCommand)..." $zertoUser = Get-SsoPersonUser -Name $zertoUsername -Domain $domain if($zertoUser) { $newPassword = GenerateRandomPassword Set-SsoPersonUser -User $zertoUser -NewPassword $newPassword -ErrorAction Stop $PersistentSecrets.ZertoPassword = $newPassword Write-Host "Password for $zertoUsername changed successfully" } else{ throw "Error! Failed to reset Zerto password for $zertoUsername, user doesn't exist" } } } Function SetSSHTimeout{ <# .DESCRIPTION Determines how long SSH service and SSH session remains open .PARAMETER HostName Host Name to connect with SSH .PARAMETER SSHTimeout SSH timeout value .EXAMPLE SetSSHTimeout -HostName <HostName> -SSHTimeout <SSHTimeout> #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $false)] param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName, [Parameter(Mandatory = $true, HelpMessage = "SSH timeout value")] [string]$SSHTimeout ) process { Write-Host "Starting $($MyInvocation.MyCommand)..." $vmHost = Get-VMHost -Name $HostName Get-AdvancedSetting -Entity $vmHost -Name "UserVars.ESXiShellTimeOut" -ErrorAction SilentlyContinue| Set-AdvancedSetting -Value $SSHTimeout -Confirm:$false -ErrorAction SilentlyContinue Write-Host "Set configuration setting ""UserVars.ESXiShellTimeOut"" on $HostName to $SSHTimeout" Get-AdvancedSetting -Entity $vmHost -Name "UserVars.ESXiShellInteractiveTimeOut" -ErrorAction SilentlyContinue | Set-AdvancedSetting -Value $SSHTimeout -Confirm:$false -ErrorAction SilentlyContinue Write-Host "Set configuration setting ""UserVars.ESXiShellInteractiveTimeOut"" on $HostName to $SSHTimeout" } } Function CreateZertoFolderOnHost { 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 = RunSSHCommands -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 VerifyAndUploadFilesFromPSEngineToHost { param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName ) Write-Host "Starting $($MyInvocation.MyCommand)..." CreateZertoFolderOnHost -HostName $HostName foreach ($file in Get-ChildItem $LOCAL_TEMP_FOLDER_FOR_DOWNLOADED_FILES* -Include *.sh, *.o) { $signature = ("{0}_signature" -f $file) $isVerified = (openssl dgst -sha256 -verify $PUBLIC_KEY -signature $signature $file 2>&1) -join ";" if ($isVerified -eq "Verified OK") { Set-SFTPItem -SessionId ($SFTP_Sessions[$HostName]).Value.SessionId -Destination $ZERTO_FOLDER_ON_HOST -Path $file -Force } else { throw "Error! host $HostName failed to verify $file with $signature, openSSL output: $isVerified" } } } Function DownloadFilesFromDatastoreToPSEngine { param( [Parameter(Mandatory = $true, HelpMessage = "Datastore Name")] [string]$DatastoreName, [Parameter(Mandatory = $true, HelpMessage = "Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid")] [string]$BiosUuid ) Write-Host "Starting $($MyInvocation.MyCommand)..." $psDriverName = "ds" $FullRemoteFileLocation = ('{0}:\zagentid\{1}\*' -f $psDriverName, $BiosUuid) $datastore = Get-Datastore $DatastoreName Write-Host "Going to download files from $darastore ($FullRemoteFileLocation) to PS engine ($LOCAL_TEMP_FOLDER_FOR_DOWNLOADED_FILES)." New-PSDrive -Location $datastore -Name $psDriverName -PSProvider VimDatastore -Root "\" -ErrorAction Stop Copy-DatastoreItem -Item $FullRemoteFileLocation -Destination $LOCAL_TEMP_FOLDER_FOR_DOWNLOADED_FILES -Force -ErrorAction Stop $files = (Get-ChildItem -Path $LOCAL_TEMP_FOLDER_FOR_DOWNLOADED_FILES -Name) -join ";" Write-Host "ZertoFiles: {$files} were copied from darastore $DatastoreName ($FullRemoteFileLocation) to PS engine ($LOCAL_TEMP_FOLDER_FOR_DOWNLOADED_FILES)" Remove-PSDrive -Name $psDriverName } Function CopyFilesFromDatastoreToHost { param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName, [Parameter(Mandatory = $true, HelpMessage = "Datastore Name")] [string]$DatastoreName, [Parameter(Mandatory = $true, HelpMessage = "Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid")] [string]$BiosUuid ) Write-Host "Starting $($MyInvocation.MyCommand)..." DownloadFilesFromDatastoreToPSEngine -DatastoreName $DatastoreName -BiosUuid $BiosUuid VerifyAndUploadFilesFromPSEngineToHost -HostName $HostName } Function RunSSHCommands { 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 "Error! failed to Invoke-SSHCommand ""$Command"" on host $HostName" } $ExitStatus = $SSH.ExitStatus $Error = $SSH.Error $Output = ($SSH.Output -join ";") if ($ExitStatus -ne 0 -Or $Error) { if (($ExitStatus -eq 1) -And (!$Error) -And ($ExitStatusAction -eq "Skip")) { Write-Host "ExitStatus of ""$Command"" is 1, while ExitStatusAction = Skip. Skipping..." } else { throw "Error! failed to run ""$Command"" on host $HostName, ExitStatus: $ExitStatus, Output: $Output, Error: $Error, ExitStatusAction: $ExitStatusAction" } } Write-Host "Finish to run ""$Command"" on host $HostName, ExitStatus: $ExitStatus, Output: $Output, Error: $Error" $NamedOutputs["$($i)_cmd"] = $Command $NamedOutputs["$($i)_exitStatus"] = $ExitStatus $NamedOutputs["$($i)_output"] = $Output $NamedOutputs["$($i)_error"] = $Error $i++; } return $NamedOutputs } } Function Get-HostTempFolderInfo { <# .DESCRIPTION Display information about the available disk space (For Internal Use) .PARAMETER HostName Host Name to connect with ssh .EXAMPLE Get-HostTempFolderInfo -HostName xxx.xxx.xxx.xxx #> [CmdletBinding()] [AVSAttribute(5, UpdatesSDDC = $false)] param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName ) process { Write-Host "Starting $($MyInvocation.MyCommand)..." $Command = "vdf" return RunSSHCommands -HostName $HostName -Commands $Command } } Function EnsureConnectivity { <# .DESCRIPTION Check if the host is up and running (For Internal Use) .PARAMETER HostName Host Name to connect with ssh .EXAMPLE EnsureConnectivity -HostName xxx.xxx.xxx.xxx #> [CmdletBinding()] [AVSAttribute(5, UpdatesSDDC = $false)] param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName ) process { Write-Host "Starting $($MyInvocation.MyCommand)..." $Command = "echo testing123" return RunSSHCommands -HostName $HostName -Commands $Command } } Function Get-HostEsxiVersion { <# .DESCRIPTION Retrieve the ESXi version (For Internal Use) .PARAMETER HostName Host Name to connect with ssh .EXAMPLE Get-HostEsxiVersion -HostName xxx.xxx.xxx.xxx #> [CmdletBinding()] [AVSAttribute(5, UpdatesSDDC = $false)] param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName ) process { Write-Host "Starting $($MyInvocation.MyCommand)..." $Command = "vmware -l" return RunSSHCommands -HostName $HostName -Commands $Command } } Function ChangeStartupFile { <# .DESCRIPTION Responsible for loading the driver when the host is booting. /etc/rc.local.d/local.sh file is executed after all the normal system services are started .PARAMETER HostName Host Name to connect with ssh .PARAMETER DatastoreName Datastore Name .PARAMETER BiosUuid "Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid" .EXAMPLE ChangeStartupFile -HostName xxx.xxx.xxx.xxx -DatastoreName xxx -BiosUuid xxx #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $false)] param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName, [Parameter(Mandatory = $true, HelpMessage = "Datastore Name")] [string]$DatastoreName, [Parameter(Mandatory = $true, HelpMessage = "Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid")] [string]$BiosUuid ) Process { Write-Host "Starting $($MyInvocation.MyCommand)..." $zloadmod = ('{0}/zloadmod.sh' -f $ZERTO_FOLDER_ON_HOST) CopyFilesFromDatastoreToHost -HostName $HostName -DatastoreName $DatastoreName -BiosUuid $BiosUuid $startupFile = ('{0}/startup_file.sh' -f $ZERTO_FOLDER_ON_HOST) $Commands = ('grep -v "ZeRTO\|exit 0" /etc/rc.local.d/local.sh > {0}' -f $startupFile), ('echo \#ZeRTO\ >> {0}' -f $startupFile), ('echo sh {0} load {1} {2} \"\" \"\" 1 \> /etc/vmware/zloadmod.txt \2\>\&\1 \#ZeRTO\ >> {3}' -f $zloadmod, $DatastoreName, $BiosUuid, $startupFile), ('echo \#ZeRTO\ >> {0}' -f $startupFile), ('echo "exit 0" >> {0}' -f $startupFile), ('cp -f {0} /etc/rc.local.d/local.sh' -f $startupFile), ('chmod a+x {0}' -f $zloadmod) return RunSSHCommands -HostName $HostName -Commands $Commands } } Function InstallDriver { <# .DESCRIPTION Install the driver .PARAMETER HostName Host Name to connect with SSH .PARAMETER DatastoreName Datastore Name .PARAMETER BiosUuid Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid .PARAMETER IsInit Init or load the driver .PARAMETER EsxiVersion Esxi version .EXAMPLE InstallDriver -HostName xxx.xxx.xxx.xxx -DatastoreName <DatastoreName> -BiosUuid <UUID> -IsInit <init/load> -EsxiVersion xx #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $false)] param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName, [Parameter(Mandatory = $true, HelpMessage = "Datastore Name")] [string]$DatastoreName, [Parameter(Mandatory = $true, HelpMessage = "Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid")] [string]$BiosUuid, [Parameter(Mandatory = $true, HelpMessage = "Init or load the driver")] [string]$IsInit, [Parameter(Mandatory = $true, HelpMessage = "Esxi version")] [string]$EsxiVersion ) Process { Write-Host "Starting $($MyInvocation.MyCommand)..." if (IsZertoDriverLoaded $HostName) { Write-Host "Warning! Zerto driver is already loaded on $HostName" } $zloadmod = ('{0}/zloadmod.sh' -f $ZERTO_FOLDER_ON_HOST) CopyFilesFromDatastoreToHost -HostName $HostName -DatastoreName $DatastoreName -BiosUuid $BiosUuid $Commands = ('chmod a+x {0}' -f $zloadmod), ('{0} {1} {2} {3} 1 {4} 1 > /etc/vmware/zloadmod.txt' -f $zloadmod, $IsInit, $DatastoreName, $BiosUuid, $EsxiVersion) return RunSSHCommands -HostName $HostName -Commands $Commands } } Function UninstallDriver { <# .DESCRIPTION Uninstall the driver .PARAMETER HostName Host Name to connect with SSH .PARAMETER DatastoreName Datastore Name .PARAMETER BiosUuid Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid .EXAMPLE UninstallDriver -HostName xxx.xxx.xxx.xxx -DatastoreName <DatastoreName> -BiosUuid <UUID> #> [CmdletBinding()] [AVSAttribute(30, UpdatesSDDC = $false)] param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName, [Parameter(Mandatory = $true, HelpMessage = "Datastore Name")] [string]$DatastoreName, [Parameter(Mandatory = $true, HelpMessage = "Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid")] [string]$BiosUuid ) process { Write-Host "Starting $($MyInvocation.MyCommand)..." if (IsZertoDriverLoaded $HostName) { $zunloadmod = ('{0}/zunloadmod.sh' -f $ZERTO_FOLDER_ON_HOST) CopyFilesFromDatastoreToHost -HostName $HostName -DatastoreName $DatastoreName -BiosUuid $BiosUuid $Commands = ('chmod a+x {0}' -f $zunloadmod), ('{0} cleanup > /etc/vmware/zunloadmod.txt' -f $zunloadmod) return RunSSHCommands -HostName $HostName -Commands $Commands } else { throw "Error! Failed to run UninstallDriver, Zerto driver is not loaded on $HostName." } } } |