As part of the VMware open source program, we have to update this repository with the correct license and copyright information. We add the BSD-2 Clause License for this repository. We mark all source code provided by VMware with the Copyright notice under BSD-2 Clause license. * Update repository license to BSD 2-Clause License * Update Copyright
432 lines
14 KiB
PowerShell
432 lines
14 KiB
PowerShell
<#
|
|
Copyright 2017-2021 VMware, Inc.
|
|
SPDX-License-Identifier: Apache-2.0
|
|
#>
|
|
<#
|
|
Copyright 2021 VMware, Inc.
|
|
SPDX-License-Identifier: BSD-2-Clause
|
|
#>
|
|
|
|
# SRM Helper Methods - https://github.com/benmeadowcroft/SRM-Cmdlets
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Get the subset of protection groups matching the input criteria
|
|
|
|
.PARAMETER Name
|
|
Return protection groups matching the specified name
|
|
|
|
.PARAMETER Type
|
|
Return protection groups matching the specified protection group
|
|
type. For SRM 5.0-5.5 this is either 'san' for protection groups
|
|
consisting of a set of replicated datastores or 'vr' for vSphere
|
|
Replication based protection groups.
|
|
|
|
.PARAMETER RecoveryPlan
|
|
Return protection groups associated with a particular recovery
|
|
plan
|
|
|
|
.PARAMETER SrmServer
|
|
the SRM server to use for this operation.
|
|
#>
|
|
Function Get-ProtectionGroup {
|
|
[cmdletbinding()]
|
|
Param(
|
|
[Parameter(position=1)][string] $Name,
|
|
[string] $Type,
|
|
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan[]] $RecoveryPlan,
|
|
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
|
)
|
|
begin {
|
|
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
|
|
$pgs = @()
|
|
}
|
|
process {
|
|
if ($RecoveryPlan) {
|
|
foreach ($rp in $RecoveryPlan) {
|
|
$pgs += $RecoveryPlan.GetInfo().ProtectionGroups
|
|
}
|
|
$pgs = Select_UniqueByMoRef($pgs)
|
|
} else {
|
|
$pgs += $api.Protection.ListProtectionGroups()
|
|
}
|
|
}
|
|
end {
|
|
$pgs | ForEach-Object {
|
|
$pg = $_
|
|
$pgi = $pg.GetInfo()
|
|
$selected = (-not $Name -or ($Name -eq $pgi.Name)) -and (-not $Type -or ($Type -eq $pgi.Type))
|
|
if ($selected) {
|
|
Add-Member -InputObject $pg -MemberType NoteProperty -Name "Name" -Value $pgi.Name
|
|
$pg
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Get the subset of protected VMs matching the input criteria
|
|
|
|
.PARAMETER Name
|
|
Return protected VMs matching the specified name
|
|
|
|
.PARAMETER State
|
|
Return protected VMs matching the specified state. For protected
|
|
VMs on the protected site this is usually 'ready', for
|
|
placeholder VMs this is 'shadowing'
|
|
|
|
.PARAMETER ProtectionGroup
|
|
Return protected VMs associated with particular protection
|
|
groups
|
|
#>
|
|
Function Get-ProtectedVM {
|
|
[cmdletbinding()]
|
|
Param(
|
|
[Parameter(position=1)][string] $Name,
|
|
[VMware.VimAutomation.Srm.Views.SrmProtectionGroupProtectionState] $State,
|
|
[VMware.VimAutomation.Srm.Views.SrmProtectionGroupProtectionState] $PeerState,
|
|
[switch] $ConfiguredOnly,
|
|
[switch] $UnconfiguredOnly,
|
|
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup[]] $ProtectionGroup,
|
|
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan[]] $RecoveryPlan,
|
|
[string] $ProtectionGroupName,
|
|
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
|
)
|
|
|
|
if ($null -eq $ProtectionGroup) {
|
|
$ProtectionGroup = Get-ProtectionGroup -Name $ProtectionGroupName -RecoveryPlan $RecoveryPlan -SrmServer $SrmServer
|
|
}
|
|
$ProtectionGroup | ForEach-Object {
|
|
$pg = $_
|
|
$pg.ListProtectedVms() | ForEach-Object {
|
|
# try and update the view data for the protected VM
|
|
try {
|
|
$_.Vm.UpdateViewData()
|
|
} catch {
|
|
Write-Error $_
|
|
} finally {
|
|
$_
|
|
}
|
|
} | Where-object { -not $Name -or ($Name -eq $_.Vm.Name) } |
|
|
where-object { -not $State -or ($State -eq $_.State) } |
|
|
where-object { -not $PeerState -or ($PeerState -eq $_.PeerState) } |
|
|
where-object { ($ConfiguredOnly -and $_.NeedsConfiguration -eq $false) -or ($UnconfiguredOnly -and $_.NeedsConfiguration -eq $true) -or (-not $ConfiguredOnly -and -not $UnconfiguredOnly) }
|
|
}
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Get the unprotected VMs that are associated with a protection group
|
|
|
|
.PARAMETER ProtectionGroup
|
|
Return unprotected VMs associated with particular protection
|
|
groups. For VR protection groups this is VMs that are associated
|
|
with the PG but not configured, For ABR protection groups this is
|
|
VMs on replicated datastores associated with the group that are not
|
|
configured.
|
|
#>
|
|
Function Get-UnProtectedVM {
|
|
[cmdletbinding()]
|
|
Param(
|
|
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup[]] $ProtectionGroup,
|
|
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan[]] $RecoveryPlan,
|
|
[string] $ProtectionGroupName,
|
|
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
|
)
|
|
|
|
if ($null -eq $ProtectionGroup) {
|
|
$ProtectionGroup = Get-ProtectionGroup -Name $ProtectionGroupName -RecoveryPlan $RecoveryPlan -SrmServer $SrmServer
|
|
}
|
|
|
|
$associatedVMs = @()
|
|
$protectedVmRefs = @()
|
|
|
|
$ProtectionGroup | ForEach-Object {
|
|
$pg = $_
|
|
# For VR listAssociatedVms to get list of VMs
|
|
if ($pg.GetInfo().Type -eq 'vr') {
|
|
$associatedVMs += @($pg.ListAssociatedVms() | Get-VIObjectByVIView)
|
|
}
|
|
# TODO test this: For ABR get VMs on GetProtectedDatastore
|
|
if ($pg.GetInfo().Type -eq 'san') {
|
|
$pds = @(Get-ProtectedDatastore -ProtectionGroup $pg)
|
|
$pds | ForEach-Object {
|
|
$ds = Get-Datastore -id $_.MoRef
|
|
$associatedVMs += @(Get-VM -Datastore $ds)
|
|
}
|
|
}
|
|
|
|
# get protected VMs
|
|
$protectedVmRefs += @(Get-ProtectedVM -ProtectionGroup $pg | ForEach-Object { $_.Vm.MoRef } | Select-Object -Unique)
|
|
}
|
|
|
|
# get associated but unprotected VMs
|
|
$associatedVMs | Where-Object { $protectedVmRefs -notcontains $_.ExtensionData.MoRef }
|
|
}
|
|
|
|
|
|
#Untested as I don't have ABR setup in my lab yet
|
|
<#
|
|
.SYNOPSIS
|
|
Get the subset of protected Datastores matching the input criteria
|
|
|
|
.PARAMETER ProtectionGroup
|
|
Return protected datastores associated with particular protection
|
|
groups
|
|
#>
|
|
Function Get-ProtectedDatastore {
|
|
[cmdletbinding()]
|
|
Param(
|
|
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup[]] $ProtectionGroup,
|
|
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan[]] $RecoveryPlan,
|
|
[string] $ProtectionGroupName,
|
|
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
|
)
|
|
|
|
if (-not $ProtectionGroup) {
|
|
$ProtectionGroup = Get-ProtectionGroup -Name $ProtectionGroupName -RecoveryPlan $RecoveryPlan -SrmServer $SrmServer
|
|
}
|
|
$ProtectionGroup | ForEach-Object {
|
|
$pg = $_
|
|
if ($pg.GetInfo().Type -eq 'san') { # only supported for array based replication datastores
|
|
$pg.ListProtectedDatastores()
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#Untested as I don't have ABR setup in my lab yet
|
|
<#
|
|
.SYNOPSIS
|
|
Get the replicated datastores that aren't associated with a protection group.
|
|
#>
|
|
Function Get-ReplicatedDatastore {
|
|
[cmdletbinding()]
|
|
Param(
|
|
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
|
)
|
|
|
|
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
|
|
|
|
$api.Protection.ListUnassignedReplicatedDatastores()
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Protect a VM using SRM
|
|
|
|
.PARAMETER ProtectionGroup
|
|
The protection group that this VM will belong to
|
|
|
|
.PARAMETER Vm
|
|
The virtual machine to protect
|
|
#>
|
|
Function Protect-VM {
|
|
[cmdletbinding()]
|
|
Param(
|
|
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup] $ProtectionGroup,
|
|
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine] $Vm,
|
|
[Parameter (ValueFromPipeline=$true)][VMware.Vim.VirtualMachine] $VmView
|
|
)
|
|
|
|
$moRef = Get_MoRefFromVmObj -Vm $Vm -VmView $VmView
|
|
|
|
$pgi = $ProtectionGroup.GetInfo()
|
|
#TODO query protection status first
|
|
|
|
if ($moRef) {
|
|
if ($pgi.Type -eq 'vr') {
|
|
$ProtectionGroup.AssociateVms(@($moRef))
|
|
}
|
|
$protectionSpec = New-Object VMware.VimAutomation.Srm.Views.SrmProtectionGroupVmProtectionSpec
|
|
$protectionSpec.Vm = $moRef
|
|
$protectTask = $ProtectionGroup.ProtectVms($protectionSpec)
|
|
while(-not $protectTask.IsComplete()) { Start-Sleep -Seconds 1 }
|
|
$protectTask.GetResult()
|
|
} else {
|
|
throw "Can't protect the VM, no MoRef found."
|
|
}
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Unprotect a VM using SRM
|
|
|
|
.PARAMETER ProtectionGroup
|
|
The protection group that this VM will be removed from
|
|
|
|
.PARAMETER Vm
|
|
The virtual machine to unprotect
|
|
#>
|
|
Function Unprotect-VM {
|
|
[cmdletbinding()]
|
|
Param(
|
|
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup] $ProtectionGroup,
|
|
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine] $Vm,
|
|
[Parameter (ValueFromPipeline=$true)][VMware.Vim.VirtualMachine] $VmView,
|
|
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroupProtectedVm] $ProtectedVm
|
|
)
|
|
|
|
$moRef = Get_MoRefFromVmObj -Vm $Vm -VmView $VmView -ProtectedVm $ProtectedVm
|
|
|
|
$pgi = $ProtectionGroup.GetInfo()
|
|
$protectTask = $ProtectionGroup.UnprotectVms($moRef)
|
|
while(-not $protectTask.IsComplete()) { Start-Sleep -Seconds 1 }
|
|
if ($pgi.Type -eq 'vr') {
|
|
$ProtectionGroup.UnassociateVms(@($moRef))
|
|
}
|
|
$protectTask.GetResult()
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Get a protection group folder
|
|
|
|
.PARAMETER SrmServer
|
|
The SRM Server to query for the protection group folder
|
|
#>
|
|
Function Get-ProtectionGroupFolder {
|
|
[cmdletbinding()]
|
|
Param(
|
|
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
|
)
|
|
|
|
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
|
|
|
|
$folder = $api.Protection.GetProtectionGroupRootFolder()
|
|
|
|
return $folder
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Create a new protection group
|
|
|
|
.PARAMETER Name
|
|
The name of the protection group
|
|
|
|
.PARAMETER Description
|
|
Description of the protection group
|
|
|
|
.PARAMETER Folder
|
|
The protection group folder in which to create the new protection group
|
|
|
|
.PARAMETER ArrayReplication
|
|
Set if protection group is for replicating VMs using Array based replication
|
|
|
|
.PARAMETER vSphereReplication
|
|
Set if protection group is for replicating VMs with vSphere Replication
|
|
|
|
.PARAMETER VMs
|
|
For vSphere Replication based protection, the VMs to add to the replication
|
|
group. These should already be replicated.
|
|
|
|
.PARAMETER VMViews
|
|
For vSphere Replication based protection, the VMs to add to the replication
|
|
group. These should already be replicated.
|
|
|
|
.PARAMETER SrmServer
|
|
The SRM Server to perform the operation against
|
|
#>
|
|
Function New-ProtectionGroup {
|
|
[cmdletbinding(DefaultParameterSetName="VR", SupportsShouldProcess=$True, ConfirmImpact="Medium")]
|
|
[OutputType([VMware.VimAutomation.Srm.Views.SrmProtectionGroup])]
|
|
Param(
|
|
[Parameter (Mandatory=$true)] $Name,
|
|
$Description,
|
|
[VMware.VimAutomation.Srm.Views.SrmProtectionGroupFolder] $Folder,
|
|
[Parameter (ParameterSetName="ABR", Mandatory=$true)][switch] $ArrayReplication,
|
|
[Parameter (ValueFromPipeline=$true, ParameterSetName="ABR")][VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore[]] $Datastores,
|
|
[Parameter (ValueFromPipeline=$true, ParameterSetName="ABR")][VMware.Vim.Datastore[]] $DatastoreViews,
|
|
[Parameter (ParameterSetName="VR", Mandatory=$true)][switch] $vSphereReplication,
|
|
[Parameter (ValueFromPipeline=$true, ParameterSetName="VR")][VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine[]] $VMs,
|
|
[Parameter (ValueFromPipeline=$true, ParameterSetName="VR")][VMware.Vim.VirtualMachine[]] $VMViews,
|
|
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
|
)
|
|
|
|
$api = Get-ServerApiEndpoint $SrmServer
|
|
[VMware.VimAutomation.Srm.Views.SrmCreateProtectionGroupTask] $task = $null
|
|
|
|
#get root folder if this wasn't specified as a parameter
|
|
if(-not $Folder) {
|
|
$Folder = Get-ProtectionGroupFolder -SrmServer $SrmServer
|
|
}
|
|
|
|
if ($vSphereReplication) {
|
|
#create list of managed object references from VM and/or VM view arrays
|
|
[VMware.Vim.ManagedObjectReference[]]$moRefs = @()
|
|
foreach ($vm in $VMs) {
|
|
$moRefs += Get_MoRefFromVmObj -Vm $Vm
|
|
}
|
|
foreach ($VmView in $VMViews) {
|
|
$moRefs += Get_MoRefFromVmObj -VmView $VmView
|
|
}
|
|
|
|
if ($pscmdlet.ShouldProcess($Name, "New")) {
|
|
$task = $api.Protection.CreateHbrProtectionGroup($Folder.MoRef, $Name, $Description, $moRefs)
|
|
}
|
|
|
|
} elseif ($ArrayReplication) {
|
|
#create list of managed object references from VM and/or VM view arrays
|
|
$moRefs = @()
|
|
foreach ($ds in $Datastores) {
|
|
$moRefs += $ds.ExtensionData.MoRef
|
|
}
|
|
foreach ($DsView in $DatastoreViews) {
|
|
$moRefs += $DsView.MoRef
|
|
}
|
|
|
|
if ($pscmdlet.ShouldProcess($Name, "New")) {
|
|
$task = $api.Protection.CreateAbrProtectionGroup($Folder.MoRef, $Name, $Description, $moRefs)
|
|
}
|
|
|
|
} else {
|
|
throw "Undetermined protection group type"
|
|
}
|
|
|
|
# Complete task
|
|
while(-not $task.IsCreateProtectionGroupComplete()) { Start-Sleep -Seconds 1 }
|
|
|
|
# Retrieve the protection group, and protect associated VMs
|
|
$pg = $task.GetNewProtectionGroup()
|
|
if ($pg) {
|
|
$unProtectedVMs = Get-UnProtectedVM -ProtectionGroup $pg
|
|
$unProtectedVMs | Protect-VM -ProtectionGroup $pg
|
|
}
|
|
|
|
return $pg
|
|
}
|
|
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Delete a protection group
|
|
|
|
.PARAMETER ProtectionGroup
|
|
The protection group to remove
|
|
|
|
.PARAMETER SrmServer
|
|
The SRM Server to perform the operation against
|
|
#>
|
|
Function Remove-ProtectionGroup {
|
|
[cmdletbinding(SupportsShouldProcess=$True, ConfirmImpact="High")]
|
|
[OutputType([VMware.VimAutomation.Srm.Views.RemoveProtectionGroupTask])]
|
|
Param(
|
|
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup] $ProtectionGroup,
|
|
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
|
)
|
|
|
|
$api = Get-ServerApiEndpoint $SrmServer
|
|
[VMware.VimAutomation.Srm.Views.RemoveProtectionGroupTask] $task = $null
|
|
|
|
$pginfo = $ProtectionGroup.GetInfo()
|
|
if ($pscmdlet.ShouldProcess($pginfo.Name, "Remove")) {
|
|
$task = $api.Protection.RemoveProtectionGroup($ProtectionGroup.MoRef)
|
|
}
|
|
|
|
return $task
|
|
}
|