Skip to content

[Storage] Support Planned and Unplanned failoverType in Storage account failover #20311

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Storage/Storage.Management/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
- Additional information about change #1
-->
## Upcoming Release
* Supported Planned and Unplanned types in Storage account failover type
- `Invoke-AzStorageAccountFailover`
* Supported TierToCold and TierToHot in Storage account management policy
- `Add-AzStorageAccountManagementPolicyAction`
* Supported MaxPageSize, Include, and Filter parameters for listing encryption scopes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ public class InvokeAzureStorageAccountFailoverCommand : StorageAccountBaseCmdlet
[ValidateNotNullOrEmpty]
public string Name { get; set; }

[Parameter(
Mandatory = false,
HelpMessage = "Specify the failover type. Possible values are: Unplanned, Planned. If not specified, the default failover type is Unplanned.")]
[PSArgumentCompleter(AccountFailoverType.Planned,
AccountFailoverType.Unplanned)]
public string FailoverType { get; set; }

[Parameter(Mandatory = true,
HelpMessage = "Storage account object",
ValueFromPipeline = true,
Expand All @@ -83,30 +90,53 @@ public override void ExecuteCmdlet()

if (ShouldProcess(this.Name, "Invoke Failover of Storage Account"))
{
StringBuilder shouldContinuePrompt = new StringBuilder();
shouldContinuePrompt.AppendLine("Failover the storage account, the secondary cluster will become primary after failover. Please understand the following impact to your storage account before you initiate the failover:");
shouldContinuePrompt.AppendLine(" 1. Please check the Last Sync Time using Get-"+ ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "StorageAccount cmdlet with -IncludeGeoReplicationStats parameter, and check GeoReplicationStats property of your account. This is the data you may lose if you initiate the failover.");
shouldContinuePrompt.AppendLine(" 2. After the failover, your storage account type will be converted to locally redundant storage (LRS). You can convert your account to use geo-redundant storage (GRS).");
shouldContinuePrompt.AppendLine(" 3. Once you re-enable GRS for your storage account, Microsoft will replicate data to your new secondary region. Replication time is dependent on the amount of data to replicate. Please note that there are bandwidth charges for the bootstrap. Please refer to doc: https://azure.microsoft.com/en-us/pricing/details/bandwidth/");


if (this.force || ShouldContinue(shouldContinuePrompt.ToString(), ""))
if (ParameterSetName == AccountObjectParameterSet)
{
if (ParameterSetName == AccountObjectParameterSet)
this.ResourceGroupName = InputObject.ResourceGroupName;
this.Name = InputObject.StorageAccountName;
}

StorageModels.FailoverType? type = null;
if (!String.IsNullOrEmpty(this.FailoverType)) {
if (this.FailoverType.ToLower() == AccountFailoverType.Planned.ToLower())
{
this.ResourceGroupName = InputObject.ResourceGroupName;
this.Name = InputObject.StorageAccountName;
type = StorageModels.FailoverType.Planned;
}
else if (this.FailoverType.ToLower() != AccountFailoverType.Unplanned.ToLower())
{
throw new ArgumentException(string.Format("The Failover Type {0} is invalid.", this.FailoverType), "FailoverType");
}
}

this.StorageClient.StorageAccounts.Failover(
this.ResourceGroupName,
this.Name);

var storageAccount = this.StorageClient.StorageAccounts.GetProperties(this.ResourceGroupName, this.Name);
if (type == null) {
StringBuilder shouldContinuePrompt = new StringBuilder();
shouldContinuePrompt.AppendLine("Failover the storage account, the secondary cluster will become primary after failover. Please understand the following impact to your storage account before you initiate the failover:");
shouldContinuePrompt.AppendLine(" 1. Please check the Last Sync Time using Get-" + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "StorageAccount cmdlet with -IncludeGeoReplicationStats parameter, and check GeoReplicationStats property of your account. This is the data you may lose if you initiate the failover.");
shouldContinuePrompt.AppendLine(" 2. After the failover, your storage account type will be converted to locally redundant storage (LRS). You can convert your account to use geo-redundant storage (GRS).");
shouldContinuePrompt.AppendLine(" 3. Once you re-enable GRS for your storage account, Microsoft will replicate data to your new secondary region. Replication time is dependent on the amount of data to replicate. Please note that there are bandwidth charges for the bootstrap. Please refer to doc: https://azure.microsoft.com/en-us/pricing/details/bandwidth/");

if (this.force || ShouldContinue(shouldContinuePrompt.ToString(), ""))
{
ExecuteFailover(type);
}

WriteStorageAccount(storageAccount);
} else
{
ExecuteFailover(type);
}
}
}

private void ExecuteFailover(StorageModels.FailoverType? type = null)
{
this.StorageClient.StorageAccounts.Failover(
this.ResourceGroupName,
this.Name,
type);

var storageAccount = this.StorageClient.StorageAccounts.GetProperties(this.ResourceGroupName, this.Name);

WriteStorageAccount(storageAccount);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ protected struct DefaultSharePermissionType
internal const string StorageFileDataSmbShareOwner = "StorageFileDataSmbShareOwner";
}

protected struct AccountFailoverType
{
internal const string Planned = "Planned";
internal const string Unplanned = "Unplanned";
}

public IStorageManagementClient StorageClient
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ Invokes failover of a Storage account.

### AccountName (Default)
```
Invoke-AzStorageAccountFailover [-ResourceGroupName] <String> [-Name] <String> [-Force] [-AsJob]
[-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm] [<CommonParameters>]
Invoke-AzStorageAccountFailover [-ResourceGroupName] <String> [-Name] <String> [-FailoverType <String>]
[-Force] [-AsJob] [-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm] [<CommonParameters>]
```

### AccountObject
```
Invoke-AzStorageAccountFailover -InputObject <PSStorageAccount> [-Force] [-AsJob]
Invoke-AzStorageAccountFailover [-FailoverType <String>] -InputObject <PSStorageAccount> [-Force] [-AsJob]
[-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm] [<CommonParameters>]
```

Expand All @@ -34,22 +34,55 @@ Please understand the following impact to your storage account before you initia

## EXAMPLES

### Example 1: Invoke failover of a Storage account
### Example 1: Invoke an unplanned failover of a Storage account
<!-- Skip: Output cannot be splitted from code -->


```
PS C:\>$account = Get-AzStorageAccount -ResourceGroupName "MyResourceGroup" -Name "mystorageaccount" -IncludeGeoReplicationStats
PS C:\>$account.GeoReplicationStats

Status LastSyncTime
------ ------------
Live 11/13/2018 2:44:22 AM
Status LastSyncTime CanFailover
------ ------------ -----------
Live 11/29/2018 6:41:03 AM True

PS C:\>$job = Invoke-AzStorageAccountFailover -ResourceGroupName "MyResourceGroup" -Name "mystorageaccount" -Force -AsJob
PS C:\>$job | Wait-Job
```

This command check the last sync time of a Storage account then invokes failover of it, the secondary cluster will become primary after failover. Since failover takes a long time, suggest to run it in the backend with -Asjob parameter, and then wait for the job complete.

### Example 2: Invoke a planned failover of a Storage account
<!-- Skip: Output cannot be splitted from code -->
```
PS C:\>$account = Get-AzStorageAccount -ResourceGroupName "MyResourceGroup" -Name "mystorageaccount" -IncludeGeoReplicationStats
PS C:\>$account.GeoReplicationStats

Status LastSyncTime CanFailover
------ ------------ -----------
Live 11/29/2022 6:41:03 AM True

PS C:\>$job = Invoke-AzStorageAccountFailover -ResourceGroupName "MyResourceGroup" -Name "mystorageaccount" -FailoverType Planned -Force -AsJob
PS C:\>$job | Wait-Job
```
This command check the last sync time and canFailover status of a Storage account and then invokes a planned failover of it.

### Example 3: Invoke an unplanned failover of a Storage account with FailoverType set to Unplanned
<!-- Skip: Output cannot be splitted from code -->
```
PS C:\>$account = Get-AzStorageAccount -ResourceGroupName "MyResourceGroup" -Name "mystorageaccount" -IncludeGeoReplicationStats
PS C:\>$account.GeoReplicationStats

Status LastSyncTime CanFailover
------ ------------ -----------
Live 11/29/2022 6:41:03 AM True

PS C:\>$job = Invoke-AzStorageAccountFailover -ResourceGroupName "MyResourceGroup" -Name "mystorageaccount" -FailoverType Unplanned -Force -AsJob
PS C:\>$job | Wait-Job
```
This command check the last sync time and canFailover status of a Storage account and then invokes an unplanned failover of it.


## PARAMETERS

### -AsJob
Expand Down Expand Up @@ -82,6 +115,21 @@ Accept pipeline input: False
Accept wildcard characters: False
```

### -FailoverType
Specify the failover type. Possible values are: Unplanned, Planned. If not specified, the default failover type is Unplanned.

```yaml
Type: System.String
Parameter Sets: (All)
Aliases:

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### -Force
Force to Failover the Account

Expand Down Expand Up @@ -174,11 +222,11 @@ 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).
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

### System.String
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this line changed by generate help tool?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it is.

### Microsoft.Azure.Commands.Management.Storage.Models.PSStorageAccount

## OUTPUTS

Expand Down