In a previous blog I wrote about Getting Started With Site Recovery Manager REST API. The post focused on using the VMware SRM Rest API Explorer. This is a great way to get started with testing the SRM API. But to do anything practical with the API you will most likely want to use it with scripting. In this post I go through the process of leveraging PowerShell to make SRM REST API calls.
The process to making SRM API calls in PowerShell is fairly standard, we use Invoke-RestMethod to make all our calls and retrieve data. What is needed to be understand is the process to authenticate which is greatly simplified when using the SRM API Explorer.
Below I explain the process to get started working with the SRM REST APIs. The environment I used consisted of two sites with vCenter 7 U3 (U2 is the minimum version required to use the REST APIs) and SRM 8.6 deployed. SRM was configured with a single site pair connection between the vCenters and two Protection Groups.
The steps to making SRM REST API calls in PowerShell is very similar to the SRM REST API Explorer. So we will attempt to break it down the same way and build a complete PowerShell script. It’s worth noting that I’m using PowerShell 7 and I’m using the -SkipCertificateCheck parameter available to Invoke-RestMethod in POSH 7.
Step 1. Authenticating to SRM and retrieve a Session ID
Below we create a simple PowerShell script that will take our username and password and pass it Base64 encoded in an Authorization Header of our REST call. The username and password needs to be separated by a colon (:). For example, ‘bob:monkey123’
$srmFQDN = "srm_fqdn"
$srmUserPass = "username:password"
[string]$stringToEncode=$srmUserPass
$encodedString=[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($stringToEncode))
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("content-type", "application/json")
$headers.Add("accept", "application/json")
$headers.Add("Authorization", "Basic " + $encodedString)
$URI = "https://$srmFQDN/api/rest/srm/v1/session"
$request = Invoke-RestMethod -Uri $URI -UserAgent $UserAgent -Headers $headers -Method POST -SkipCertificateCheck
$sessionID = $request.session_id
Write-Host $request
What is returned is a Session ID which we save to the $sessionID variable for later use.
Step 2. Use the session ID for subsequent calls
Next we need to take the Session ID and pass that in an addition Header called “x-dr-session.
$headers.Add("x-dr-session", $sessionID)
Step 3. Get Pairings
In this step we need to get our Site Pairing ID. We need to update our URI used and retrieve the Pairing ID.
$URI = "https://$srmFQDN/api/rest/srm/v1/pairings"
$request = Invoke-RestMethod -Uri $URI -UserAgent $UserAgent -Headers $headers -Method GET -SkipCertificateCheck
$sitePair = $request.list.pairing_id
We store our Site Pair ID in the $sitePair variable.
Step 4. Create a session to the remote Site Recovery Manager
This step has two parts. First we need to take our remote SRM username and password and Base64 encode it. Then we update our REST call URI to pass this to our SRM appliance. It’s important to note that we remove our original Authorization Header and replace it with a new one using the remote SRM credentials Base64 encoded.
$remoteUserPass = "[email protected]:monkey123"
[string]$stringToEncode=$remoteUserPass
$encodedString=[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($stringToEncode))
$headers.Remove("Authorization")
$headers.Add("Authorization", "Basic " + $encodedString)
### Let's try this pairing stuff
$URI = "https://$srmFQDN/api/rest/srm/v1/pairings/$sitePair/remote-session"
$request = Invoke-RestMethod -Uri $URI -UserAgent $UserAgent -Headers $headers -Method POST -SkipCertificateCheck
This request does not return any data. All that we should see if a 204 successful call status.
Step 5. Begin making your calls
We’re now finally ready to start working with the SRM REST API. Let’s run a simple GET request to obtain a Recovery Plan ID and then run a Test Plan using a POST request. The POST request is a little more complicated as we need to also submit a payload with it.
### Get Recovery Plan
$URI = "https://$srmFQDN/api/rest/srm/v1/pairings/$sitePair/recovery-management/plans"
$request = Invoke-RestMethod -Uri $URI -UserAgent $UserAgent -Headers $headers -Method GET -SkipCertificateCheck
$recoveryPlan = $request.list.id
### Test Recovery Plan
$URI = "https://$srmFQDN/api/rest/srm/v1/pairings/$sitePair/recovery-management/plans/$recoveryPlan/actions/test"
$payload = @"
{
"sync_data": false
}
"@
$request = Invoke-RestMethod -Uri $URI -UserAgent $UserAgent -Headers $headers -body $payload -Method POST -SkipCertificateCheck
$request.status
If all successful what should come back is a RUNNING status response of our Test Plan.
Putting it all together
Let’s finally put it all together to see what this might look like as one complete script.
$srmFQDN = "srm_fqdn"
$srmUserPass = "username:password"
[string]$stringToEncode=$srmUserPass
$encodedString=[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($stringToEncode))
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("content-type", "application/json")
$headers.Add("accept", "application/json")
$headers.Add("Authorization", "Basic " + $encodedString)
$URI = "https://$srmFQDN/api/rest/srm/v1/session"
$request = Invoke-RestMethod -Uri $URI -UserAgent $UserAgent -Headers $headers -Method POST -SkipCertificateCheck
$sessionID = $request.session_id
Write-Host $request
$headers.Add("x-dr-session", $sessionID)
### Just find any site pair to use
$URI = "https://$srmFQDN/api/rest/srm/v1/pairings"
$request = Invoke-RestMethod -Uri $URI -UserAgent $UserAgent -Headers $headers -Method GET -SkipCertificateCheck
$sitePair = $request.list.pairing_id
### Create remote session
$remoteUserPass = "[email protected]:monkey123"
[string]$stringToEncode=$remoteUserPass
$encodedString=[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($stringToEncode))
$headers.Remove("Authorization")
$headers.Add("Authorization", "Basic " + $encodedString)
### Let's try this pairing stuff
$URI = "https://$srmFQDN/api/rest/srm/v1/pairings/$sitePair/remote-session"
$request = Invoke-RestMethod -Uri $URI -UserAgent $UserAgent -Headers $headers -Method POST -SkipCertificateCheck
### Get Recovery Plan
$URI = "https://$srmFQDN/api/rest/srm/v1/pairings/$sitePair/recovery-management/plans"
$request = Invoke-RestMethod -Uri $URI -UserAgent $UserAgent -Headers $headers -Method GET -SkipCertificateCheck
$recoveryPlan = $request.list.id
### Test Recovery Plan
$URI = "https://$srmFQDN/api/rest/srm/v1/pairings/$sitePair/recovery-management/plans/$recoveryPlan/actions/test"
$payload = @"
{
"sync_data": false
}
"@
$request = Invoke-RestMethod -Uri $URI -UserAgent $UserAgent -Headers $headers -body $payload -Method POST -SkipCertificateCheck
$request.status
And that’s basically the foundation to start leveraging the Site Recovery Manager REST API with PowerShell. If you haven’t done so already, certainly go over my previous post Getting Started With Site Recovery Manager REST API. It provides good information on identifying all the different GET and POST requests that can be done against the SRM API.
As I also mentioned in my previous post. This new REST API is a great welcomed addition to the product. It opens the door to some interesting new opportunities to automate and orchestrate SRM.
Great post! Was wondering if you could point me in a direction for a particular set of actions using Powershell/REST. To be brief, when we do a test failover, we have a subset of servers that do not replicate 2-3 drives. Once the VMs are failed over, we add the drives and put them on specific iSCSI controllers by hand, log in, online and format the drives. Would love to know if this is even possible, aka, via SRM. TIA!
Thank you! I would think this is possible with vCenter REST APIs, PowerShell and PowerCLI, rather than SRM API. I don’t have an examples on hand. But you should be able to programmatically add in drives with vCenter. You would then need to investigate how to format the drives in the OS. Possibly using PowerShell for Windows or Bash for Linux. There will certainly be lots of example how to do this on the web.
Thank you for posting this wonderful script! I haven’t tried this script but some doubts came into my mind while I was going through the script. Please bear with me if I ask stupid questions. I have listed my questions below.
1) Invoke-RestMethod uses the variable $UserAgent, but this variable is not assigned anywhere in the script. What should we assign to this variable?
2) Are the username and password used in the final script line number 4 and 32 the same?
I usually pass a UserAgent in my requests so I can more easily filter where requests are coming from. You can put whatever you want in here. I usually put “PowerShell” so I know it’s a PowerShell API request.
The passwords are whatever you use for your local and remote vCenters. If they are different you will have different passwords.
Thank you so much, Mark, for your response!
Hello Mark,
Great article!
I have a question about plain coding the username/password in the Powershell script as follows:
$srmUserPass = “username:password”
For security purposes, isn’t there a way around it?
Yep there is. Check out PowerShell SecretManagement.
https://learn.microsoft.com/en-us/powershell/utility-modules/secretmanagement/overview?view=ps-modules