- This topic has 8 replies, 2 voices, and was last updated May 8, 2020 by
Alex S.
Create Simple VPG using PowerShell and API
-
Dave SApril 3, 2019 08:02:15 PM
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..
Dave SApril 4, 2019 07:53:12 PMI 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.
Tobias BApril 24, 2019 06:41:24 AMHi 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
Alex SOctober 14, 2019 03:03:33 PMHey, 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?
Alex SOctober 14, 2019 03:33:45 PMIf 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 TrustAllCertsPolicyfunction 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