Merge remote-tracking branch 'vmware/master'
This commit is contained in:
1
Modules/SRM/.gitattributes
vendored
Normal file
1
Modules/SRM/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.psd1 diff
|
||||
1
Modules/SRM/.gitignore
vendored
Normal file
1
Modules/SRM/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.zip
|
||||
167
Modules/SRM/Examples/ReportConfiguration.ps1
Normal file
167
Modules/SRM/Examples/ReportConfiguration.ps1
Normal file
@@ -0,0 +1,167 @@
|
||||
# Depends on SRM Helper Methods - https://github.com/benmeadowcroft/SRM-Cmdlets
|
||||
# It is assumed that the connection to VC and SRM Server have already been made
|
||||
|
||||
Function Get-SrmConfigReportSite {
|
||||
Param(
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
Get-SrmServer $SrmServer |
|
||||
Format-Table -Wrap -AutoSize @{Label="SRM Site Name"; Expression={$_.ExtensionData.GetSiteName()} },
|
||||
@{Label="SRM Host"; Expression={$_.Name} },
|
||||
@{Label="SRM Port"; Expression={$_.Port} },
|
||||
@{Label="Version"; Expression={$_.Version} },
|
||||
@{Label="Build"; Expression={$_.Build} },
|
||||
@{Label="SRM Peer Site Name"; Expression={$_.ExtensionData.GetPairedSite().Name} }
|
||||
}
|
||||
|
||||
Function Get-SrmConfigReportPlan {
|
||||
Param(
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
Get-SrmRecoveryPlan -SrmServer $SrmServer | %{
|
||||
$rp = $_
|
||||
$rpinfo = $rp.GetInfo()
|
||||
$peerState = $rp.GetPeer().State
|
||||
$pgs = Get-SrmProtectionGroup -RecoveryPlan $rp
|
||||
$pgnames = $pgs | %{ $_.GetInfo().Name }
|
||||
|
||||
$output = "" | select plan, state, peerState, groups
|
||||
$output.plan = $rpinfo.Name
|
||||
$output.state = $rpinfo.State
|
||||
$output.peerState = $peerState
|
||||
if ($pgnames) {
|
||||
$output.groups = [string]::Join(",`r`n", $pgnames)
|
||||
} else {
|
||||
$output.groups = "NONE"
|
||||
}
|
||||
|
||||
$output
|
||||
} | Format-Table -Wrap -AutoSize @{Label="Recovery Plan Name"; Expression={$_.plan} },
|
||||
@{Label="Recovery State"; Expression={$_.state} },
|
||||
@{Label="Peer Recovery State"; Expression={$_.peerState} },
|
||||
@{Label="Protection Groups"; Expression={$_.groups}}
|
||||
}
|
||||
|
||||
|
||||
Function Get-SrmConfigReportProtectionGroup {
|
||||
Param(
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
Get-SrmProtectionGroup -SrmServer $SrmServer | %{
|
||||
$pg = $_
|
||||
$pginfo = $pg.GetInfo()
|
||||
$pgstate = $pg.GetProtectionState()
|
||||
$peerState = $pg.GetPeer().State
|
||||
$rps = Get-SrmRecoveryPlan -ProtectionGroup $pg
|
||||
$rpnames = $rps | %{ $_.GetInfo().Name }
|
||||
|
||||
$output = "" | select name, type, state, peerState, plans
|
||||
$output.name = $pginfo.Name
|
||||
$output.type = $pginfo.Type
|
||||
$output.state = $pgstate
|
||||
$output.peerState = $peerState
|
||||
if ($rpnames) {
|
||||
$output.plans = [string]::Join(",`r`n", $rpnames)
|
||||
} else {
|
||||
$output.plans = "NONE"
|
||||
}
|
||||
|
||||
$output
|
||||
} | Format-Table -Wrap -AutoSize @{Label="Protection Group Name"; Expression={$_.name} },
|
||||
@{Label="Type"; Expression={$_.type} },
|
||||
@{Label="Protection State"; Expression={$_.state} },
|
||||
@{Label="Peer Protection State"; Expression={$_.peerState} },
|
||||
@{Label="Recovery Plans"; Expression={$_.plans} }
|
||||
}
|
||||
|
||||
|
||||
Function Get-SrmConfigReportProtectedDatastore {
|
||||
Param(
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
Get-SrmProtectionGroup -SrmServer $SrmServer -Type "san" | %{
|
||||
$pg = $_
|
||||
$pginfo = $pg.GetInfo()
|
||||
$pds = Get-SrmProtectedDatastore -ProtectionGroup $pg
|
||||
$pds | %{
|
||||
$pd = $_
|
||||
$output = "" | select datacenter, group, name, capacity, free
|
||||
$output.datacenter = $pd.Datacenter.Name
|
||||
$output.group = $pginfo.Name
|
||||
$output.name = $pd.Name
|
||||
$output.capacity = $pd.CapacityGB
|
||||
$output.free = $pd.FreeSpaceGB
|
||||
|
||||
$output
|
||||
|
||||
}
|
||||
} | Format-Table -Wrap -AutoSize -GroupBy "datacenter" @{Label="Datastore Name"; Expression={$_.name} },
|
||||
@{Label="Capacity GB"; Expression={$_.capacity} },
|
||||
@{Label="Free GB"; Expression={$_.free} },
|
||||
@{Label="Protection Group"; Expression={$_.group} }
|
||||
}
|
||||
|
||||
|
||||
Function Get-SrmConfigReportProtectedVm {
|
||||
Param(
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
$srmversion = Get-SrmServerVersion -SrmServer $SrmServer
|
||||
$srmMajorVersion, $srmMinorVersion = $srmversion -split "\."
|
||||
|
||||
Get-SrmProtectionGroup -SrmServer $SrmServer | %{
|
||||
$pg = $_
|
||||
$pginfo = $pg.GetInfo()
|
||||
$pvms = Get-SrmProtectedVM -ProtectionGroup $pg
|
||||
$rps = Get-SrmRecoveryPlan -ProtectionGroup $pg
|
||||
$rpnames = $rps | %{ $_.GetInfo().Name }
|
||||
$pvms | %{
|
||||
$pvm = $_
|
||||
if ($srmMajorVersion -ge 6 -or ($srmMajorVersion -eq 5 -and $srmMinorVersion -eq 8)) {
|
||||
$rs = $rps | Select -First 1 | %{ $_.GetRecoverySettings($pvm.Vm.MoRef) }
|
||||
}
|
||||
$output = "" | select group, name, moRef, needsConfiguration, state, plans, priority, finalPowerState, preCallouts, postCallouts
|
||||
$output.group = $pginfo.Name
|
||||
$output.name = $pvm.Vm.Name
|
||||
$output.moRef = $pvm.Vm.MoRef # this is necessary in case we can't retrieve the name when VC is unavailable
|
||||
$output.needsConfiguration = $pvm.NeedsConfiguration
|
||||
$output.state = $pvm.State
|
||||
$output.plans = [string]::Join(",`r`n", $rpnames)
|
||||
if ($rs) {
|
||||
$output.priority = $rs.RecoveryPriority
|
||||
$output.finalPowerState = $rs.FinalPowerState
|
||||
$output.preCallouts = $rs.PrePowerOnCallouts.Count
|
||||
$output.postCallouts = $rs.PostPowerOnCallouts.Count
|
||||
}
|
||||
$output
|
||||
|
||||
}
|
||||
} | Format-Table -Wrap -AutoSize @{Label="VM Name"; Expression={$_.name} },
|
||||
@{Label="VM MoRef"; Expression={$_.moRef} },
|
||||
@{Label="Needs Config"; Expression={$_.needsConfiguration} },
|
||||
@{Label="VM Protection State"; Expression={$_.state} },
|
||||
@{Label="Protection Group"; Expression={$_.group} },
|
||||
@{Label="Recovery Plans"; Expression={$_.plans} },
|
||||
@{Label="Recovery Priority"; Expression={$_.priority} },
|
||||
@{Label="Final Power State"; Expression={$_.finalPowerState} },
|
||||
@{Label="Pre-PowerOn Callouts"; Expression={$_.preCallouts} },
|
||||
@{Label="Post-PowerOn Callouts"; Expression={$_.postCallouts} }
|
||||
|
||||
}
|
||||
|
||||
Function Get-SrmConfigReport {
|
||||
Param(
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
Get-SrmConfigReportSite -SrmServer $SrmServer
|
||||
Get-SrmConfigReportPlan -SrmServer $SrmServer
|
||||
Get-SrmConfigReportProtectionGroup -SrmServer $SrmServer
|
||||
Get-SrmConfigReportProtectedDatastore -SrmServer $SrmServer
|
||||
Get-SrmConfigReportProtectedVm -SrmServer $SrmServer
|
||||
}
|
||||
34
Modules/SRM/Examples/SrmTagging.ps1
Normal file
34
Modules/SRM/Examples/SrmTagging.ps1
Normal file
@@ -0,0 +1,34 @@
|
||||
# Depends on SRM Helper Methods - https://github.com/benmeadowcroft/SRM-Cmdlets
|
||||
# It is assumed that the connections to active VC and SRM Server have already been made
|
||||
|
||||
Import-Module Meadowcroft.SRM -Prefix Srm
|
||||
|
||||
$TagCategoryName = 'Meadowcroft.SRM.VM'
|
||||
$TagCategoryDescription = 'Tag category for tagging VMs with SRM state'
|
||||
|
||||
# If the tag category doesn't exist, create it and the relevant tags
|
||||
$TagCategory = Get-TagCategory -Name $TagCategoryName -ErrorAction SilentlyContinue
|
||||
if (-Not $TagCategory) {
|
||||
Write-Output "Creating Tag Category $TagCategoryName"
|
||||
$TagCategory = New-TagCategory -Name $TagCategoryName -Description $TagCategoryDescription -EntityType 'VirtualMachine'
|
||||
|
||||
Write-Output "Creating Tag SrmProtectedVm"
|
||||
New-Tag -Name 'SrmProtectedVm' -Category $TagCategory -Description "VM protected by VMware SRM"
|
||||
Write-Output "Creating Tag SrmTestVm"
|
||||
New-Tag -Name 'SrmTestVm' -Category $TagCategory -Description "Test VM instantiated by VMware SRM"
|
||||
Write-Output "Creating Tag SrmPlaceholderVm"
|
||||
New-Tag -Name 'SrmPlaceholderVm' -Category $TagCategory -Description "Placeholder VM used by VMware SRM"
|
||||
}
|
||||
|
||||
$protectedVmTag = Get-Tag -Name 'SrmProtectedVm' -Category $TagCategory
|
||||
$testVmTag = Get-Tag -Name 'SrmTestVm' -Category $TagCategory
|
||||
$placeholderVmTag = Get-Tag -Name 'SrmPlaceholderVm' -Category $TagCategory
|
||||
|
||||
# Assign protected tag to a VM, use ready state to get "local" protected VMs
|
||||
Get-SrmProtectedVM -State Ready | %{ New-TagAssignment -Tag $protectedVmTag -Entity $(Get-VIObjectByVIView $_.Vm) | Out-Null }
|
||||
|
||||
# Assign test tag to a VM
|
||||
Get-SrmTestVM | %{ New-TagAssignment -Tag $testVmTag -Entity $_ | Out-Null }
|
||||
|
||||
# Assign placeholder tag to a VM
|
||||
Get-SrmPlaceholderVM | %{ New-TagAssignment -Tag $placeholderVmTag -Entity $_ | Out-Null }
|
||||
74
Modules/SRM/LICENSE.txt
Normal file
74
Modules/SRM/LICENSE.txt
Normal file
@@ -0,0 +1,74 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
||||
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
||||
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
|
||||
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
||||
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied.
|
||||
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
422
Modules/SRM/Meadowcroft.Srm.Protection.ps1
Normal file
422
Modules/SRM/Meadowcroft.Srm.Protection.ps1
Normal file
@@ -0,0 +1,422 @@
|
||||
# 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
|
||||
}
|
||||
556
Modules/SRM/Meadowcroft.Srm.Recovery.ps1
Normal file
556
Modules/SRM/Meadowcroft.Srm.Recovery.ps1
Normal file
@@ -0,0 +1,556 @@
|
||||
# SRM Helper Methods - https://github.com/benmeadowcroft/SRM-Cmdlets
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Get the subset of recovery plans matching the input criteria
|
||||
|
||||
.PARAMETER Name
|
||||
Return recovery plans matching the specified name
|
||||
|
||||
.PARAMETER ProtectionGroup
|
||||
Return recovery plans associated with particular protection
|
||||
groups
|
||||
#>
|
||||
Function Get-RecoveryPlan {
|
||||
[cmdletbinding()]
|
||||
Param(
|
||||
[Parameter(position=1)][string] $Name,
|
||||
[Parameter (ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup[]] $ProtectionGroup,
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
begin {
|
||||
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
|
||||
$rps = @()
|
||||
}
|
||||
process {
|
||||
if ($ProtectionGroup) {
|
||||
foreach ($pg in $ProtectionGroup) {
|
||||
$rps += $pg.ListRecoveryPlans()
|
||||
}
|
||||
$rps = Select_UniqueByMoRef($rps)
|
||||
} else {
|
||||
$rps += $api.Recovery.ListPlans()
|
||||
}
|
||||
}
|
||||
end {
|
||||
$rps | ForEach-Object {
|
||||
$rp = $_
|
||||
$rpi = $rp.GetInfo()
|
||||
$selected = (-not $Name -or ($Name -eq $rpi.Name))
|
||||
if ($selected) {
|
||||
Add-Member -InputObject $rp -MemberType NoteProperty -Name "Name" -Value $rpi.Name
|
||||
$rp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Start a Recovery Plan action like test, recovery, cleanup, etc.
|
||||
|
||||
.PARAMETER RecoveryPlan
|
||||
The recovery plan to start
|
||||
|
||||
.PARAMETER RecoveryMode
|
||||
The recovery mode to invoke on the plan. May be one of "Test", "Cleanup", "Failover", "Migrate", "Reprotect"
|
||||
#>
|
||||
Function Start-RecoveryPlan {
|
||||
[cmdletbinding(SupportsShouldProcess=$True, ConfirmImpact="High")]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true, ValueFromPipeline=$true, Position=1)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
|
||||
[VMware.VimAutomation.Srm.Views.SrmRecoveryPlanRecoveryMode] $RecoveryMode = [VMware.VimAutomation.Srm.Views.SrmRecoveryPlanRecoveryMode]::Test,
|
||||
[bool] $SyncData = $True
|
||||
)
|
||||
|
||||
# Validate with informative error messages
|
||||
$rpinfo = $RecoveryPlan.GetInfo()
|
||||
|
||||
# Create recovery options
|
||||
$rpOpt = New-Object VMware.VimAutomation.Srm.Views.SrmRecoveryOptions
|
||||
$rpOpt.SyncData = $SyncData
|
||||
|
||||
# Prompt the user to confirm they want to execute the action
|
||||
if ($pscmdlet.ShouldProcess($rpinfo.Name, $RecoveryMode)) {
|
||||
if ($rpinfo.State -eq 'Protecting') {
|
||||
throw "This recovery plan action needs to be initiated from the other SRM instance"
|
||||
}
|
||||
|
||||
$RecoveryPlan.Start($RecoveryMode, $rpOpt)
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Stop a running Recovery Plan action.
|
||||
|
||||
.PARAMETER RecoveryPlan
|
||||
The recovery plan to stop
|
||||
#>
|
||||
Function Stop-RecoveryPlan {
|
||||
[cmdletbinding(SupportsShouldProcess=$True,ConfirmImpact="High")]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true, ValueFromPipeline=$true, Position=1)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan
|
||||
)
|
||||
|
||||
# Validate with informative error messages
|
||||
$rpinfo = $RecoveryPlan.GetInfo()
|
||||
|
||||
# Prompt the user to confirm they want to cancel the running action
|
||||
if ($pscmdlet.ShouldProcess($rpinfo.Name, 'Cancel')) {
|
||||
|
||||
$RecoveryPlan.Cancel()
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieve the historical results of a recovery plan
|
||||
|
||||
.PARAMETER RecoveryPlan
|
||||
The recovery plan to retrieve the history for
|
||||
#>
|
||||
Function Get-RecoveryPlanResult {
|
||||
[cmdletbinding()]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true, ValueFromPipeline=$true, Position=1)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
|
||||
[VMware.VimAutomation.Srm.Views.SrmRecoveryPlanRecoveryMode] $RecoveryMode,
|
||||
[VMware.VimAutomation.Srm.Views.SrmRecoveryResultResultState] $ResultState,
|
||||
[DateTime] $StartedAfter,
|
||||
[DateTime] $startedBefore,
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
|
||||
|
||||
# Get the history objects
|
||||
$history = $api.Recovery.GetHistory($RecoveryPlan.MoRef)
|
||||
$resultCount = $history.GetResultCount()
|
||||
|
||||
if ($resultCount -gt 0) {
|
||||
$results = $history.GetRecoveryResult($resultCount)
|
||||
|
||||
$results |
|
||||
Where-Object { -not $RecoveryMode -or $_.RunMode -eq $RecoveryMode } |
|
||||
Where-Object { -not $ResultState -or $_.ResultState -eq $ResultState } |
|
||||
Where-Object { $null -eq $StartedAfter -or $_.StartTime -gt $StartedAfter } |
|
||||
Where-Object { $null -eq $StartedBefore -or $_.StartTime -lt $StartedBefore }
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Exports a recovery plan result object to XML format
|
||||
|
||||
.PARAMETER RecoveryPlanResult
|
||||
The recovery plan result to export
|
||||
#>
|
||||
Function Export-RecoveryPlanResultAsXml {
|
||||
[cmdletbinding()]
|
||||
[OutputType([xml])]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true, ValueFromPipeline=$true, Position=1)][VMware.VimAutomation.Srm.Views.SrmRecoveryResult] $RecoveryPlanResult,
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
|
||||
|
||||
$RecoveryPlan = $RecoveryPlanResult.Plan
|
||||
$history = $api.Recovery.GetHistory($RecoveryPlan.MoRef)
|
||||
$lines = $history.GetResultLength($RecoveryPlanResult.Key)
|
||||
[xml] $history.RetrieveStatus($RecoveryPlanResult.Key, 0, $lines)
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Add a protection group to a recovery plan. This requires SRM 5.8 or later.
|
||||
|
||||
.PARAMETER RecoveryPlan
|
||||
The recovery plan the protection group will be associated with
|
||||
|
||||
.PARAMETER ProtectionGroup
|
||||
The protection group to associate with the recovery plan
|
||||
#>
|
||||
Function Add-ProtectionGroupToRecoveryPlan {
|
||||
[cmdletbinding()]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true, Position=1)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
|
||||
[Parameter (Mandatory=$true, ValueFromPipeline=$true, Position=2)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup] $ProtectionGroup
|
||||
)
|
||||
|
||||
if ($RecoveryPlan -and $ProtectionGroup) {
|
||||
foreach ($pg in $ProtectionGroup) {
|
||||
try {
|
||||
$RecoveryPlan.AddProtectionGroup($pg.MoRef)
|
||||
} catch {
|
||||
Write-Error $_
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Remove a protection group to a recovery plan. This requires SRM 6.5 or later.
|
||||
|
||||
.PARAMETER RecoveryPlan
|
||||
The recovery plan the protection group will be disassociated from
|
||||
|
||||
.PARAMETER ProtectionGroup
|
||||
The protection group to disassociate from the recovery plan
|
||||
#>
|
||||
Function Remove-ProtectionGroupFromRecoveryPlan {
|
||||
[cmdletbinding()]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
|
||||
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmProtectionGroup] $ProtectionGroup
|
||||
)
|
||||
|
||||
if ($RecoveryPlan -and $ProtectionGroup) {
|
||||
foreach ($pg in $ProtectionGroup) {
|
||||
try {
|
||||
$RecoveryPlan.RemoveProtectionGroupFromRecoveryPlan($pg.MoRef)
|
||||
} catch {
|
||||
Write-Error $_
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Get the recovery settings of a protected VM. This requires SRM 5.8 or later.
|
||||
|
||||
.PARAMETER RecoveryPlan
|
||||
The recovery plan the settings will be retrieved from.
|
||||
|
||||
.PARAMETER Vm
|
||||
The virtual machine to retieve recovery settings for.
|
||||
|
||||
#>
|
||||
Function Get-RecoverySetting {
|
||||
[cmdletbinding()]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
|
||||
[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
|
||||
|
||||
if ($RecoveryPlan -and $moRef) {
|
||||
$RecoveryPlan.GetRecoverySettings($moRef)
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Get the recovery settings of a protected VM. This requires SRM 5.8 or later.
|
||||
|
||||
.PARAMETER RecoveryPlan
|
||||
The recovery plan the settings will be retrieved from.
|
||||
|
||||
.PARAMETER Vm
|
||||
The virtual machine to configure recovery settings on.
|
||||
|
||||
.PARAMETER RecoverySettings
|
||||
The recovery settings to configure. These should have been retrieved via a
|
||||
call to Get-RecoverySettings
|
||||
|
||||
#>
|
||||
Function Set-RecoverySetting {
|
||||
[cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="Medium")]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
|
||||
[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,
|
||||
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoverySettings] $RecoverySettings
|
||||
)
|
||||
|
||||
|
||||
$moRef = Get_MoRefFromVmObj -Vm $Vm -VmView $VmView -ProtectedVm $ProtectedVm
|
||||
|
||||
if ($RecoveryPlan -and $moRef -and $RecoverySettings) {
|
||||
if ($PSCmdlet.ShouldProcess("$moRef", "Set")) {
|
||||
$RecoveryPlan.SetRecoverySettings($moRef, $RecoverySettings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Create a new per-Vm command to add to the SRM Recovery Plan
|
||||
|
||||
.PARAMETER Command
|
||||
The command script to execute.
|
||||
|
||||
.PARAMETER Description
|
||||
The user friendly description of this script.
|
||||
|
||||
.PARAMETER Timeout
|
||||
The number of seconds this command has to execute before it will be timedout.
|
||||
|
||||
.PARAMETER RunInRecoveredVm
|
||||
For a post-power on command this flag determines whether it will run on the
|
||||
recovered VM or on the SRM server.
|
||||
|
||||
#>
|
||||
Function New-Command {
|
||||
[cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="None")]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true)][string] $Command,
|
||||
[Parameter (Mandatory=$true)][string] $Description,
|
||||
[int] $Timeout = 300,
|
||||
[switch] $RunInRecoveredVm = $false
|
||||
)
|
||||
|
||||
if($PSCmdlet.ShouldProcess("Description", "New")) {
|
||||
$srmWsdlCmd = New-Object VMware.VimAutomation.Srm.WsdlTypes.SrmCommand
|
||||
$srmCmd = New-Object VMware.VimAutomation.Srm.Views.SrmCommand -ArgumentList $srmWsdlCmd
|
||||
$srmCmd.Command = $Command
|
||||
$srmCmd.Description = $Description
|
||||
$srmCmd.RunInRecoveredVm = $RunInRecoveredVm
|
||||
$srmCmd.Timeout = $Timeout
|
||||
$srmCmd.Uuid = [guid]::NewGuid()
|
||||
|
||||
return $srmCmd
|
||||
}
|
||||
}
|
||||
|
||||
<# Internal function #>
|
||||
Function Add_Command {
|
||||
[cmdletbinding()]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoverySettings] $RecoverySettings,
|
||||
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmCommand] $SrmCommand,
|
||||
[Parameter (Mandatory=$true)][bool] $PostRecovery
|
||||
)
|
||||
|
||||
if ($PostRecovery) {
|
||||
$commands = $RecoverySettings.PostPowerOnCallouts
|
||||
} else {
|
||||
$commands = $RecoverySettings.PrePowerOnCallouts
|
||||
}
|
||||
|
||||
if (-not $commands) {
|
||||
$commands = New-Object System.Collections.Generic.List[VMware.VimAutomation.Srm.Views.SrmCallout]
|
||||
}
|
||||
$commands.Add($SrmCommand)
|
||||
|
||||
if ($PostRecovery) {
|
||||
$RecoverySettings.PostPowerOnCallouts = $commands
|
||||
} else {
|
||||
$RecoverySettings.PrePowerOnCallouts = $commands
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Add an SRM command to the set of pre recovery callouts for a VM.
|
||||
|
||||
.PARAMETER RecoverySettings
|
||||
The recovery settings to update. These should have been retrieved via a
|
||||
call to Get-RecoverySettings
|
||||
|
||||
.PARAMETER SrmCommand
|
||||
The command to add to the list.
|
||||
|
||||
#>
|
||||
Function Add-PreRecoveryCommand {
|
||||
[cmdletbinding()]
|
||||
[OutputType([VMware.VimAutomation.Srm.Views.SrmRecoverySettings])]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoverySettings] $RecoverySettings,
|
||||
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmCommand] $SrmCommand
|
||||
)
|
||||
Add_Command -RecoverySettings $RecoverySettings -SrmCommand $SrmCommand -PostRecovery $false
|
||||
return $RecoverySettings
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Remove an SRM command from the set of pre recovery callouts for a VM.
|
||||
|
||||
.PARAMETER RecoverySettings
|
||||
The recovery settings to update. These should have been retrieved via a
|
||||
call to Get-RecoverySettings
|
||||
|
||||
.PARAMETER SrmCommand
|
||||
The command to remove from the list.
|
||||
|
||||
#>
|
||||
Function Remove-PreRecoveryCommand {
|
||||
[cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="Low")]
|
||||
[OutputType([VMware.VimAutomation.Srm.Views.SrmRecoverySettings])]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoverySettings] $RecoverySettings,
|
||||
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmCommand] $SrmCommand
|
||||
)
|
||||
|
||||
if ($pscmdlet.ShouldProcess($SrmCommand.Description, "Remove")) {
|
||||
$RecoverySettings.PrePowerOnCallouts.Remove($SrmCommand)
|
||||
}
|
||||
|
||||
return $RecoverySettings
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Add an SRM command to the set of post recovery callouts for a VM.
|
||||
|
||||
.PARAMETER RecoverySettings
|
||||
The recovery settings to update. These should have been retrieved via a
|
||||
call to Get-RecoverySettings
|
||||
|
||||
.PARAMETER SrmCommand
|
||||
The command to add to the list.
|
||||
|
||||
#>
|
||||
Function Add-PostRecoveryCommand {
|
||||
[cmdletbinding()]
|
||||
[OutputType([VMware.VimAutomation.Srm.Views.SrmRecoverySettings])]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoverySettings] $RecoverySettings,
|
||||
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmCommand] $SrmCommand
|
||||
)
|
||||
|
||||
Add_Command -RecoverySettings $RecoverySettings -SrmCommand $SrmCommand -PostRecovery $true
|
||||
|
||||
return $RecoverySettings
|
||||
}
|
||||
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Remove an SRM command from the set of post recovery callouts for a VM.
|
||||
|
||||
.PARAMETER RecoverySettings
|
||||
The recovery settings to update. These should have been retrieved via a
|
||||
call to Get-RecoverySettings
|
||||
|
||||
.PARAMETER SrmCommand
|
||||
The command to remove from the list.
|
||||
|
||||
#>
|
||||
Function Remove-PostRecoveryCommand {
|
||||
[cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="Low")]
|
||||
[OutputType([VMware.VimAutomation.Srm.Views.SrmRecoverySettings])]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true, ValueFromPipeline=$true)][VMware.VimAutomation.Srm.Views.SrmRecoverySettings] $RecoverySettings,
|
||||
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmCommand] $SrmCommand
|
||||
)
|
||||
|
||||
if ($pscmdlet.ShouldProcess($SrmCommand.Description, "Remove")) {
|
||||
$RecoverySettings.PostPowerOnCallouts.Remove($SrmCommand)
|
||||
}
|
||||
|
||||
return $RecoverySettings
|
||||
}
|
||||
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Create a new recovery plan
|
||||
|
||||
.PARAMETER Name
|
||||
The name for this recovery plan
|
||||
|
||||
.PARAMETER Description
|
||||
A description of the recovery plan
|
||||
|
||||
.PARAMETER Folder
|
||||
The recovery plan folder in which to create this recovery plan. Will default to
|
||||
the root recovery plan folder
|
||||
|
||||
.PARAMETER ProtectionGroups
|
||||
The protection groups to associate with this recovery plan
|
||||
|
||||
.PARAMETER TestNetworkMappings
|
||||
The test network mappings to configure as part of this recovery plan
|
||||
|
||||
.PARAMETER SrmServer
|
||||
The SRM Server to operate against
|
||||
#>
|
||||
Function New-RecoveryPlan {
|
||||
[cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="Medium")]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true)][string] $Name,
|
||||
[string] $Description,
|
||||
[VMware.VimAutomation.Srm.Views.SrmRecoveryPlanFolder] $Folder,
|
||||
[VMware.VimAutomation.Srm.Views.SrmProtectionGroup[]] $ProtectionGroups,
|
||||
[VMware.VimAutomation.Srm.Views.SrmRecoveryTestNetworkMapping[]] $TestNetworkMappings,
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
|
||||
|
||||
if (-not $Folder) {
|
||||
$Folder = Get-RecoveryPlanFolder -SrmServer $SrmServer
|
||||
}
|
||||
|
||||
$protectionGroupmRefs += @( $ProtectionGroups | ForEach-Object { $_.MoRef } | Select-Object -Unique)
|
||||
|
||||
[VMware.VimAutomation.Srm.Views.CreateRecoveryPlanTask] $task = $null
|
||||
|
||||
if ($PSCmdlet.ShouldProcess($Name, "New")) {
|
||||
$task = $api.Recovery.CreateRecoveryPlan(
|
||||
$Name,
|
||||
$Folder.MoRef,
|
||||
$protectionGroupmRefs,
|
||||
$Description,
|
||||
$TestNetworkMappings
|
||||
)
|
||||
}
|
||||
|
||||
while(-not $task.IsCreateRecoveryPlanComplete()) { Start-Sleep -Seconds 1 }
|
||||
|
||||
$task.GetNewRecoveryPlan()
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Remove a recovery plan permanently
|
||||
|
||||
.PARAMETER RecoveryPlan
|
||||
The recovery plan to remove
|
||||
|
||||
.PARAMETER SrmServer
|
||||
The SRM Server to operate against
|
||||
#>
|
||||
Function Remove-RecoveryPlan {
|
||||
[cmdletbinding(SupportsShouldProcess=$True, ConfirmImpact="High")]
|
||||
Param(
|
||||
[Parameter (Mandatory=$true)][VMware.VimAutomation.Srm.Views.SrmRecoveryPlan] $RecoveryPlan,
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
|
||||
|
||||
$rpinfo = $RecoveryPlan.GetInfo()
|
||||
if ($pscmdlet.ShouldProcess($rpinfo.Name, "Remove")) {
|
||||
$api.Recovery.DeleteRecoveryPlan($RecoveryPlan.MoRef)
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Get a recovery plan folder
|
||||
|
||||
.PARAMETER SrmServer
|
||||
The SRM Server to query for the recovery plan folder
|
||||
#>
|
||||
Function Get-RecoveryPlanFolder {
|
||||
[cmdletbinding()]
|
||||
Param(
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
|
||||
|
||||
$folder = $api.Recovery.GetRecoveryPlanRootFolder()
|
||||
|
||||
return $folder
|
||||
}
|
||||
24
Modules/SRM/Meadowcroft.Srm.Storage.ps1
Normal file
24
Modules/SRM/Meadowcroft.Srm.Storage.ps1
Normal file
@@ -0,0 +1,24 @@
|
||||
# SRM Helper Methods - https://github.com/benmeadowcroft/SRM-Cmdlets
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Trigger Discover Devices for Site Recovery Manager
|
||||
|
||||
.OUTPUTS
|
||||
Returns discover devices task
|
||||
#>
|
||||
Function Start-DiscoverDevice {
|
||||
[cmdletbinding(SupportsShouldProcess=$True, ConfirmImpact="Medium")]
|
||||
[OutputType([VMware.VimAutomation.Srm.Views.DiscoverDevicesTask])]
|
||||
Param(
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
$api = Get-ServerApiEndpoint -SrmServer $SrmServer
|
||||
$name = $SrmServer.Name
|
||||
[VMware.VimAutomation.Srm.Views.DiscoverDevicesTask] $task = $null
|
||||
if ($pscmdlet.ShouldProcess($name, "Rescan Storage Devices")) {
|
||||
$task = $api.Storage.DiscoverDevices()
|
||||
}
|
||||
return $task
|
||||
}
|
||||
92
Modules/SRM/Meadowcroft.Srm.psd1
Normal file
92
Modules/SRM/Meadowcroft.Srm.psd1
Normal file
@@ -0,0 +1,92 @@
|
||||
#
|
||||
# Module manifest for module 'Meadowcroft.Srm'
|
||||
#
|
||||
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
RootModule = 'Meadowcroft.Srm.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '0.2'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = 'f9247009-9168-4a21-831b-819f82884ffe'
|
||||
|
||||
# Author of this module
|
||||
Author = 'Ben Meadowcroft'
|
||||
|
||||
# Company or vendor of this module
|
||||
CompanyName = 'VMware, Inc'
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = '(c) 2014 - 2017. All rights reserved.'
|
||||
|
||||
# Description of the functionality provided by this module
|
||||
# Description = ''
|
||||
|
||||
# Minimum version of the Windows PowerShell engine required by this module
|
||||
# PowerShellVersion = ''
|
||||
|
||||
# Name of the Windows PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the Windows PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of Microsoft .NET Framework required by this module
|
||||
# DotNetFrameworkVersion = ''
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module
|
||||
# CLRVersion = ''
|
||||
|
||||
# Processor architecture (None, X86, Amd64) required by this module
|
||||
# ProcessorArchitecture = ''
|
||||
|
||||
# Modules that must be imported into the global environment prior to importing this module
|
||||
RequiredModules = @{ModuleName='VMware.VimAutomation.Srm'; ModuleVersion='6.5'}
|
||||
|
||||
# Assemblies that must be loaded prior to importing this module
|
||||
# RequiredAssemblies = @()
|
||||
|
||||
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
|
||||
# ScriptsToProcess = @()
|
||||
|
||||
# Type files (.ps1xml) to be loaded when importing this module
|
||||
# TypesToProcess = @()
|
||||
|
||||
# Format files (.ps1xml) to be loaded when importing this module
|
||||
# FormatsToProcess = @()
|
||||
|
||||
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
|
||||
NestedModules = 'Meadowcroft.Srm.Recovery.ps1','Meadowcroft.Srm.Protection.ps1','Meadowcroft.Srm.Storage.ps1'
|
||||
# NestedModules = @()
|
||||
|
||||
# Functions to export from this module, note that internal functions use '_' not '-' as separator
|
||||
FunctionsToExport = '*-*'
|
||||
|
||||
# Cmdlets to export from this module
|
||||
CmdletsToExport = '*'
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = '*'
|
||||
|
||||
# Aliases to export from this module
|
||||
AliasesToExport = '*'
|
||||
|
||||
# List of all modules packaged with this module
|
||||
# ModuleList = @()
|
||||
|
||||
# List of all files packaged with this module
|
||||
# FileList = @()
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
||||
# PrivateData = ''
|
||||
|
||||
# HelpInfo URI of this module
|
||||
# HelpInfoURI = ''
|
||||
|
||||
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
|
||||
DefaultCommandPrefix = 'Srm'
|
||||
|
||||
}
|
||||
148
Modules/SRM/Meadowcroft.Srm.psm1
Normal file
148
Modules/SRM/Meadowcroft.Srm.psm1
Normal file
@@ -0,0 +1,148 @@
|
||||
# SRM Helper Methods - https://github.com/benmeadowcroft/SRM-Cmdlets
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This is intended to be an "internal" function only. It filters a
|
||||
pipelined input of objects and elimiates duplicates as identified
|
||||
by the MoRef property on the object.
|
||||
|
||||
.LINK
|
||||
https://github.com/benmeadowcroft/SRM-Cmdlets/
|
||||
#>
|
||||
Function Select_UniqueByMoRef {
|
||||
|
||||
Param(
|
||||
[Parameter (ValueFromPipeline=$true)] $in
|
||||
)
|
||||
process {
|
||||
$moref = New-Object System.Collections.ArrayList
|
||||
$in | Sort-Object | Select-Object MoRef -Unique | ForEach-Object { $moref.Add($_.MoRef) } > $null
|
||||
$in | ForEach-Object {
|
||||
if ($_.MoRef -in $moref) {
|
||||
$moref.Remove($_.MoRef)
|
||||
$_ #output
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This is intended to be an "internal" function only. It gets the
|
||||
MoRef property of a VM from either a VM object, a VM view, or the
|
||||
protected VM object.
|
||||
#>
|
||||
Function Get_MoRefFromVmObj {
|
||||
Param(
|
||||
[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 = $null
|
||||
if ($Vm.ExtensionData.MoRef) { # VM object
|
||||
$moRef = $Vm.ExtensionData.MoRef
|
||||
} elseif ($VmView.MoRef) { # VM view
|
||||
$moRef = $VmView.MoRef
|
||||
} elseif ($protectedVm) {
|
||||
$moRef = $ProtectedVm.Vm.MoRef
|
||||
}
|
||||
|
||||
$moRef
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Lookup the srm instance for a specific server.
|
||||
#>
|
||||
Function Get-Server {
|
||||
[cmdletbinding()]
|
||||
Param(
|
||||
[string] $SrmServerAddress,
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
$found = $null
|
||||
|
||||
if ($SrmServer) {
|
||||
$found = $SrmServer
|
||||
} elseif ($SrmServerAddress) {
|
||||
# search for server address in default servers
|
||||
$global:DefaultSrmServers | ForEach-Object {
|
||||
if ($_.Name -ieq $SrmServerAddress) {
|
||||
$found = $_
|
||||
}
|
||||
}
|
||||
if (-not $found) {
|
||||
throw "SRM server $SrmServerAddress not found. Connect-Server must be called first."
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $found) {
|
||||
#default result
|
||||
$found = $global:DefaultSrmServers[0]
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieve the SRM Server Version
|
||||
#>
|
||||
Function Get-ServerVersion {
|
||||
[cmdletbinding()]
|
||||
Param(
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
$srm = Get-Server $SrmServer
|
||||
$srm.Version
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Lookup the SRM API endpoint for a specific server.
|
||||
#>
|
||||
Function Get-ServerApiEndpoint {
|
||||
[cmdletbinding()]
|
||||
Param(
|
||||
[string] $SrmServerAddress,
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $SrmServer
|
||||
)
|
||||
|
||||
[VMware.VimAutomation.Srm.Types.V1.SrmServer] $server = Get-Server -SrmServerAddress $SrmServerAddress -SrmServer $SrmServer
|
||||
|
||||
return $server.ExtensionData
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Get the placeholder VMs that are associated with SRM
|
||||
#>
|
||||
Function Get-PlaceholderVM {
|
||||
[cmdletbinding()]
|
||||
Param()
|
||||
Get-VM @Args | Where-Object {$_.ExtensionData.Config.ManagedBy.extensionKey -like "com.vmware.vcDr*" -and $_.ExtensionData.Config.ManagedBy.Type -ieq 'placeholderVm'}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Get the test VMs that are associated with SRM
|
||||
#>
|
||||
Function Get-TestVM {
|
||||
[cmdletbinding()]
|
||||
Param()
|
||||
Get-VM @Args | Where-Object {$_.ExtensionData.Config.ManagedBy.extensionKey -like "com.vmware.vcDr*" -and $_.ExtensionData.Config.ManagedBy.Type -ieq 'testVm'}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Get the VMs that are replicated using vSphere Replication. These may not be SRM
|
||||
protected VMs.
|
||||
#>
|
||||
Function Get-ReplicatedVM {
|
||||
[cmdletbinding()]
|
||||
Param()
|
||||
Get-VM @Args | Where-Object {($_.ExtensionData.Config.ExtraConfig | Where-Object { $_.Key -eq 'hbr_filter.destination' -and $_.Value } )}
|
||||
}
|
||||
7
Modules/SRM/NOTICE.txt
Normal file
7
Modules/SRM/NOTICE.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||
|
||||
This product is licensed to you under the Apache License version 2.0 (the "License"). You may not use this product except in compliance with the License.
|
||||
|
||||
This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file.
|
||||
|
||||
81
Modules/SRM/README.md
Normal file
81
Modules/SRM/README.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# SRM PowerCLI Cmdlets
|
||||
|
||||
Helper functions for working with VMware SRM 6.5 with PowerCLI 6.5.1 or later. PowerShell 5.0 and above is required.
|
||||
|
||||
This module is provided for illustrative/educational purposes to explain how the PowerCLI access to the SRM public API can be used.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Getting the SRM cmdlets
|
||||
|
||||
The latest version of the software can be cloned from the git repository:
|
||||
|
||||
git clone https://github.com/benmeadowcroft/SRM-Cmdlets.git
|
||||
|
||||
Or downloaded as a [zip file](https://github.com/benmeadowcroft/SRM-Cmdlets/archive/master.zip).
|
||||
|
||||
Specific releases (compatible with earlier PowerCLI and SRM versions) can be downloaded via the [release page](https://github.com/benmeadowcroft/SRM-Cmdlets/releases).
|
||||
|
||||
### Deploy SRM-Cmdlets module
|
||||
|
||||
After cloning (or downloading and extracting) the PowerShell module, you can import the module into your current PowerShell session by by passing the path to `Meadowcroft.Srm.psd1` to the `Import-Module` cmdlet, e.g.:
|
||||
|
||||
Import-Module -Name .\SRM-Cmdlets\Meadowcroft.Srm.psd1
|
||||
|
||||
You can also install the module into the PowerShell path so it can be loaded implicitly. See [Microsoft's Installing Modules instructions](http://msdn.microsoft.com/en-us/library/dd878350) for more details on how to do this.
|
||||
|
||||
The module uses the default prefix of `Srm` for the custom functions it defines. This can be overridden when importing the module by setting the value of the `-Prefix` parameter when calling `Import-Module`.
|
||||
|
||||
### Connecting to SRM
|
||||
|
||||
After installing the module the next step is to connect to the SRM server. Details of how to do this are located in the [PowerCLI 6.5.1 User's Guide](http://pubs.vmware.com/vsphere-65/topic/com.vmware.powercli.ug.doc/GUID-A5F206CF-264D-4565-8CB9-4ED1C337053F.html)
|
||||
|
||||
$credential = Get-Credential
|
||||
Connect-VIServer -Server vc-a.example.com -Credential $credential
|
||||
Connect-SrmServer -Credential $credential -RemoteCredential $credential
|
||||
|
||||
At this point we've just been using the cmdlets provided by PowerCLI, the PowerCLI documentation also provides some examples of how to call the SRM API to perform various tasks. In the rest of this introduction we'll perform some of those tasks using the custom functions defined in this project.
|
||||
|
||||
### Report the Protected Virtual Machines and Their Protection Groups
|
||||
|
||||
Goal: Create a simple report listing the VMs protected by SRM and the protection group they belong to.
|
||||
|
||||
Get-SrmProtectionGroup | %{
|
||||
$pg = $_
|
||||
Get-SrmProtectedVM -ProtectionGroup $pg } | %{
|
||||
$output = "" | select VmName, PgName
|
||||
$output.VmName = $_.Vm.Name
|
||||
$output.PgName = $pg.GetInfo().Name
|
||||
$output
|
||||
} | Format-Table @{Label="VM Name"; Expression={$_.VmName} },
|
||||
@{Label="Protection group name"; Expression={$_.PgName}
|
||||
}
|
||||
|
||||
### Report the Last Recovery Plan Test
|
||||
|
||||
Goal: Create a simple report listing the state of the last test of a recovery plan
|
||||
|
||||
Get-SrmRecoveryPlan | %{ $_ |
|
||||
Get-SrmRecoveryPlanResult -RecoveryMode Test | select -First 1
|
||||
} | Select Name, StartTime, RunMode, ResultState | Format-Table
|
||||
|
||||
|
||||
### Execute a Recovery Plan Test
|
||||
|
||||
Goal: for a specific recovery plan, execute a test failover. Note the "local" SRM server we are connected to should be the recovery site in order for this to be successful.
|
||||
|
||||
Get-SrmRecoveryPlan -Name "Name of Plan" | Start-SrmRecoveryPlan -RecoveryMode Test
|
||||
|
||||
### Export the Detailed XML Report of the Last Recovery Plan Workflow
|
||||
|
||||
Goal: get the XML report of the last recovery plan execution for a specific recovery plan.
|
||||
|
||||
Get-SrmRecoveryPlan -Name "Name of Plan" | Get-SrmRecoveryPlanResult |
|
||||
select -First 1 | Export-SrmRecoveryPlanResultAsXml
|
||||
|
||||
### Protect a Replicated VM
|
||||
|
||||
Goal: Take a VM replicated using vSphere Replication or Array Based Replication, add it to an appropriate protection group and configure it for protection
|
||||
|
||||
$pg = Get-SrmProtectionGroup "Name of Protection Group"
|
||||
Get-VM vm-01a | Protect-SrmVM -ProtectionGroup $pg
|
||||
@@ -8018,9 +8018,11 @@ function Get-HVEntitlement {
|
||||
$doaminFilter = Get-HVQueryFilter 'base.domain' -Eq $Domain
|
||||
$AndFilter += $doaminFilter
|
||||
}
|
||||
$IsGroup = ($Type -eq 'Group')
|
||||
$groupFilter = Get-HVQueryFilter 'base.group' -Eq $IsGroup
|
||||
$AndFilter += $groupFilter
|
||||
if ($type -eq 'group'){
|
||||
$IsGroup = ($Type -eq 'Group')
|
||||
$groupFilter = Get-HVQueryFilter 'base.group' -Eq $IsGroup
|
||||
$AndFilter += $groupFilter
|
||||
}
|
||||
$info = $services.PodFederation.PodFederation_get()
|
||||
$cpaEnabled = ("ENABLED" -eq $info.localPodStatus.status)
|
||||
switch($ResourceType) {
|
||||
@@ -8218,13 +8220,12 @@ function Remove-HVEntitlement {
|
||||
$confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys
|
||||
$AndFilter = @()
|
||||
$results = $null
|
||||
$userInfo = Get-UserInfo -UserName $User
|
||||
$UserOrGroupName = $userInfo.Name
|
||||
$Domain = $userInfo.Domain
|
||||
$nameFilter = Get-HVQueryFilter 'base.name' -Eq $UserOrGroupName
|
||||
$doaminFilter = Get-HVQueryFilter 'base.domain' -Eq $Domain
|
||||
$IsGroup = ($Type -eq 'Group')
|
||||
$groupFilter = Get-HVQueryFilter 'base.group' -Eq $IsGroup
|
||||
if ($User) {
|
||||
$userInfo = Get-UserInfo -UserName $User
|
||||
$AndFilter += Get-HVQueryFilter 'base.loginName' -Eq $userInfo.Name
|
||||
$AndFilter += Get-HVQueryFilter 'base.domain' -Eq $userInfo.Domain
|
||||
}
|
||||
$AndFilter += Get-HVQueryFilter 'base.group' -Eq ($Type -eq 'Group')
|
||||
[VMware.Hv.UserEntitlementId[]] $userEntitlements = $null
|
||||
if ($ResourceName) {
|
||||
$info = $services.PodFederation.PodFederation_get()
|
||||
@@ -8240,10 +8241,15 @@ function Remove-HVEntitlement {
|
||||
$results = Get-HVQueryResult -EntityType EntitledUserOrGroupLocalSummaryView -Filter $filters -HvServer $HvServer
|
||||
if ($results) {
|
||||
foreach ($result in $Results) {
|
||||
$userEntitlements = $result.localData.desktopUserEntitlements
|
||||
Write-Host $userEntitlements.Length " desktopUserEntitlement(s) will be removed for UserOrGroup " $user
|
||||
$deleteResources = @()
|
||||
for ($i = 0; $i -lt $result.localdata.desktops.length; $i++) {
|
||||
if ($ResourceObjs.Id.id -eq $result.localdata.Desktops[$i].id) {
|
||||
$deleteResources += $result.localdata.DesktopUserEntitlements[$i]
|
||||
}
|
||||
}
|
||||
Write-Host $deleteResources.Length " desktopUserEntitlement(s) will be removed for UserOrGroup " $user
|
||||
if (!$confirmFlag -OR $pscmdlet.ShouldProcess($User)) {
|
||||
$services.UserEntitlement.UserEntitlement_DeleteUserEntitlements($userEntitlements)
|
||||
$services.UserEntitlement.UserEntitlement_DeleteUserEntitlements($deleteResources)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8345,10 +8351,15 @@ function Remove-HVEntitlement {
|
||||
$results = Get-HVQueryResult -EntityType EntitledUserOrGroupGlobalSummaryView -Filter $AndFilter -HvServer $HvServer
|
||||
if ($results) {
|
||||
foreach ($result in $Results) {
|
||||
$userEntitlements = $result.globalData.globalUserEntitlements
|
||||
Write-Host $userEntitlements.Length " GlobalEntitlement(s) will be removed for UserOrGroup " $user
|
||||
$deleteResources = @()
|
||||
for ($i = 0; $i -lt $result.globalData.globalEntitlements.length; $i++) {
|
||||
if ($ResourceObjs.Id.id -eq $result.globalData.globalEntitlements[$i].id) {
|
||||
$deleteResources += $result.globalData.globalUserEntitlements[$i]
|
||||
}
|
||||
}
|
||||
Write-Host $deleteResources.Length " GlobalEntitlement(s) will be removed for UserOrGroup " $user
|
||||
if (!$confirmFlag -OR $pscmdlet.ShouldProcess($User)) {
|
||||
$services.UserEntitlement.UserEntitlement_DeleteUserEntitlements($userEntitlements)
|
||||
$services.UserEntitlement.UserEntitlement_DeleteUserEntitlements($deleteResources)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8445,6 +8456,11 @@ PARAMETER Key
|
||||
[Parameter(Mandatory = $false)]
|
||||
$Value,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidatePattern("^.+?[@\\].+?$")]
|
||||
[string]
|
||||
$User,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
$HvServer = $null
|
||||
)
|
||||
@@ -8472,6 +8488,11 @@ PARAMETER Key
|
||||
$machineList.add($macineObj.id, $macineObj.base.Name)
|
||||
}
|
||||
}
|
||||
if ($machineList.count -eq 0) {
|
||||
Write-Error "Machine $machineName not found - try fqdn"
|
||||
[System.gc]::collect()
|
||||
return
|
||||
}
|
||||
} elseif ($PSCmdlet.MyInvocation.ExpectingInput -or $Machine) {
|
||||
foreach ($item in $machine) {
|
||||
if (($item.GetType().name -eq 'MachineNamesView') -or ($item.GetType().name -eq 'MachineInfo')) {
|
||||
@@ -8489,6 +8510,22 @@ PARAMETER Key
|
||||
} elseif ($key -or $value) {
|
||||
Write-Error "Both key:[$key] and value:[$value] needs to be specified"
|
||||
}
|
||||
if ($User) {
|
||||
$userInfo = Get-UserInfo -UserName $User
|
||||
$UserOrGroupName = $userInfo.Name
|
||||
$Domain = $userInfo.Domain
|
||||
$filter1 = Get-HVQueryFilter 'base.name' -Eq $UserOrGroupName
|
||||
$filter2 = Get-HVQueryFilter 'base.domain' -Eq $Domain
|
||||
$filter3 = Get-HVQueryFilter 'base.group' -Eq $false
|
||||
$andFilter = Get-HVQueryFilter -And -Filters @($filter1, $filter2, $filter3)
|
||||
$results = Get-HVQueryResult -EntityType ADUserOrGroupSummaryView -Filter $andFilter -HvServer $HvServer
|
||||
if ($results.length -ne 1) {
|
||||
Write-Host "Unable to find specific user with given search parameters"
|
||||
[System.gc]::collect()
|
||||
return
|
||||
}
|
||||
$updates += Get-MapEntry -key 'base.user' -value $results[0].id
|
||||
}
|
||||
|
||||
if ($Maintenance) {
|
||||
if ($Maintenance -eq 'ENTER_MAINTENANCE_MODE') {
|
||||
@@ -9150,68 +9187,67 @@ function Remove-HVGlobalEntitlement {
|
||||
|
||||
}
|
||||
|
||||
function Get-HVPodSession {
|
||||
function Get-HVGlobalSession {
|
||||
<#
|
||||
.Synopsis
|
||||
Gets the total amount of sessions for all Pods in a Federation
|
||||
.SYNOPSIS
|
||||
Provides a list with all Global sessions in a Cloud Pod Architecture
|
||||
|
||||
.DESCRIPTION
|
||||
Gets the total amout of current sessions (connected and disconnected) for all Pods in a Federation (CPA)
|
||||
based on the global query service.
|
||||
The default object response is used which contains both success and fault information as well as the
|
||||
session count per pod and the ID of each pod.
|
||||
The get-hvglobalsession gets all local session by using view API service object(hvServer) of Connect-HVServer cmdlet.
|
||||
|
||||
.PARAMETER HvServer
|
||||
Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then
|
||||
first element from global:DefaultHVServers would be considered inplace of hvServer
|
||||
View API service object of Connect-HVServer cmdlet.
|
||||
|
||||
.EXAMPLE
|
||||
Get-HVPodSession
|
||||
|
||||
.OUTPUTS
|
||||
Returns list of objects of type GlobalSessionPodSessionCounter
|
||||
Get-hvglobalsession
|
||||
Gets all global sessions
|
||||
|
||||
.NOTES
|
||||
Author : Rasmus Sjoerslev
|
||||
Author email : rasmus.sjorslev@vmware.com
|
||||
Author : Wouter Kursten.
|
||||
Author email : wouter@retouw.nl
|
||||
Version : 1.0
|
||||
|
||||
===Tested Against Environment====
|
||||
Horizon View Server Version : 7.0.2
|
||||
PowerCLI Version : PowerCLI 6.5
|
||||
Horizon View Server Version : 7.0.2, 7.1.0, 7.3.2
|
||||
PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1
|
||||
PowerShell Version : 5.0
|
||||
#>
|
||||
|
||||
[CmdletBinding(
|
||||
SupportsShouldProcess = $true,
|
||||
ConfirmImpact = 'High'
|
||||
)]
|
||||
#>
|
||||
[CmdletBinding(
|
||||
SupportsShouldProcess = $true,
|
||||
ConfirmImpact = 'High'
|
||||
)]
|
||||
|
||||
param(
|
||||
param(
|
||||
[Parameter(Mandatory = $false)]
|
||||
$HvServer = $null
|
||||
)
|
||||
)
|
||||
|
||||
$services = Get-ViewAPIService -hvServer $hvServer
|
||||
if ($null -eq $services) {
|
||||
Write-Error "Could not retrieve ViewApi services from connection object"
|
||||
break
|
||||
}
|
||||
|
||||
$query_service_helper = New-Object VMware.Hv.GlobalSessionQueryServiceService
|
||||
$count_spec = New-Object VMware.Hv.GlobalSessionQueryServiceCountSpec
|
||||
$queryResults = @()
|
||||
|
||||
foreach ($pod in $services.Pod.Pod_List()) {
|
||||
$count_spec.Pod = $pod.Id
|
||||
$info = $query_service_helper.GlobalSessionQueryService_GetCountWithSpec($services,$count_spec)
|
||||
|
||||
foreach ($res in $info) {
|
||||
if ($pod.Id.Id -eq $res.Id.Id) {
|
||||
$queryResults += $res
|
||||
}
|
||||
}
|
||||
}
|
||||
return $queryResults
|
||||
$services = Get-ViewAPIService -HvServer $HvServer
|
||||
if ($null -eq $services) {
|
||||
Write-Error "Could not retrieve ViewApi services from connection object."
|
||||
break
|
||||
}
|
||||
|
||||
$query_service_helper = New-Object VMware.Hv.GlobalSessionQueryServiceService
|
||||
$query=new-object vmware.hv.GlobalSessionQueryServiceQuerySpec
|
||||
|
||||
$SessionList = @()
|
||||
$GetNext = $false
|
||||
foreach ($pod in $services.Pod.Pod_List()) {
|
||||
$query.pod=$pod.id
|
||||
$queryResults = $query_service_helper.GlobalSessionQueryService_QueryWithSpec($services, $query)
|
||||
do {
|
||||
if ($GetNext) { $queryResults = $query_service_helper.GlobalSessionQueryService_GetNext($services, $queryResults.id) }
|
||||
$SessionList += $queryResults.results
|
||||
$GetNext = $true
|
||||
} while ($queryResults.remainingCount -gt 0)
|
||||
$query_service_helper.GlobalSessionQueryService_Delete($services, $queryresults.id)
|
||||
|
||||
}
|
||||
return $sessionlist
|
||||
}
|
||||
|
||||
function Set-HVApplicationIcon {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
@@ -9822,4 +9858,136 @@ function Set-HVGlobalSettings {
|
||||
}
|
||||
}
|
||||
|
||||
Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Get-HVPodSession, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure
|
||||
function get-HVlocalsession {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Provides a list with all sessions on the local pod (works in CPA and non-CPA)
|
||||
|
||||
.DESCRIPTION
|
||||
The get-hvlocalsession gets all local session by using view API service object(hvServer) of Connect-HVServer cmdlet.
|
||||
|
||||
.PARAMETER HvServer
|
||||
View API service object of Connect-HVServer cmdlet.
|
||||
|
||||
.EXAMPLE
|
||||
Get-hvlocalsession
|
||||
Get all local sessions
|
||||
|
||||
.NOTES
|
||||
Author : Wouter Kursten.
|
||||
Author email : wouter@retouw.nl
|
||||
Version : 1.0
|
||||
|
||||
===Tested Against Environment====
|
||||
Horizon View Server Version : 7.0.2, 7.1.0, 7.3.2
|
||||
PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1
|
||||
PowerShell Version : 5.0
|
||||
|
||||
#>
|
||||
[CmdletBinding(
|
||||
SupportsShouldProcess = $true,
|
||||
ConfirmImpact = 'High'
|
||||
)]
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory = $false)]
|
||||
$HvServer = $null
|
||||
)
|
||||
|
||||
$services = Get-ViewAPIService -HvServer $HvServer
|
||||
if ($null -eq $services) {
|
||||
Write-Error "Could not retrieve ViewApi services from connection object."
|
||||
break
|
||||
}
|
||||
|
||||
$query_service_helper = New-Object VMware.Hv.QueryServiceService
|
||||
$query = New-Object VMware.Hv.QueryDefinition
|
||||
|
||||
$query.queryEntityType = 'SessionLocalSummaryView'
|
||||
$SessionList = @()
|
||||
$GetNext = $false
|
||||
$queryResults = $query_service_helper.QueryService_Create($services, $query)
|
||||
do {
|
||||
if ($GetNext) { $queryResults = $query_service_helper.QueryService_GetNext($services, $queryResults.id) }
|
||||
$SessionList += $queryResults.results
|
||||
$GetNext = $true
|
||||
}
|
||||
while ($queryResults.remainingCount -gt 0)
|
||||
$query_service_helper.QueryService_Delete($services, $queryResults.id)
|
||||
|
||||
|
||||
return $sessionlist
|
||||
[System.gc]::collect()
|
||||
}
|
||||
|
||||
function Reset-HVMachine {
|
||||
<#
|
||||
.Synopsis
|
||||
Resets Horizon View desktops.
|
||||
|
||||
.DESCRIPTION
|
||||
Queries and resets virtual machines, the machines list would be determined
|
||||
based on queryable fields machineName. Use an asterisk (*) as wildcard. If the result has multiple machines all will be reset.
|
||||
Please note that on an Instant Clone Pool this will do the same as a recover of the machine.
|
||||
|
||||
.PARAMETER MachineName
|
||||
The name of the Machine(s) to query for.
|
||||
This is a required value.
|
||||
|
||||
.PARAMETER HvServer
|
||||
Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then
|
||||
first element from global:DefaultHVServers would be considered in-place of hvServer
|
||||
|
||||
.EXAMPLE
|
||||
reset-HVMachine -MachineName 'PowerCLIVM'
|
||||
Queries VM(s) with given parameter machineName
|
||||
|
||||
|
||||
.EXAMPLE
|
||||
reset-HVMachine -MachineName 'PowerCLIVM*'
|
||||
Queries VM(s) with given parameter machinename with wildcard character *
|
||||
|
||||
.NOTES
|
||||
Author : Wouter Kursten
|
||||
Author email : wouter@retouw.nl
|
||||
Version : 1.0
|
||||
|
||||
===Tested Against Environment====
|
||||
Horizon View Server Version : 7.3.2
|
||||
PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1
|
||||
PowerShell Version : 5.0
|
||||
#>
|
||||
|
||||
[CmdletBinding(
|
||||
SupportsShouldProcess = $true,
|
||||
ConfirmImpact = 'High'
|
||||
)]
|
||||
|
||||
param(
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]
|
||||
$MachineName,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
$HvServer = $null
|
||||
)
|
||||
|
||||
|
||||
$services = Get-ViewAPIService -hvServer $hvServer
|
||||
if ($null -eq $services) {
|
||||
Write-Error "Could not retrieve ViewApi services from connection object"
|
||||
break
|
||||
}
|
||||
|
||||
$machineList = Find-HVMachine -Param $PSBoundParameters
|
||||
if (!$machineList) {
|
||||
Write-Host "Reset-HVMachine: No Virtual Machine(s) Found with given search parameters"
|
||||
break
|
||||
}
|
||||
foreach ($machine in $machinelist){
|
||||
$services.machine.Machine_ResetMachines($machine.id)
|
||||
}
|
||||
}
|
||||
|
||||
Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-hvlocalsession, Get-HVGlobalSession, Reset-HVMachine
|
||||
|
||||
Binary file not shown.
@@ -320,4 +320,373 @@ Function Get-VMCSDDCVersion {
|
||||
}
|
||||
}
|
||||
}
|
||||
Export-ModuleMember -Function 'Get-VMCCommand', 'Connect-VMCVIServer', 'Get-VMCOrg', 'Get-VMCSDDC', 'Get-VMCTask', 'Get-VMCSDDCDefaultCredential', 'Get-VMCSDDCPublicIP', 'Get-VMCVMHost', 'Get-VMCSDDCVersion'
|
||||
|
||||
Function Get-VMCFirewallRule {
|
||||
<#
|
||||
.NOTES
|
||||
===========================================================================
|
||||
Created by: William Lam
|
||||
Date: 11/19/2017
|
||||
Organization: VMware
|
||||
Blog: https://www.virtuallyghetto.com
|
||||
Twitter: @lamw
|
||||
===========================================================================
|
||||
|
||||
.SYNOPSIS
|
||||
Retruns VMC Firewall Rules for a given Gateway (MGW or CGW)
|
||||
.DESCRIPTION
|
||||
Retruns VMC Firewall Rules for a given Gateway (MGW or CGW)
|
||||
.EXAMPLE
|
||||
Get-VMCFirewallRule -OrgName <Org Name> -SDDCName <SDDC Name> -GatewayType <MGW or CGW>
|
||||
.EXAMPLE
|
||||
Get-VMCFirewallRule -OrgName <Org Name> -SDDCName <SDDC Name> -GatewayType <MGW or CGW> -ShowAll
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$false)][String]$SDDCName,
|
||||
[Parameter(Mandatory=$false)][String]$OrgName,
|
||||
[Parameter(Mandatory=$false)][Switch]$ShowAll,
|
||||
[Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType
|
||||
)
|
||||
|
||||
if($GatewayType -eq "MGW") {
|
||||
$EdgeId = "edge-1"
|
||||
} else {
|
||||
$EdgeId = "edge-2"
|
||||
}
|
||||
|
||||
$orgId = (Get-VMCOrg -Name $OrgName).Id
|
||||
$sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id
|
||||
|
||||
$firewallConfigService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config
|
||||
|
||||
$firewallRules = ($firewallConfigService.get($orgId, $sddcId, $EdgeId)).firewall_rules.firewall_rules
|
||||
if(-not $ShowAll) {
|
||||
$firewallRules = $firewallRules | where { $_.rule_type -ne "default_policy" -and $_.rule_type -ne "internal_high" -and $_.name -ne "vSphere Cluster HA" -and $_.name -ne "Outbound Access" } | Sort-Object -Property rule_tag
|
||||
} else {
|
||||
$firewallRules = $firewallRules | Sort-Object -Property rule_tag
|
||||
}
|
||||
|
||||
$results = @()
|
||||
foreach ($firewallRule in $firewallRules) {
|
||||
if($firewallRule.source.ip_address.Count -ne 0) {
|
||||
$source = $firewallRule.source.ip_address
|
||||
} else { $source = "ANY" }
|
||||
|
||||
if($firewallRule.application.service.protocol -ne $null) {
|
||||
$protocol = $firewallRule.application.service.protocol
|
||||
} else { $protocol = "ANY" }
|
||||
|
||||
if($firewallRule.application.service.port -ne $null) {
|
||||
$port = $firewallRule.application.service.port
|
||||
} else { $port = "ANY" }
|
||||
|
||||
$tmp = [pscustomobject] @{
|
||||
ID = $firewallRule.rule_id;
|
||||
Name = $firewallRule.name;
|
||||
Type = $firewallRule.rule_type;
|
||||
Action = $firewallRule.action;
|
||||
Protocol = $protocol;
|
||||
Port = $port;
|
||||
SourceAddress = $source
|
||||
DestinationAddress = $firewallRule.destination.ip_address;
|
||||
}
|
||||
$results+=$tmp
|
||||
}
|
||||
$results
|
||||
}
|
||||
|
||||
Function Export-VMCFirewallRule {
|
||||
<#
|
||||
.NOTES
|
||||
===========================================================================
|
||||
Created by: William Lam
|
||||
Date: 11/19/2017
|
||||
Organization: VMware
|
||||
Blog: https://www.virtuallyghetto.com
|
||||
Twitter: @lamw
|
||||
===========================================================================
|
||||
|
||||
.SYNOPSIS
|
||||
Exports all "customer" created VMC Firewall Rules to JSON file
|
||||
.DESCRIPTION
|
||||
Exports all "customer" created VMC Firewall Rules to JSON file
|
||||
.EXAMPLE
|
||||
Export-VMCFirewallRule -OrgName <Org Name> -SDDCName <SDDC Name> -GatewayType <MGW or CGW> -Path "C:\Users\lamw\Desktop\VMCFirewallRules.json"
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$false)][String]$SDDCName,
|
||||
[Parameter(Mandatory=$false)][String]$OrgName,
|
||||
[Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType,
|
||||
[Parameter(Mandatory=$false)][String]$Path
|
||||
)
|
||||
|
||||
if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break }
|
||||
|
||||
if($GatewayType -eq "MGW") {
|
||||
$EdgeId = "edge-1"
|
||||
} else {
|
||||
$EdgeId = "edge-2"
|
||||
}
|
||||
|
||||
$orgId = (Get-VMCOrg -Name $OrgName).Id
|
||||
$sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id
|
||||
|
||||
if(-not $orgId) {
|
||||
Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input"
|
||||
break
|
||||
}
|
||||
if(-not $sddcId) {
|
||||
Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input"
|
||||
break
|
||||
}
|
||||
|
||||
$firewallConfigService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config
|
||||
|
||||
$firewallRules = ($firewallConfigService.get($orgId, $sddcId, $EdgeId)).firewall_rules.firewall_rules
|
||||
if(-not $ShowAll) {
|
||||
$firewallRules = $firewallRules | where { $_.rule_type -ne "default_policy" -and $_.rule_type -ne "internal_high" -and $_.name -ne "vSphere Cluster HA" -and $_.name -ne "Outbound Access" } | Sort-Object -Property rule_tag
|
||||
} else {
|
||||
$firewallRules = $firewallRules | Sort-Object -Property rule_tag
|
||||
}
|
||||
|
||||
$results = @()
|
||||
$count = 0
|
||||
foreach ($firewallRule in $firewallRules) {
|
||||
if($firewallRule.source.ip_address.Count -ne 0) {
|
||||
$source = $firewallRule.source.ip_address
|
||||
} else {
|
||||
$source = "ANY"
|
||||
}
|
||||
|
||||
$tmp = [pscustomobject] @{
|
||||
Name = $firewallRule.name;
|
||||
Action = $firewallRule.action;
|
||||
Protocol = $firewallRule.application.service.protocol;
|
||||
Port = $firewallRule.application.service.port;
|
||||
SourcePort = $firewallRule.application.service.source_port;
|
||||
ICMPType = $firewallRule.application.service.icmp_type;
|
||||
SourceAddress = $firewallRule.source.ip_address;
|
||||
DestinationAddress = $firewallRule.destination.ip_address;
|
||||
Enabled = $firewallRule.enabled;
|
||||
Logging = $firewallRule.logging_enabled;
|
||||
}
|
||||
$count+=1
|
||||
$results+=$tmp
|
||||
}
|
||||
if($Path) {
|
||||
Write-Host -ForegroundColor Green "Exporting $count VMC Firewall Rules to $Path ..."
|
||||
$results | ConvertTo-Json | Out-File $Path
|
||||
} else {
|
||||
$results | ConvertTo-Json
|
||||
}
|
||||
}
|
||||
|
||||
Function Import-VMCFirewallRule {
|
||||
<#
|
||||
.NOTES
|
||||
===========================================================================
|
||||
Created by: William Lam
|
||||
Date: 11/19/2017
|
||||
Organization: VMware
|
||||
Blog: https://www.virtuallyghetto.com
|
||||
Twitter: @lamw
|
||||
===========================================================================
|
||||
|
||||
.SYNOPSIS
|
||||
Imports VMC Firewall Rules from exported JSON configuration file
|
||||
.DESCRIPTION
|
||||
Imports VMC Firewall Rules from exported JSON configuration file
|
||||
.EXAMPLE
|
||||
Import-VMCFirewallRule -OrgName <Org Name> -SDDCName <SDDC Name> -GatewayType <MGW or CGW> -Path "C:\Users\lamw\Desktop\VMCFirewallRules.json"
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$false)][String]$SDDCName,
|
||||
[Parameter(Mandatory=$false)][String]$OrgName,
|
||||
[Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType,
|
||||
[Parameter(Mandatory=$false)][String]$Path
|
||||
)
|
||||
|
||||
if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break }
|
||||
|
||||
if($GatewayType -eq "MGW") {
|
||||
$EdgeId = "edge-1"
|
||||
} else {
|
||||
$EdgeId = "edge-2"
|
||||
}
|
||||
|
||||
$orgId = (Get-VMCOrg -Name $OrgName).Id
|
||||
$sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id
|
||||
|
||||
if(-not $orgId) {
|
||||
Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input"
|
||||
break
|
||||
}
|
||||
if(-not $sddcId) {
|
||||
Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input"
|
||||
break
|
||||
}
|
||||
|
||||
$firewallService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules
|
||||
|
||||
$vmcFirewallRulesJSON = Get-Content -Raw $Path | ConvertFrom-Json
|
||||
|
||||
# Create top level Firewall Rules Object
|
||||
$firewallRules = $firewallService.Help.add.firewall_rules.Create()
|
||||
# Create top top level Firewall Rule Spec which will be an array of individual Firewall rules as we process them in next section
|
||||
$ruleSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Create()
|
||||
|
||||
foreach ($vmcFirewallRule in $vmcFirewallRulesJSON) {
|
||||
# Create Individual Firewall Rule Element Spec
|
||||
$ruleElementSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.Create()
|
||||
|
||||
# AppSpec
|
||||
$appSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.application.Create()
|
||||
# ServiceSpec
|
||||
$serviceSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.application.service.Element.Create()
|
||||
|
||||
$protocol = $null
|
||||
if($vmcFirewallRule.Protocol -ne $null) {
|
||||
$protocol = $vmcFirewallRule.Protocol
|
||||
}
|
||||
$serviceSpec.protocol = $protocol
|
||||
|
||||
# Process ICMP Type from JSON
|
||||
$icmpType = $null
|
||||
if($vmcFirewallRule.ICMPType -ne $null) {
|
||||
$icmpType = $vmcFirewallRule.ICMPType
|
||||
}
|
||||
$serviceSpec.icmp_type = $icmpType
|
||||
|
||||
# Process Source Ports from JSON
|
||||
$sourcePorts = @()
|
||||
if($vmcFirewallRule.SourcePort -eq "any" -or $vmcFirewallRule.SourcePort -ne $null) {
|
||||
foreach ($port in $vmcFirewallRule.SourcePort) {
|
||||
$sourcePorts+=$port
|
||||
}
|
||||
} else {
|
||||
$sourcePorts = @("any")
|
||||
}
|
||||
$serviceSpec.source_port = $sourcePorts
|
||||
|
||||
# Process Ports from JSON
|
||||
$ports = @()
|
||||
if($vmcFirewallRule.Port -ne "null") {
|
||||
foreach ($port in $vmcFirewallRule.Port) {
|
||||
$ports+=$port
|
||||
}
|
||||
}
|
||||
$serviceSpec.port = $ports
|
||||
$addSpec = $appSpec.service.Add($serviceSpec)
|
||||
|
||||
# Create Source Spec
|
||||
$srcSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.source.Create()
|
||||
$srcSpec.exclude = $false
|
||||
# Process Source Address from JSON
|
||||
$sourceAddess = @()
|
||||
if($vmcFirewallRule.SourceAddress -ne "null") {
|
||||
foreach ($address in $vmcFirewallRule.SourceAddress) {
|
||||
$sourceAddess+=$address
|
||||
}
|
||||
}
|
||||
$srcSpec.ip_address = $sourceAddess;
|
||||
|
||||
# Create Destination Spec
|
||||
$destSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.destination.Create()
|
||||
$destSpec.exclude = $false
|
||||
# Process Destination Address from JSON
|
||||
$destinationAddess = @()
|
||||
if($vmcFirewallRule.DestinationAddress -ne "null") {
|
||||
foreach ($address in $vmcFirewallRule.DestinationAddress) {
|
||||
$destinationAddess+=$address
|
||||
}
|
||||
}
|
||||
$destSpec.ip_address = $destinationAddess
|
||||
|
||||
# Add various specs
|
||||
if($vmcFirewallRule.Protocol -ne $null -and $vmcFirewallRule.port -ne $null) {
|
||||
$ruleElementSpec.application = $appSpec
|
||||
}
|
||||
|
||||
$ruleElementSpec.source = $srcSpec
|
||||
$ruleElementSpec.destination = $destSpec
|
||||
$ruleElementSpec.rule_type = "user"
|
||||
|
||||
# Process Enabled from JSON
|
||||
$fwEnabled = $false
|
||||
if($vmcFirewallRule.Enabled -eq "true") {
|
||||
$fwEnabled = $true
|
||||
}
|
||||
$ruleElementSpec.enabled = $fwEnabled
|
||||
|
||||
# Process Logging from JSON
|
||||
$loggingEnabled = $false
|
||||
if($vmcFirewallRule.Logging -eq "true") {
|
||||
$loggingEnabled = $true
|
||||
}
|
||||
$ruleElementSpec.logging_enabled = $loggingEnabled
|
||||
|
||||
$ruleElementSpec.action = $vmcFirewallRule.Action
|
||||
$ruleElementSpec.name = $vmcFirewallRule.Name
|
||||
|
||||
# Add the individual FW rule spec into our overall firewall rules array
|
||||
Write-host "Creating VMC Firewall Rule Spec:" $vmcFirewallRule.Name "..."
|
||||
$ruleSpecAdd = $ruleSpec.Add($ruleElementSpec)
|
||||
}
|
||||
$firewallRules.firewall_rules = $ruleSpec
|
||||
|
||||
Write-host "Adding VMC Firewall Rules ..."
|
||||
$firewallRuleAdd = $firewallService.add($orgId,$sddcId,$EdgeId,$firewallRules)
|
||||
}
|
||||
|
||||
Function Remove-VMCFirewallRule {
|
||||
<#
|
||||
.NOTES
|
||||
===========================================================================
|
||||
Created by: William Lam
|
||||
Date: 11/19/2017
|
||||
Organization: VMware
|
||||
Blog: https://www.virtuallyghetto.com
|
||||
Twitter: @lamw
|
||||
===========================================================================
|
||||
|
||||
.SYNOPSIS
|
||||
Removes VMC Firewall Rule given Rule Id
|
||||
.DESCRIPTION
|
||||
Removes VMC Firewall Rule given Rule Id
|
||||
.EXAMPLE
|
||||
Import-VMCFirewallRule -OrgName <Org Name> -SDDCName <SDDC Name> -GatewayType <MGW or CGW> -RuleId <Rule Id>
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$false)][String]$SDDCName,
|
||||
[Parameter(Mandatory=$false)][String]$OrgName,
|
||||
[Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType,
|
||||
[Parameter(Mandatory=$false)][String]$RuleId
|
||||
)
|
||||
|
||||
if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break }
|
||||
|
||||
if($GatewayType -eq "MGW") {
|
||||
$EdgeId = "edge-1"
|
||||
} else {
|
||||
$EdgeId = "edge-2"
|
||||
}
|
||||
|
||||
$orgId = (Get-VMCOrg -Name $OrgName).Id
|
||||
$sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id
|
||||
|
||||
if(-not $orgId) {
|
||||
Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input"
|
||||
break
|
||||
}
|
||||
if(-not $sddcId) {
|
||||
Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input"
|
||||
break
|
||||
}
|
||||
|
||||
$firewallService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules
|
||||
Write-Host "Removing VMC Firewall Rule Id $RuleId ..."
|
||||
$firewallService.delete($orgId,$sddcId,$EdgeId,$RuleId)
|
||||
}
|
||||
|
||||
|
||||
Export-ModuleMember -Function 'Get-VMCCommand', 'Connect-VMCVIServer', 'Get-VMCOrg', 'Get-VMCSDDC', 'Get-VMCTask', 'Get-VMCSDDCDefaultCredential', 'Get-VMCSDDCPublicIP', 'Get-VMCVMHost', 'Get-VMCSDDCVersion', 'Get-VMCFirewallRule', 'Export-VMCFirewallRule', 'Import-VMCFirewallRule', 'Remove-VMCFirewallRule'
|
||||
20
Scripts/Sample VMC firewall rules management.ps1
Normal file
20
Scripts/Sample VMC firewall rules management.ps1
Normal file
@@ -0,0 +1,20 @@
|
||||
$MyRefreshToken = "XXXX-XXXX-XXXX-XXXX"
|
||||
Connect-VMC -RefreshToken $MyRefreshToken
|
||||
|
||||
#List the user firewall Rules for MGW
|
||||
Get-VMCFirewallRule -SDDCName "vGhetto" -OrgName "BashFest - Red Team" -GatewayType MGW
|
||||
|
||||
#List the firewall rules including system firewall rules for MGW
|
||||
Get-VMCFirewallRule -SDDCName "vGhetto" -OrgName "BashFest - Red Team" -GatewayType MGW -ShowAll
|
||||
|
||||
#Export Firewall Rules from original SDDC
|
||||
Export-VMCFirewallRule -SDDCName "vGhetto" -OrgName "BashFest - Red Team" -GatewayType MGW -Path ~/Desktop/VMCFirewallRules.json
|
||||
|
||||
#Import Firewall Rules to new SDDC
|
||||
Import-VMCFirewallRule -SDDCName “Single-Host-SDDC” -OrgName "BashFest - Red Team" -GatewayType MGW -Path ~/Desktop/VMCFirewallRules.json
|
||||
|
||||
#Remove the firewall Rules we just created for the SDDC
|
||||
$Rules = Get-VMCFirewallRule -SDDCName "Single-Host-SDDC" -OrgName "BashFest - Red Team" -GatewayType MGW
|
||||
Foreach ($rule in $rules){
|
||||
Remove-VMCFirewallRule -SDDCName “Single-Host-SDDC” -OrgName "BashFest - Red Team" -GatewayType MGW -RuleId $rule.id
|
||||
}
|
||||
34
Scripts/VMC Example Script.ps1
Executable file
34
Scripts/VMC Example Script.ps1
Executable file
@@ -0,0 +1,34 @@
|
||||
#List the commands available for the VMC module
|
||||
Get-VMCCommand
|
||||
|
||||
#Connect to VMC
|
||||
$MyRefreshToken = "XXXX-XXXX-XXXX-XXXX"
|
||||
Connect-VMC -RefreshToken $MyRefreshToken
|
||||
|
||||
#List the Orgs available to us
|
||||
Get-VMCOrg
|
||||
|
||||
#List the SDDCs
|
||||
Get-VMCSDDC -Org BashFest*
|
||||
|
||||
#List the Tasks for a particular Org
|
||||
Get-VMCTask -Org BashFest* | Select-Object task_type, Sub_Status, start_time, End_time, user_name | Sort-Object Start_Time | Format-Table
|
||||
|
||||
#Get the Public IPs for a SDDC
|
||||
Get-VMCSDDCPublicIPPool -org bashfest*
|
||||
|
||||
#Get all ESXi hosts for given SDDC
|
||||
Get-VMCVMHost -org bashfest* -Sddc virtu-al
|
||||
|
||||
#Get the credentials of a SDDC so we can login via vSphere cmdlets
|
||||
Get-VMCSDDCDefaultCredential -org bashfest* -Sddc virtu-al
|
||||
|
||||
#Connect to your VMC vCenter with default creds
|
||||
Connect-VmcVIServer -org bashfest* -Sddc virtu-al
|
||||
|
||||
#Run some vSphere cmdlets
|
||||
|
||||
#List all VMs from On-Premises and VMC SDDC
|
||||
Get-VM | Select vCenterServer, Name, PowerState, VMHost
|
||||
|
||||
|
||||
99
Scripts/VMware_Cloud_on_AWS/L2VPN-vMotion-OnPrem-to-VMC.ps1
Executable file
99
Scripts/VMware_Cloud_on_AWS/L2VPN-vMotion-OnPrem-to-VMC.ps1
Executable file
@@ -0,0 +1,99 @@
|
||||
<#
|
||||
.NOTES
|
||||
===========================================================================
|
||||
Created by: Brian Graf
|
||||
Date: January 8, 2018
|
||||
Organization: VMware
|
||||
Blog: brianjgraf.com
|
||||
Twitter: @vBrianGraf
|
||||
===========================================================================
|
||||
|
||||
.DESCRIPTION
|
||||
This will allow you to vMotion workloads from your on-premises environment to VMware Cloud on AWS.
|
||||
|
||||
.NOTES
|
||||
PLEASE NOTE THAT THIS REQUIRES L2 Stretch Network between your on-prem environment and VMC. Without the Layer2 VPN, vMotion will not work.
|
||||
|
||||
.Example
|
||||
# ------------- VARIABLES SECTION - EDIT THE VARIABLES BELOW -------------
|
||||
$destinationvCenter = "vcenter.sddc-52-53-75-20.vmc.vmware.com"
|
||||
$destinationvCenterUser = "clouduser@cloud.local"
|
||||
$destinationvCenterPassword = 'VMware1!'
|
||||
$DestinationResourcePool = "Compute-ResourcePool"
|
||||
$DestinationPortGroup = "L2-Stretch-Network"
|
||||
$DestinationDatastore = "WorkloadDatastore"
|
||||
$DestinationFolder = "Workloads"
|
||||
|
||||
$SourcevCenter = "vcsa-tmm-02.utah.lab" # This is your on-prem vCenter
|
||||
$SourcevCenterUser = "administrator@vsphere.local"
|
||||
$SourcevCenterPassword = "VMware1!"
|
||||
|
||||
# This is an easy way to select which VMs will vMotion up to VMC. The Asterisk
|
||||
# acts as a wildcard
|
||||
$VMs = "BG_Ubuntu_*"
|
||||
#>
|
||||
|
||||
# ------------- VARIABLES SECTION - EDIT THE VARIABLES BELOW -------------
|
||||
$destinationvCenter = "" # This is your VMware Cloud on AWS SDDC
|
||||
$destinationvCenterUser = ""
|
||||
$destinationvCenterPassword = ''
|
||||
$DestinationResourcePool = "" # Name of the resource pool where the VM will be migrated to
|
||||
$DestinationPortGroup = "" # Portgroup name that the VM will be connected to
|
||||
$DestinationDatastore = "" # Name of the vSAN datastore
|
||||
$DestinationFolder = "" # VM folder where the VM will reside
|
||||
|
||||
$SourcevCenter = "" # This is your on-prem vCenter
|
||||
$SourcevCenterUser = ""
|
||||
$SourcevCenterPassword = ""
|
||||
|
||||
# This is an easy way to select which VMs will vMotion up to VMC.
|
||||
$VMs = ""
|
||||
# ------------- END VARIABLES - DO NOT EDIT BELOW THIS LINE -------------
|
||||
|
||||
# Connect to VMC Server
|
||||
$destVCConn = Connect-VIServer -Server $destinationvCenter -User $destinationvCenterUser -Password $destinationvCenterPassword
|
||||
|
||||
# Connect to On-Prem Server
|
||||
$sourceVCConn = connect-viserver $SourcevCenter -User $SourcevCenterUser -Password $SourcevCenterPassword
|
||||
|
||||
# Start numbering for status updates
|
||||
$i = 1
|
||||
|
||||
# Count total VMs selected to move
|
||||
$CountVMstoMove = (Get-VM $VMs -Server $sourceVCConn).Count
|
||||
|
||||
# For each VM Get the necessary information for the migration
|
||||
foreach ($VM in (get-VM $VMs -Server $sourceVCConn)) {
|
||||
|
||||
# Get the network adapter information
|
||||
$networkAdapter = Get-NetworkAdapter -VM $vm -Server $sourceVCConn
|
||||
|
||||
# Get the destination resource pool
|
||||
$destination = Get-Resourcepool $DestinationResourcePool -Server $destVCConn
|
||||
|
||||
# Get the destination portgroup
|
||||
$destinationPortGroup = Get-VDPortgroup -Name $DestinationPortGroup -Server $destVCConn
|
||||
|
||||
# Get the destination datastore
|
||||
$destinationDatastore = Get-Datastore $DestinationDatastore -Server $destVCConn
|
||||
|
||||
# Get the destination folder
|
||||
$folder = get-folder $DestinationFolder -server $destVCConn
|
||||
|
||||
# Write updates as each VM is being migrated
|
||||
Write-host "($i of $CountVMsToMove) Moving " -NoNewline
|
||||
Write-host "$($VM.name) " -NoNewline -ForegroundColor Yellow
|
||||
Write-host "from " -NoNewline
|
||||
Write-host "($SourcevCenter) " -NoNewline -ForegroundColor Yellow
|
||||
Write-host "to " -NoNewline
|
||||
Write-host "($DestinationvCenter) " -ForegroundColor Yellow
|
||||
|
||||
# The actual vMotion command along with a measurement to time the duration of the vMotion
|
||||
$Duration = Measure-Command {Move-VM -VM $vm -Destination $destination -NetworkAdapter $networkAdapter -PortGroup $destinationPortGroup -Datastore $destinationDatastore -InventoryLocation $folder | Out-Null}
|
||||
|
||||
# Write the completion string
|
||||
Write-host " ($i of $CountVMsToMove) Move of $($VM.name) Completed in ($Duration) Minutes!" -ForegroundColor Green
|
||||
|
||||
# Increase our integer by one and move on
|
||||
$i++
|
||||
}
|
||||
Reference in New Issue
Block a user