Skip to content

Commit

Permalink
Added support for enabling Disk access settings for managed VM restor…
Browse files Browse the repository at this point in the history
…es (#26504)

Updated help
Updated changelog
Added test case
  • Loading branch information
hiaga authored Nov 4, 2024
1 parent 1026dba commit 8349058
Show file tree
Hide file tree
Showing 11 changed files with 1,636 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ public static RecoveryPointBase GetPSAzureVMRecoveryPoint(
Zones = recoveryPoint.Zones,
RehydrationExpiryTime = (DateTime?)null,
ExtendedLocation = recoveryPoint.ExtendedLocation,
IsPrivateAccessEnabledOnAnyDisk = recoveryPoint.IsPrivateAccessEnabledOnAnyDisk
};

if (recoveryPoint.RecoveryPointTierDetails != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class AzureVmRecoveryPoint : AzureRecoveryPoint
/// Identifies whether this recovery point represents
/// an encrypted VM at the time of backup.
/// </summary>
public bool EncryptionEnabled { get; set; }
public bool EncryptionEnabled { get; set; }

/// <summary>
/// Identifies whether an ILR session is already active
Expand Down Expand Up @@ -93,6 +93,12 @@ public class AzureVmRecoveryPoint : AzureRecoveryPoint
/// </summary>
public ExtendedLocation ExtendedLocation { get; set; }

/// <summary>
/// Identifies whether any of the disks in the VM are using
/// Private access network setting
/// </summary>
public bool? IsPrivateAccessEnabledOnAnyDisk { get; set; }

public AzureVmRecoveryPoint()
{

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ public enum RestoreVMBackupItemParams
TargetVNetResourceGroup,
TargetSubnetName,
TargetSubscriptionId,
RestoreToEdgeZone
RestoreToEdgeZone,
DiskAccessOption,
TargetDiskAccessId
}

public enum RestoreFSBackupItemParams
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,8 @@ public RestAzureNS.AzureOperationResponse TriggerRestore()
bool restoreToEdgeZone = (bool)ProviderData[RestoreVMBackupItemParams.RestoreToEdgeZone];
string auxiliaryAccessToken = ProviderData.ContainsKey(ResourceGuardParams.Token) ? (string)ProviderData[ResourceGuardParams.Token] : null;
bool isMUAOperation = ProviderData.ContainsKey(ResourceGuardParams.IsMUAOperation) ? (bool)ProviderData[ResourceGuardParams.IsMUAOperation] : false;

ServiceClientModel.TargetDiskNetworkAccessOption? diskAccessOption = ProviderData.ContainsKey(RestoreVMBackupItemParams.DiskAccessOption) ? (ServiceClientModel.TargetDiskNetworkAccessOption?)ProviderData[RestoreVMBackupItemParams.DiskAccessOption] : null;
string targetDiskAccessId = ProviderData.ContainsKey(RestoreVMBackupItemParams.TargetDiskAccessId) ? (string)ProviderData[RestoreVMBackupItemParams.TargetDiskAccessId] : null;

Dictionary<UriEnums, string> uriDict = HelperUtils.ParseUri(rp.Id);
string containerUri = HelperUtils.GetContainerUri(uriDict, rp.Id);
Expand Down Expand Up @@ -629,6 +630,17 @@ public RestAzureNS.AzureOperationResponse TriggerRestore()
restoreRequest.ExtendedLocation = rp.ExtendedLocation;
}

if (diskAccessOption != null)
{
restoreRequest.TargetDiskNetworkAccessSettings = new TargetDiskNetworkAccessSettings();
restoreRequest.TargetDiskNetworkAccessSettings.TargetDiskNetworkAccessOption = diskAccessOption;

if(!string.IsNullOrEmpty(targetDiskAccessId))
{
restoreRequest.TargetDiskNetworkAccessSettings.TargetDiskAccessId = targetDiskAccessId;
}
}

if (restoreType == "OriginalLocation") // replace existing
{
restoreRequest.RecoveryType = RecoveryType.OriginalLocation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,5 +315,17 @@ public void TestAzureVaultSoftDelete()
"Test-AzureVaultSoftDelete"
);
}

