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.
Table of Contents
- List protection groups
- List protected VMs in one specific protection group
- Protect a VM that can’t be protected
- 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
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
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()
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.
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”
- 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.
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.