Skip to content

Commit 2d55a0f

Browse files
authored
Merge pull request Azure#11378 from MabOneSdk/users/sarath/disk-ex
[RecoveryServices.Backup] Added support for disk exclusion during Backup and Restore
2 parents db13fab + 083affa commit 2d55a0f

File tree

15 files changed

+699019
-23
lines changed

15 files changed

+699019
-23
lines changed

src/RecoveryServices/RecoveryServices.Backup.Models/AzureModels/AzureItem.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ public class AzureItem : ItemBase
2727
/// </summary>
2828
public ItemProtectionStatus ProtectionStatus { get; set; }
2929

30+
/// <summary>
31+
/// Policy ID Associated with item
32+
/// </summary>
33+
public string PolicyId { get; set; }
34+
3035
/// <summary>
3136
/// Protection State of the item
3237
/// </summary>
@@ -67,6 +72,7 @@ public AzureItem(ProtectedItemResource protectedItemResource,
6772
: base(protectedItemResource, containerName, containerType)
6873
{
6974
ProtectionPolicyName = policyName;
75+
PolicyId = protectedItemResource.Properties.PolicyId;
7076
}
7177
}
7278
public class AzureItemExtendedInfo : ItemExtendedInfoBase

src/RecoveryServices/RecoveryServices.Backup.Models/CmdletParamEnums.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ public enum RestoreBackupItemParams
5858
public enum RestoreVMBackupItemParams
5959
{
6060
TargetResourceGroupName,
61-
OsaOption
61+
OsaOption,
62+
RestoreDiskList,
63+
RestoreOnlyOSDisk,
64+
RestoreAsUnmanagedDisks
6265
}
6366

6467
public enum RestoreFSBackupItemParams
@@ -118,7 +121,11 @@ public enum ItemParams
118121
BackupType,
119122
EnableCompression,
120123
DeleteState,
121-
FriendlyName
124+
FriendlyName,
125+
InclusionDisksList,
126+
ExclusionDisksList,
127+
ResetExclusionSettings,
128+
ExcludeAllDataDisks
122129
}
123130

124131
public enum ProtectionCheckParams

src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.Designer.cs

Lines changed: 46 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.resx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,4 +586,16 @@ Please contact Microsoft for further assistance.</value>
586586
<data name="TargetContainerRequiredException" xml:space="preserve">
587587
<value>Target Container parameter is required for this operation.</value>
588588
</data>
589+
<data name="DiskExclusionParametersRedundant" xml:space="preserve">
590+
<value>Multiple Parameters Provided. Please specify only one of the parameters from InclusionDisksList, ExclusionDisksList, ResetExclusionSetting and ExcludeAllDataDisks.</value>
591+
</data>
592+
<data name="InclusionListRedundantError" xml:space="preserve">
593+
<value>Both Inclusion and Exclusion lists provided. Please provide only one of them.</value>
594+
</data>
595+
<data name="TargetRGUnmanagedRestoreDuplicateParamsException" xml:space="preserve">
596+
<value>Both RestoreAsUnmanagedDisks and TargetResourceGroupName can't be spceified. Please give Only one parameter and retry.</value>
597+
</data>
598+
<data name="UnmanagedVMRestoreWarning" xml:space="preserve">
599+
<value>The disks of the managed VM will be restored as unmanaged since TargetResourceGroupName parameter is not provided. This will NOT leverage the instant restore functionality and hence can be significantly slow based on given storage account. To leverage instant restore, provide the TargetResourceGroupName parameter. Otherwise, provide the intent next time by passing the RestoreAsUnmanagedDisks parameter</value>
600+
</data>
589601
</root>

src/RecoveryServices/RecoveryServices.Backup.Models/RecoveryServices.Backup.Models.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<PsModuleName>RecoveryServices</PsModuleName>
@@ -14,5 +14,5 @@
1414
<ItemGroup>
1515
<PackageReference Include="Microsoft.Azure.Management.RecoveryServices.Backup" Version="4.0.1-preview" />
1616
</ItemGroup>
17-
17+
1818
</Project>