[Fact]
[Trait(Category.AcceptanceType, Category.CheckIn)]
[Trait(TestConstants.Workload, TestConstants.AzureVM)]
public void TestAzurePERestore()
{
TestRunner.RunTestScript(
$"Import-Module {_IaasVmcommonModule.AsAbsoluteLocation()}",
$"Import-Module {_IaasVmtestModule.AsAbsoluteLocation()}",
"Test-AzurePERestore"
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,41 @@
# limitations under the License.
# ----------------------------------------------------------------------------------

function Test-AzurePERestore
{
$location = "eastus2euap"
$resourceGroupName = "arpja"
$vaultName = "arpja-pe-e2e-validation-vault"
$vmName = "peval-ecy-win44"
$subId = "f2edfd5d-5496-4683-b94f-b3588c579009"
$subName = "sriramsa-IaaSVmBackup Canary Subscription"
$saName = "arpjapevalrestoresa"
$targetVMName = "ps-diskaccess"
$targetVNetName = "arpjavnet238"
$targetVNetRG = "arpja"
$targetSubnetName = "default"
$recoveryPointId = "252905611419763" # latest recovery point
$targetDiskAccessId = "/subscriptions/f2edfd5d-5496-4683-b94f-b3588c579009/resourceGroups/arpja/providers/Microsoft.Compute/diskAccesses/arpja-peval-restore-da"

try
{
# Setup
$vault = Get-AzRecoveryServicesVault -ResourceGroupName $resourceGroupName -Name $vaultName
$item = Get-AzRecoveryServicesBackupItem -BackupManagementType AzureVM -WorkloadType AzureVM `
-VaultId $vault.ID | Where-Object { $_.Name -match $vmName }

$rp = Get-AzRecoveryServicesBackupRecoveryPoint -Item $item[0] -VaultId $vault.ID -RecoveryPointId $recoveryPointId

$diskAccessRestoreJob = Restore-AzRecoveryServicesBackupItem -VaultLocation $vault.Location -RecoveryPoint $rp[0] -StorageAccountName $saName -StorageAccountResourceGroupName $vault.ResourceGroupName -TargetResourceGroupName $vault.ResourceGroupName -TargetVMName $targetVMName -TargetVNetName $targetVNetName -TargetVNetResourceGroup $targetVNetRG -TargetSubnetName $targetSubnetName -VaultId $vault.Id -DiskAccessOption EnablePrivateAccessForAllDisks -TargetDiskAccessId $targetDiskAccessId | Wait-AzRecoveryServicesBackupJob -VaultId $vault.ID

Assert-True { $diskAccessRestoreJob.Status -eq "Completed" }
}
finally
{
Delete-VM $resourceGroupName $targetVMName
}
}

function Test-AzureVaultSoftDelete
{
$resourceGroupName = "hiagarg"
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,19 @@ public class RestoreAzureRmRecoveryServicesBackupItem : RSBackupVaultCmdletBase
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsgs.ResourceGuard.AuxiliaryAccessToken, ValueFromPipeline = false)]
public string Token;

[Parameter(Mandatory = false, ParameterSetName = AzureManagedVMCreateNewParameterSet,
HelpMessage = ParamHelpMsgs.RestoreVM.DiskAccessOption)]
[Parameter(Mandatory = false, ParameterSetName = AzureManagedVMReplaceExistingParameterSet,
HelpMessage = ParamHelpMsgs.RestoreVM.DiskAccessOption)]
public ServiceClientModel.TargetDiskNetworkAccessOption? DiskAccessOption { get; set; }

[Parameter(Mandatory = false, ParameterSetName = AzureManagedVMCreateNewParameterSet,
HelpMessage = ParamHelpMsgs.RestoreVM.TargetDiskAccessId)]
[Parameter(Mandatory = false, ParameterSetName = AzureManagedVMReplaceExistingParameterSet,
HelpMessage = ParamHelpMsgs.RestoreVM.TargetDiskAccessId)]
[ValidatePattern(@"^/subscriptions/[^/]+/resourceGroups/[^/]+/providers/Microsoft.Compute/diskAccesses/[^/]+$")]
public string TargetDiskAccessId { get; set; }

public override void ExecuteCmdlet()
{
ExecutionBlock(() =>
Expand Down Expand Up @@ -430,6 +443,43 @@ public override void ExecuteCmdlet()
}
}
if (DiskAccessOption != null)
{
AzureVmRecoveryPoint rp = (AzureVmRecoveryPoint)RecoveryPoint;
if (!(bool)rp.IsPrivateAccessEnabledOnAnyDisk)
{
throw new ArgumentException("DiskAccessOption parameter can't be provided since private access is not enabled in given recovery point");
}
if (DiskAccessOption == ServiceClientModel.TargetDiskNetworkAccessOption.EnablePrivateAccessForAllDisks)
{
if (string.IsNullOrEmpty(TargetDiskAccessId))
{
throw new ArgumentException("TargetDiskAccessId must be provided when DiskAccessOption is set to EnablePrivateAccessForAllDisks.");
}
}
else if (RestoreToSecondaryRegion.IsPresent && DiskAccessOption == ServiceClientModel.TargetDiskNetworkAccessOption.SameAsOnSourceDisks)
{
throw new ArgumentException("Given DiskAccessOption isn't applicable to cross region restore");
}
else if (!string.IsNullOrEmpty(TargetDiskAccessId))
{
throw new ArgumentException("TargetDiskAccessId can't be provided for the given DiskAccessOption.");
}
providerParameters.Add(RestoreVMBackupItemParams.DiskAccessOption, DiskAccessOption);
providerParameters.Add(RestoreVMBackupItemParams.TargetDiskAccessId, TargetDiskAccessId);
}
else if (string.Equals(this.ParameterSetName, AzureManagedVMCreateNewParameterSet, StringComparison.Ordinal) ||
string.Equals(this.ParameterSetName, AzureManagedVMReplaceExistingParameterSet, StringComparison.Ordinal))
{
AzureVmRecoveryPoint rp = (AzureVmRecoveryPoint)RecoveryPoint;
if ((bool)rp.IsPrivateAccessEnabledOnAnyDisk)
{
throw new ArgumentException("DiskAccessOption parameter must be provided since private access is enabled in given recovery point");
}
}
if (TargetZoneNumber != null)
{
// get storage type
Expand Down
2 changes: 2 additions & 0 deletions src/RecoveryServices/RecoveryServices.Backup/ParamHelpMsgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ internal static class RestoreVM
public const string TargetVNetResourceGroup = "Name of the resource group which contains the target VNet, in the case of Alternate Location restore to a new VM";
public const string TargetSubnetName = "Name of the subnet in which the target VM should be created, in the case of Alternate Location restore to a new VM";
public const string TargetSubscriptionId = "ID of the target subscription to which the resource should be restored. Use this parameter for Cross subscription restore";
public const string DiskAccessOption = "Specifies the disk access option for target disks";
public const string TargetDiskAccessId = "Specifies the target disk access ID when DiskAccessOption set to EnablePrivateAccessForAllDisks";
}

internal static class RestoreFS
Expand Down
3 changes: 2 additions & 1 deletion src/RecoveryServices/RecoveryServices/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- Additional information about change #1
-->
## Upcoming Release
* Added support for enabling Disk access settings for managed VM restores.

## Version 7.2.0
* Fixed bug for making RecoveryAzureStorageAccountId parameter optional in `New-ASRReplicationProtectedItem` cmdlet of H2A.
Expand All @@ -27,7 +28,7 @@
* Added additional properties to the output of Get-AzRecoveryServicesVault cmdlet - MoveDetails, MoveState, RedundancySettings, SecureScore, BcdrSecurityLevel, EncryptionProperty.

## Version 7.0.0
* [Breaking Change] Renamed the property `ResouceType` of `ASRVaultSettings` to `ResourceType`.
* [Breaking Change] Renamed the property `ResouceType` of `ASRVaultSettings` to `ResourceType`.

## Version 6.9.0
* Added support for MUA for disabling vault Immutability, increasing RPO for policy schedule, restore, stop protection with retain data.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ Restore-AzRecoveryServicesBackupItem [-VaultLocation <String>] [-RecoveryPoint]
[-StorageAccountName] <String> [-StorageAccountResourceGroupName] <String> [-RestoreOnlyOSDisk]
[-RestoreDiskList <String[]>] [-DiskEncryptionSetId <String>] [-RestoreToSecondaryRegion]
[-TargetZoneNumber <Int32>] [-RehydratePriority <String>] [-UseSystemAssignedIdentity]
[-UserAssignedIdentityId <String>] [-VaultId <String>] [-DefaultProfile <IAzureContextContainer>]
[-UserAssignedIdentityId <String>] [-DiskAccessOption <TargetDiskNetworkAccessOption>]
[-TargetDiskAccessId <String>] [-VaultId <String>] [-DefaultProfile <IAzureContextContainer>]
[-RehydrateDuration <String>] [-Token <String>] [-WhatIf] [-Confirm]
[<CommonParameters>]
```
Expand Down Expand Up @@ -54,9 +55,9 @@ Restore-AzRecoveryServicesBackupItem [-VaultLocation <String>] [-RecoveryPoint]
[-TargetZoneNumber <Int32>] [-RehydratePriority <String>] [-UseSystemAssignedIdentity]
[-UserAssignedIdentityId <String>] [-TargetVMName <String>] [-TargetVNetName <String>]
[-TargetVNetResourceGroup <String>] [-TargetSubnetName <String>] [-TargetSubscriptionId <String>]
[-RestoreToEdgeZone] [-VaultId <String>] [-DefaultProfile <IAzureContextContainer>]
[-RehydrateDuration <String>] [-Token <String>] [-WhatIf] [-Confirm]
[<CommonParameters>]
[-RestoreToEdgeZone] [-DiskAccessOption <TargetDiskNetworkAccessOption>] [-TargetDiskAccessId <String>]
[-VaultId <String>] [-DefaultProfile <IAzureContextContainer>] [-RehydrateDuration <String>] [-Token <String>]
[-WhatIf] [-Confirm] [<CommonParameters>]
```

### AzureVMUnManagedDiskParameterSet
Expand Down Expand Up @@ -146,7 +147,7 @@ $BackupItem = Get-AzRecoveryServicesBackupItem -BackupManagementType "AzureVM" -
$StartDate = (Get-Date).AddDays(-7)
$EndDate = Get-Date
$RP = Get-AzRecoveryServicesBackupRecoveryPoint -Item $BackupItem -StartDate $StartDate.ToUniversalTime() -EndDate $EndDate.ToUniversalTime() -VaultId $vault.ID
$AlternateLocationRestoreJob = Restore-AzRecoveryServicesBackupItem -RecoveryPoint $RP[0] -TargetResourceGroupName "Target_RG" -StorageAccountName "DestStorageAccount" -StorageAccountResourceGroupName "DestStorageAccRG" -TargetVMName "TagetVirtualMachineName" -TargetVNetName "Target_VNet" -TargetVNetResourceGroup "" -TargetSubnetName "subnetName" -VaultId $vault.ID -VaultLocation $vault.Location
$AlternateLocationRestoreJob = Restore-AzRecoveryServicesBackupItem -RecoveryPoint $RP[0] -TargetResourceGroupName "Target_RG" -StorageAccountName "DestStorageAccount" -StorageAccountResourceGroupName "DestStorageAccRG" -TargetVMName "TagetVirtualMachineName" -TargetVNetName "Target_VNet" -TargetVNetResourceGroup "Target_VNet_RG" -TargetSubnetName "subnetName" -VaultId $vault.ID -VaultLocation $vault.Location
$OriginalLocationRestoreJob = Restore-AzRecoveryServicesBackupItem -RecoveryPoint $RP[0] -StorageAccountName "DestStorageAccount" -StorageAccountResourceGroupName "DestStorageAccRG" -VaultId $vault.ID -VaultLocation $vault.Location
```

Expand Down Expand Up @@ -329,6 +330,23 @@ $restoreJob = Restore-AzRecoveryServicesBackupItem -VaultId $vault.ID -VaultLoca

In this example, we use RestoreToEdgeZone parameter to trigger a restore to new edge zone vm in alternate location. For Original location restore (OLR), restore will implicitly be an edge zone restore if the source VM is an edge zone VM.

### Example 12: Restore a Managed AzureVM using DiskAccessOption

```powershell
$vault = Get-AzRecoveryServicesVault -ResourceGroupName "resourceGroup" -Name "vaultName"
$BackupItem = Get-AzRecoveryServicesBackupItem -BackupManagementType "AzureVM" -WorkloadType "AzureVM" -Name "V2VM" -VaultId $vault.ID
$RP = Get-AzRecoveryServicesBackupRecoveryPoint -VaultId $vault.ID -Item $item
$AlternateLocationRestoreJob = Restore-AzRecoveryServicesBackupItem -RecoveryPoint $RP[0] -TargetResourceGroupName "Target_RG" -StorageAccountName "DestStorageAccount" -StorageAccountResourceGroupName "DestStorageAccRG" -TargetVMName "TagetVirtualMachineName" -TargetVNetName "Target_VNet" -TargetVNetResourceGroup "Target_VNet_RG" -TargetSubnetName "subnetName" -VaultId $vault.ID -VaultLocation $vault.Location -DiskAccessOption EnablePrivateAccessForAllDisks -TargetDiskAccessId "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgName/providers/Microsoft.Compute/diskAccesses/target-diskaccess"
```

```output
WorkloadName Operation Status StartTime EndTime
------------ --------- ------ --------- -------
V2VM Restore InProgress 26-Jul-24 1:14:01 PM 01-Jan-01 12:00:00 AM
```

In this example, we use DiskAccessOption parameter to trigger a restore to new VM with private access enabled for all disks. DiskAccessOption parameter can be used to specify the disk access option for target disks. The acceptable values for this parameter are: SameAsOnSourceDisks, EnablePrivateAccessForAllDisks, EnablePublicAccessForAllDisks. TargetDiskAccessId parameter is used to specify the disk access id for the target disks. This parameter is required when DiskAccessOption is set to EnablePrivateAccessForAllDisks.

## PARAMETERS

### -DefaultProfile
Expand All @@ -347,6 +365,22 @@ Accept pipeline input: False
Accept wildcard characters: False
```
### -DiskAccessOption
Specifies the disk access option for target disks
```yaml
Type: System.Nullable`1[Microsoft.Azure.Management.RecoveryServices.Backup.Models.TargetDiskNetworkAccessOption]
Parameter Sets: AzureManagedVMReplaceExistingParameterSet, AzureManagedVMCreateNewParameterSet
Aliases:
Accepted values: SameAsOnSourceDisks, EnablePrivateAccessForAllDisks, EnablePublicAccessForAllDisks

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -DiskEncryptionSetId
The DES ID to encrypt the restored disks.
Expand Down Expand Up @@ -611,6 +645,21 @@ Accept pipeline input: False
Accept wildcard characters: False
```
### -TargetDiskAccessId
Specifies the target disk access ID when DiskAccessOption set to EnablePrivateAccessForAllDisks
```yaml
Type: System.String
Parameter Sets: AzureManagedVMReplaceExistingParameterSet, AzureManagedVMCreateNewParameterSet
Aliases:

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TargetFileShareName
The File Share to which the file share has to be restored to.
Expand Down

0 comments on commit 8349058

Please sign in to comment.