ZertoAVSModule.psm1
using module Microsoft.AVS.Management $PUBLIC_KEY = ('{0}/ZertoPublicKey.pem' -f $psScriptRoot) $ZERTO_FOLDER_ON_HOST = "/var/zerto" $LOCAL_TEMP_FOLDER_FOR_DOWNLOADED_FILES = ('{0}/filesFromDatastore/' -f $psScriptRoot) Function TestConnection { return "TestConnection" } Function GenerateRandomPassword { #Generate a password with at least 2 uppercase, 4 lowercase, 4 digits & 2 special character (!@#$%^&*()) $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{ $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" ) $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 # Create a new role New-VIRole -name $zertoRole -Privilege (Get-VIPrivilege -Server $VC_ADDRESS -id $zertoPrivileges) -Server $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 } } Function CreateZertoFolderOnHost { param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName ) process { $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" } } } Function VerifyAndUploadFilesFromPSEngineToHost { param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName ) 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 Uuid")] [string]$DatastoreUuid, [Parameter(Mandatory = $true, HelpMessage = "Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid")] [string]$BiosUuid ) $psDriverName = "ds" $FullRemoteFileLocation = ('{0}:\zagentid\{1}\*' -f $psDriverName, $BiosUuid) $datastore = Get-Datastore $DatastoreUuid New-PSDrive -Location $datastore -Name $psDriverName -PSProvider VimDatastore -Root "\" Copy-DatastoreItem -Item $FullRemoteFileLocation -Destination $LOCAL_TEMP_FOLDER_FOR_DOWNLOADED_FILES -Force Remove-PSDrive -Name $psDriverName } Function CopyFilesFromDatastoreToHost { param( [Parameter(Mandatory = $true, HelpMessage = "Host Name to connect with SSH")] [string]$HostName, [Parameter(Mandatory = $true, HelpMessage = "Datastore Uuid")] [string]$DatastoreUuid, [Parameter(Mandatory = $true, HelpMessage = "Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid")] [string]$BiosUuid ) DownloadFilesFromDatastoreToPSEngine -DatastoreUuid $DatastoreUuid -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 ) process { $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 if ($ExitStatus -ne 0 -Or $Error) { throw "Error! failed to run ""$Command"" on host $HostName, exitStatus: $ExitStatus, error: $Error" } $NamedOutputs["$($i)_cmd"] = $Command $NamedOutputs["$($i)_exitStatus"] = $ExitStatus $NamedOutputs["$($i)_output"] = ($SSH.Output -join ";") $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 { $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 { $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 { $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 DatastoreUuid Datastore Uuid .PARAMETER BiosUuid "Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid" .EXAMPLE ChangeStartupFile -HostName xxx.xxx.xxx.xxx -DatastoreUuid 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 Uuid")] [string]$DatastoreUuid, [Parameter(Mandatory = $true, HelpMessage = "Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid")] [string]$BiosUuid ) Process { $zloadmod = ('{0}/zloadmod.sh' -f $ZERTO_FOLDER_ON_HOST) CopyFilesFromDatastoreToHost -HostName $HostName -DatastoreUuid $DatastoreUuid -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, $DatastoreUuid, $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 DatastoreUuid Datastore Uuid .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 -DatastoreUuid <UUID> -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 Uuid")] [string]$DatastoreUuid, [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 { $zloadmod = ('{0}/zloadmod.sh' -f $ZERTO_FOLDER_ON_HOST) CopyFilesFromDatastoreToHost -HostName $HostName -DatastoreUuid $DatastoreUuid -BiosUuid $BiosUuid $Commands = ('chmod a+x {0}' -f $zloadmod), ('{0} {1} {2} {3} 1 {4} 1 > /etc/vmware/zloadmod.txt' -f $zloadmod, $IsInit, $DatastoreUuid, $BiosUuid, $EsxiVersion) return RunSSHCommands -HostName $HostName -Commands $Commands } } Function UninstallDriver { <# .DESCRIPTION Uninstall the driver .PARAMETER HostName Host Name to connect with SSH .PARAMETER DatastoreUuid Datastore Uuid .PARAMETER BiosUuid Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid .EXAMPLE UninstallDriver -HostName xxx.xxx.xxx.xxx -DatastoreUuid <UUID> -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 Uuid")] [string]$DatastoreUuid, [Parameter(Mandatory = $true, HelpMessage = "Host Bios Uuid || mob-> Property Path: host.hardware.systemInfo.uuid")] [string]$BiosUuid ) process { $zunloadmod = ('{0}/zunloadmod.sh' -f $ZERTO_FOLDER_ON_HOST) CopyFilesFromDatastoreToHost -HostName $HostName -DatastoreUuid $DatastoreUuid -BiosUuid $BiosUuid $Commands = ('chmod a+x {0}' -f $zunloadmod), ('{0} cleanup > /etc/vmware/zunloadmod.txt' -f $zunloadmod) return RunSSHCommands -HostName $HostName -Commands $Commands } } |