src/RecoveryServices/RecoveryServices.Backup.Providers/Providers/IaasVmPsBackupProvider.cs

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using Microsoft.Azure.Commands.RecoveryServices.Backup.Properties;
2020
using Microsoft.Azure.Management.Internal.Resources.Models;
2121
using Microsoft.Azure.Management.RecoveryServices.Backup.Models;
22+
using Microsoft.Rest;
2223
using Microsoft.Rest.Azure.OData;
2324
using System;
2425
using System.Collections.Generic;
@@ -74,21 +75,31 @@ public RestAzureNS.AzureOperationResponse<ProtectedItemResource> EnableProtectio
7475
string azureVMCloudServiceName = (string)ProviderData[ItemParams.AzureVMCloudServiceName];
7576
string azureVMResourceGroupName = (string)ProviderData[ItemParams.AzureVMResourceGroupName];
7677
string parameterSetName = (string)ProviderData[ItemParams.ParameterSetName];
78+
string[] inclusionDisksList = (string[])ProviderData[ItemParams.InclusionDisksList];
79+
string[] exclusionDisksList = (string[])ProviderData[ItemParams.ExclusionDisksList];
80+
SwitchParameter resetDiskExclusionSetting = (SwitchParameter)ProviderData[ItemParams.ResetExclusionSettings];
81+
bool excludeAllDataDisks = (bool)ProviderData[ItemParams.ExcludeAllDataDisks];
7782

7883
PolicyBase policy = (PolicyBase)ProviderData[ItemParams.Policy];
7984

8085
ItemBase itemBase = (ItemBase)ProviderData[ItemParams.Item];
8186

8287
AzureVmItem item = (AzureVmItem)ProviderData[ItemParams.Item];
8388

89+
bool isDiskExclusionParamPresent = ValidateDiskExclusionParameters(
90+
inclusionDisksList, exclusionDisksList, resetDiskExclusionSetting, excludeAllDataDisks);
91+
8492
// do validations
8593
string containerUri = "";
8694
string protectedItemUri = "";
8795
bool isComputeAzureVM = false;
8896
string sourceResourceId = null;
8997

9098
AzureVmPolicy azureVmPolicy = (AzureVmPolicy)ProviderData[ItemParams.Policy];
91-
ValidateProtectedItemCount(azureVmPolicy);
99+
if (azureVmPolicy != null)
100+
{
101+
ValidateProtectedItemCount(azureVmPolicy);
102+
}
92103

93104
if (itemBase == null)
94105
{
@@ -126,6 +137,14 @@ public RestAzureNS.AzureOperationResponse<ProtectedItemResource> EnableProtectio
126137
sourceResourceId = iaasVmProtectableItem.VirtualMachineId;
127138
}
128139
}
140+
else if(isDiskExclusionParamPresent && parameterSetName.Contains("Modify"))
141+
{
142+
isComputeAzureVM = IsComputeAzureVM(item.VirtualMachineId);
143+
Dictionary<UriEnums, string> keyValueDict = HelperUtils.ParseUri(item.Id);
144+
containerUri = HelperUtils.GetContainerUri(keyValueDict, item.Id);
145+
protectedItemUri = HelperUtils.GetProtectedItemUri(keyValueDict, item.Id);
146+
sourceResourceId = item.SourceResourceId;
147+
}
129148
else
130149
{
131150
ValidateAzureVMWorkloadType(item.WorkloadType, policy.WorkloadType);
@@ -150,9 +169,49 @@ public RestAzureNS.AzureOperationResponse<ProtectedItemResource> EnableProtectio
150169
properties = new AzureIaaSComputeVMProtectedItem();
151170
}
152171

153-
properties.PolicyId = policy.Id;
172+
if(policy != null)
173+
{
174+
properties.PolicyId = policy.Id;
175+
}
176+
else
177+
{
178+
properties.PolicyId = item.PolicyId;
179+
}
154180
properties.SourceResourceId = sourceResourceId;
155181

