supporting restore from db (#429)

* supporting restore from db
This commit is contained in:
Leila Lali
2017-08-09 11:01:52 -07:00
committed by GitHub
parent a4a27f9559
commit 6696b7e72f
12 changed files with 1143 additions and 369 deletions

View File

@@ -3,34 +3,76 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.Collections.Generic;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Hosting.Contracts;
using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts;
using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
{
public class RestoreOptionsHelper
{
//The key names of restore info in the resquest of response
//Option name keepReplication
internal const string KeepReplication = "keepReplication";
//Option name replaceDatabase
internal const string ReplaceDatabase = "replaceDatabase";
//Option name setRestrictedUser
internal const string SetRestrictedUser = "setRestrictedUser";
//Option name recoveryState
internal const string RecoveryState = "recoveryState";
//Option name backupTailLog
internal const string BackupTailLog = "backupTailLog";
internal const string DefaultBackupTailLog = "defaultBackupTailLog";
//Option name tailLogBackupFile
internal const string TailLogBackupFile = "tailLogBackupFile";
internal const string DefaultTailLogBackupFile = "defaultTailLogBackupFile";
//Option name tailLogWithNoRecovery
internal const string TailLogWithNoRecovery = "tailLogWithNoRecovery";
//Option name closeExistingConnections
internal const string CloseExistingConnections = "closeExistingConnections";
//Option name relocateDbFiles
internal const string RelocateDbFiles = "relocateDbFiles";
//Option name dataFileFolder
internal const string DataFileFolder = "dataFileFolder";
internal const string DefaultDataFileFolder = "defaultDataFileFolder";
//Option name logFileFolder
internal const string LogFileFolder = "logFileFolder";
internal const string DefaultLogFileFolder = "defaultLogFileFolder";
//The key name to use to set the session id in the request
internal const string SessionId = "sessionId";
//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 target database name in the request
internal const string TargetDatabaseName = "targetDatabaseName";
//The key name to use to set the source database name in the request
internal const string SourceDatabaseName = "sourceDatabaseName";
//The key name to use to set the selected backup sets in the request
internal const string SelectedBackupSets = "selectedBackupSets";
//The key name to use to set the standby file sets in the request
internal const string StandbyFile = "standbyFile";
internal const string DefaultStandbyFile = "defaultStandbyFile";
//The key name to use to set source db names in restore response
internal const string SourceDatabaseNamesWithBackupSets = "sourceDatabaseNamesWithBackupSets";
//The key name to use to set in the requst. If set to true, the backup files will be used to restore otherwise the source database name
internal const string ReadHeaderFromMedia = "readHeaderFromMedia";
/// <summary>
/// Creates the options metadata available for restore operations
@@ -187,5 +229,201 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
return options;
}
internal static Dictionary<string, RestorePlanDetailInfo> CreateRestorePlanOptions(IRestoreDatabaseTaskDataObject restoreDataObject)
{
Validate.IsNotNull(nameof(restoreDataObject), restoreDataObject);
Dictionary<string, RestorePlanDetailInfo> options = new Dictionary<string, RestorePlanDetailInfo>();
string databaseName = restoreDataObject.RestorePlan == null ? string.Empty : restoreDataObject.RestorePlan.DatabaseName;
//Files
// Default Data folder path in the target server
options.Add(RestoreOptionsHelper.DataFileFolder, RestorePlanDetailInfo.Create(
name: RestoreOptionsHelper.DataFileFolder,
currentValue: restoreDataObject.DataFilesFolder,
defaultValue: restoreDataObject.DefaultDataFileFolder,
isReadOnly: !restoreDataObject.RelocateAllFiles,
isVisible: true
));
// Default log folder path in the target server
options.Add(RestoreOptionsHelper.LogFileFolder, RestorePlanDetailInfo.Create(
name: RestoreOptionsHelper.LogFileFolder,
currentValue: restoreDataObject.LogFilesFolder,
defaultValue: restoreDataObject.DefaultLogFileFolder,
isReadOnly: !restoreDataObject.RelocateAllFiles,
isVisible: true
));
// Relocate all files
options.Add(RestoreOptionsHelper.RelocateDbFiles, RestorePlanDetailInfo.Create(
name: RestoreOptionsHelper.RelocateDbFiles,
currentValue: restoreDataObject.RelocateAllFiles,
defaultValue: false,
isReadOnly: restoreDataObject.DbFiles.Count == 0,
isVisible: true
));
//Options
//With Replace
options.Add(RestoreOptionsHelper.ReplaceDatabase, RestorePlanDetailInfo.Create(
name: RestoreOptionsHelper.ReplaceDatabase,
currentValue: restoreDataObject.RestoreOptions.ReplaceDatabase,
defaultValue: false,
isReadOnly: false,
isVisible: true
));
//Keep replication
options.Add(RestoreOptionsHelper.KeepReplication, RestorePlanDetailInfo.Create(
name: RestoreOptionsHelper.KeepReplication,
currentValue: restoreDataObject.RestoreOptions.KeepReplication,
defaultValue: false,
isReadOnly: restoreDataObject.RestoreOptions.RecoveryState == DatabaseRecoveryState.WithNoRecovery,
isVisible: true
));
//Restricted user
options.Add(RestoreOptionsHelper.SetRestrictedUser, RestorePlanDetailInfo.Create(
name: RestoreOptionsHelper.SetRestrictedUser,
currentValue: restoreDataObject.RestoreOptions.SetRestrictedUser,
defaultValue: false,
isReadOnly: false,
isVisible: true
));
//State recovery
options.Add(RestoreOptionsHelper.RecoveryState, RestorePlanDetailInfo.Create(
name: RestoreOptionsHelper.RecoveryState,
currentValue: restoreDataObject.RestoreOptions.RecoveryState.ToString(),
defaultValue: DatabaseRecoveryState.WithRecovery.ToString(),
isReadOnly: false,
isVisible: true
));
// stand by file path for when RESTORE WITH STANDBY is selected
options.Add(RestoreOptionsHelper.StandbyFile, RestorePlanDetailInfo.Create(
name: RestoreOptionsHelper.StandbyFile,
currentValue: restoreDataObject.RestoreOptions.StandByFile,
defaultValue: restoreDataObject.GetDefaultStandbyFile(databaseName),
isReadOnly: restoreDataObject.RestoreOptions.RecoveryState != DatabaseRecoveryState.WithStandBy,
isVisible: true
));
// Tail-log backup
// TODO:These methods are internal in SMO. after making them public, they can be removed from RestoreDatabaseTaskDataObject
bool isTailLogBackupPossible = restoreDataObject.IsTailLogBackupPossible(databaseName);
bool isTailLogBackupWithNoRecoveryPossible = restoreDataObject.IsTailLogBackupWithNoRecoveryPossible(databaseName);
options.Add(RestoreOptionsHelper.BackupTailLog, RestorePlanDetailInfo.Create(
name: RestoreOptionsHelper.BackupTailLog,
currentValue: restoreDataObject.BackupTailLog,
defaultValue: isTailLogBackupPossible,
isReadOnly: !isTailLogBackupPossible,
isVisible: true
));
options.Add(RestoreOptionsHelper.TailLogBackupFile, RestorePlanDetailInfo.Create(
name: RestoreOptionsHelper.TailLogBackupFile,
currentValue: restoreDataObject.TailLogBackupFile,
defaultValue: restoreDataObject.GetDefaultTailLogbackupFile(databaseName),
isReadOnly: !isTailLogBackupPossible,
isVisible: true
));
options.Add(RestoreOptionsHelper.TailLogWithNoRecovery, RestorePlanDetailInfo.Create(
name: RestoreOptionsHelper.TailLogWithNoRecovery,
currentValue: restoreDataObject.TailLogWithNoRecovery,
defaultValue: isTailLogBackupWithNoRecoveryPossible,
isReadOnly: !isTailLogBackupWithNoRecoveryPossible,
isVisible: true
));
//TODO: make the method public in SMO bool canDropExistingConnections = restoreDataObject.RestorePlan.CanDropExistingConnections(this.Data.RestorePlanner.DatabaseName);
options.Add(RestoreOptionsHelper.CloseExistingConnections, RestorePlanDetailInfo.Create(
name: RestoreOptionsHelper.CloseExistingConnections,
currentValue: restoreDataObject.CloseExistingConnections,
defaultValue: false,
isReadOnly: false, //TODO: !canDropExistingConnections
isVisible: true
));
return options;
}
/// <summary>
/// Add options to restore plan response
/// </summary>
internal static void AddOptions(RestorePlanResponse response, RestoreDatabaseTaskDataObject restoreDataObject)
{
Validate.IsNotNull(nameof(response), response);
Validate.IsNotNull(nameof(restoreDataObject), restoreDataObject);
Validate.IsNotNull(nameof(restoreDataObject.RestorePlanner), restoreDataObject.RestorePlanner);
var options = RestoreOptionsHelper.CreateRestorePlanOptions(restoreDataObject);
foreach (var item in options)
{
response.PlanDetails.Add(item.Key, item.Value);
}
}
internal static T GetOptionValue<T>(string optionkey, Dictionary<string, RestorePlanDetailInfo> optionsMetadata, IRestoreDatabaseTaskDataObject restoreDataObject)
{
RestorePlanDetailInfo optionMetadata = null;
if(optionsMetadata.TryGetValue(optionkey, out optionMetadata))
{
if (!optionMetadata.IsReadOnly)
{
return restoreDataObject.RestoreParams.GetOptionValue<T>(optionkey);
}
else
{
return (T)Convert.ChangeType(optionMetadata.DefaultValue, typeof(T));
}
}
else
{
return default(T);
}
}
/// <summary>
/// Load options in restore plan
/// </summary>
internal static void UpdateOptionsInPlan(IRestoreDatabaseTaskDataObject restoreDataObject)
{
var options = RestoreOptionsHelper.CreateRestorePlanOptions(restoreDataObject);
//Files
restoreDataObject.LogFilesFolder = GetOptionValue<string>(RestoreOptionsHelper.LogFileFolder, options, restoreDataObject);
restoreDataObject.DataFilesFolder = GetOptionValue<string>(RestoreOptionsHelper.DataFileFolder, options, restoreDataObject);
restoreDataObject.RelocateAllFiles = GetOptionValue<bool>(RestoreOptionsHelper.RelocateDbFiles, options, restoreDataObject);
//Options
object databaseRecoveryState;
string recoveryState = GetOptionValue<string>(RestoreOptionsHelper.RecoveryState, options, restoreDataObject);
if (Enum.TryParse(typeof(DatabaseRecoveryState), recoveryState, out databaseRecoveryState))
{
restoreDataObject.RestoreOptions.RecoveryState = (DatabaseRecoveryState)databaseRecoveryState;
}
restoreDataObject.RestoreOptions.KeepReplication = GetOptionValue<bool>(RestoreOptionsHelper.KeepReplication, options, restoreDataObject);
restoreDataObject.RestoreOptions.ReplaceDatabase = GetOptionValue<bool>(RestoreOptionsHelper.ReplaceDatabase, options, restoreDataObject);
restoreDataObject.RestoreOptions.SetRestrictedUser = GetOptionValue<bool>(RestoreOptionsHelper.SetRestrictedUser, options, restoreDataObject);
restoreDataObject.RestoreOptions.StandByFile = GetOptionValue<string>(RestoreOptionsHelper.StandbyFile, options, restoreDataObject);
restoreDataObject.BackupTailLog = GetOptionValue<bool>(RestoreOptionsHelper.BackupTailLog, options, restoreDataObject);
restoreDataObject.TailLogBackupFile = GetOptionValue<string>(RestoreOptionsHelper.TailLogBackupFile, options, restoreDataObject);
restoreDataObject.TailLogWithNoRecovery = GetOptionValue<bool>(RestoreOptionsHelper.TailLogWithNoRecovery, options, restoreDataObject);
restoreDataObject.CloseExistingConnections = GetOptionValue<bool>(RestoreOptionsHelper.CloseExistingConnections, options, restoreDataObject);
}
}
}