Skip to content

Commit 4e60cdb

Browse files
authored
[RecoveryServices.Backup] Adding data source move feature - Copy-AzRecoveryServicesVault cmdlet (#12783)
* Adding data source move feature - Copy-AzRecoveryServicesVault cmdlet * help text fix * resolving PR issues * reverting ASR changes * resolving comments
1 parent 440b4eb commit 4e60cdb

File tree

26 files changed

+10686
-16
lines changed

26 files changed

+10686
-16
lines changed

src/RecoveryServices/RecoveryServices.Backup.Helpers/RecoveryServices.Backup.Helpers.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</PropertyGroup>
1313

1414
<ItemGroup>
15-
<PackageReference Include="Microsoft.Azure.Management.RecoveryServices.Backup" Version="4.0.1-preview" />
15+
<PackageReference Include="Microsoft.Azure.Management.RecoveryServices.Backup" Version="4.1.2-preview" />
1616
<PackageReference Include="TimeZoneConverter" Version="3.0.0" />
1717
</ItemGroup>
1818

src/RecoveryServices/RecoveryServices.Backup.Helpers/TrackingHelpers.cs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// ----------------------------------------------------------------------------------
1414

1515
using System;
16+
using Microsoft.Azure.Management.RecoveryServices.Backup.Models;
1617
using Microsoft.WindowsAzure.Commands.Utilities.Common;
1718
using RestAzureNS = Microsoft.Rest.Azure;
1819
using ServiceClientModel = Microsoft.Azure.Management.RecoveryServices.Backup.Models;
@@ -110,6 +111,31 @@ public static RestAzureNS.AzureOperationResponse GetOperationResult(
110111
return opStatusResponse;
111112
}
112113

114+
/// <summary>
115+
/// Block to track the operation to completion.
116+
/// Waits till the status of the data-move operation is InProgress.
117+
/// </summary>
118+
/// <param name="response">Response of the operation returned by the service.</param>
119+
/// <param name="getOpStatus">Delegate method to fetch the operation status of the operation.</param>
120+
/// <returns>Result of the operation once it completes.</returns>
121+
public static RestAzureNS.AzureOperationResponse<T> GetOperationStatusDataMove<T>(
122+
RestAzureNS.AzureOperationResponse response,
123+
Func<string, RestAzureNS.AzureOperationResponse<T>> getOpStatus)
124+
where T: ServiceClientModel.OperationStatus
125+
{
126+
var operationId = response.Response.Headers.GetOperationResultId();
127+
var opStatusResponse = getOpStatus(operationId);
128+
129+
while (opStatusResponse.Body.Status == "InProgress")
130+
{
131+
TestMockSupport.Delay(_defaultSleepForOperationTracking * 1000);
132+
opStatusResponse = getOpStatus(operationId);
133+
}
134+
opStatusResponse = getOpStatus(operationId);
135+
136+
return opStatusResponse;
137+
}
138+
113139
/// <summary>
114140
/// Block to track the operation to completion.
115141
/// Waits till the HTTP status code of the operation becomes something other than Accepted.
@@ -123,18 +149,29 @@ public static RestAzureNS.AzureOperationResponse<T> GetOperationResult<T>(
123149
where T: ServiceClientModel.ProtectionContainerResource
124150
{
125151
var operationId = response.Response.Headers.GetOperationResultId();
126-
127152
var opStatusResponse = getOpStatus(operationId);
128153

129154
while (opStatusResponse.Response.StatusCode == SystemNet.HttpStatusCode.Accepted)
130155
{
131156
TestMockSupport.Delay(_defaultSleepForOperationTracking * 1000);
132-
133157
opStatusResponse = getOpStatus(operationId);
134158
}
135-
136159
opStatusResponse = getOpStatus(operationId);
160+
return opStatusResponse;
161+
}
137162

163+
/// <summary>
164+
/// This method is used to fetch the prepare data move CorrelationId.
165+
/// </summary>
166+
/// <param name="response">Response of the operation returned by the service.</param>
167+
/// <param name="getCorrelationId">Delegate method to fetch the correlation id of the operation.</param>
168+
/// <returns>Result of the operation once it completes.</returns>
169+
public static PrepareDataMoveResponse GetCorrelationId(
170+
RestAzureNS.AzureOperationResponse response,
171+
Func<string, PrepareDataMoveResponse> getCorrelationId)
172+
{
173+
var operationId = response.Response.Headers.GetAzureAsyncOperationId();
174+
var opStatusResponse = getCorrelationId(operationId);
138175
return opStatusResponse;
139176
}
140177

src/RecoveryServices/RecoveryServices.Backup.Models/CommonModels/Enums.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,12 @@ public enum JobOperation
326326
/// <summary>
327327
/// Disable protection with delete data
328328
/// </summary>
329-
DeleteBackupData
329+
DeleteBackupData,
330+
331+
/// <summary>
332+
/// Data move between source and target vaults
333+
/// </summary>
334+
BackupDataMove
330335
}
331336

332337
/// <summary>

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

Lines changed: 22 additions & 0 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: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,4 +604,10 @@ Please contact Microsoft for further assistance.</value>
604604
<data name="AzureFileSourceFilePathRedundantException" xml:space="preserve">
605605
<value>Both source file path and multiple source file paths provided. Please give only one option</value>
606606
</data>
607+
<data name="TargetVaultNotEmptyException" xml:space="preserve">
608+
<value>Please provide an empty target vault. The target vault should not have any backup items or backup containers</value>
609+
</data>
610+
<data name="TargetVaultStorageRedundancy" xml:space="preserve">
611+
<value>Are you sure you want to copy items to the {0} whose storage redundancy is {1}</value>
612+
</data>
607613
</root>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</PropertyGroup>
1313

1414
<ItemGroup>
15-
<PackageReference Include="Microsoft.Azure.Management.RecoveryServices.Backup" Version="4.0.1-preview" />
15+
<PackageReference Include="Microsoft.Azure.Management.RecoveryServices.Backup" Version="4.1.2-preview" />
1616
</ItemGroup>
1717

1818
</Project>

src/RecoveryServices/RecoveryServices.Backup.Providers/RecoveryServices.Backup.Providers.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>
@@ -12,7 +12,7 @@
1212
</PropertyGroup>
1313

1414
<ItemGroup>
15-
<PackageReference Include="Microsoft.Azure.Management.RecoveryServices.Backup" Version="4.0.1-preview" />
15+
<PackageReference Include="Microsoft.Azure.Management.RecoveryServices.Backup" Version="4.1.2-preview" />
1616
</ItemGroup>
1717

1818
<ItemGroup>

src/RecoveryServices/RecoveryServices.Backup.ServiceClientAdapter/BMSAPIs/ContainerAPIs.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,23 @@ public IEnumerable<ProtectableContainerResource> ListUnregisteredContainers(
125125
return HelperUtils.GetPagedList(listAsync, listNextAsync);
126126
}
127127

128+
/// <summary>
129+
/// Gets Backup Usage Summary - registered containers/items within the vault
130+
/// </summary>
131+
/// <returns></returns>
132+
public IEnumerable<BackupManagementUsage> GetBackupUsageSummary(string vaultName, string resourceGroupName,
133+
ODataQuery<BMSBackupSummariesQueryObject> queryFilter)
134+
{
135+
Func<IEnumerable<BackupManagementUsage>> listAsync = () => BmsAdapter.Client.BackupUsageSummaries.ListWithHttpMessagesAsync(
136+
vaultName,
137+
resourceGroupName,
138+
queryFilter,
139+
skipToken: null,
140+
cancellationToken: BmsAdapter.CmdletCancellationToken).Result.Body;
141+
142+
return listAsync();
143+
}
144+
128145
/// <summary>
129146
/// Triggers refresh of container catalog in service
130147
/// </summary>

src/RecoveryServices/RecoveryServices.Backup.ServiceClientAdapter/BMSAPIs/OperationStatusAPIs.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// limitations under the License.
1313
// ----------------------------------------------------------------------------------
1414

15+
using Microsoft.Azure.Management.RecoveryServices.Backup.Models;
1516
using RestAzureNS = Microsoft.Rest.Azure;
1617
using ServiceClientModel = Microsoft.Azure.Management.RecoveryServices.Backup.Models;
1718

@@ -99,6 +100,42 @@ public RestAzureNS.AzureOperationResponse<ServiceClientModel.ProtectionContainer
99100
operationId).Result;
100101
}
101102

