In the previous post, I gave a walkthrough on how the Site Recovery Manager (SRM) module works and we know that everything starts from $DefaultSrmServers.extensiondata. It’s time to have a look at getting some data gathered in Powershell and do some exploration in the module.

Because this article is supposed to be educational, we are not going to cover everything you can do with the module, this is the role of the API developer’s guide combined with your own digging.

Protect Your Data with BDRSuite

Cost-Effective Backup Solution for VMs, Servers, Endpoints, Cloud VMs & SaaS applications. Supports On-Premise, Remote, Hybrid and Cloud Backup, including Disaster Recovery, Ransomware Defense & more!

Table of Contents

  1. List protection groups
  2. List protected VMs in one specific protection group
  3. Protect a VM that can’t be protected
  4. Conclusion

Here we are going to go through the process of figuring out how to get useful information so you can apply the same method for any other use case. To serve as an example, we will use the most obvious case of listing protected VMs and protecting a VM.

At the end of the article, I will provide a bonus function that may help you save time with the configuration of unprotected VMs.

List protection groups

API developer’s guide page 42 & 48

Download Banner

The goal here is to get a list of all the protection groups. If you look in part 2 at the output of get-Member on $DefaultSrmServers.extensiondata we notice a property called Protection.

  • Let’s look into it by running Get-Member on it (Again I removed definition to make it readable)

PS> $DefaultSrmServers.extensiondata.Protection | Get-Member

Name MemberType
CreateAbrProtectionGroup Method
CreateHbrProtectionGroup Method
Equals Method
GetHashCode Method
GetType Method
ListInventoryMappings Method
ListProtectedDatastores Method
ListProtectedVms Method
ListProtectionGroups Method
ListReplicatedDatastores Method
ListUnassignedReplicatedDatastores Method
ListUnassignedReplicatedVms Method
RemoveProtectionGroup Method
ToString Method
MoRef Property
  • We find in the above that there is a method called ListProtectionGroups() which sounds a lot like what we are after

If you look at the definition field you will see that no argument is needed (empty parenthesis) and that the output will be of type

[VMware.VimAutomation.Srm.Views.SrmProtectionGroup].

System.Collections.Generic.List[VMware.VimAutomation.Srm.Views.SrmProtectionGroup] ListProtectionGroups()

  • Let’s verify this by calling the method

PS> $DefaultSrmServers.extensiondata.Protection.ListProtectionGroups()

MoRef

SrmProtectionGroup-srm-vm-protection-group-6400388
SrmProtectionGroup-srm-vm-protection-group-6399416
SrmProtectionGroup-srm-vm-protection-group-6837358

It gives us the list of IDs of all the protection groups configured in Site Recovery Manager(SRM). Granted these are not really useful from a human perspective. To get the names of the protection groups you need to call the GetInfo() method on the listed protection groups.

PS> $DefaultSrmServers.extensiondata.Protection.ListProtectionGroups().Getinfo()

Name Description Type
PG-SAP san
PG-EMAIL san
PG-WEB san

You can see that the output contains the Name property which you can leverage to filter out later on.

List protected VMs in one specific protection group

API developer’s guide page 44

Now given what we just demonstrated about the names, you might already know what is going to happen in order to get more information about one protection group. First, we need to isolate the protection group we are interested in.

  • We are using the output of GetInfo().name in a Where clause to filter the protection group by its name. I am also storing the output in a variable so it will be a lot easier to use

$PGSAP = $DefaultSrmServers.extensiondata.Protection.ListProtectionGroups() | Where {$_.GetInfo().name -eq “PG-SAP”}

Look into the variable (again with Get-Member) to find the method that will help us list the protected VMs. The purpose of this how-to is to be educational material so we are going the long way, though you could very well find this information in the API developer’s guide.

PS> $PGSAP | Get-Member

Name MemberType
AssociateVms Method
CheckConfigured Method
Equals Method
GetHashCode Method
GetInfo Method
GetParentFolder Method
GetPeer Method
GetProtectionState Method
GetType Method
ListAssociatedVms Method
ListProtectedDatastores Method
ListProtectedVms Method
ListRecoveryPlans Method
ProtectionGroupGetOperationalLocation Method
ProtectVms Method
QueryVmProtection Method
ToString Method
UnassociateVms Method
UnprotectVms Method
MoRef Property
  • We call the ListProtectedVMs() method. (Screenshot below shows all the fields)

