From 42b923cef5f9852929269cfaa607318886bd6b79 Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Tue, 22 Oct 2019 13:26:10 -0400 Subject: [PATCH 1/9] Create EvacuateVra Function --- .../Public/Invoke-ZertoEvacuateVra.ps1 | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 diff --git a/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 b/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 new file mode 100644 index 0000000..9e6eb0f --- /dev/null +++ b/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 @@ -0,0 +1,58 @@ +function Invoke-ZertoEvacuateVra { + [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = "VraIdentifier")] + param ( + # HostName Option + [Parameter( + Mandatory, + HelpMessage = "Name of the Host to Evacuate", + ParameterSetName = "HostName" + )] + [String]$HostName, + # VRA Option + [Parameter( + Mandatory, + HelpMessage = "Name of the VRA to Evacuate", + ParameterSetName = "VraName" + )] + [String]$VraName, + # VRAIdentifier Option + [Parameter( + Mandatory, + HelpMessage, "Identifier of the VRA to be evacuated", + ParameterSetName = "VraIdentifier", + ValueFromPipelineByPropertyName, + ValueFromPipeline + )] + [Alias("VraId", "Identifier")] + [String]$VraIdentifier + ) + + begin { + + } + + process { + switch ($PSCmdlet.ParameterSetName) { + "HostName" { + $VraName = "Z-VRA-" + $HostName + Invoke-ZertoEvacuateVra -VraName $VraName + } + + "VraName" { + $VraIdentifier = (Get-ZertoVra -vraName $VraName).Identifier + Invoke-ZertoEvacuateVra -VraIdentifier $VraIdentifier + } + + "VraIdentifier" { + $Uri = "vras/{0}/changerecoveryvra/execute" -f $VraIdentifier + if ($PSCmdlet.ShouldProcess($VraIdentifier, "Evacuating VRA with Identifier:")) { + Invoke-ZertoRestRequest -Uri $Uri -Method "POST" + } + } + } + } + + end { + + } +} From 28d66806a552c051e4659d108137787b68147201 Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Tue, 22 Oct 2019 13:31:10 -0400 Subject: [PATCH 2/9] Add ExternalHelp Def --- ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 b/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 index 9e6eb0f..0fd15f4 100644 --- a/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 +++ b/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 @@ -1,3 +1,4 @@ +<# .ExternalHelp ./en-us/ZertoApiWrapper-help.xml #> function Invoke-ZertoEvacuateVra { [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = "VraIdentifier")] param ( From 4a0885f731cdaacedc32d5eeda8ad0b16f33c701 Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Tue, 22 Oct 2019 13:35:49 -0400 Subject: [PATCH 3/9] Fix Help Message Typo --- ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 b/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 index 0fd15f4..c1100a6 100644 --- a/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 +++ b/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 @@ -19,7 +19,7 @@ function Invoke-ZertoEvacuateVra { # VRAIdentifier Option [Parameter( Mandatory, - HelpMessage, "Identifier of the VRA to be evacuated", + HelpMessage = "Identifier of the VRA to be evacuated", ParameterSetName = "VraIdentifier", ValueFromPipelineByPropertyName, ValueFromPipeline From 30422d0421973fdb81fac166b7cd9c0f6c275614 Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Wed, 23 Oct 2019 09:52:09 -0400 Subject: [PATCH 4/9] Create Invoke-ZertoEvacuateVra.md --- docs/Invoke-ZertoEvacuateVra.md | 147 ++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 docs/Invoke-ZertoEvacuateVra.md diff --git a/docs/Invoke-ZertoEvacuateVra.md b/docs/Invoke-ZertoEvacuateVra.md new file mode 100644 index 0000000..bea1ad3 --- /dev/null +++ b/docs/Invoke-ZertoEvacuateVra.md @@ -0,0 +1,147 @@ +--- +external help file: ZertoApiWrapper-help.xml +Module Name: ZertoApiWrapper +online version: https://github.com/ZertoPublic/ZertoApiWrapper/blob/master/docs/Invoke-ZertoEvacuateVra.md +schema: 2.0.0 +--- + +# Invoke-ZertoEvacuateVra + +## SYNOPSIS +This operation will move all VMs currently replicating to the selected host or VRA to different hosts based on internal Zerto algorithms. + +## SYNTAX + +### VraIdentifier (Default) +``` +Invoke-ZertoEvacuateVra -VraIdentifier [-WhatIf] [-Confirm] [] +``` + +### HostName +``` +Invoke-ZertoEvacuateVra -HostName [-WhatIf] [-Confirm] [] +``` + +### VraName +``` +Invoke-ZertoEvacuateVra -VraName [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +This operation will move all VMs currently replicating to the selected host or VRA to different hosts based on internal Zerto algorithms. + +This will return a Zerto Task Identifier so the task progress can be tracked. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Invoke-ZertoEvacuateVra -HostName 'host01' +``` + +Will move all VMs currently replicating to the selected host to different hosts. + +### Example 2 +```powershell +PS C:\> Invoke-ZertoEvacuateVra -VraName 'Z-VRA-host01' +``` + +Will move all VMs currently replicating to the selected VRA to different VRAs. + +### Example 3 +```powershell +PS C:\> Invoke-ZertoEvacuateVra -VraIdentifier '1234-1234-4312-9856' +``` + +Will move all VMs currently replicating to the selected VRA to different VRAs. + +## PARAMETERS + +### -HostName +HostName Option + +```yaml +Type: String +Parameter Sets: HostName +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -VraIdentifier +VRAIdentifier Option + +```yaml +Type: String +Parameter Sets: VraIdentifier +Aliases: VraId, Identifier + +Required: True +Position: Named +Default value: None +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### -VraName +VRA Option + +```yaml +Type: String +Parameter Sets: VraName +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS +[Zerto REST API Evacuate VRA End Point Documentation](http://s3.amazonaws.com/zertodownload_docs/Latest/Zerto%20Virtual%20Replication%20Zerto%20Virtual%20Manager%20%28ZVM%29%20-%20vSphere%20Online%20Help/index.html#page/RestfulAPIs%2FStatusAPIs.5.129.html%23) + From 7641d283071196cd6d3d936d2ef704f53204ef4b Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Wed, 23 Oct 2019 10:00:42 -0400 Subject: [PATCH 5/9] Add parameter validation --- ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 b/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 index c1100a6..72a9cab 100644 --- a/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 +++ b/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 @@ -8,6 +8,7 @@ function Invoke-ZertoEvacuateVra { HelpMessage = "Name of the Host to Evacuate", ParameterSetName = "HostName" )] + [ValidateNotNullOrEmpty()] [String]$HostName, # VRA Option [Parameter( @@ -15,6 +16,7 @@ function Invoke-ZertoEvacuateVra { HelpMessage = "Name of the VRA to Evacuate", ParameterSetName = "VraName" )] + [ValidateNotNullOrEmpty()] [String]$VraName, # VRAIdentifier Option [Parameter( @@ -25,6 +27,7 @@ function Invoke-ZertoEvacuateVra { ValueFromPipeline )] [Alias("VraId", "Identifier")] + [ValidateNotNullOrEmpty()] [String]$VraIdentifier ) From 07de073bf137b1650ddc9d46b2497a7d4cf2af6d Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Thu, 24 Oct 2019 07:25:38 -0400 Subject: [PATCH 6/9] Create Invoke-ZertoEvacuateVra.Tests.ps1 --- .../Public/Invoke-ZertoEvacuateVra.Tests.ps1 | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 Tests/Public/Invoke-ZertoEvacuateVra.Tests.ps1 diff --git a/Tests/Public/Invoke-ZertoEvacuateVra.Tests.ps1 b/Tests/Public/Invoke-ZertoEvacuateVra.Tests.ps1 new file mode 100644 index 0000000..c518f90 --- /dev/null +++ b/Tests/Public/Invoke-ZertoEvacuateVra.Tests.ps1 @@ -0,0 +1,53 @@ +#Requires -Modules Pester +$global:here = (Split-Path -Parent $MyInvocation.MyCommand.Path) +$global:function = ((Split-Path -leaf $MyInvocation.MyCommand.Path).Split('.'))[0] + +Describe $global:function -Tag 'Unit', 'Source', 'Built' { + + Context "$global:function::Parameter Unit Tests" { + it "$global:function should have exactly 16 parameters defined" { + (get-command $global:function).Parameters.Count | Should -Be 16 + } + + $ParameterTestCases = @( + @{ParameterName = 'hostName'; Type = 'String'; Mandatory = $true; Validation = 'NotNullOrEmpty'; ParameterSet = @('hostName') } + @{ParameterName = 'vraName'; Type = 'String'; Mandatory = $true; Validation = 'NotNullOrEmpty' ; ParameterSet = @('vraName') } + @{ParameterName = 'vraIdentifier'; Type = 'String'; Mandatory = $true; Validation = 'NotNullOrEmpty' ; ParameterSet = @('vraIdentifier') } + ) + + It " parameter is of type" -TestCases $ParameterTestCases { + param($ParameterName, $Type, $Mandatory, $Validation) + Get-Command $global:function | Should -HaveParameter $ParameterName -Mandatory:$Mandatory -Type $Type + } + + It " parameter has correct validation setting" -TestCases $ParameterTestCases { + param($ParameterName, $Validation) + Switch ($Validation) { + 'NotNullOrEmpty' { + $attrs = (Get-Command $global:function).Parameters[$ParameterName].Attributes + $attrs.Where{ $_ -is [ValidateNotNullOrEmpty] }.Count | Should -Be 1 + } + + $null { + $attrs = (Get-Command $global:function).Parameters[$ParameterName].Attributes + $attrs.TypeId.Count | Should -Be 2 + } + } + } + + It " parameter is part of the correct ParameterSet(s)" -TestCases $ParameterTestCases { + param($ParameterName, $ParameterSet) + $commandParameterSets = (Get-Command $global:function).Parameters[$ParameterName].ParameterSets + foreach ($Set in $ParameterSet) { + $commandParameterSets.ContainsKey($Set) | Should -BeTrue + } + } + } + + Context "$global:function::Parameter Functional Tests" { + + } +} + +Remove-Variable -Name here -Scope Global +Remove-Variable -Name function -Scope Global From 3d8acf03f68ac7231373d3d7012b405591438249 Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Thu, 24 Oct 2019 13:50:52 -0400 Subject: [PATCH 7/9] Update Tests to include set counts --- Tests/Public/Invoke-ZertoEvacuateVra.Tests.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Tests/Public/Invoke-ZertoEvacuateVra.Tests.ps1 b/Tests/Public/Invoke-ZertoEvacuateVra.Tests.ps1 index c518f90..47629c7 100644 --- a/Tests/Public/Invoke-ZertoEvacuateVra.Tests.ps1 +++ b/Tests/Public/Invoke-ZertoEvacuateVra.Tests.ps1 @@ -5,8 +5,8 @@ $global:function = ((Split-Path -leaf $MyInvocation.MyCommand.Path).Split('.'))[ Describe $global:function -Tag 'Unit', 'Source', 'Built' { Context "$global:function::Parameter Unit Tests" { - it "$global:function should have exactly 16 parameters defined" { - (get-command $global:function).Parameters.Count | Should -Be 16 + It "$global:function should have exactly 16 parameters defined" { + (Get-Command $global:function).Parameters.Count | Should -Be 16 } $ParameterTestCases = @( @@ -41,6 +41,7 @@ Describe $global:function -Tag 'Unit', 'Source', 'Built' { foreach ($Set in $ParameterSet) { $commandParameterSets.ContainsKey($Set) | Should -BeTrue } + $commandParameterSets.Count | Should -Be $ParameterSet.Count } } From b4a7df970c1fa0ad01bca00fc270ef581ab590a3 Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Thu, 24 Oct 2019 13:51:26 -0400 Subject: [PATCH 8/9] Correct VraIdentifier Property --- ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 b/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 index 72a9cab..d01ae9e 100644 --- a/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 +++ b/ZertoApiWrapper/Public/Invoke-ZertoEvacuateVra.ps1 @@ -43,7 +43,7 @@ function Invoke-ZertoEvacuateVra { } "VraName" { - $VraIdentifier = (Get-ZertoVra -vraName $VraName).Identifier + $VraIdentifier = (Get-ZertoVra -vraName $VraName).VraIdentifier Invoke-ZertoEvacuateVra -VraIdentifier $VraIdentifier } From 1ca3d6704b6dcffff3cef0ff3cff0f3178e975b9 Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Fri, 25 Oct 2019 13:49:59 -0400 Subject: [PATCH 9/9] Update Release Notes for Evacuate Function --- RELEASENOTES.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0cddecd..88b7fb5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -4,7 +4,8 @@ * [Zerto version 7.5 has been released.](https://s3.amazonaws.com/zertodownload_docs/Latest/Zerto%20Virtual%20Replication%20Release%20Notes.pdf) As part of this release Zerto has added API functionality that requires the following updates. * A token is now required to pair two sites together. The need is discussed in [Issue 46](https://github.com/ZertoPublic/ZertoApiWrapper/issues/46). To implement this change a `-token` parameter has been added to the `Add-ZertoPeerSite` function. - * A new function has been added; `New-ZertoPairingToken`. This function will allow users to generate a pairing authentication token from the target ZVM to be used in the pairing process. [Issue 47](https://github.com/ZertoPublic/ZertoApiWrapper/issues) covers additional details. + * A new function has been added; `New-ZertoPairingToken`. This function will allow users to generate a pairing authentication token from the target ZVM to be used in the pairing process. [Issue 47](https://github.com/ZertoPublic/ZertoApiWrapper/issues/47) covers additional details. + * A new function has been added; `Invoke-ZertoEvacuateVra`. This function will allow users to evacuate a target VRA by specifying a Host Name, VRA Name, or VRA Identifier. All VMs currently replicating to the specified location will be migrated to different targets. [Issue 51](https://github.com/ZertoPublic/ZertoApiWrapper/issues/51) ### Zerto Analytics