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 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

        if ( $Res.ExitStatus -ne '0' ) {
            throw "failed to create $ZERTO_FOLDER_ON_HOST on host"
        }
    }
}

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
        
        if ($isVerified -eq "Verified OK") {
            Set-SFTPItem -SessionId ($SFTP_Sessions[$HostName]).Value -Destination $ZERTO_FOLDER_ON_HOST -Path $file -Force
        }
        else {
            throw "Error! failed to verify $file, 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
            
            $NamedOutputs["$($i)_cmd"] = $Command
            $NamedOutputs["$($i)_exitStatus"] = $SSH.ExitStatus
            $NamedOutputs["$($i)_output"] = ($SSH.Output -join ";")

            $i++;
        }
    }

    return $NamedOutputs

}

<#
.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
#>

Function Get-HostTempFolderInfo {
    [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
    }
}

<#
.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
#>

Function EnsureConnectivity {    
    [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
    }
}

<#
.DESCRIPTION
 
Retrieve the ESXi version (For Internal Use)
 
    .PARAMETER HostName
    Host Name to connect with ssh
 
.EXAMPLE
 
Get-HostEsxiVersion -HostName xxx.xxx.xxx.xxx
#>

Function Get-HostEsxiVersion {
    [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
    }
}

<#
.DESCRIPTION
 
Responsible for loading the driver when the host is booting.
Rc.local 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
 
ChangeRcLocal -HostName xxx.xxx.xxx.xxx -DatastoreUuid xxx -BiosUuid xxx
#>

Function ChangeRcLocal {
    [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

        $rcLocal = ('{0}/rc.local' -f $ZERTO_FOLDER_ON_HOST)
    
        $Commands =    ('grep -v ZeRTO /etc/rc.local > {0}' -f $rcLocal),
        ('echo \#ZeRTO\ >> {0}' -f $rcLocal),
        ('echo sh {0} load {1} {2} \"\" \"\" 1 > /etc/vmware/zloadmod.txt \2\>\&\1 \#ZeRTO\ >> {3}' -f $zloadmod, $DatastoreUuid, $BiosUuid, $rcLocal),
        ('echo \#ZeRTO\ >> {0}' -f $rcLocal),
        ('cp -f {0} /etc/rc.local' -f $rcLocal)
                    
        return RunSSHCommands -HostName $HostName -Commands $Commands
    }
}

<#
.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
#>

Function InstallDriver {
    [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
    }
}

<#
.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>
#>

Function UninstallDriver {
    [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
    }
}