$PGSAP.ListProtectedVms()

Site-Recovery-Manager

Again the output contains IDs and not VI objects.

In order to find usable information about the virtual machines, we need to look into the VM property. This part is a little bit tricky as the VM property does not contain the name of the VM, it is the equivalent of a “Get-View object” stripped down to the bare minimum.

To get the name, we need to use the MoRef property located inside the VM property to find the VM with Get-View.

  • To improve the execution speed, I will only retrieve the name property in Get-View. (Note the [0] which means only the first protected VM is processed in the list)

PS> Get-View $PGSAP.ListProtectedVms()[0].Vm.moref -Property Name

Capability :
Config :
Layout :
LayoutEx :
Storage :
EnvironmentBrowser :
ResourcePool :
ParentVApp :
ResourceConfig :
Runtime :
Guest :
Summary :
Datastore :
Network :
Snapshot :
RootSnapshot :
GuestHeartbeatStatus : gray
LinkedView :
Parent :
CustomValue :
OverallStatus : gray
ConfigStatus : gray
ConfigIssue :
EffectiveRole :
Permission :
Name : SRV-SAP-01
DisabledMethod :
RecentTask :
DeclaredAlarmState :
TriggeredAlarmState :
AlarmActionsEnabled : False
Tag :
Value :
AvailableField :
MoRef : VirtualMachine-vm-9970
Client : VMware.Vim.VimClientImpl

This was merely an example, once you grasp the idea you can start working with the VM view object in a bit more depth and use it for various purpose.
As you can see, it can get confusing so it will take some time to get your head around this module.

Protect a VM that can’t be protected

API developer’s guide page 52

I have to admit it, the title of this section is a bit confusing. How could you protect a VM that can’t be protected… a “VM that can be protected” is a VM that has been moved to a protected data store or a VM which had its protection removed For example. As opposed to VMs that have a replication issue that prevents the automatic protection to complete or a VM in error because it was deleted or moved to another datastore for instance.

The method

If you look at the output of the Get-Member property we ran on $PGSAP in part 2, you will find a method called ProtectVMs(). Now if we look at the definition property of this method (in Get-Member) here is what it says:

VMware.VimAutomation.Srm.Views.SrmProtectionTask ProtectVms(VMware.VimAutomation.Srm.Views.SrmProtectionGroupVmProtectionSpec[] vms)

A few interesting things to note here, let’s take them one by one to really understand it:

VMware.VimAutomation.Srm.Views.SrmProtectionTask

The output of executing the method will be an object of type SrmProtectionTask. This object is interesting because it contains methods and properties about the status of the tasks, which could be interesting if we want to wait for the task to finish.

VMware.VimAutomation.Srm.Views.SrmProtectionGroupVmProtectionSpec

The argument that is passed to this method must be an object of this type. You can’t just run ProtectVms(“VirtualMachine-vm-16227”), it will not work. We will see a bit further on how to get the right object for this method.

[ ]

The two square brackets mean that the method can take multiple arguments, meaning it is possible to protect several VMs with only one call. So let’s get to it.

Using the method

For this example, I am using the VM named Xav-SRM-1 which I manually unprotected.

Site-Recovery-Manager

As you may have noticed by now, everything is done using IDs and not names in the SRM module. Meaning you need to specify the ID of the VM in order to protect it. You would typically automate it in a script or function but here we are doing it manually to demonstrate.

Find the ID of the VM to protect.

PS> Get-VM xav-srm-1 | Select id

Id
VirtualMachine-vm-16227

  • Create the object that will be passed as an argument to the method (see the previous chapter). Then we look at the object to figure out what to do with it. We place this object in a $VMProtect variable

We see that this object type only contains the VM property which is self explanatory.

PS> $VMProtect = New-Object -TypeName VMware.VimAutomation.Srm.Views.SrmProtectionGroupVmProtectionSpec

PS> $VMProtect | Get-Member

TypeName: VMware.VimAutomation.Srm.Views.SrmProtectionGroupVmProtectionSpec

Name MemberType Definition
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
GetInfo Method type GetType()
Vm Property VMware.Vim.ManagedObjectReference Vm {get;set;}
  • Populate the name of the VM in the $VMProtect variable

