Add AFS Cross Region Restore support for RSV PowerShell cmdlets#29836
Add AFS Cross Region Restore support for RSV PowerShell cmdlets#29836bharatpurwar wants to merge 11 commits into
Conversation
… AFS AzureFileShareRecoveryPoint was not handled in the secondary region filter in ListRecoveryPoints(), causing all AFS recovery points to be silently dropped when -UseSecondaryRegion is specified. Added AzureFileShareRecoveryPoint case returning true (AFS has no archive tier to filter). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add useSecondaryRegion branch in AzureFilesPsBackupProvider.TriggerRestore() to call GetCRRAccessToken + RestoreDiskSecondryRegion for CRR path - Fix GetAADProperties() in VaultAPIs.cs to include AzureStorage filter when backupManagementType is AzureStorage (without this, wrong servicePrincipalObjectId is returned causing CRR jobs to fail) - Add ALR-only validation for AFS CRR in TriggerRestore() - Add RecoveryPointTier mapping for AFS in GetPSAzureFileRecoveryPoint() by parsing RecoveryPointTierDetails (HardenedRP, InstantRP) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| Thanks for your contribution! The pull request validation has started. Please revisit this comment for updated status. |
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Adds Cross Region Restore (CRR) support for Azure File Share (AFS) scenarios in Recovery Services Vault backup cmdlets, aligning AFS behavior with existing CRR flows for other workloads and ensuring correct AAD properties are used for AzureStorage restores.
Changes:
- Fix secondary-region recovery point filtering to include AzureFileShareRecoveryPoint results.
- Add an AFS CRR restore execution path that acquires a CRR access token and triggers restore in the secondary region.
- Populate AFS
RecoveryPointTierfromRecoveryPointTierDetails, and ensureGetAADProperties()supports AzureStorage filtering.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/RecoveryServices/RecoveryServices.Backup.ServiceClientAdapter/BMSAPIs/VaultAPIs.cs | Adds AzureStorage query filtering in GetAADProperties() to return the correct AAD properties for CRR. |
| src/RecoveryServices/RecoveryServices.Backup.Providers/Providers/AzureFilesPsBackupProvider.cs | Implements CRR restore branch for AFS restores, including ALR-only validation and CRR request construction. |
| src/RecoveryServices/RecoveryServices.Backup.Providers/AzureWorkloadProviderHelper.cs | Ensures AFS recovery points aren’t incorrectly dropped by the secondary-region archive-tier filter. |
| src/RecoveryServices/RecoveryServices.Backup.Helpers/Conversions/RecoveryPointConversions.cs | Maps AFS recovery points’ tier details into RecoveryPointTier (Snapshot/VaultStandard/Both). |
|
/azp run |
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
…SecondaryRegion - Route AFS ListProtectedItem through the CRR SDK path when -UseSecondaryRegion is set, mirroring the IaaS VM provider (ListProtectedItemsByContainerCrr / ListProtectedItemsByItemNameCrr), and populate ExtendedInfo the same way VM/SQL do. - Add CRR-model constructor for AzureFileShareItem that surfaces soft-delete state (DeleteState/IsScheduledForDeferredDelete/DeferredDeleteTimeInUtc). DateOfPurge is left null because SoftDeleteRetentionPeriodInDays is not in the CRR (2021-11-15) SDK. - Enable the AFS branch in ConversionHelpers.GetItemModelListCrr via a new GetAzureFileShareItemModelCrr helper. - Remove the AFS RecoveryPointTierDetails tier-setting block from GetPSAzureFileRecoveryPoint (recoveryPointTierDetails is not modeled in any swagger). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 98d71075-adf0-4b3a-82a1-ec2acd27366e
…ion) Add live-recorded scenario tests mirroring the IaaS VM CRR test, covering the AFS CRR changes: - Test-AzureFSGetItemSecondaryRegion: Get-AzRecoveryServicesBackupItem -UseSecondaryRegion returns items; named item populates ExtendedInfo; DeleteState surfaces soft-delete state. - Test-AzureFSGetRPsSecondaryRegion: Get-AzRecoveryServicesBackupRecoveryPoint -UseSecondaryRegion returns recovery points. - Test-AzureFSRestoreToSecondaryRegion: Restore-AzRecoveryServicesBackupItem -RestoreToSecondaryRegion full CRR restore plus a negative check asserting the Alternate-Location-Restore-only guard. Tests are marked [Fact(Skip=...)] pending HTTP recordings, consistent with the existing AFS soft-delete and VM CRR scenario tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 98d71075-adf0-4b3a-82a1-ec2acd27366e
|
/azp run |
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
Sebby37
left a comment
There was a problem hiding this comment.
Looks good! Could you take a look at the Copilot reviews and resolve them?
Document Azure File share Cross Region Restore support: ChangeLog entry, Get-AzRecoveryServicesBackupItem -UseSecondaryRegion example, and Restore-AzRecoveryServicesBackupItem CRR (ALR-only, full-share) example and parameter notes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 98d71075-adf0-4b3a-82a1-ec2acd27366e
Enforce ALR-only, full-share-only restore for Azure File share Cross Region Restore in the provider (client-side guards with new Resources strings), and add record/playback scenario tests for secondary-region item/RP retrieval and restore validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 98d71075-adf0-4b3a-82a1-ec2acd27366e
|
/azp run |
|
Commenter does not have sufficient privileges for PR 29836 in repo Azure/azure-powershell |
|
Hi, have updated and resolve the comments. please review. |
…r_softdelete # Conflicts: # src/RecoveryServices/RecoveryServices/ChangeLog.md # src/RecoveryServices/RecoveryServices/help/Restore-AzRecoveryServicesBackupItem.md
…eorder CRR validation, doc/resource polish - AzureWorkloadProviderHelper: populate ExtendedInfo for CRR items queried by FriendlyName - AzureFilesPsBackupProvider: run CRR-specific ALR/item-level guards before generic location validation; require both target storage account and file share - Resources: hyphenate "Item-level"/"full-share" in CRR message - ChangeLog/Restore help: consistent "Azure File Share" naming, comma-separated cmdlets Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 98d71075-adf0-4b3a-82a1-ec2acd27366e
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 12 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.Designer.cs: Generated file
Comments suppressed due to low confidence (2)
src/RecoveryServices/RecoveryServices/help/Restore-AzRecoveryServicesBackupItem.md:375
- In the example title, "Azure File share" has inconsistent capitalization compared to the rest of the document ("Azure File Share").
### Example 15: Cross Region Restore of an Azure File share to an alternate location
src/RecoveryServices/RecoveryServices/help/Restore-AzRecoveryServicesBackupItem.md:390
- In the example description, "Azure File share" has inconsistent capitalization compared to the rest of the document ("Azure File Share").
This example triggers a Cross Region Restore for an Azure File share. The first command gets the vault. The second command gets the backup item from the secondary region using `-UseSecondaryRegion`. The third command gets the secondary region recovery points. The last command restores the entire file share to an alternate location in the secondary region using `-RestoreToSecondaryRegion`. Cross Region Restore for Azure File shares supports only full-share restore to an alternate location; item-level restore and original-location restore are not supported.
Un-skip and finalize the three Azure File Share Cross-Region Restore scenario tests (GetItem, GetRPs, Restore-to-secondary-region) and add their playback recordings. - Harden .Count assertions with @() so single-object results are counted - Anchor RP query window on item LastBackupTime for deterministic playback - Comment out the live CRR restore trigger (VARIATION-3): triggering a real CRR restore leaves an in-flight job and the CrrJobDetails read returns NotFound until it materializes, so it is not reliably recordable - Match hyphenated "Item-level restore is not supported" resource string Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 98d71075-adf0-4b3a-82a1-ec2acd27366e
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 15 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.Designer.cs: Generated file
Comments suppressed due to low confidence (2)
src/RecoveryServices/RecoveryServices/help/Restore-AzRecoveryServicesBackupItem.md:375
- Help text capitalization is inconsistent in the new CRR example heading: “Azure File share” should be “Azure File Share” to match the rest of the help and product naming.
### Example 15: Cross Region Restore of an Azure File share to an alternate location
src/RecoveryServices/RecoveryServices/help/Restore-AzRecoveryServicesBackupItem.md:390
- Help text capitalization is inconsistent in the new CRR example description: “Azure File share” should be “Azure File Share” for consistent product naming.
This example triggers a Cross Region Restore for an Azure File share. The first command gets the vault. The second command gets the backup item from the secondary region using `-UseSecondaryRegion`. The third command gets the secondary region recovery points. The last command restores the entire file share to an alternate location in the secondary region using `-RestoreToSecondaryRegion`. Cross Region Restore for Azure File shares supports only full-share restore to an alternate location; item-level restore and original-location restore are not supported.
Un-comment VARIATION-3 to perform a real end-to-end Cross-Region Restore (Restore-AzRecoveryServicesBackupItem -RestoreToSecondaryRegion) and re-record its playback JSON. The previously blocking in-flight CRR job on afscrrfs has cleared, so the trigger now registers and the CrrJobDetails read succeeds. Playback verified deterministic across repeated runs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 98d71075-adf0-4b3a-82a1-ec2acd27366e
|
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 15 changed files in this pull request and generated 2 comments.
Files not reviewed (1)
- src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.Designer.cs: Generated file
Comments suppressed due to low confidence (3)
src/RecoveryServices/RecoveryServices/help/Restore-AzRecoveryServicesBackupItem.md:375
- The new example heading uses inconsistent product capitalization (“Azure File share”). Elsewhere in this help and in the module, “Azure File Share” is used; please keep this consistent for searchability and professionalism.
### Example 15: Cross Region Restore of an Azure File share to an alternate location
src/RecoveryServices/RecoveryServices/help/Restore-AzRecoveryServicesBackupItem.md:390
- This paragraph repeats the inconsistent capitalization (“Azure File share” / “Azure File shares”). Please use “Azure File Share(s)” consistently (matching the rest of the help text and cmdlet naming).
This example triggers a Cross Region Restore for an Azure File share. The first command gets the vault. The second command gets the backup item from the secondary region using `-UseSecondaryRegion`. The third command gets the secondary region recovery points. The last command restores the entire file share to an alternate location in the secondary region using `-RestoreToSecondaryRegion`. Cross Region Restore for Azure File shares supports only full-share restore to an alternate location; item-level restore and original-location restore are not supported.
src/RecoveryServices/RecoveryServices.Backup.Providers/Providers/AzureFilesPsBackupProvider.cs:1036
- In the
-UseSecondaryRegionpath, this code callsAzureWorkloadProviderHelper.ListProtectedItemsByItemNameCrr(...), which fetches each item’s ExtendedInfo viaServiceClientAdapter.GetProtectedItem(...)(primary-region ProtectedItems API) rather than a secondary-region/CRR endpoint (the helper even notes this as a bug: “below API calls should be made to secondary region”). This can causeGet-AzRecoveryServicesBackupItem -UseSecondaryRegionto return primary-region ExtendedInfo or fail if the item isn’t available/consistent in the primary region. Consider either (1) using a CRR/secondary-region GET that supportsexpand=extendedinfo, or (2) avoiding the extra GET and returning secondary-region items without ExtendedInfo if CRR doesn’t support it.
// 2. Filter by item name from secondary region
itemModels = AzureWorkloadProviderHelper.ListProtectedItemsByItemNameCrr(
protectedItemsCrr,
itemName,
vaultName,
resourceGroupName,
(itemModel, protectedItemGetResponse) =>
{
AzureFileShareItemExtendedInfo extendedInfo = new AzureFileShareItemExtendedInfo();
var serviceClientExtendedInfo = ((AzureFileshareProtectedItem)protectedItemGetResponse.Properties).ExtendedInfo;
if (serviceClientExtendedInfo.OldestRecoveryPoint.HasValue)
{
extendedInfo.OldestRecoveryPoint = serviceClientExtendedInfo.OldestRecoveryPoint;
}
extendedInfo.PolicyState = serviceClientExtendedInfo.PolicyState.ToString();
extendedInfo.RecoveryPointCount =
(int)(serviceClientExtendedInfo.RecoveryPointCount.HasValue ?
serviceClientExtendedInfo.RecoveryPointCount : 0);
((AzureFileShareItem)itemModel).ExtendedInfo = extendedInfo;
}, friendlyName);
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 15 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.Designer.cs: Generated file
Comments suppressed due to low confidence (1)
src/RecoveryServices/RecoveryServices.Backup.Providers/AzureWorkloadProviderHelper.cs:1050
- The new secondary-region recovery point filter now allows
AzureFileShareRecoveryPointthrough unconditionally, butAzureFileShareRecoveryPoint.RecoveryPointTieris never populated in the conversion layer (bothGetPSAzureFileRecoveryPointandGetPSAzureFileRecoveryPointForSecondaryRegiononly setFileShareSnapshotUri). This meansGet-AzRecoveryServicesBackupRecoveryPoint -Tier ...will not work for Azure File Share (tier stays default), and it also contradicts the PR description that says tier mapping was added even thoughrecoveryPointTierDetailsis present in the recorded responses.
Please map recoveryPoint.RecoveryPointTierDetails (InstantRP/HardenedRP) to RecoveryPointTier for Azure File Share recovery points in RecoveryPointConversions.cs (primary + secondary-region conversions), similar to the existing mapping logic used for Azure Workload recovery points.
if (recoveryPoint.GetType() == typeof(CmdletModel.AzureFileShareRecoveryPoint))
{
//no archive tier currently for AFS, so return true for all RPs
return true;
}
|
/azp run |
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
There was a problem hiding this comment.
Approach is sound — the GetAADProperties AzureStorage fix is the right root cause, and the ALR-only / no-item-level guards are good. See inline comments for the substantive items. Three quick notes:
• Description lists a RecoveryPointConversions.cs RP-tier change that isn't in the diff — please update the description or restore it.
• The // code should never reach here... comment in ListProtectedItemsByItemNameCrr is now false, and its as -cast can NRE — worth cleaning up.
• The ExtendedInfo lambda is duplicated across the CRR/non-CRR branches; consider extracting it
| IsScheduledForDeferredDelete = protectedItem.IsScheduledForDeferredDelete; | ||
| DeferredDeleteTimeInUtc = protectedItem.DeferredDeleteTimeInUtc; | ||
|
|
||
| //DateOfPurge = null; |
There was a problem hiding this comment.
Soft-delete parity: primary ctor sets DateOfPurge/SoftDeleteRetentionPeriodInDays, but the CRR ctor leaves them null. Please compute DateOfPurge here so secondary-region items match.
| DataSourceType.AzureFileShare); | ||
|
|
||
| // 2. Filter by item name from secondary region | ||
| itemModels = AzureWorkloadProviderHelper.ListProtectedItemsByItemNameCrr( |
There was a problem hiding this comment.
ListProtectedItemsByItemNameCrr reads ExtendedInfo from the primary region (helper's own // bug). This PR first activates that path for AFS, so -UseSecondaryRegion will show primary data or fail in a real DR outage — please fix or track explicitly.
| { | ||
| var restoreRequestSerialized = JsonConvert.SerializeObject(restoreRequest); | ||
| CrrModel.AzureFileShareRestoreRequest restoreRequestCrr = | ||
| JsonConvert.DeserializeObject<CrrModel.AzureFileShareRestoreRequest>(restoreRequestSerialized); |
There was a problem hiding this comment.
This JSON serialize/deserialize bridge silently drops fields if the two models diverge. Please null-check the result and validate key fields (TargetDetails, SourceResourceId) survived.
| crrRestoreRequest.CrossRegionRestoreAccessDetails = accessToken; | ||
| crrRestoreRequest.RestoreRequest = restoreRequestCrr; | ||
|
|
||
| return ServiceClientAdapter.RestoreDiskSecondryRegion( |
There was a problem hiding this comment.
Two gaps: (1) target-SA region is not validated (the adapter skips the check for AzureStorage), and (2) the MUA auxiliaryAccessToken is dropped here. Please add a region check and either forward the token or fail explicitly.
| -TargetFileShareName $targetFileShareName ` | ||
| -ResolveConflict Overwrite ` | ||
| -RestoreToSecondaryRegion | ||
| Assert-NotNull $crrJob |
There was a problem hiding this comment.
Assert-NotNull passes for an empty array — use Assert-True { @($crrJob).Count -gt 0 } to actually guard the job.
Description
Adds Cross Region Restore (CRR) support for Azure File Share (AFS) workload in Recovery Services Vault PowerShell cmdlets.
Changes
1. Fix Get-AzRecoveryServicesBackupRecoveryPoint -UseSecondaryRegion for AFS
File: RecoveryServices.Backup.Providers/AzureWorkloadProviderHelper.cs
2. Add CRR path in Restore-AzRecoveryServicesBackupItem -RestoreToSecondaryRegion for AFS
File: RecoveryServices.Backup.Providers/Providers/AzureFilesPsBackupProvider.cs
3. Fix GetAADProperties() for AzureStorage workload
File: RecoveryServices.Backup.ServiceClientAdapter/BMSAPIs/VaultAPIs.cs
4. Add RecoveryPointTier mapping for AFS recovery points
File: RecoveryServices.Backup.Helpers/Conversions/RecoveryPointConversions.cs
Testing