182+
ExtendedProperties extendedProperties = null;
183+
if (resetDiskExclusionSetting.IsPresent)
184+
{
185+
extendedProperties = new ExtendedProperties();
186+
extendedProperties.DiskExclusionProperties = null;
187+
}
188+
else
189+
{
190+
if(inclusionDisksList != null)
191+
{
192+
IList<int?> inclusionList = Array.ConvertAll(inclusionDisksList, s => int.Parse(s)).OfType<int?>().ToList();
193+
DiskExclusionProperties diskExclusionProperties = new DiskExclusionProperties(inclusionList, true);
194+
extendedProperties = new ExtendedProperties();
195+
extendedProperties.DiskExclusionProperties = diskExclusionProperties;
196+
}
197+
else if(exclusionDisksList != null)
198+
{
199+
IList<int?> exclusionList = Array.ConvertAll(exclusionDisksList, s => int.Parse(s)).OfType<int?>().ToList();
200+
DiskExclusionProperties diskExclusionProperties = new DiskExclusionProperties(exclusionList, false);
201+
extendedProperties = new ExtendedProperties();
202+
extendedProperties.DiskExclusionProperties = diskExclusionProperties;
203+
}
204+
else if(excludeAllDataDisks == true)
205+
{
206+
IList<int?> exclusionList = new List<int?>();
207+
DiskExclusionProperties diskExclusionProperties = new DiskExclusionProperties(exclusionList, true);
208+
extendedProperties = new ExtendedProperties();
209+
extendedProperties.DiskExclusionProperties = diskExclusionProperties;
210+
}
211+
}
212+
213+
properties.ExtendedProperties = extendedProperties;
214+
156215
ProtectedItemResource serviceClientRequest = new ProtectedItemResource()
157216
{
158217
Properties = properties
@@ -327,6 +386,10 @@ public RestAzureNS.AzureOperationResponse TriggerRestore()
327386
ProviderData.ContainsKey(RestoreVMBackupItemParams.TargetResourceGroupName) ?
328387
ProviderData[RestoreVMBackupItemParams.TargetResourceGroupName].ToString() : null;
329388
bool osaOption = (bool)ProviderData[RestoreVMBackupItemParams.OsaOption];
389+
string[] restoreDiskList = (string[])ProviderData[RestoreVMBackupItemParams.RestoreDiskList];
390+
SwitchParameter restoreOnlyOSDisk = (SwitchParameter)ProviderData[RestoreVMBackupItemParams.RestoreOnlyOSDisk];
391+
SwitchParameter restoreAsUnmanagedDisks = (SwitchParameter)ProviderData[RestoreVMBackupItemParams.RestoreAsUnmanagedDisks];
392+
330393
Dictionary<UriEnums, string> uriDict = HelperUtils.ParseUri(rp.Id);
331394
string containerUri = HelperUtils.GetContainerUri(uriDict, rp.Id);
332395

@@ -343,11 +406,36 @@ public RestAzureNS.AzureOperationResponse TriggerRestore()
343406
throw new Exception(string.Format(Resources.RestoreDiskStorageTypeError, vmType));
344407
}
345408

409+
if(targetResourceGroupName != null && restoreAsUnmanagedDisks.IsPresent)
410+
{
411+
throw new Exception(Resources.TargetRGUnmanagedRestoreDuplicateParamsException);
412+
}
413+
346414
if (targetResourceGroupName != null && rp.IsManagedVirtualMachine == false)
347415
{
348416
Logger.Instance.WriteWarning(Resources.UnManagedBackupVmWarning);
349417
}
350418

