• This topic has 4 replies, 3 voices, and was last updated February 15, 2017 by Jason D.

Need help adding VM to an existing VPG

  • I am trying to add new VMs to an existing VPG using the PowerShell Rest API.  We’re running vmware 6.0 and Zerto 5.0.  I’m following the the Zerto Rest API Reference Guide.  I can create the VPG Settings, and poll the vpgsettings/VPGSETTINGSID using a GET method and return the results.   I create the JSON to add the VM to the VPG using a POST method.  The new VM doesn’t show up in the settings if I do another GET from the vpg settings ID.  If I try and commit it, a task is created to update the VPG, but it doesn’t update anything.  I’d assume that is because I have something wrong with my POST to add the VM to the VPG.  I haven’t been able to pinpoint this yet, and would love to get this working.  We can’t add entire groups of VMs to a VPG at a time or we tend to overload our infrastructure during the initial synch.
    <p class=”p1″><span class=”s1″> </span></p>

    <pre class=”EnlighterJSRAW” data-enlighter-language=”null”>$VMName = “myprotectedvm1”
    $VPGName = “myvpg”

    #Get the Zerto Connection Token and BaseURL
    #I have a function that uses get-credential and returns a variable that contains the BaseURL and SessionHeader
    $connZerto = Connect-ZertoServer -ZertoServer zertozvm01 -ZertoPort 9669 -creds $creds

    #Get the Site ID of our Protected Site
    $SiteIDURL = $connZerto.BaseURL+”localsite”
    $SiteIDCMD = Invoke-RestMethod -Uri $SiteIDURL -TimeoutSec 100 -Headers $connZerto.SessionHeader -ContentType “application/JSON”
    $SiteIdentifier = $SiteIDCMD | select SiteIdentifier -ExpandProperty SiteIdentifier

    #Get the Zerto VM ID
    $GetVMURL = $connZerto.BaseURL+”virtualizationsites/”+$SiteIdentifier+”/vms”
    $GetVMCMD = Invoke-RestMethod -Uri $GetVMURL -TimeoutSec 100 -Headers $connZerto.SessionHeader -ContentType “application/JSON”
    $VMIdentifier = $GetVMCMD | where {$_.VMName -like “$VMName”} | select VMIdentifier -ExpandProperty VMIdentifier

    #Build the JSON for the VM Identifier
    $JSONVMIDMain =
    “{“”VMIdentifier””:””$VMIdentifier””}”
    <#Example Output with my made up VMIdentifier
    $JSONVMIDMain
    {“VMIdentifier”:”aa1a1111-11aa-11aa-111a-1a111aa1111a.vm-1111″}
    #>

    #Get a VPG Settings Object from the VPG by Name
    $GetVPGIDURL = $connZerto.BaseURL+”vpgs”
    $GetVPGIDCMD = Invoke-RestMethod -Uri $GetVPGIDURL -TimeoutSec 100 -Headers $connZerto.SessionHeader -ContentType “application/JSON”
    $VPGIdentifier = $GetVPGIDCMD | where {$_.VPGName -like $VpgName} | select VpgIdentifier -ExpandProperty VpgIdentifier

    #Build the JSON for the VPGIdentifier
    $JSONVPGIDMain =
    “{“”VpgIdentifier””:””$VpgIdentifier””}”
    <#Example Output of a VPG Settings ID JSON
    $JSONVPGIDMain
    {“VpgIdentifier”:”1a1a1111-11aa-11aa-a1aa-1111a11a1a11″}
    #>

    #Create the VPG Settings ID
    $VPGSettingsURL = $connZerto.BaseURL+”vpgSettings”
    $VPGSettingsID = Invoke-RestMethod -Uri $VPGSettingsURL -TimeoutSec 100 -Headers $connZerto.SessionHeader -ContentType “application/JSON” -Body $JSONVPGIDMain -Method Post
    <#Example Output of the new VPG Settings ID
    11a1111a-a111-1111-a111-11aa11a111aa
    #>

    #Updating the VPG Settings with the New VM Identifier
    #This is the part that doesn’t seem to work. It doesn’t add the VM to the VPG Settings.
    $VPGAddVMURL = $connZerto.BaseURL+”vpgsettings/”+$VPGSettingsID+”/vms”
    $VPGAddVMCMD = Invoke-RestMethod -Uri $VPGAddVMURL -TimeoutSec 100 -Headers $connZerto.SessionHeader -ContentType “application/JSON” -Body $JSONVMIDMain -Method Post
    $VPGAddVMCMD
    #I get no response from this command.

    #This is just to see what the VPG Settings object looks like. It does not contain the new VM, only the one old one.
    $VPGGetSettingsURL = $connZerto.BaseURL+”vpgsettings/”+$VPGSettingsID
    $VPGGetSettingsCMD = Invoke-RestMethod -Uri $VPGGetSettingsURL -TimeoutSec 100 -Headers $connZerto.SessionHeader -Method Get
    $VPGGetSettingsCMD

    #This would commit the settings to the VPG. In my current situation, it commits my unchanged VPG settings object.
    #It shows in the ZVM UI that it is updating the VPG, but no changes are applied.
    $VPGSettingsCommitURL = $connZerto.BaseURL+”vpgsettings/”+$VPGSettingsID+”/commit”
    $VPGSettingsCommitCMD = Invoke-RestMethod -Uri $VPGSettingsCommitURL -TimeoutSec 100 -Headers $connZerto.SessionHeader -ContentType “application/JSON” -Method Post
    $VPGSettingsCommitCMD

    Hey Jason,

    You’ve come to the right place! First thing is that I recommend building your script to both add a VM to a VPG and to create a VPG if it doesn’t exist. An easy check of the name with an IF statement will do this:

    $VPGToCreate = “MyFirstVPG”
    # Checking to see if VPG exists using CustomerName
    $SourceZVMVPGsURL = $SourceZVMBaseURL+”vpgs”
    $SourceZVMVPGsCMD = Invoke-RestMethod -Uri $SourceZVMVPGsURL -TimeoutSec 100 -Headers $SourceZVMSessionHeader -ContentType $JSONContent
    $VPGIdentifier = $SourceZVMVPGsCMD | Where-Object {$_.Vpgname -eq $VPGToCreate} | Select-Object -ExpandProperty VpgIdentifier
    # IF VPG does EXIST, adding VMs to VPG
    ################################################################################################
    if ($VPGIdentifier -ne $null)
    {
    write-host “
    VPG $VPGToCreate EXISTS”
    # Add VM to VPG here
    }
    if ($VPGIdentifier -eq $null)
    {
    write-host “
    VPG $VPGToCreate DOES NOT EXIST”
    # Create VPG script here
    }</h6>
    Now we’ve got this covered lets look at adding the VM to an existing VPG. First I need the VPG settings identifier, then I need to build the VM JSON, POST the new VM to the VPG settings and finally commit the VPG settings:
    <h6>################################################
    # Building Zerto API string and invoking API
    ################################################
    $baseURL = “https://” + $ZertoServer + “:”+$ZertoPort+”/v1/”
    # Authenticating with Zerto APIs
    $xZertoSessionURL = $baseURL + “session/add”
    $authInfo = (“{0}:{1}” -f $ZertoUser,$ZertoPassword)
    $authInfo = [System.Text.Encoding]::UTF8.GetBytes($authInfo)
    $authInfo = [System.Convert]::ToBase64String($authInfo)
    $headers = @{Authorization=(“Basic {0}” -f $authInfo)}
    $sessionBody = ‘{“AuthenticationMethod”: “1”}’
    $TypeJSON = “application/json”
    $TypeXML = “application/xml”
    $xZertoSessionResponse = Invoke-WebRequest -Uri $xZertoSessionURL -Headers $headers -Method POST -Body $sessionBody -ContentType $TypeJSON
    #Extracting x-zerto-session from the response, and adding it to the actual API
    $xZertoSession = $xZertoSessionResponse.headers.get_item(“x-zerto-session”)
    $zertosessionHeader = @{“x-zerto-session”=$xZertoSession}
    ################################################
    # Getting VPG & VM lists to get identifiers of VPG and VMs to add
    ################################################
    # URL to create VPG settings
    $CreateVPGURL = $BaseURL+”vpgSettings”
    # VPG URL and List
    $vpgListApiUrl = $baseURL+”vpgs”
    $vpgList = Invoke-RestMethod -Uri $vpgListApiUrl -TimeoutSec 100 -Headers $zertoSessionHeader -ContentType $TypeXML
    # Build List of VMs
    $vmListApiUrl = $baseURL+”vms”
    $vmList = Invoke-RestMethod -Uri $vmListApiUrl -TimeoutSec 100 -Headers $zertoSessionHeader -ContentType $TypeJSON
    # Select IDs from the API array
    $zertoprotectiongrouparray = $vpgList.ArrayOfVpgApi.VpgApi | Select-Object OrganizationName,vpgname,vmscount,vpgidentifier
    $VPGIdentifier = $zertoprotectiongrouparray | Where-Object {$_.VpgName -eq $VPGName} | select-object VpgIdentifier -ExpandProperty VpgIdentifier
    # Building JSON for edit request
    $JSON =
    “{
    “”VpgIdentifier””:””$VPGidentifier””
    }”
    ################################################

    # Posting the VPG JSON Request to the API
    ################################################
    Try
    {
    $VPGSettingsIdentifier = Invoke-RestMethod -Method Post -Uri $CreateVPGURL -Body $JSON -ContentType $TypeJSON -Headers $zertosessionHeader
    write-host “VPGSettingsIdentifier: $VPGSettingsIdentifier”
    }
    Catch {
    Write-Host $_.Exception.ToString()
    $error[0] | Format-List -Force
    }
    ################################################
    # Getting the Zerto VM Identifiers for the VM to be created in this VPG
    ################################################
    # Get SiteIdentifier for getting Local Identifier later in the script
    $SiteInfoURL = $BaseURL+”localsite”
    $SiteInfoCMD = Invoke-RestMethod -Uri $SiteInfoURL -TimeoutSec 100 -Headers $zertosessionHeader -ContentType $TypeJSON
    $LocalSiteIdentifier = $SiteInfoCMD | Select SiteIdentifier -ExpandProperty SiteIdentifier
    # Getting VM identifier
    $VMInfoURL = $BaseURL+”virtualizationsites/$LocalSiteIdentifier/vms”
    $VMInfoCMD = Invoke-RestMethod -Uri $VMInfoURL -TimeoutSec 100 -Headers $zertosessionHeader -ContentType $TypeJSON
    $VMIdentifier = $VMInfoCMD | Where-Object {$_.VmName -eq $VMName} | select VmIdentifier -ExpandProperty VmIdentifier
    ################################################
    # Building URLs, JSON and Posting request
    ################################################
    $AddVMURL = $BaseURL+”vpgSettings/”+”$VPGSettingsIdentifier”+”/vms”
    $JSONVM = “{“”VmIdentifier””:””$vmIdentifier””}”
    Try
    {
    $AddVMPOST = Invoke-RestMethod -Method POST -Uri $AddVMURL -Body $JSONVM -ContentType $TypeJSON -Headers $zertosessionHeader -TimeoutSec 100
    }
    Catch {
    Write-Host $_.Exception.ToString()
    $error[0] | Format-List -Force
    }
    ################################################
    # Committing the VPG settings to be created
    ################################################
    $CommitVPGSettingURL = $BaseURL+”vpgSettings/”+”$VPGSettingsIdentifier”+”/commit”
    write-host “CommitVPGSettingURL:$CommitVPGSettingURL”
    Try
    {
    Invoke-RestMethod -Method Post -Uri $CommitVPGSettingURL -ContentType $TypeJSON -Headers $zertosessionHeader -TimeoutSec 100
    $VPGCreationStatus = “PASSED”
    }
    Catch {
    $VPGCreationStatus = “FAILED”
    Write-Host $_.Exception.ToString()
    $error[0] | Format-List -Force
    }

    And that’s it! Once you’ve edited the variables to match your script it should be very simple. Let me know if you have any issues getting this working. Thanks,

    Joshua

    Thank you Joshua!  That is a good idea, to create the VPG if it doesn’t exist.  I’ve been writing functions for each of the API methods that we will use, so I had to piece this example together from all of my functions to make it as basic as possible to post in the forum.  🙂   I am going to look through the API documents now to see if we can specify a datastore when we add a VM to an existing VPG.  I can specify the datastore when I create a new VPG, but I’m still new to adding a VM.  Thanks for your help!

     

    This is the section that I had wrong.  I had two issues here.  “VMIdentifier” should be “VmIdentifier” with the lowercase M.  Also, I had to move the $JSONVMIDMain = <span style=”color: #555555;”>“{“”VmIdentifier””:””$VMIdentifier””}” to the same line.</span>

     

     

     

    ####This is the WRONG WAY!!!  It does NOT work!####

    <span style=”color: #555555;”>#Build the JSON for the VM Identifier</span><br style=”color: #555555;” /><span style=”color: #555555;”>$JSONVMIDMain =</span><br style=”color: #555555;” /><span style=”color: #555555;”>“{“”VMIdentifier””:””$VMIdentifier””}”</span>

    ##############################################

     

    ####This is the right way.  This one will work!####

    <em style=”color: #555555;”>################################################<br style=”color: #555555;” /><em style=”color: #555555;”># Building URLs, JSON and Posting request<br style=”color: #555555;” /><em style=”color: #555555;”>################################################<br style=”color: #555555;” /><em style=”color: #555555;”>$AddVMURL = $BaseURL+”vpgSettings/”+”$VPGSettingsIdentifier”+”/vms”<br style=”color: #555555;” /><em style=”color: #555555;”>$JSONVM = “{“”VmIdentifier””:””$vmIdentifier””}”

     

    Jason –

     

    I’ve created a PS Module that wraps most of Rest API functionality in simple Powershell commandlets available here https://www.powershellgallery.com/packages/ZertoModule/ .

    For example, to get the local site’s information you would use:

    Get-ZertoLocalSite

    In your case, you’d use something like:

    $VPGID = Get-ZertoVPGID -VpgName "MyVPG"
    $VPGSettingID = Convert-ZertoVPGToVPGSetting -ZertoVpgIdentifier $VPGID
    $NewVM = New-ZertoVPGSettingVM -VmIdentifier  (Get-ZertoSiteVMID -ZertoSiteIdentifier (Get-ZertoLocalSiteID) -VMName "MyVM"
    Add-ZertoVPGSettingVM -ZertoVpgSettingsIdentifier $VPGSettingID -ZertoVPGSettingVM $NewVM
    Commit-ZertoVPGSetting -ZertoVpgSettingsIdentifier $VPGSettingID

    Much simpler 🙂

    Chris

    Chris@ChristopherLewis.com

    I’ve been working on a similar project.   I’ve also checked your project out recently when I found it in another post while browsing these forums.   I didn’t notice the Add-ZertoVPGSettingVM function, that would’ve been helpful.  Not sure, but I don’t think we can choose a different datastore when we add a VM to a VPG via the REST API.

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