RP4VM consistency group creation API

This post will give you information about step to RP4VM consistency group creation API. I created on PowerCLI script to create consistency group with in build Power Shell  command Invoke-Restmethod.

This script assumes you have two different vCenters. One for Production and one for Disaster recovery. Feel free to customize it based on your requirement.

  1. Source Site is in different VC and
  2. Target site is in different VC.

Please refer below script.

Note – You need to create RP4VM Cluster on both sides, need to join them before running this script. I wrote OVA Deployment script and can be found here RP4VM OVA Deployment via PowerCLI

$global:DateTime = $((Get-Date).ToString('yyyy-MM-dd-hh-mm')) 
$logpath = "$HOME\Desktop\CGCreation-log-$global:DateTime.txt"
Start-Transcript -path $logpath -append 


& 'C:\Program Files (x86)\VMware\Infrastructure\PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1'

Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -DefaultVIServerMode Multiple
$cred = Get-Credential
$RPCred = Get-Credential
Connect-VIServer Sourcevcenter1, Targetvcenter2 -Credential $cred

##### Collect vCenter Instance UID ################

$vc = $global:DefaultVIServers | sort Name

$sourcevc = $vc[0].InstanceUuid
$targetvc = $vc[1].InstanceUuid

###############  Change setting to ignore TLS/SSL Error ################################
if (-not ([System.Management.Automation.PSTypeName]'ServerCertificateValidationCallback').Type)
{
$certCallback = @"
    using System;
    using System.Net;
    using System.Net.Security;
    using System.Security.Cryptography.X509Certificates;
    public class ServerCertificateValidationCallback
    {
        public static void Ignore()
        {
            if(ServicePointManager.ServerCertificateValidationCallback ==null)
            {
                ServicePointManager.ServerCertificateValidationCallback += 
                    delegate
                    (
                        Object obj, 
                        X509Certificate certificate, 
                        X509Chain chain, 
                        SslPolicyErrors errors
                    )
                    {
                        return true;
                    };
            }
        }
    }
"@
    Add-Type $certCallback
 }
[ServerCertificateValidationCallback]::Ignore()

$dc = 'dc name'