103+
/// <summary>
104+
/// Gets status of prepare data move operation on the source vault
105+
/// </summary>
106+
/// <param name="operationId">ID of the operation in progress</param>
107+
/// <returns></returns>
108+
public RestAzureNS.AzureOperationResponse<ServiceClientModel.OperationStatus>
109+
GetDataMoveOperationStatus(
110+
string operationId,
111+
string vaultName = null,
112+
string resourceGroupName = null)
113+
{
114+
return BmsAdapter.Client.GetOperationStatusWithHttpMessagesAsync(
115+
vaultName,
116+
resourceGroupName,
117+
operationId).Result;
118+
}
119+
120+
/// <summary>
121+
/// Gets correlationId result of prepare data move operation on the source vault
122+
/// </summary>
123+
/// <param name="operationId">ID of the operation in progress</param>
124+
/// <returns></returns>
125+
public ServiceClientModel.PrepareDataMoveResponse
126+
GetPrepareDataMoveOperationResult(
127+
string operationId,
128+
string vaultName = null,
129+
string resourceGroupName = null)
130+
{
131+
PrepareDataMoveResponse prepareResponse = BmsAdapter.Client.BMSPrepareDataMoveOperationResult.BeginGetWithHttpMessagesAsync(
132+
vaultName,
133+
resourceGroupName,
134+
operationId).Result.Body;
135+
136+
return prepareResponse;
137+
}
138+
102139
/// <summary>
103140
/// Gets result of the cancel operation on the job using the operation ID
104141
/// </summary>