419+
if(rp.IsManagedVirtualMachine == true && targetResourceGroupName == null
420+
&& restoreAsUnmanagedDisks.IsPresent == false)
421+
{
422+
Logger.Instance.WriteWarning(Resources.UnmanagedVMRestoreWarning);
423+
}
424+
425+
IList<int?> restoreDiskLUNS;
426+
if(restoreOnlyOSDisk.IsPresent)
427+
{
428+
restoreDiskLUNS = new List<int?>();
429+
}
430+
else if(restoreDiskList != null)
431+
{
432+
restoreDiskLUNS = Array.ConvertAll(restoreDiskList, s => int.Parse(s)).OfType<int?>().ToList();
433+
}
434+
else
435+
{
436+
restoreDiskLUNS = null;
437+
}
438+
351439
IaasVMRestoreRequest restoreRequest = new IaasVMRestoreRequest()
352440
{
353441
CreateNewCloudService = false,
@@ -360,6 +448,7 @@ public RestAzureNS.AzureOperationResponse TriggerRestore()
360448
"/subscriptions/" + ServiceClientAdapter.SubscriptionId + "/resourceGroups/" + targetResourceGroupName :
361449
null,
362450
OriginalStorageAccountOption = useOsa,
451+
RestoreDiskLunList = restoreDiskLUNS
363452
};
364453

365454
RestoreRequestResource triggerRestoreRequest = new RestoreRequestResource();
@@ -987,6 +1076,33 @@ private void ValidateAzureVMModifyProtectionRequest(ItemBase itemBase,
9871076
}
9881077
}
9891078

1079+
private bool ValidateDiskExclusionParameters(string[] inclusionDiskList, string[] exclusionDiskList,
1080+
SwitchParameter resetDiskExclusion, bool excludeAllDataDisks)
1081+
{
1082+
bool isDiskExclusionParamPresent = false;
1083+
if(inclusionDiskList != null || exclusionDiskList != null || resetDiskExclusion.IsPresent || excludeAllDataDisks)
1084+
{
1085+
isDiskExclusionParamPresent = true;
1086+
}
1087+
1088+
if(inclusionDiskList != null && exclusionDiskList != null)
1089+
{
1090+
throw new ArgumentException(Resources.InclusionListRedundantError);
1091+
}
1092+
1093+
if(resetDiskExclusion.IsPresent && (inclusionDiskList != null && exclusionDiskList != null))
1094+
{
1095+
throw new ArgumentException(Resources.DiskExclusionParametersRedundant);
1096+
}
1097+
1098+
if(excludeAllDataDisks && (inclusionDiskList != null || exclusionDiskList != null || resetDiskExclusion.IsPresent))
1099+
{
1100+
throw new ArgumentException(Resources.DiskExclusionParametersRedundant);
1101+
}
1102+
1103+
return isDiskExclusionParamPresent;
1104+
}
1105+
9901106
private void ValidateAzureVMDisableProtectionRequest(ItemBase itemBase)
9911107
{
9921108

@@ -1140,6 +1256,7 @@ private bool IsDiscoveryNeeded(
11401256
{
11411257
IaaSVMProtectableItem iaaSVMProtectableItem =
11421258
(IaaSVMProtectableItem)protectableItem.Properties;
1259+
11431260
if (iaaSVMProtectableItem != null &&
11441261
string.Compare(iaaSVMProtectableItem.FriendlyName, vmName, true) == 0
11451262
&& iaaSVMProtectableItem.VirtualMachineId.IndexOf(virtualMachineId,

src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/IaasVm/ItemTests.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,5 +121,14 @@ public void TestAzureVMSetVaultProperty()
121121
TestController.NewInstance.RunPsTest(
122122
_logger, PsBackupProviderTypes.IaasVm, "Test-AzureVMSetVaultProperty");
123123
}
124+
125+
[Fact]
126+
[Trait(Category.AcceptanceType, Category.CheckIn)]
127+
[Trait(TestConstants.Workload, TestConstants.AzureVM)]
128+
public void TestAzureVMDiskExclusion()
129+
{
130+
TestController.NewInstance.RunPsTest(
131+
_logger, PsBackupProviderTypes.IaasVm, "Test-AzureVMDiskExclusion");
132+
}
124133
}
125134
}

0 commit comments

Comments
 (0)