From 0630cbb20e0c9ccb512a26f01575b02c7dec2065 Mon Sep 17 00:00:00 2001 From: Brownstein Date: Fri, 21 Aug 2020 21:04:15 -0400 Subject: [PATCH 1/8] new param sets, pipeline input --- ZertoApiWrapper/Public/Invoke-ZertoMove.ps1 | 121 ++++++++++++-------- 1 file changed, 75 insertions(+), 46 deletions(-) diff --git a/ZertoApiWrapper/Public/Invoke-ZertoMove.ps1 b/ZertoApiWrapper/Public/Invoke-ZertoMove.ps1 index 476f7d3..6ea5d04 100644 --- a/ZertoApiWrapper/Public/Invoke-ZertoMove.ps1 +++ b/ZertoApiWrapper/Public/Invoke-ZertoMove.ps1 @@ -1,22 +1,57 @@ <# .ExternalHelp ./en-us/ZertoApiWrapper-help.xml #> function Invoke-ZertoMove { - [CmdletBinding( DefaultParameterSetName = "main", SupportsShouldProcess = $true )] + [CmdletBinding( DefaultParameterSetName = "id", SupportsShouldProcess = $true )] param( [Parameter( + ParameterSetName = 'name', + HelpMessage = "Name(s) of the VPG(s) you want to move.", + Mandatory + )] + [Parameter( + ParameterSetName = 'commitName', HelpMessage = "Name(s) of the VPG(s) you want to move.", Mandatory )] [ValidateNotNullOrEmpty()] [string[]]$vpgName, [Parameter( + ParameterSetName = 'id', + HelpMessage = "ID(s) of the VPG(s) you want to move.", + Mandatory, + ValueFromPipelineByPropertyName + )] + [Parameter( + ParameterSetName = 'commitId', + HelpMessage = "ID(s) of the VPG(s) you want to move.", + Mandatory, + ValueFromPipelineByPropertyName + )] + [ValidateNotNullOrEmpty()] + [guid[]]$vpgIdentifier, + [Parameter( + ParameterSetName = 'commitName', HelpMessage = "'Rollback': After the seconds specified in the commitValue setting have elapsed, the failover is rolled back. 'Commit': After the seconds specified in the commitValue setting have elapsed, the failover continues, committing the virtual machines in the recovery site. 'None': The virtual machines in the VPG being failed over remain in the Before Commit state until either they are committed with Commit a failover, or rolled back with Roll back a failover. - Default is the Site Settings setting." + Default is the Site Settings setting.", + Mandatory + )] + [Parameter( + ParameterSetName = 'commitId', + HelpMessage = "'Rollback': After the seconds specified in the commitValue setting have elapsed, the failover is rolled back. + 'Commit': After the seconds specified in the commitValue setting have elapsed, the failover continues, committing the virtual machines in the recovery site. + 'None': The virtual machines in the VPG being failed over remain in the Before Commit state until either they are committed with Commit a failover, or rolled back with Roll back a failover. + Default is the Site Settings setting.", + Mandatory )] [ValidateSet("Rollback", "Commit", "None")] [string]$commitPolicy, [Parameter( + ParameterSetName = 'commitName', + HelpMessage = "The amount of time, in seconds, the Move is in a 'Before Commit' state, before performing the commitPolicy setting. If omitted, the site settings default will be applied." + )] + [Parameter( + ParameterSetName = 'commitId', HelpMessage = "The amount of time, in seconds, the Move is in a 'Before Commit' state, before performing the commitPolicy setting. If omitted, the site settings default will be applied." )] # Min 5 Minutes, Max 24 Hours, Default Site Settigns. @@ -27,15 +62,11 @@ function Invoke-ZertoMove { )] [switch]$forceShutdown, [Parameter( - ParameterSetName = "disableReverseProtection", - HelpMessage = "Do not enable reverse protection. The VPG definition is kept with the status Needs Configuration and the reverse settings in the VPG definition are not set.", - Mandatory + HelpMessage = "Do not enable reverse protection. The VPG definition is kept with the status Needs Configuration and the reverse settings in the VPG definition are not set." )] [switch]$disableReverseProtection, [Parameter( - ParameterSetName = "keepSourceVms", - HelpMessage = "Prevent the protected virtual machines from being deleted in the protected site. Using this setting disables reverse protection.", - Mandatory + HelpMessage = "Prevent the protected virtual machines from being deleted in the protected site. Using this setting disables reverse protection." )] [switch]$keepSourceVms, [Parameter( @@ -46,52 +77,50 @@ function Invoke-ZertoMove { begin { $baseUri = "vpgs" + $body = @{ + forceShutdown = $forceShutdown.IsPresent + ContinueOnPreScriptFailure = $ContinueOnPreScriptFailure.IsPresent + keepSourceVms = $keepSourceVms.IsPresent + reverseProtection = -not $disableReverseProtection.IsPresent + } + + if ( $keepSourceVms -and -not $disableReverseProtection ) { + Write-Verbose 'Disabling reverse protection as keepSourceVms requires it' + $body['reverseProtection'] = $false + } + + if ($PSBoundParameters.ContainsKey('commitPolicy')) { + $body['commitPolicy'] = $commitPolicy + if ($PSBoundParameters.ContainsKey('commitPolicyTimeout')) { + $body['commitPolicyTimeout'] = $commitPolicyTimeout + } + } } process { - $body = @{ } - #TODO - use a foreach loop to populate the body without all the if statments - if ($PSBoundParameters.ContainsKey('commitPolicy')) { - $body['commitPolicy'] = $commitPolicy - } - if ($PSBoundParameters.ContainsKey('commitPolicyTimeout')) { - $body['commitPolicyTimeout'] = $commitPolicyTimeout - } - if ($PSBoundParameters.ContainsKey('forceShutdown')) { - $body['forceShutdown'] = $true - } else { - $body['forceShutdown'] = $false - } - if ($PSBoundParameters.ContainsKey('ContinueOnPreScriptFailure')) { - $body['ContinueOnPreScriptFailure'] = $true - } else { - $body['ContinueOnPreScriptFailure'] = $false - } + switch ($PSCmdlet.ParameterSetName) { - "disableReverseProtection" { - $body['reverseProtection'] = $false - $body['keepSourceVms'] = $false + { $_ -in 'name', 'commitName' } { + $vpgIds = foreach ($name in $vpgName) { + $vpgId = $(Get-ZertoVpg -name $name).vpgIdentifier + if ( -not $vpgId ) { + Write-Error "VPG: '$name' not found. Please check the name and try again. Skipping" + } else { + Write-Verbose "VPG: $name, ID: $vpgId" + $vpgId + } + } } - "keepSourceVms" { - $body['reverseProtection'] = $false - $body['keepSourceVms'] = $true - } - - "main" { - $body['reverseProtection'] = $true - $body['keepSourceVms'] = $false + { $_ -in 'id', 'commitId' } { + $vpgIds = $vpgIdentifier } } - foreach ($name in $vpgName) { - $vpgId = $(Get-ZertoVpg -name $name).vpgIdentifier - if ( -not $vpgId ) { - Write-Error "VPG: $name not found. Please check the name and try again. Skipping" - } else { - $uri = "{0}/{1}/move" -f $baseUri, $vpgId - if ($PSCmdlet.ShouldProcess("Moving VPG: $name with settings: $($body | convertto-json)")) { - Invoke-ZertoRestRequest -uri $uri -method "POST" -body $($body | ConvertTo-Json) - } + + foreach ($thisId in $vpgIds) { + $uri = "{0}/{1}/move" -f $baseUri, $thisId + if ($PSCmdlet.ShouldProcess("Moving VPG: $thisId with settings: $($body | ConvertTo-Json)")) { + Invoke-ZertoRestRequest -uri $uri -method "POST" -body $($body | ConvertTo-Json) } } } From eea6e959881ee1ca0d772f4c187f89cabb445c5f Mon Sep 17 00:00:00 2001 From: Brownstein Date: Thu, 27 Aug 2020 15:08:28 -0400 Subject: [PATCH 2/8] update test and help files --- Tests/Public/Invoke-ZertoMove.Tests.ps1 | 8 +-- docs/Invoke-ZertoMove.md | 73 +++++++++++++++++++------ 2 files changed, 59 insertions(+), 22 deletions(-) diff --git a/Tests/Public/Invoke-ZertoMove.Tests.ps1 b/Tests/Public/Invoke-ZertoMove.Tests.ps1 index aaca87b..d3b398b 100644 --- a/Tests/Public/Invoke-ZertoMove.Tests.ps1 +++ b/Tests/Public/Invoke-ZertoMove.Tests.ps1 @@ -5,8 +5,8 @@ $global:function = ((Split-Path -leaf $PSCommandPath).Split('.'))[0] Describe $global:function -Tag 'Unit', 'Source', 'Built' { Context "$global:function::Parameter Unit Tests" { - It "$global:function should have exactly 20 parameters defined" { - (Get-Command $global:function).Parameters.Count | Should -Be 20 + It "$global:function should have exactly 21 parameters defined" { + (Get-Command $global:function).Parameters.Count | Should -Be 21 } $ParameterTestCases = @( @@ -14,8 +14,8 @@ Describe $global:function -Tag 'Unit', 'Source', 'Built' { @{ParameterName = 'commitPolicy'; Type = 'String'; Mandatory = $false; Validation = 'Set' } @{ParameterName = 'commitPolicyTimeout'; Type = 'Int'; Mandatory = $false; Validation = 'Range' } @{ParameterName = 'forceShutdown'; Type = 'Switch'; Mandatory = $false; Validation = $null } - @{ParameterName = 'disableReverseProtection'; Type = 'Switch'; Mandatory = $true; Validation = $null } - @{ParameterName = 'keepSourceVms'; Type = 'Switch'; Mandatory = $true; Validation = $null } + @{ParameterName = 'disableReverseProtection'; Type = 'Switch'; Mandatory = $false; Validation = $null } + @{ParameterName = 'keepSourceVms'; Type = 'Switch'; Mandatory = $false; Validation = $null } @{ParameterName = 'ContinueOnPreScriptFailure'; Type = 'Switch'; Mandatory = $false; Validation = $null } @{ParameterName = 'whatIf'; Type = 'Switch'; Mandatory = $false; Validation = 'ShouldProcess' } ) diff --git a/docs/Invoke-ZertoMove.md b/docs/Invoke-ZertoMove.md index eb1c661..030ba21 100644 --- a/docs/Invoke-ZertoMove.md +++ b/docs/Invoke-ZertoMove.md @@ -12,22 +12,30 @@ Start a move of a VPG. ## SYNTAX -### main (Default) +### id (Default) ``` -Invoke-ZertoMove -vpgName [-commitPolicy ] [-commitPolicyTimeout ] [-forceShutdown] +Invoke-ZertoMove -vpgIdentifier [-forceShutdown] [-disableReverseProtection] [-keepSourceVms] [-ContinueOnPreScriptFailure] [-WhatIf] [-Confirm] [] ``` -### disableReverseProtection +### commitName ``` -Invoke-ZertoMove -vpgName [-commitPolicy ] [-commitPolicyTimeout ] [-forceShutdown] - [-disableReverseProtection] [-ContinueOnPreScriptFailure] [-WhatIf] [-Confirm] [] +Invoke-ZertoMove -vpgName -commitPolicy [-commitPolicyTimeout ] [-forceShutdown] + [-disableReverseProtection] [-keepSourceVms] [-ContinueOnPreScriptFailure] [-WhatIf] [-Confirm] + [] ``` -### keepSourceVms +### name ``` -Invoke-ZertoMove -vpgName [-commitPolicy ] [-commitPolicyTimeout ] [-forceShutdown] - [-keepSourceVms] [-ContinueOnPreScriptFailure] [-WhatIf] [-Confirm] [] +Invoke-ZertoMove -vpgName [-forceShutdown] [-disableReverseProtection] [-keepSourceVms] + [-ContinueOnPreScriptFailure] [-WhatIf] [-Confirm] [] +``` + +### commitId +``` +Invoke-ZertoMove -vpgIdentifier -commitPolicy [-commitPolicyTimeout ] [-forceShutdown] + [-disableReverseProtection] [-keepSourceVms] [-ContinueOnPreScriptFailure] [-WhatIf] [-Confirm] + [] ``` ## DESCRIPTION @@ -37,10 +45,24 @@ Start a move of a VPG. ### Example 1 ```powershell -PS C:\> Invoke-ZertoMove -vpgName "MyVpg" +PS C:\> Invoke-ZertoMove -vpgName 'MyVpg' ``` -Starts a move operation of VPG "MyVpg" +Specify the name of a vpg to move + +### Example 2 +```powershell +PS C:\> Invoke-ZertoMove -vpgIdentifier '2fbbf6b5-cddc-4653-b1fe-564f069eeb64' +``` + +Specify the identifier of a vpg to move + +### Example 3 +```powershell +PS C:\> Get-ZertoVpg | Invoke-ZertoMove +``` + +Utilize the pipeline to move multiple vpgs ## PARAMETERS @@ -55,11 +77,11 @@ Default is the Site Settings setting. ```yaml Type: String -Parameter Sets: (All) +Parameter Sets: commitName, commitId Aliases: Accepted values: Rollback, Commit, None -Required: False +Required: True Position: Named Default value: None Accept pipeline input: False @@ -72,7 +94,7 @@ If omitted, the site settings default will be applied. ```yaml Type: Int32 -Parameter Sets: (All) +Parameter Sets: commitName, commitId Aliases: Required: False @@ -102,10 +124,10 @@ Do not enable reverse protection. The VPG definition is kept with the status Nee ```yaml Type: SwitchParameter -Parameter Sets: disableReverseProtection +Parameter Sets: (All) Aliases: -Required: True +Required: False Position: Named Default value: None Accept pipeline input: False @@ -132,13 +154,28 @@ Use this switch to Prevent the protected virtual machines from being deleted in ```yaml Type: SwitchParameter -Parameter Sets: keepSourceVms +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -vpgIdentifier +ID(s) of the VPG(s) you want to move. + +```yaml +Type: Guid[] +Parameter Sets: id, commitId Aliases: Required: True Position: Named Default value: None -Accept pipeline input: False +Accept pipeline input: True (ByPropertyName) Accept wildcard characters: False ``` @@ -147,7 +184,7 @@ Name(s) of the VPG(s) you want to move. ```yaml Type: String[] -Parameter Sets: (All) +Parameter Sets: commitName, name Aliases: Required: True From 139e52f3e27f85bb41261dfe8de38d0ee327fcf9 Mon Sep 17 00:00:00 2001 From: Brownstein Date: Thu, 27 Aug 2020 15:28:01 -0400 Subject: [PATCH 3/8] add new parameter to test --- Tests/Public/Invoke-ZertoMove.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Public/Invoke-ZertoMove.Tests.ps1 b/Tests/Public/Invoke-ZertoMove.Tests.ps1 index d3b398b..efb1260 100644 --- a/Tests/Public/Invoke-ZertoMove.Tests.ps1 +++ b/Tests/Public/Invoke-ZertoMove.Tests.ps1 @@ -10,6 +10,7 @@ Describe $global:function -Tag 'Unit', 'Source', 'Built' { } $ParameterTestCases = @( + @{ParameterName = 'vpgIdentifier'; Type = 'Guid[]'; Mandatory = $true; Validation = 'NotNullOrEmpty' } @{ParameterName = 'vpgName'; Type = 'String[]'; Mandatory = $true; Validation = 'NotNullOrEmpty' } @{ParameterName = 'commitPolicy'; Type = 'String'; Mandatory = $false; Validation = 'Set' } @{ParameterName = 'commitPolicyTimeout'; Type = 'Int'; Mandatory = $false; Validation = 'Range' } From f0279633dd86a521b6fdad365afdc9e6285374b9 Mon Sep 17 00:00:00 2001 From: Brownstein Date: Fri, 28 Aug 2020 13:43:22 -0400 Subject: [PATCH 4/8] add missing .IsPresent for switch value --- ZertoApiWrapper/Public/Invoke-ZertoMove.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZertoApiWrapper/Public/Invoke-ZertoMove.ps1 b/ZertoApiWrapper/Public/Invoke-ZertoMove.ps1 index 6ea5d04..a63bb98 100644 --- a/ZertoApiWrapper/Public/Invoke-ZertoMove.ps1 +++ b/ZertoApiWrapper/Public/Invoke-ZertoMove.ps1 @@ -84,7 +84,7 @@ function Invoke-ZertoMove { reverseProtection = -not $disableReverseProtection.IsPresent } - if ( $keepSourceVms -and -not $disableReverseProtection ) { + if ( $keepSourceVms.IsPresent -and -not $disableReverseProtection.IsPresent ) { Write-Verbose 'Disabling reverse protection as keepSourceVms requires it' $body['reverseProtection'] = $false } From e6b5777e64f33f41e246dcf509a1501cd1dfdbcc Mon Sep 17 00:00:00 2001 From: jonsouzerto <57370019+jonsouzerto@users.noreply.github.com> Date: Thu, 3 Sep 2020 12:45:35 -0400 Subject: [PATCH 5/8] Updated recovery host key Attempting to resolve issue 108 --- ZertoApiWrapper/Public/New-ZertoVpg.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ZertoApiWrapper/Public/New-ZertoVpg.ps1 b/ZertoApiWrapper/Public/New-ZertoVpg.ps1 index 710f51d..582e0cc 100644 --- a/ZertoApiWrapper/Public/New-ZertoVpg.ps1 +++ b/ZertoApiWrapper/Public/New-ZertoVpg.ps1 @@ -295,11 +295,11 @@ function New-ZertoVpg { "recoveryHostDatastoreCluster" { $baseSettings.Recovery.DefaultDatastoreClusterIdentifier = $identifiersTable['datastoreClusterIdentifier'] - $baseSettings.Recovery.DefaultHostIdentifier = $identifiersTable['hostIdentifier'] + $baseSettings.Recovery.DefaultHostIdentifier = $identifiersTable['recoveryHostIdentifier'] } "recoveryHostDatastore" { - $baseSettings.Recovery.DefaultHostIdentifier = $identifiersTable['hostIdentifier'] + $baseSettings.Recovery.DefaultHostIdentifier = $identifiersTable['recoveryHostIdentifier'] $baseSettings.Recovery.DefaultDatastoreIdentifier = $identifiersTable['datastoreIdentifier'] } From bb5dbaa0d46c2a3cf63d3c6f5f504e5ada1a811a Mon Sep 17 00:00:00 2001 From: jonsouzerto <57370019+jonsouzerto@users.noreply.github.com> Date: Thu, 3 Sep 2020 12:50:49 -0400 Subject: [PATCH 6/8] Update CHANGELOG.md Added fix information --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index beb3345..0c82604 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project is transitioning to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Zerto Virtual Manager + +#### Fixed + +* Fixed an [issue](https://github.com/ZertoPublic/ZertoApiWrapper/issues/108) with `New-ZertoVpg` where the Host Identifier was incorrect when inputting a single recovery host, changed to recoveryHostIdentifier. + ## [1.5.0] ### Zerto Virtual Manager From 5c2dd620d88a09e5fbf9a3e725fbe8cf8990e981 Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Tue, 8 Sep 2020 08:20:29 -0400 Subject: [PATCH 7/8] Update for Release Notes --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c82604..ffc6a35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project is transitioning to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## [1.5.1] ### Zerto Virtual Manager #### Fixed -* Fixed an [issue](https://github.com/ZertoPublic/ZertoApiWrapper/issues/108) with `New-ZertoVpg` where the Host Identifier was incorrect when inputting a single recovery host, changed to recoveryHostIdentifier. +* Fixed an [issue](https://github.com/ZertoPublic/ZertoApiWrapper/issues/108) with `New-ZertoVpg` where when specifying a single host as a recovery target, the host identifier was not properly assigned. - Thanks @jonsouzerto! +* Fixed an [issue](https://github.com/ZertoPublic/ZertoApiWrapper/issues/86) with `Invoke-ZertoMoveVpg` where parameters should have been mandatory in certain workflows. - Thanks @gdbarron! ## [1.5.0] From e6e6be9eded0b209d547a15b18412764a7eaa7c9 Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Tue, 8 Sep 2020 08:21:10 -0400 Subject: [PATCH 8/8] Bump Version --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index bc80560..26ca594 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.5.0 +1.5.1