src/RecoveryServices/RecoveryServices.Backup.ServiceClientAdapter/BMSAPIs/VaultAPIs.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,17 @@ public BackupResourceVaultConfigResource GetVaultProperty(string vaultName, stri
3838
return BmsAdapter.Client.BackupResourceVaultConfigs.GetWithHttpMessagesAsync(
3939
vaultName, resourceGroupName).Result.Body;
4040
}
41+
42+
/// <summary>
43+
/// Method to Get Azure Recovery Services Vault Backup Properties
44+
/// </summary>
45+
/// <param name="resouceGroupName">Name of the resouce group</param>
46+
/// <param name="vaultName">Name of the vault</param>
47+
/// <returns>Azure Resource Storage response object.</returns>
48+
public BackupResourceConfigResource GetVaultStorageType(string resouceGroupName, string vaultName)
49+
{
50+
return BmsAdapter.Client.BackupResourceStorageConfigs.GetWithHttpMessagesAsync(
51+
vaultName, resouceGroupName).Result.Body;
52+
}
4153
}
4254
}

src/RecoveryServices/RecoveryServices.Backup.ServiceClientAdapter/RecoveryServices.Backup.ServiceClientAdapter.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
<ItemGroup>
1515
<PackageReference Include="Microsoft.Azure.Management.RecoveryServices" Version="4.3.0-preview" />
16-
<PackageReference Include="Microsoft.Azure.Management.RecoveryServices.Backup" Version="4.0.1-preview" />
16+
<PackageReference Include="Microsoft.Azure.Management.RecoveryServices.Backup" Version="4.1.2-preview" />
1717
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.4.1" />
1818
</ItemGroup>
1919