PS> $VMProtect.Vm = “VirtualMachine-vm-16227”

  • Call the ProtectVMs() method using the newly created object as an argument

I am storing the output of this command inside a variable to show a few things about the task object.

PS> $VMProtect.Vm = “VirtualMachine-vm-16227”

Site-Recovery-Manager

  • Explore the task object generated by the ProtectVMs() method

API developer’s guide page 55

This object is interesting because it gives some information about the VM protection task such as the result of the task, is it complete… When running a protected task, the task is started and the prompt automatically comes back in Powershell, the IsComplete() method can be useful to simulate a synchronous task where you wait for its execution to complete.

PS> $ProtectTask | Get-Member

TypeName: VMware.VimAutomation.Srm.Views.SrmProtectionTask

Name MemberType Definition
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetProtectionStatus Method System.Collections.Generic.List[VMware.V…
GetResult Method System.Collections.Generic.List[VMware.V…
GetTasks Method System.Collections.Generic.List[VMware.V…
GetType Method type GetType()
IsComplete Method bool IsComplete()
ToString Method string ToString()
MoRef Property VMware.Vim.ManagedObjectReference MoRef…
  • Check if the task completed by using the IsComplete() method on the $ProtectTask variable that contains the task. The output will be either True or False

PS> $ProtectTask.IsComplete()
True

Bonus function

In the previous chapter, I showed you step by step how to manually run a protection task on a virtual machine. The function provided below do that automatically based on the protection group in an Array-Based Replication environment. You can specify one, multiple or all the protection groups with the $ProtectionGroups variable. You can also set the $WaitTask switch to wait for the task completion (see the previous chapter).

The syntax to use is very easy. Note that before using it, you need to be connected to the SRM pair and to the protected vCenter server.

  • Protect all VMs that can be protected “asynchronously”

Protect-SRMUnconfiguredVM

  • Protect all VMs that can be configured in all protection which name matches SAP and wait for task completion

Protect-SRMUnconfiguredVM -ProtectionGroups *sap* -WaitTask

To use this function, paste it in Powershell or place it in a module you can access.

Function Protect-SRMUnconfiguredVM {

param(
[VMware.VimAutomation.Srm.Interop.V1.SrmServerInterop[]] $SRMServer = $DefaultSRMServers,

[string] $ProtectionGroups,

[switch] $WaitTask
)

# List all protection groups
$protectiongroup = $SRMServer.extensiondata.Protection.ListProtectionGroups()

# Filter protection groups based on parameter – If parameter is specified – If not, all protection groups are used.
if ($ProtectionGroups) {$protectiongroup = $protectiongroup | where { $_.GetInfo().name -like $ProtectionGroups } }

# Enters loop in each protection group
foreach ($pg in $protectiongroup) {

# List all protected datastores in this protection group
$PGDSVM = get-view $pg.ListProtectedDatastores().moref -Property vm | select -ExpandProperty vm

if ($PGDSVM) {

# List all VMs that have the status “CanBeProtected”
$VmToProtectID = $pg.QueryVmProtection(($PGDSVM|ForEach-Object{[string]$_})) | where Status -eq “CanBeProtected” | select -ExpandProperty vm | select -ExpandProperty moref

if ($VmToProtectID) {

# Create the object with the VM ID
$VmToProtect = $VmToProtectID | ForEach-Object {
$SrmObj = New-Object -TypeName VMware.VimAutomation.Srm.Views.SrmProtectionGroupVmProtectionSpec
$SrmObj.Vm = [string]$_
$SrmObj
}

# Run the VM Protection task
$Task = $pg.protectVMs($VmToProtect)

# Wait for the task to complete if the switch was set to true
if ($WaitTask) {
while (!$Task.IsComplete()) {sleep -Milliseconds 100}
}

$Task

}

}

}

}

Conclusion

Here we are at the end of the 3rd part and the last part of the SRM module in PowerCLI. I am not writing more content about it partly because the function provided above also serves as self-learning material to get you started in working in an array-based replication environment. You will quickly realize that the script is, in fact, a lot simpler than it looks and hopefully it will help create a lot more of them.

Related Posts:
SRM in PowerCLI Part 2 – How it works
SRM in PowerCLI: Part 1 – Introduction

Follow our Twitter and Facebook feeds for new releases, updates, insightful posts and more.

Rate this post