Backup/Restore Managed Instance (#1428)

* Enabled backup to and restore from URL

* Created RPC, but when process tries to load Microsoft.Azure.Storage.Blob.dll, it crashes

* Added create shared access token

* Code refactor

* Minor changes

* Changed RPC path

* Moved createSas RPC to the newly created BlobService, fixed PR comments

* Added sas expiration date parameter to the RPC

* Added copyright headers

* Removed ConnectionInstance property from BlobService

* Removed unhelpful comment

* Removed unused using statements

* Changed copy/paste comments

* Disposable objects fix

* Small formatting fix

* Changed backup to/restore from url supported device types

* Added backup to url integration test

* Created restore integration test. Test are now getting azure blob params from env variables instead of file.

* Culture invariant epiration date param, fixed comment, and typo

* Updated headers

* PR comments fix

* Changed supported device type logic

* string localization fix

* String formatting fix

* build failure fix

* Typo

* Updated supported restore device types
This commit is contained in:
Nemanja Milovančević
2022-04-20 23:01:13 +02:00
committed by GitHub
parent 35e1782a3f
commit 881c335cdf
21 changed files with 828 additions and 7 deletions

View File

@@ -211,12 +211,12 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
{
string destName = Convert.ToString(this.backupInfo.BackupPathList[i], System.Globalization.CultureInfo.InvariantCulture);
int deviceType = (int)(this.backupInfo.BackupPathDevices[destName]);
int backupDeviceType =
GetDeviceType(Convert.ToString(destName,
System.Globalization.CultureInfo.InvariantCulture));
switch (deviceType)
{
case (int)DeviceType.LogicalDevice:
int backupDeviceType =
GetDeviceType(Convert.ToString(destName,
System.Globalization.CultureInfo.InvariantCulture));
if (this.backupDeviceType == BackupDeviceType.Disk && backupDeviceType == constDeviceTypeFile)
{
@@ -229,6 +229,12 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
this.backup.Devices.AddDevice(destName, DeviceType.File);
}
break;
case (int)DeviceType.Url:
if (this.backupDeviceType == BackupDeviceType.Url)
{
this.backup.Devices.AddDevice(destName, DeviceType.Url);
}
break;
}
}

View File

@@ -51,6 +51,18 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts
}
}
internal int DeviceType
{
get
{
return GetOptionValue<int>(RestoreOptionsHelper.DeviceType);
}
set
{
SetOptionValue(RestoreOptionsHelper.DeviceType, value);
}
}
/// <summary>
/// Target Database name to restore to
/// </summary>

View File

@@ -77,6 +77,12 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
private bool? isTailLogBackupWithNoRecoveryPossible = null;
private string backupMediaList = string.Empty;
private Server server;
private static readonly DeviceType[] managedInstanceSupportedDeviceTypes = { DeviceType.Url };
private static readonly DeviceType[] defaultSupportedDeviceTypes = { DeviceType.File, DeviceType.Url };
private static readonly Dictionary<Edition, DeviceType[]> specialEngineEditionSupportedDeviceTypes = new Dictionary<Edition, DeviceType[]>
{
{ Edition.SqlManagedInstance, managedInstanceSupportedDeviceTypes },
};
public RestoreDatabaseTaskDataObject(Server server, String databaseName)
{
@@ -195,8 +201,10 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
/// Add a backup file to restore plan media list
/// </summary>
/// <param name="filePaths"></param>
public void AddFiles(string filePaths)
/// <param name="deviceType"></deviceType>
public void AddDevices(string filePaths, DeviceType deviceType)
{
ThrowIfUnsupportedDeviceType(this.Server.EngineEdition, deviceType);
backupMediaList = filePaths;
PlanUpdateRequired = true;
if (!string.IsNullOrWhiteSpace(filePaths))
@@ -209,7 +217,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
{
this.RestorePlanner.BackupMediaList.Add(new BackupDeviceItem
{
DeviceType = DeviceType.File,
DeviceType = deviceType,
Name = file
});
}
@@ -223,6 +231,20 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
}
}
private void ThrowIfUnsupportedDeviceType(Edition engineEdition, DeviceType deviceType)
{
if (!IsSupportedDeviceType(engineEdition, deviceType))
{
throw new UnsupportedDeviceTypeException(engineEdition, deviceType);
}
}
private bool IsSupportedDeviceType(Edition engineEdition, DeviceType deviceType)
{
return (defaultSupportedDeviceTypes.Contains(deviceType) && !specialEngineEditionSupportedDeviceTypes.ContainsKey(engineEdition))
|| (specialEngineEditionSupportedDeviceTypes.ContainsKey(engineEdition) && specialEngineEditionSupportedDeviceTypes[engineEdition].Contains(deviceType));
}
/// <summary>
/// Returns the last backup taken
@@ -1368,7 +1390,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
if (!string.IsNullOrEmpty(RestoreParams.BackupFilePaths) && RestoreParams.ReadHeaderFromMedia)
{
AddFiles(RestoreParams.BackupFilePaths);
AddDevices(RestoreParams.BackupFilePaths, (DeviceType)RestoreParams.DeviceType);
}
else
{

View File

@@ -0,0 +1,17 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
{
public class UnsupportedDeviceTypeException: Exception
{
public UnsupportedDeviceTypeException(Edition engineEdition, DeviceType deviceType) : base(SR.UnsupportedDeviceType(deviceType.ToString(), engineEdition.ToString()))
{
}
}
}

View File

@@ -62,6 +62,9 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
//The key name to use to set the backup file paths in the request
internal const string BackupFilePaths = "backupFilePaths";
//The key name to use to set the device type
internal const string DeviceType = "deviceType";
//The key name to use to set the target database name in the request
internal const string TargetDatabaseName = "targetDatabaseName";