src/RecoveryServices/RecoveryServices.Backup.Test/RecoveryServices.Backup.Test.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<PackageReference Include="Microsoft.Azure.Management.Compute" Version="38.1.0" />
1515
<PackageReference Include="Microsoft.Azure.Management.Network" Version="20.0.2-preview" />
1616
<PackageReference Include="Microsoft.Azure.Management.RecoveryServices" Version="4.3.0-preview" />
17-
<PackageReference Include="Microsoft.Azure.Management.RecoveryServices.Backup" Version="4.0.1-preview" />
17+
<PackageReference Include="Microsoft.Azure.Management.RecoveryServices.Backup" Version="4.1.2-preview" />
1818
</ItemGroup>
1919

2020
<ItemGroup>

src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/IaasVm/Common.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function Create-VM(
6464
$tags += @{"AutoShutDown"="No"}
6565
$tags += @{"DeleteBy"="05-2020"}
6666

67-
$vmConfig = New-AzVMConfig -VMName $vmName -VMSize Standard_D1 | `
67+
$vmConfig = New-AzVMConfig -VMName $vmName -VMSize Standard_D1_v2 | `
6868
Set-AzVMOperatingSystem -Windows -ComputerName $vmName -Credential $Credential | `
6969
Set-AzVMSourceImage -PublisherName MicrosoftWindowsServer -Offer WindowsServer `
7070
-Skus 2016-Datacenter -Version latest | Add-AzVMNetworkInterface -Id $nic.Id

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,5 +130,14 @@ public void TestAzureVMDiskExclusion()
130130
TestController.NewInstance.RunPsTest(
131131
_logger, PsBackupProviderTypes.IaasVm, "Test-AzureVMDiskExclusion");
132132
}
133+
134+
[Fact(Skip = "CCY region is down and the testing for DS Move is restricted")]
135+
[Trait(Category.AcceptanceType, Category.CheckIn)]
136+
[Trait(TestConstants.Workload, TestConstants.AzureVM)]
137+
public void TestAzureBackupDataMove()
138+
{
139+
TestController.NewInstance.RunPsTest(
140+
_logger, PsBackupProviderTypes.IaasVm, "Test-AzureBackupDataMove");
141+
}
133142
}
134143
}

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,32 @@
1212
# limitations under the License.
1313
# ----------------------------------------------------------------------------------
1414

15+
function Test-AzureBackupDataMove
16+
{
17+
$sourceLocation = "eastus2euap"
18+
$sourceResourceGroup = Create-ResourceGroup $sourceLocation 21
19+
20+
$targetLocation = "centraluseuap"
21+
$targetResourceGroup = Create-ResourceGroup $targetLocation 23
22+
23+
$vm = Create-VM $sourceResourceGroup $sourceLocation 3
24+
$vault1 = Create-RecoveryServicesVault $sourceResourceGroup $sourceLocation
25+
$vault2 = Create-RecoveryServicesVault $targetResourceGroup $targetLocation
26+
Enable-Protection $vault1 $vm
27+
28+
# disable soft delete for successful cleanup
29+
Set-AzRecoveryServicesVaultProperty -VaultId $vault1.ID -SoftDeleteFeatureState "Disable"
30+
Set-AzRecoveryServicesVaultProperty -VaultId $vault2.ID -SoftDeleteFeatureState "Disable"
31+
32+
# data move v2 to v1 fails due to TargetVaultNotEmpty
33+
Assert-ThrowsContains { Copy-AzRecoveryServicesVault -SourceVault $vault2 -TargetVault $vault1 -Force } `
34+
"Please provide an empty target vault. The target vault should not have any backup items or backup containers";
35+
36+
# data move from v1 to v2 succeeds
37+
$dataMove = Copy-AzRecoveryServicesVault -SourceVault $vault1 -TargetVault $vault2 -Force;
38+
Assert-True { $dataMove -contains "Please monitor the operation using Az-RecoveryServicesBackupJob cmdlet" }
39+
}
40+
1541
function Test-AzureVMGetItems
1642
{
1743
$location = "southeastasia"

0 commit comments

Comments
 (0)