lib/VRAs.ps1


#region Zerto VRAs

# .ExternalHelp ZertoModule.psm1-help.xml
Function Get-ZertoVRA {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false, HelpMessage = 'Zerto Session Name')][String]$ZertoSession = "Default",
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto VRA Name')] [string] $VRAName,
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto VRA Status')] [ZertoVRAStatus] $VRAStatus,
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto VRA Version')] [string] $VRAVersion,
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto Host Version')] [string] $HostVersion,
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto VRA IP Address')] [string] $IPAddress,
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto VRA Group')] [string] $VRAGroup,
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto VRA Datastore Name')] [string] $DatastoreName,
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto VRA Datastore Cluster Name')] [string] $DatastoreClusterName,
        [Parameter(Mandatory = $false, ParameterSetName = "Filter", HelpMessage = 'Zerto VRA Network Name')] [string] $NetworkName,
        [Parameter(Mandatory = $true, ParameterSetName = "ID", HelpMessage = 'Zerto VRA Identifier')] [string] $ZertoVraIdentifier
   )

    ## Get Session Configuration
    $ZertoSessionConfig = $global:ZertoSessions[$ZertoSession]
    if (-not $ZertoSessionConfig) {
        Write-Host 'TMSession: [' -NoNewline
        Write-Host $ZertoSession -ForegroundColor Cyan
        Write-Host '] was not Found. Please use the New-ZertoSession command.'
        Throw "Zerto Session Not Found. Use New-TMSession command before using features."
    }

    #Honor SSL Settings
    if ($ZertoSessionConfig.AllowInsecureSSL) {
        $ZertoCertSettings = @{SkipCertificateCheck = $true }
    }
    else {
        $ZertoCertSettings = @{SkipCertificateCheck = $false }
    }

    $baseURL = "https://" + $ZertoSessionConfig.ZertoServer + ":" + $ZertoSessionConfig.ZertoPort + "/v1/"
    $TypeJSON = "application/json"



    switch ($PsCmdlet.ParameterSetName) {
        "ID" {
            if ([string]::IsNullOrEmpty($ZertoVraIdentifier)  ) {
                throw "Missing Zerto VRA Identifier"
            }

            $FullURL = $baseURL + "vras"
        }
        Default {
            $FullURL = $baseURL + "vras"
            if ($VRAName -or $VRAStatus -ne $null -or $VRAVersion -or $HostVersion -or $IPAddress `
                    -or $VRAGroup -or $DatastoreName -or $DatastoreClusterName -or $NetworkName ) {
                $qs = [ordered] @{}
                if ($VRAName) { $qs.Add("VRAName", $VRAName) }
                if ($VRAStatus -ne $null) { $qs.Add("Status", $VRAStatus) }
                if ($VRAVersion) { $qs.Add("VRAVersion", $VRAVersion) }
                if ($HostVersion) { $qs.Add("HostVersion", $HostVersion) }
                if ($IPAddress) { $qs.Add("IPAddress", $IPAddress) }
                if ($VRAGroup) { $qs.Add("VRAGroup", $VRAGroup) }
                if ($DatastoreName) { $qs.Add("DatastoreName", $DatastoreName) }
                if ($DatastoreClusterName) { $qs.Add("DatastoreClusterName", $DatastoreClusterName) }
                if ($NetworkName) { $qs.Add("type", $NetworkName) }

                $FullURL += Get-QueryStringFromHashTable -QueryStringHash $QS
            }
        }
    }
    Write-Verbose $FullURL

    try {
        $RestMethodSplat = @{
            Uri         = $FullURL
            TimeoutSec  = 100
            ContentType = $TypeJSON
            Method      = 'GET'
            WebSession  = $ZertoSessionConfig.ZertoWebSession
        }
        $Result = Invoke-RestMethod @RestMethodSplat @ZertoCertSettings
    }
    catch {
        throw $_.Exception.Message
    }

    #Filter by ID if needed
    switch ($PsCmdlet.ParameterSetName) {
        "ID" {
            $Result = $Result | Where-Object { $_.VraIdentifier -eq $ZertoVraIdentifier }
        }
        Default {
        }
    }

    return $Result
}

# .ExternalHelp ZertoModule.psm1-help.xml
Function Get-ZertoVRAID {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false, HelpMessage = 'Zerto Session Name')][String]$ZertoSession = "Default",
        [Parameter(Mandatory = $true, HelpMessage = 'Zerto VRA Name')] [string] $VraName
    )

    $ID = Get-ZertoVRA -ZertoServer $ZertoServer -ZertoPort $ZertoPort -ZertoToken $ZertoToken | `
        Where-Object { $_.VraName -eq $VraName } | `
        Select-Object VraIdentifier -ExpandProperty VraIdentifier

    if ($ID.Count -gt 1) { Throw "'$VraName' returned more than one ID" }
    if ($ID.Count -eq 0) { Throw "'$VraName' was not found" }

    return $ID.ToString()
}

# .ExternalHelp ZertoModule.psm1-help.xml
Function Get-ZertoVRAIPConfigurationType {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false, HelpMessage = 'Zerto Session Name')][String]$ZertoSession = "Default"
   )

    ## Get Session Configuration
    $ZertoSessionConfig = $global:ZertoSessions[$ZertoSession]
    if (-not $ZertoSessionConfig) {
        Write-Host 'TMSession: [' -NoNewline
        Write-Host $ZertoSession -ForegroundColor Cyan
        Write-Host '] was not Found. Please use the New-ZertoSession command.'
        Throw "Zerto Session Not Found. Use New-TMSession command before using features."
    }

    #Honor SSL Settings
    if ($ZertoSessionConfig.AllowInsecureSSL) {
        $ZertoCertSettings = @{SkipCertificateCheck = $true }
    }
    else {
        $ZertoCertSettings = @{SkipCertificateCheck = $false }
    }

    $baseURL = "https://" + $ZertoSessionConfig.ZertoServer + ":" + $ZertoSessionConfig.ZertoPort + "/v1/"
    $TypeJSON = "application/json"



    $FullURL = $baseURL + "vras/ipconfigurationtypes"
    Write-Verbose $FullURL

    try {
        $RestMethodSplat = @{
            Uri         = $FullURL
            TimeoutSec  = 100
            ContentType = $TypeJSON
            Method      = 'GET'
            WebSession  = $ZertoSessionConfig.ZertoWebSession
        }
        $Result = Invoke-RestMethod @RestMethodSplat @ZertoCertSettings
    }
    catch {
        throw $_.Exception.Message
    }
    return $Result
}

# .ExternalHelp ZertoModule.psm1-help.xml
Function Get-ZertoVRAStatus {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false, HelpMessage = 'Zerto Session Name')][String]$ZertoSession = "Default"
   )

    ## Get Session Configuration
    $ZertoSessionConfig = $global:ZertoSessions[$ZertoSession]
    if (-not $ZertoSessionConfig) {
        Write-Host 'TMSession: [' -NoNewline
        Write-Host $ZertoSession -ForegroundColor Cyan
        Write-Host '] was not Found. Please use the New-ZertoSession command.'
        Throw "Zerto Session Not Found. Use New-TMSession command before using features."
    }

    #Honor SSL Settings
    if ($ZertoSessionConfig.AllowInsecureSSL) {
        $ZertoCertSettings = @{SkipCertificateCheck = $true }
    }
    else {
        $ZertoCertSettings = @{SkipCertificateCheck = $false }
    }

    $baseURL = "https://" + $ZertoSessionConfig.ZertoServer + ":" + $ZertoSessionConfig.ZertoPort + "/v1/"
    $TypeJSON = "application/json"



    $FullURL = $baseURL + "vras/statuses"
    Write-Verbose $FullURL

    try {
        $RestMethodSplat = @{
            Uri         = $FullURL
            TimeoutSec  = 100
            ContentType = $TypeJSON
            Method      = 'GET'
            WebSession  = $ZertoSessionConfig.ZertoWebSession
        }
        $Result = Invoke-RestMethod @RestMethodSplat @ZertoCertSettings
    }
    catch {
        throw $_.Exception.Message
    }
    return $Result
}

# .ExternalHelp ZertoModule.psm1-help.xml
Function Remove-ZertoVRA {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false, HelpMessage = 'Zerto Session Name')][String]$ZertoSession = "Default",
        [Parameter(Mandatory = $true, HelpMessage = 'Zerto VRA Identifier')] [string] $ZertoVraIdentifier
   )

    ## Get Session Configuration
    $ZertoSessionConfig = $global:ZertoSessions[$ZertoSession]
    if (-not $ZertoSessionConfig) {
        Write-Host 'TMSession: [' -NoNewline
        Write-Host $ZertoSession -ForegroundColor Cyan
        Write-Host '] was not Found. Please use the New-ZertoSession command.'
        Throw "Zerto Session Not Found. Use New-TMSession command before using features."
    }

    #Honor SSL Settings
    if ($ZertoSessionConfig.AllowInsecureSSL) {
        $ZertoCertSettings = @{SkipCertificateCheck = $true }
    }
    else {
        $ZertoCertSettings = @{SkipCertificateCheck = $false }
    }

    $baseURL = "https://" + $ZertoSessionConfig.ZertoServer + ":" + $ZertoSessionConfig.ZertoPort + "/v1/"
    $TypeJSON = "application/json"

       if ([string]::IsNullOrEmpty($ZertoVraIdentifier)  ) {
        throw "Missing Zerto VRA Identifier"
    }

    $FullURL = $baseURL + "vras/" + $ZertoVraIdentifier
    Write-Verbose $FullURL

    try {
        $RestMethodSplat = @{
            Uri         = $FullURL
            TimeoutSec  = 100
            ContentType = $TypeJSON
            Method      = 'GET'
            WebSession  = $ZertoSessionConfig.ZertoWebSession
        }
        $Result = Invoke-RestMethod @RestMethodSplat @ZertoCertSettings -Method Delete
    }
    catch {
        throw $_.Exception.Message
    }
    return $Result
}

# .ExternalHelp ZertoModule.psm1-help.xml
Function Invoke-ZertoVRAUpgrade {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false, HelpMessage = 'Zerto Session Name')][String]$ZertoSession = "Default",
        [Parameter(Mandatory = $true, HelpMessage = 'Zerto VRA Identifier')] [string] $ZertoVraIdentifier
   )

    ## Get Session Configuration
    $ZertoSessionConfig = $global:ZertoSessions[$ZertoSession]
    if (-not $ZertoSessionConfig) {
        Write-Host 'TMSession: [' -NoNewline
        Write-Host $ZertoSession -ForegroundColor Cyan
        Write-Host '] was not Found. Please use the New-ZertoSession command.'
        Throw "Zerto Session Not Found. Use New-TMSession command before using features."
    }

    #Honor SSL Settings
    if ($ZertoSessionConfig.AllowInsecureSSL) {
        $ZertoCertSettings = @{SkipCertificateCheck = $true }
    }
    else {
        $ZertoCertSettings = @{SkipCertificateCheck = $false }
    }

    $baseURL = "https://" + $ZertoSessionConfig.ZertoServer + ":" + $ZertoSessionConfig.ZertoPort + "/v1/"
    $TypeJSON = "application/json"

       if ([string]::IsNullOrEmpty($ZertoVraIdentifier)  ) {
        throw "Missing Zerto VRA Identifier"
    }

    $FullURL = $baseURL + "vras/" + $ZertoVraIdentifier + "/upgrade"
    Write-Verbose $FullURL

    try {
        $RestMethodSplat = @{
            Uri         = $FullURL
            TimeoutSec  = 100
            ContentType = $TypeJSON
            Method      = 'GET'
            WebSession  = $ZertoSessionConfig.ZertoWebSession
        }
        $Result = Invoke-RestMethod @RestMethodSplat @ZertoCertSettings -Method Post
    }
    catch {
        throw $_.Exception.Message
    }
    return $Result
}

# .ExternalHelp ZertoModule.psm1-help.xml
Function Add-ZertoVRA {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false, HelpMessage = 'Zerto Session Name')][String]$ZertoSession = "Default",
        [Parameter(Mandatory = $true, HelpMessage = 'Zerto Datastore Name')] [string] $DatastoreName,
        [Parameter(Mandatory = $False, HelpMessage = 'Zerto VRA Group Name (optional)')] [string] $VRAGroupName,
        [Parameter(Mandatory = $true, HelpMessage = 'Zerto Host Name')] [string] $HostName,
        [Parameter(Mandatory = $true, HelpMessage = 'Zerto Network Name')] [string] $NetworkName,
        [Parameter(Mandatory = $false, HelpMessage = 'Memory in GB for new VRA (1-16, defaults to 16)')] [string] $MemoryInGB = 16,
        [Parameter(Mandatory = $true, ParameterSetName = "Password", HelpMessage = 'Zerto Host Root Password')] [string] $HostRootPassword,
        [Parameter(Mandatory = $true, ParameterSetName = "PublicKey", HelpMessage = 'Use vCenter PublicKey instead of Password')] [bool] $UseVCenterPublicKey = $true,
        [Parameter(Mandatory = $true, HelpMessage = 'VRA IP Configuration')] [VRAIPAddressConfig] $VRAIPConfiguration

        , [Parameter(Mandatory = $false, HelpMessage = 'Dump Json without posting for debug')] [switch] $DumpJson
   )

    ## Get Session Configuration
    $ZertoSessionConfig = $global:ZertoSessions[$ZertoSession]
    if (-not $ZertoSessionConfig) {
        Write-Host 'TMSession: [' -NoNewline
        Write-Host $ZertoSession -ForegroundColor Cyan
        Write-Host '] was not Found. Please use the New-ZertoSession command.'
        Throw "Zerto Session Not Found. Use New-TMSession command before using features."
    }

    #Honor SSL Settings
    if ($ZertoSessionConfig.AllowInsecureSSL) {
        $ZertoCertSettings = @{SkipCertificateCheck = $true }
    }
    else {
        $ZertoCertSettings = @{SkipCertificateCheck = $false }
    }

    $baseURL = "https://" + $ZertoSessionConfig.ZertoServer + ":" + $ZertoSessionConfig.ZertoPort + "/v1/"
    $TypeJSON = "application/json"


    #Validate
    if ($UseVCenterPublicKey -and $HostRootPassword) {
        throw "Cannot specify both HostRootPassword and Use vCenter Public Key"
    }
    if ($MemoryInGB -lt 1 -or $MemoryInGB -gt 16) {
        throw "Invalid MemoryInGB - must be from 1 to 16"
    }

    #Get Identifiers
    $LocalSiteID = Get-ZertoLocalSiteID -ZertoServer $ZertoServer -ZertoPort $ZertoPort -ZertoToken $ZertoToken
    if ([string]::IsNullOrEmpty($LocalSiteID)  ) { throw "Could not find Local Site ID" }

    $HostID = Get-ZertoSiteHostID -ZertoServer $ZertoServer -ZertoPort $ZertoPort -ZertoToken $ZertoToken -ZertoSiteIdentifier $LocalSiteID -HostName $HostName

    $DatastoreID = Get-ZertoSiteDatastoreID -ZertoServer $ZertoServer -ZertoPort $ZertoPort -ZertoToken $ZertoToken -ZertoSiteIdentifier $LocalSiteID -DatastoreName $DatastoreName

    $NetworkID = Get-ZertoSiteNetworkID -ZertoServer $ZertoServer -ZertoPort $ZertoPort -ZertoToken $ZertoToken -ZertoSiteIdentifier $LocalSiteID -NetworkName $NetworkName

    #Validate IDs
    if ([string]::IsNullOrEmpty($DatastoreID)  ) { throw "Could not find Datastore ID for $DatastoreName " }
    if ([string]::IsNullOrEmpty($HostID)  ) { throw "Could not find Datastore ID for $DatastoreName " }
    if ([string]::IsNullOrEmpty($NetworkID)  ) { throw "Could not find Network ID for $NetworkName " }

    $FullURL = $baseURL + "vras"
    Write-Verbose $FullURL

    $BodyHash = [ordered] @{}
    $BodyHash.Add("DatastoreIdentifier", $DatastoreID)
    $BodyHash.Add("GroupName", $VRAGroupName)
    $BodyHash.Add("HostIdentifier", $HostID)
    If ($HostRootPassword) {
        $BodyHash.Add("HostRootPassword", $HostRootPassword)
        $BodyHash.Add("UsePublicKeyInsteadOfCredentials", $false)
    }
    else {
        $BodyHash.Add("HostRootPassword", $null)
        $BodyHash.Add("UsePublicKeyInsteadOfCredentials", $UseVCenterPublicKey)
    }

    $BodyHash.Add("MemoryInGb", $MemoryInGB)
    $BodyHash.Add("NetworkIdentifier", $NetworkID)
    $NewVRAIPInfo = [ordered] @{}
    $NewVRAIPInfo.Add("DefaultGateway", $VRAIPConfiguration.Gateway )
    $NewVRAIPInfo.Add("SubnetMask", $VRAIPConfiguration.SubnetMask )
    $NewVRAIPInfo.Add("VraIPAddress", $VRAIPConfiguration.IPAddress )
    $NewVRAIPInfo.Add("VraIPConfigurationTypeApi", $VRAIPConfiguration.VRAIPType.ToString() )
    $BodyHash.Add("VraNetworkDataApi", $NewVRAIPInfo)

    #Convert VPG Hash to JSON - Remember DEPTH!!!
    $BodyJson = $BodyHash | ConvertTo-Json -Depth 20

    Write-Verbose $NewVRAJson

    if ($DumpJson ) {
        #Display JSON, and exit
        Write-Host $BodyJson
        return
    }

    try {
        $RestMethodSplat = @{
            Uri         = $FullURL
            TimeoutSec  = 100
            ContentType = $TypeJSON
            Method      = 'GET'
            WebSession  = $ZertoSessionConfig.ZertoWebSession
        }
        $Result = Invoke-RestMethod @RestMethodSplat @ZertoCertSettings -Method Post -Body $BodyJson
    }
    catch {
        throw $_.Exception.Message
    }
    return $Result
}

# .ExternalHelp ZertoModule.psm1-help.xml
Function Update-ZertoVRA {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false, HelpMessage = 'Zerto Session Name')][String]$ZertoSession = "Default",
        [Parameter(Mandatory = $true, HelpMessage = 'Zerto VRA Identifier')] [string] $ZertoVraIdentifier,
        [Parameter(Mandatory = $False, HelpMessage = 'Zerto VRA Group Name (optional)')] [string] $VRAGroupName,
        [Parameter(Mandatory = $true, ParameterSetName = "Password", HelpMessage = 'Zerto Host Root Password')] [string] $HostRootPassword,
        [Parameter(Mandatory = $true, ParameterSetName = "PublicKey", HelpMessage = 'Use vCenter PublicKey instead of Password')] [bool] $UseVCenterPublicKey = $true,
        [Parameter(Mandatory = $true, HelpMessage = 'VRA IP Configuration')] [VRAIPAddressConfig] $VRAIPConfiguration
        , [Parameter(Mandatory = $false, HelpMessage = 'Dump Json without posting for debug')] [switch] $DumpJson
   )

    ## Get Session Configuration
    $ZertoSessionConfig = $global:ZertoSessions[$ZertoSession]
    if (-not $ZertoSessionConfig) {
        Write-Host 'TMSession: [' -NoNewline
        Write-Host $ZertoSession -ForegroundColor Cyan
        Write-Host '] was not Found. Please use the New-ZertoSession command.'
        Throw "Zerto Session Not Found. Use New-TMSession command before using features."
    }

    #Honor SSL Settings
    if ($ZertoSessionConfig.AllowInsecureSSL) {
        $ZertoCertSettings = @{SkipCertificateCheck = $true }
    }
    else {
        $ZertoCertSettings = @{SkipCertificateCheck = $false }
    }

    $baseURL = "https://" + $ZertoSessionConfig.ZertoServer + ":" + $ZertoSessionConfig.ZertoPort + "/v1/"
    $TypeJSON = "application/json"


    #Validate
    if ($UseVCenterPublicKey -and $HostRootPassword) {
        throw "Cannot specify both HostRootPassword and Use vCenter Public Key"
    }

    #Get Identifiers
    $LocalSiteID = Get-ZertoLocalSiteID -ZertoServer $ZertoServer -ZertoPort $ZertoPort -ZertoToken $ZertoToken
    if ([string]::IsNullOrEmpty($LocalSiteID)  ) { throw "Could not find Local Site ID" }

    $FullURL = $baseURL + "vras/" + $ZertoVraIdentifier
    Write-Verbose $FullURL

    $BodyHash = [ordered] @{}

    $BodyHash.Add("GroupName", $VRAGroupName)
    If ($HostRootPassword) {
        $BodyHash.Add("HostRootPassword", $HostRootPassword)
        $BodyHash.Add("UsePublicKeyInsteadOfCredentials", $false)
    }
    else {
        $BodyHash.Add("HostRootPassword", $null)
        $BodyHash.Add("UsePublicKeyInsteadOfCredentials", $UseVCenterPublicKey)
    }

    $NewVRAIPInfo = [ordered] @{}
    $NewVRAIPInfo.Add("DefaultGateway", $VRAIPConfiguration.Gateway )
    $NewVRAIPInfo.Add("SubnetMask", $VRAIPConfiguration.SubnetMask )
    $NewVRAIPInfo.Add("VraIPAddress", $VRAIPConfiguration.IPAddress )
    $NewVRAIPInfo.Add("VraIPConfigurationTypeApi", $VRAIPConfiguration.VRAIPType.ToString() )
    $BodyHash.Add("VraNetworkDataApi", $NewVRAIPInfo)

    #Convert VPG Hash to JSON - Remember DEPTH!!!
    $BodyJson = $BodyHash | ConvertTo-Json -Depth 20

    Write-Verbose $BodyJson
    if ($DumpJson ) {
        #Display JSON, and exit
        Write-Host $BodyJson
        return
    }

    try {
        $RestMethodSplat = @{
            Uri         = $FullURL
            TimeoutSec  = 100
            ContentType = $TypeJSON
            Method      = 'GET'
            WebSession  = $ZertoSessionConfig.ZertoWebSession
        }
        $Result = Invoke-RestMethod @RestMethodSplat @ZertoCertSettings -Method Put -Body $BodyJson
    }
    catch {
        throw $_.Exception.Message
    }
    return $Result
}


#endregion