foreach ($storenumber in $dc){

######### Get source vRPACluster IP ######################################

$ucscluster = Get-Cluster $storenumber -Server $vc[0] | Get-VM | where {$_.Name -like "*vRPA1"} |Select Name, @{N="IPAddress";E={@($_.guest.IPAddress[0])}}

$split = $ucscluster.IPAddress

$IPbyte = $split.Split(".")
$newucsip = ($IPByte[0]+"."+$IPByte[1]+"."+$IPByte[2])

$startip = "102"

$clusipaddress = "$newucsip.$($startip+$_)"


############# Get vRPA Cluster Details ###########################


$uri = "https://$clusipaddress/fapi/rest/5_2/settings"

$jsonnew = Invoke-RestMethod -Uri $uri -Method Get -credential $RPCred -ContentType application/json

############## RPA Cluster Name ####################

$ucsRPAClustername = $jsonnew.systemSettings.clustersSettings.clusterName[1]
$targetvRPAClustername = $jsonnew.systemSettings.clustersSettings.clusterName[0]

############### source and Target RPA Cluster ID  ################

$ucsRPAClusterID = $jsonnew.systemSettings.clustersSettings.clusterUID[1].id
$targetRPAClusterID = $jsonnew.systemSettings.clustersSettings.ClusterUID[0].id


############### Get Array ID ########################

$sourcearrayUID = $jsonnew.systemSettings.clustersSettings.ampsSettings.managedArrays[1].arrayUID.id

$targetarrayUID = $jsonnew.systemSettings.clustersSettings.ampsSettings.managedArrays[0].arrayUID.id


##################Storage ResourcePoolID ################

$storageDSUID = $jsonnew.systemSettings.clustersSettings.ampsSettings.managedArrays[1].resourcePools.resourcePoolUID | sort StorageResourcePoolId

$sourceFirstDSID = $storageDSUID.StorageResourcePoolID[0]
$sourceSecondDSUID  = $storageDSUID.StorageResourcePoolID[1]

$DSUid = @()

 $DSUid += $sourceFirstDSID 
$DSUid += $sourceSecondDSUID  

$DS = 0

$targetDSUID = $jsonnew.systemSettings.clustersSettings.ampsSettings.managedArrays[0].resourcePools.resourcePoolUID.storageResourcePoolId

#$storage = (Get-Cluster $storenumber -Server $vc[1] | Get-VMHost | select -First 1 | Get-Datastore | where {$_.Name -like "VxRail*"}).ExtensionData.info.containerid


################### Pool ID ###############

$UCSPoolID = $jsonnew.systemSettings.clustersSettings.ampsSettings.managedArrays[1].resourcePools.resourcePoolUID | sort StorageResourcePoolId

$UCSPoolIDFirst = $UCSPoolID.uuid[0]
$UCSPoolIDSecond = $UCSPoolID.uuid[1]

$targetPoolID = $jsonnew.systemSettings.clustersSettings.ampsSettings.managedArrays[0].resourcePools.resourcePoolUID.uuid[0]
 

 ############### Target ESXi UID #####################

 $RestURL = Invoke-RestMethod https://$clusipaddress/fapi/rest/5_2/clusters/$targetRPAClusterID/virtual_infra_configuration -Method Get -credential $RPCred

 $targetESXiClusterID = $RestURL.virtualCentersConfiguration.datacentersConfiguration.esxClustersConfiguration.esxsConfiguration | sort Name

 $firstESX = $targetESXiClusterID.esxUID[0].uuid

 #$box = (Get-Cluster '04' -Server $vc[1] | Get-VMHost | select -First 1).extensiondata.hardware.systeminfo.uuid
 $secondESX = $targetESXiClusterID.esxUID[1].uuid
 $thirdESX = $targetESXiClusterID.esxUID[2].uuid
 $sample = @()

 $sample += $firstESX 
  $sample  += $secondESX
  $sample  += $thirdESX

 $targetDatacenterUID = $RestURL.virtualCentersConfiguration.datacentersConfiguration.datacenterUID.uuid

 $sourcecluster = Get-Cluster $storenumber -Server $vc[0]
 $i = 0
 foreach ($vm in $sourcecluster | Get-VM | where {$_.powerstate -ne "poweredoff" -and $_.Name -notlike "*Vs*" -and $_.Name -notlike "Prod*"-and  $_.Name -notlike "OST-$($sourcecluster)-W16C"} | sort name){

 if ($vm.Name -like "*Windows2016*"){

 $cgname = $sourcecluster.Name + "_" + $vm.Name + "_CG" }

 else{
 
 $cgname = $vm.Name + "_CG"}

 #$datastore  = $DSUid[$DS]

 ########## Collect VM UID ######################
 $vmuid = ($vm).extensiondata.config.instanceUuid

 $vmuid

 #### Calculate 30% of Total VM size ##########################

 $hdd = $vm | Get-HardDisk | Measure-Object -Sum CapacityGB
 $sourceHDD = [math]::Round($hdd.Sum * (20/100))

 $targetHDD = [math]::Round($hdd.Sum * (30/100))
 
 ##### Journal size in bytes #############

 $sourcejournalsize = [math]::Round($sourceHDD*1024*1024*1024)

 $targetjournalsize = [math]::Round($targetHDD*1024*1024*1024)

 $box = $sample[$i]
 $datastoreid = $DSUid[$DS]

  $json =  @"
  {
     "cgName" : "$cgname",
     "productionCopy" : {
          "clusterUID":{
               "id" : $ucsRPAClusterID
          },
          "copyUID": 0
     },
     "vmReplicationSets":
     [{
               "replicationSetVms":
               [{
                         "copyUID": {
                              "clusterUID": {
                                   "id": $targetRPAClusterID
                              },
                              "copyUID": 1
                         },
                         "vmParam": {
                              "JsonSubType": "CreateVMParam",
                              "targetVirtualCenterUID": {
                                   "uuid": "$targetvc"
                              },
                              "targetResourcePlacementParam": {
                                   "JsonSubType": "CreateTargetVMManualResourcePlacementParam",
                                   "targetEsxUID": {
                                        "uuid": "$box"
                                   }
                              },
                              "targetDatastoreUID": {
                                   "uuid": "$targetDSUID"
                              }
                         }
                    }, {
                         "copyUID": {
                              "clusterUID": {
                                   "id": $ucsRPAClusterID
                              },
                              "copyUID": 0
                         },
                         "vmParam": {
                              "JsonSubType": "ExistingVMParam",
                              "vmUID": {
                                   "uuid": "$vmuid",
                                   "virtualCenterUID": {
                                        "uuid": "$sourcevc"
                                   }
                              }
                         }
                    }
               ],
               "virtualHardwareReplicationPolicy": {
                    "provisionPolicy": "SAME_AS_SOURCE",
                    "hwChangesPolicy": "REPLICATE_HW_CHANGES"
               },
               "virtualDisksReplicationPolicy": {
                    "autoReplicateNewVirtualDisks": "true"
                   
               }
          }
     ],
     "links":
     [{
               "linkPolicy": {
                    "JsonSubType": "ConsistencyGroupLinkPolicy",
                    "protectionPolicy": {
                         "protectionType": "ASYNCHRONOUS",
                         "syncReplicationLatencyThresholds": {
                              "resumeSyncReplicationBelow": {
                                  "value": 3000,
                                   "type": "MICROSECONDS"
                              },
                              "startAsyncReplicationAbove": {
                                   "value": 5000,
                                   "type": "MICROSECONDS"
                              },
                              "thresholdEnabled": "true"
                         },
                         "syncReplicationThroughputThresholds": {
                              "resumeSyncReplicationBelow": {
                                   "value": 35000,
                                   "type": "KB"
                              },
                              "startAsyncReplicationAbove": {
                                   "value": 45000,
                                   "type": "KB"
                              },
                              "thresholdEnabled": "false"
                         },
                         "rpoPolicy": {
                              "allowRegulation": "false",
                              "maximumAllowedLag": {
                                   "value": 25,
                                   "type": "SECONDS"
                              },
                              "minimizationType": "IRRELEVANT"
                         },
                         "replicatingOverWAN": "true",
                         "compression": "LOW",
                         "bandwidthLimit": "0.0",
                         "measureLagToTargetRPA": "true",
                         "deduplication": "true",
                         "weight": 1
                    },
                    "advancedPolicy": {
                         "snapshotGranularity": "DYNAMIC",
                         "performLongInitialization": "true"
                    },
                    "snapshotShippingPolicy": null
               },
               "linkUID": {
                    "groupUID": {
                         "id": 0
                    },
                    "firstCopy": {
                         "clusterUID": {
                              "id": $ucsRPAClusterID
                         },
                         "copyUID": 0
                    },
                    "secondCopy": {
                         "clusterUID": {
                              "id": $targetRPAClusterID
                         },
                         "copyUID": 1
                    }
               }
          }
],
       "copies":
     [{
               "copyUID": {
                    "clusterUID": {
                         "id": $targetRPAClusterID
                    },
                    "copyUID": 1
               },
               "copyName": "copy1",
               "JsonSubType": "ConsistencyGroupCopyParam",
               "volumeCreationParams": {
                    "volumeParams":
                    [{
                              "JsonSubType": "VolumeCreationParams",
                              "volumeSize": {
                                   "sizeInBytes": $targetjournalsize
                              },
                              "arrayUid": {
                                   "id": $targetarrayUID,
                                   "clusterUID": {
                                        "id": $targetRPAClusterID
                                   }
                              },
                              "poolUid": {
                                   "uuid": $targetPoolID,
                                   "storageResourcePoolId": "$targetDSUID",
                                   "arrayUid": {
                                        "id": $targetarrayUID,
                                        "clusterUID": {
                                                      "id": $targetRPAClusterID
                                        }
                                   }
                              },
                              "tieringPolicy": null,
                              "resourcePoolType": "VC_DATASTORE"
                         }
                    ]
               }
          }, {
               "copyUID": {
                    "clusterUID": {
                         "id": $ucsRPAClusterID
                    },
                    "copyUID": 0
               },
               "copyName": "$vm",
               "JsonSubType": "ConsistencyGroupCopyParam",
               "volumeCreationParams": {
                    "volumeParams":
                    [{
                              "JsonSubType": "VolumeCreationParams",
                              "volumeSize": {
                                   "sizeInBytes": $sourcejournalsize
                              },
                              "arrayUid": {
                                   "id": $sourcearrayUID,
                                   "clusterUID": {
                                        "id": $ucsRPAClusterID
                                   }
                              },
                              "poolUid": {
                                   "uuid": $UCSPoolIDFirst,
                                   "storageResourcePoolId": "$datastoreid",
                                   "arrayUid": {
                                        "id": $sourcearrayUID,
                                       "clusterUID": {
                                                                        "id": $ucsRPAClusterID
                                        }
                                   }
                              },
                              "tieringPolicy": null,
                              "resourcePoolType": "VC_DATASTORE"
                         }
                    ]
               }
          }
    ], 
     "startTransfer" : false,
     "JsonSubType":  "ReplicateVmsParam"
     }
"@
     
     if($i -eq 2){
           $i = 0
		  }
     else{
     $i ++
	 }

    if($DS -eq 1){
    $DS = 0
	}
   else {
   $DS ++
   
   }

        #$body = $json | ConvertTo-Json;

        #$test = $body | ConvertTo-Json;
 
 $REST= "https://$clusipaddress/fapi/rest/5_2/groups/virtual_machines/replicate"

try{

$response = Invoke-RestMethod -Method Post -Uri $REST -Body $json -ContentType application/json -credential $RPCred -OutFile $HOME\Desktop\test_protection.txt



}
Catch [System.Net.WebException] { $exception = $_.Exception
 $respstream = $exception.Response.GetResponseStream()
$sr = new-object System.IO.StreamReader $respstream
$ErrorResult = $sr.ReadToEnd()
 write-host $ErrorResult 
}


catch {
    # Dig into the exception to get the Response details.
    # Note that value__ is not a typo.
    Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__ 
    Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
}

sleep -Seconds 180
 }
 
 ##############  Start CG replication #########################

 $state = "https://${clusipaddress}/fapi/rest/5_2/groups/transfer_state"

$json = Invoke-RestMethod  -Uri $state  -Method Get -ContentType "application/json" -credential $RPCred | ConvertTo-Json

$object = ConvertFrom-Json -InputObject $json

$object.innerSet | select -Property sourceClusterName, groupName, transferState  > $HOME\desktop\$clus.txt
$CG = $object.innerSet | sort Name| select -First 5
foreach($_ in $CG){ if($_.transferState -eq "PAUSED" ){

$groupID = $_.consistencyGroupUID.trim("@{id=}")

$data = @{

id = "$groupID"
};

$body = $data | ConvertTo-Json;

$transfer = "https://${clusipaddress}/fapi/rest/5_2/groups/$groupID/start_transfer"

Invoke-RestMethod -Uri $transfer -Credential $RPCluster -Method PUT -ContentType "application/json" -Body $body -credential $RPCred
 
 }
 }
 }

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

Stop-Transcript

Copy-Item $HOME\Desktop\CGCreation-log-$global:DateTime.txt "Log collection location path" -Confirm:$false -Force

Disconnect-VIServer * -Confirm:$false -Force

 

I have added replication step at the end of script.

Please do due diligence before running this RP4VM consistency group creation API script in the production environment.  I am working on it to improve it, if you have any suggestions feel free to drop me a message or send me an email.

2 comments

  1. please can you give me API to connect VRPA cluster in Rp4VM.

    cluster is in detached state, need API to connect it back.

    Thanks,

    1. Sorry for the late reply. As far as i know APIs are available only for Cluster not individual RP.
      you can try https://:7225/fapi/rest/5_2

      Replace 5_2 with your RP version

Comments are closed.