This topic contains 6 replies, has 3 voices, and was last updated by  Alex S October 15, 2019.

Create Simple VPG using PowerShell and API

  • Can someone post a simple template script for creating a new VPG.  I am just looking to get the understanding on getting the first one deployed using the API.  I am just looking for a simply start that gets one created successfully.  I have reviewed the API whitepaper and it is a little overwhelming at first.  I would using this to tweak some of the defaults after I get the first one created.  It would be great if variables can be defined for, names, networks, datastores, etc..

    I have reviewed the Zerto Virtual Replication RESTful APIs doc and what I am looking for is a base script like Example 2: Perform an action on page 24.  Instead of reading a CSV file with VMs, just define parameters with the VM name and other VPG properties.

    Hi Dave

    I’ve experienced the same issue. Starting with creating a VPG with the API can be frustrating. I’ve created a powershell script which just creates a almost fully populated JSON which you then can use to create a VPG.

    It uses PSCustomObject for structure and filling in the data. I think it is easier to debug with PSCustom Objects than a raw JSON.

    Please note that you have to replace most properties which ends with “Identifier” with your own.

    #---------------------------------------------------------[Initialisations]--------------------------------------------------------
    
    # ZVM Server
    $ZVMServer = "zvm.lab.local"
    
    # Get Credentials for ZVM API
    $Credentials = Get-Credential -Message "Please enter Username and Password for ZVM $($ZVMServer)" -UserName $env:USERNAME
    $username = $Credentials.UserName
    $password = $Credentials.GetNetworkCredential().Password
    
    #-----------------------------------------------------------[Functions]------------------------------------------------------------
    
    function getxZertoSession ($zvm, $userName, $password) {
        $xZertoSessionURL = $zvm+"session/add"
        $authInfo = ("{0}:{1}" -f $userName,$password)
        $authInfo = [System.Text.Encoding]::UTF8.GetBytes($authInfo)
        $authInfo = [System.Convert]::ToBase64String($authInfo)
        $headers = @{Authorization=("Basic {0}" -f $authInfo)}
        $body = '{"AuthenticationMethod": "1"}'
        $contentType = "application/json"
        $xZertoSessionResponse = Invoke-WebRequest -Uri $xZertoSessionURL -Headers $headers -Method POST -Body $body -ContentType $contentType
        return @{"x-zerto-session"=$xZertoSessionResponse.headers.get_item("x-zerto-session")}
    }
    
    #-----------------------------------------------------------[Execution]------------------------------------------------------------
    
    # Build Zerto REST API Url
    $ZertoRestURL = "https://$($ZVMServer)/v1/"
    
    # Get Zerto Session Header for Auth
    $ZertoSession = getxZertoSession "$($ZertoRestURL)" $username $password
    
    ########### BACKUP SETTINGS ###########
    $VPGSettingsBackup = $null;
    
    ########### BASIC SETTINGS ###########
    $VPGSettingsBasic= @()
    $VPGSettingsBasic = [PSCustomObject]@{
            JournalHistoryInHours = "168";
            Name = "VPGTest";
            Priority = "High";
            ProtectedSiteIdentifier = "3035c688-3fb2-469d-9034-4f729f5a6432";
            RecoverySiteIdentifier = "e63b0d4d-2c2a-47ec-a28b-78c259007e79";
            RpoInSeconds = "300";
            ServiceProfileIdentifier = $null;
            TestIntervalInMinutes = "525600";
            UseWanCompression = $true;
            ZorgIdentifier = $null
        }
    
    ########### BOOT GROUPS SETTINGS ###########
    $VPGSettingsBootGroupGroups= @()
    $VPGSettingsBootGroupGroups += [PSCustomObject]@{
            BootDelayInSeconds ="";
            BootGroupIdentifier = "00000000-0000-0000-0000-000000000001";
            Name = "Default"
        }
    
    $VPGSettingsBootGroups= @()
    $VPGSettingsBootGroups = [PSCustomObject]@{
            BootGroups = $VPGSettingsBootGroupGroups;
        }
    
    ########### JOURNAL SETTINGS ###########
    $VPGSettingsJournalLimitation = @()
    $VPGSettingsJournalLimitation = [PSCustomObject]@{
            HardLimitInMB = "153600";
            HardLimitInPercent = $null;
            WarningThresholdInMB = "128000";
            WarningThresholdInPercent = $null
        }
    
    $VPGSettingsJournal = @()
    $VPGSettingsJournal = [PSCustomObject]@{
            DatastoreIdentifier = "c0ee66b7-1c85-49cb-b7db-3ff9a83922d9.datastore-175664";
            Limitation = $VPGSettingsJournalLimitation
        }
    
    ########### NETWORK SETTINGS ###########
    $VPGSettingsNetworksFailoverHypervisor = @()
    $VPGSettingsNetworksFailoverHypervisor = [PSCustomObject]@{
            DefaultNetworkIdentifier = "4e358c65-35f7-48d4-9742-eaf45897bd9e.dvportgroup-117"
        }
    
    $VPGSettingsNetworksFailover = @()
    $VPGSettingsNetworksFailover = [PSCustomObject]@{
            Hypervisor = $VPGSettingsNetworksFailoverHypervisor
        }
    
    $VPGSettingsNetworksFailoverTestHypervisor = @()
    $VPGSettingsNetworksFailoverTestHypervisor = [PSCustomObject]@{
            DefaultNetworkIdentifier = "4e358c65-35f7-48d4-9742-eaf45897bd9e.dvportgroup-117"
        }
    
    $VPGSettingsNetworksFailoverTest = @()
    $VPGSettingsNetworksFailoverTest = [PSCustomObject]@{
            Hypervisor = $VPGSettingsNetworksFailoverTestHypervisor
        }
    
    $VPGSettingsNetworks = @()
    $VPGSettingsNetworks = [PSCustomObject]@{
            Failover = $VPGSettingsNetworksFailover;
            FailoverTest = $VPGSettingsNetworksFailoverTest
        }
    
    ########### RECOVERY SETTINGS ###########
    $VPGSettingsRecovery = @()
    $VPGSettingsRecovery = [PSCustomObject]@{
            DefaultDatastoreIdentifier = "c0ee66b7-1c85-49cb-b7db-3ff9a83922d9.datastore-175664";
            DefaultFolderIdentifier = "4e358c65-35f7-48d4-9742-eaf45897bd9e.group-v42949";
            ResourcePoolIdentifier = $null
        }
    
    
    ########### SCRIPTING SETTINGS ###########
    $VPGSettingsScriptingPostRecovery = @()
    $VPGSettingsScriptingPostRecovery = [PSCustomObject]@{
            Command = $null;
            Parameters = $null;
            TimeoutInSeconds = 0
        }
    
    $VPGSettingsScriptingPreRecovery = @()
    $VPGSettingsScriptingPreRecovery = [PSCustomObject]@{
            Command = $null;
            Parameters = $null;
            TimeoutInSeconds = 0
        }
    
    $VPGSettingsScripting = @()
    $VPGSettingsScripting = [PSCustomObject]@{
            PostBackup = $null;
            PostRecovery = $VPGSettingsScriptingPostRecovery;
            PreRecovery = $VPGSettingsScriptingPreRecovery
        }
    
    ########### VM SETTINGS ###########
    $VPGSettingsVMs = @()
    
    $VPGSettingsVMsJournal = @()
    $VPGSettingsVMsJournal = [PSCustomObject]@{
        DatastoreIdentifier = "c0ee66b7-1c85-49cb-b7db-3ff9a83922d9.datastore-175664"
    }
    
    $VPGSettingsVMsVolumes = @()
    
    $VPGSettingsVMsVolumesDatastore = @()
    $VPGSettingsVMsVolumesDatastore = [PSCustomObject]@{
        DatastoreIdentifier = "c0ee66b7-1c85-49cb-b7db-3ff9a83922d9.datastore-175664";
        IsThin = "false"
    }
    
    $VPGSettingsVMsVolumes += [PSCustomObject]@{
        VolumeIdentifier = "scsi:0:0";
        IsSwap = "false";
        Datastore = $VPGSettingsVMsVolumesDatastore
    }
    
    $VPGSettingsVMsRecovery = @()
    $VPGSettingsVMsRecovery = [PSCustomObject]@{
        FolderIdentifier = "4e358c65-35f7-48d4-9742-eaf45897bd9e.group-v42949";
        DatastoreIdentifier = "c0ee66b7-1c85-49cb-b7db-3ff9a83922d9.datastore-175664";
        HostIdentifier = "4e358c65-35f7-48d4-9742-eaf45897bd9e.host-24265"
    }
    
    $VPGSettingsVMsNics = @()
    
    $VPGSettingsVMsNicsFailoverHypervisorIPConfig= @()
    $VPGSettingsVMsNicsFailoverHypervisorIPConfig = [PSCustomObject]@{
        Gateway = $null;
        IsDhcp = "false";
        PrimaryDns = $null;
        SecondaryDns = $null;
        StaticIp = $null;
        SubnetMask = $null
    }
    
    $VPGSettingsVMsNicsFailoverTestHypervisorIPConfig= @()
    $VPGSettingsVMsNicsFailoverTestHypervisorIPConfig = [PSCustomObject]@{
        Gateway = $null;
        IsDhcp = "false";
        PrimaryDns = $null;
        SecondaryDns = $null;
        StaticIp = $null;
        SubnetMask = $null
    }
    
    $VPGSettingsVMsNicsFailoverHypervisor= @()
    $VPGSettingsVMsNicsFailoverHypervisor = [PSCustomObject]@{
        DnsSuffix = $null;
        IpConfig = $VPGSettingsVMsNicsFailoverHypervisorIPConfig;
        NetworkIdentifier = "4e358c65-35f7-48d4-9742-eaf45897bd9e.dvportgroup-117";
        ShouldReplaceMacAddress = "false"
    }
    
    $VPGSettingsVMsNicsFailoverTestHypervisor= @()
    $VPGSettingsVMsNicsFailoverTestHypervisor = [PSCustomObject]@{
        DnsSuffix = $null;
        IpConfig = $VPGSettingsVMsNicsFailoverTestHypervisorIPConfig;
        NetworkIdentifier = "4e358c65-35f7-48d4-9742-eaf45897bd9e.dvportgroup-117";
        ShouldReplaceMacAddress = "false"
    }
    
    $VPGSettingsVMsNicsFailover= @()
    $VPGSettingsVMsNicsFailover = [PSCustomObject]@{
        Hypervisor = $VPGSettingsVMsNicsFailoverHypervisor;
    }
    
    $VPGSettingsVMsNicsFailoverTest= @()
    $VPGSettingsVMsNicsFailoverTest = [PSCustomObject]@{
        Hypervisor = $VPGSettingsVMsNicsFailoverTestHypervisor;
    }
    
    $VPGSettingsVMsNics += [PSCustomObject]@{
        NicIdentifier = "Network Adapter 1";
        Failover = $VPGSettingsVMsNicsFailover;
        FailoverTest = $VPGSettingsVMsNicsFailoverTest
    }
    
    $VPGSettingsVMs += [PSCustomObject]@{
        BootGroupIdentifier = "00000000-0000-0000-0000-000000000001";
        VmIdentifier = "c0ee66b7-1c85-49cb-b7db-3ff9a83922d9.vm-130947";
        Journal = $VPGSettingsVMsJournal;
        Nics = $VPGSettingsVMsNics;
        Recovery = $VPGSettingsVMsRecovery;
        Volumes = $VPGSettingsVMsVolumes
    }
    
    ########### COMBINE ALL SETTINGS ###########
    $JSON_Raw = [PSCustomObject]@{
        Backup = $VPGSettingsBackup;
        Basic = $VPGSettingsBasic;
        BootGroups = $VPGSettingsBootGroups;
        Journal = $VPGSettingsJournal;
        Networks = $VPGSettingsNetworks;
        Recovery = $VPGSettingsRecovery;
        Scripting = $VPGSettingsScripting;
        Vms = $VPGSettingsVMs
    }
    
    # Convert the PSTableObject to JSON
    $JSON = $JSON_Raw | ConvertTo-Json -Depth 10 # Depth has to be given because default depth is 2!
    
    # Create VPG Setting
    $VPGSettingsIdentifier = Invoke-RestMethod -Method POST -Uri ("$($ZertoRestURL)VPGSettings") -Body $JSON -ContentType "application/json" -Headers $ZertoSession
    
    # Commit VPG Settings with POST
    Invoke-RestMethod -Method POST -Uri ("$($ZertoRestURL)VPGSettings/$($VPGSettingsIdentifier)/commit") -Body $JSON -ContentType "application/json" -Headers $ZertoSession

    Thanks Tobias, I will give it a shot and let you know.

    Hey, has anyone managed to get Tobias’s script working yet?

    @Tobias, apologies I am quite new to using APIs in powershell. You mention these Identifiers for example the Site identifiers? Is there a specific API you are using to get this information?

    If anyone is interested. I managed so far to get the APIs to return a VPG Identifier with the below API calls. This will also ignore a untrusted certificate.

     

    $strZVMIP = “zvm03”
    $strZVMPort = “9669”
    $strZVMUser = “domain\username”
    $Password = Read-Host -Prompt ‘Please enter your user password’ -AsSecureString
    $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)
    $strZVMPwd = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
    ####################################################
    ## Perform authentication so that Zerto APIs can run. Return a session identifier that needs tobe inserted in the header for subsequent requests.
    ################################################
    #-Certificates That are not trusted need to be accepted
    add-type @”
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
    public bool CheckValidationResult(
    ServicePoint srvPoint, X509Certificate certificate,
    WebRequest request, int certificateProblem) {
    return true;
    }
    }
    “@
    [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

    function getxZertoSession ($userName, $password){
    $baseURL = “https://” + $strZVMIP + “:”+$strZVMPort
    $xZertoSessionURL = $baseURL +”/v1/session/add”
    $authInfo = (“{0}:{1}” -f $userName,$password)
    $authInfo = [System.Text.Encoding]::UTF8.GetBytes($authInfo)
    $authInfo = [System.Convert]::ToBase64String($authInfo)
    $headers = @{Authorization=(“Basic {0}” -f $authInfo)}
    $contentType = “application/json”
    $xZertoSessionResponse = Invoke-WebRequest -Uri $xZertoSessionURL -Headers $headers -Method POST -Body $body -ContentType $contentType
    #$xZertoSessionResponse = Invoke-WebRequest -Uri $xZertoSessionURL -Headers $headers -Body $body -Method POST
    return $xZertoSessionResponse.headers.get_item(“x-zerto-session”)
    }
    #Extract x-zerto-session from the response, and add it to the actual API:
    $xZertoSession = getxZertoSession $strZVMUser $strZVMPwd
    $zertoSessionHeader = @{“x-zerto-session”=$xZertoSession}
    $zertoSessionHeader_xml = @{“Accept”=”application/xml”
    “x-zerto-session”=$xZertoSession}
    #Invoke the Zerto API:
    $vpgListApiUrl = “https://” + $strZVMIP + “:”+$strZVMPort+”/v1/vpgs”
    $VPGNAME = “NL – CUS001 – Test”
    #Iterate with XML:
    $vpgListXML = Invoke-RestMethod -Uri $vpgListApiUrl -Headers $zertoSessionHeader_xml
    foreach ($vpg in $vpgListXML.ArrayOfVpgApi.VpgApi){
    if ($vpg.VpgName -eq $VPGNAME){
    $tmpVpgIdentifier = $vpg.VpgIdentifier
    break
    }
    }
    #Iterate with JSON:
    $vpgListJSON = Invoke-RestMethod -Uri $vpgListApiUrl -Headers $zertoSessionHeader
    foreach ($vpg in $vpgListJSON){
    if ($vpg.VpgName -eq $VPGNAME){
    $tmpVpgIdentifier = $vpg.VpgIdentifier
    break
    }
    }
    write-host $tmpVpgIdentifier
    ##End of script

You must be logged in to create new topics. Click here to login