/// <summary> /// Creates response which includes information about the server given to restore (default data location, db names with backupsets) /// </summary> public RestoreConfigInfoResponse CreateConfigInfoResponse(RestoreConfigInfoRequestParams restoreConfigInfoRequest) { RestoreConfigInfoResponse response = new RestoreConfigInfoResponse(); RestoreDatabaseTaskDataObject restoreTaskObject = null; try { restoreTaskObject = CreateRestoreForNewSession(restoreConfigInfoRequest.OwnerUri); if (restoreTaskObject != null) { // Default Data folder path in the target server response.ConfigInfo.Add(RestoreOptionsHelper.DataFileFolder, restoreTaskObject.DefaultDataFileFolder); // Default log folder path in the target server response.ConfigInfo.Add(RestoreOptionsHelper.LogFileFolder, restoreTaskObject.DefaultLogFileFolder); // The db names with backup set response.ConfigInfo.Add(RestoreOptionsHelper.SourceDatabaseNamesWithBackupSets, restoreTaskObject.GetDatabaseNamesWithBackupSets()); // Default backup folder path in the target server response.ConfigInfo.Add(RestoreOptionsHelper.DefaultBackupFolder, restoreTaskObject.DefaultBackupFolder); } } catch (Exception ex) { Logger.Write(LogLevel.Warning, $"Failed to create restore config info. error: { ex.Message}"); response.ErrorMessage = ex.Message; } finally { ServerConnection serverConnection = restoreTaskObject?.Server?.ConnectionContext; if (serverConnection != null && serverConnection.IsOpen) { restoreTaskObject.Server.ConnectionContext.Disconnect(); } } return(response); }
/// <summary> /// Async task to cancel restore /// </summary> public async Task <TaskResult> CancelTaskAsync(SqlTask sqlTask) { RestoreDatabaseTaskDataObject restoreDataObject = sqlTask.TaskMetadata.Data as RestoreDatabaseTaskDataObject; TaskResult taskResult = null; if (restoreDataObject != null && restoreDataObject.IsValid) { // Create a task for backup cancellation request return(await Task.Factory.StartNew(() => { foreach (Restore restore in restoreDataObject.RestorePlan.RestoreOperations) { restore.Abort(); } return new TaskResult { TaskStatus = SqlTaskStatus.Canceled }; })); } else { taskResult = new TaskResult(); taskResult.TaskStatus = SqlTaskStatus.Failed; } return(taskResult); }
private RestoreDatabaseTaskDataObject CreateRestoreForNewSession(string ownerUri, string targetDatabaseName = null) { ConnectionInfo connInfo; DisasterRecoveryService.ConnectionServiceInstance.TryFindConnection( ownerUri, out connInfo); if (connInfo != null) { SqlConnection connection; DbConnection dbConnection = connInfo.AllConnections.First(); ReliableSqlConnection reliableSqlConnection = dbConnection as ReliableSqlConnection; SqlConnection sqlConnection = dbConnection as SqlConnection; if (reliableSqlConnection != null) { connection = reliableSqlConnection.GetUnderlyingConnection(); } else if (sqlConnection != null) { connection = sqlConnection; } else { Logger.Write(LogLevel.Warning, "Cannot find any sql connection for restore operation"); return(null); } Server server = new Server(new ServerConnection(connection)); RestoreDatabaseTaskDataObject restoreDataObject = new RestoreDatabaseTaskDataObject(server, targetDatabaseName); return(restoreDataObject); } return(null); }
/// <summary> /// Returns true if the restoring the restoreDataObject is supported in the service /// </summary> private static bool CanRestore(RestoreDatabaseTaskDataObject restoreDataObject) { if (restoreDataObject != null) { var backupTypes = restoreDataObject.GetBackupSetInfo(); return(backupTypes.Any(x => x.BackupType.StartsWith(RestoreConstants.TypeFull))); } return(false); }
/// <summary> /// Create a backup task for execution and cancellation /// </summary> /// <param name="sqlTask"></param> /// <returns></returns> internal async Task <TaskResult> RestoreTaskAsync(SqlTask sqlTask) { sqlTask.AddMessage(SR.Task_InProgress, SqlTaskStatus.InProgress, true); RestoreDatabaseTaskDataObject restoreDataObject = sqlTask.TaskMetadata.Data as RestoreDatabaseTaskDataObject; TaskResult taskResult = null; if (restoreDataObject != null) { // Create a task to perform backup return(await Task.Factory.StartNew(() => { TaskResult result = new TaskResult(); try { if (restoreDataObject.IsValid) { ExecuteRestore(restoreDataObject); result.TaskStatus = SqlTaskStatus.Succeeded; } else { result.TaskStatus = SqlTaskStatus.Failed; if (restoreDataObject.ActiveException != null) { result.ErrorMessage = restoreDataObject.ActiveException.Message; } else { result.ErrorMessage = SR.RestoreNotSupported; } } } catch (Exception ex) { result.TaskStatus = SqlTaskStatus.Failed; result.ErrorMessage = ex.Message; if (ex.InnerException != null) { result.ErrorMessage += Environment.NewLine + ex.InnerException.Message; } if (restoreDataObject != null && restoreDataObject.ActiveException != null) { result.ErrorMessage += Environment.NewLine + restoreDataObject.ActiveException.Message; } } return result; })); } else { taskResult = new TaskResult(); taskResult.TaskStatus = SqlTaskStatus.Failed; } return(taskResult); }
/// <summary> /// Executes the restore operation /// </summary> /// <param name="requestParam"></param> public void ExecuteRestore(RestoreDatabaseTaskDataObject restoreDataObject) { UpdateRestorePlan(restoreDataObject); if (restoreDataObject != null && CanRestore(restoreDataObject)) { restoreDataObject.RestorePlan.Execute(); } else { throw new InvalidOperationException(SR.RestoreNotSupported); } }
/// <summary> /// Creates anew restore task object to do the restore operations /// </summary> /// <param name="restoreParams">Restore request parameters</param> /// <returns>Restore task object</returns> public RestoreDatabaseTaskDataObject CreateRestoreDatabaseTaskDataObject(RestoreParams restoreParams) { RestoreDatabaseTaskDataObject restoreTaskObject = null; string sessionId = string.IsNullOrWhiteSpace(restoreParams.SessionId) ? Guid.NewGuid().ToString() : restoreParams.SessionId; if (!sessions.TryGetValue(sessionId, out restoreTaskObject)) { restoreTaskObject = CreateRestoreForNewSession(restoreParams.OwnerUri, restoreParams.TargetDatabaseName); sessions.AddOrUpdate(sessionId, restoreTaskObject, (key, old) => restoreTaskObject); } restoreTaskObject.SessionId = sessionId; restoreTaskObject.RestoreParams = restoreParams; return(restoreTaskObject); }
private RestoreDatabaseTaskDataObject CreateRestoreForNewSession(string ownerUri, string targetDatabaseName = null) { ConnectionInfo connInfo; DisasterRecoveryService.ConnectionServiceInstance.TryFindConnection( ownerUri, out connInfo); if (connInfo != null) { Server server = new Server(ConnectionService.OpenServerConnection(connInfo, "Restore")); RestoreDatabaseTaskDataObject restoreDataObject = new RestoreDatabaseTaskDataObject(server, targetDatabaseName); return(restoreDataObject); } return(null); }
/// <summary> /// Creates response which includes information about the server given to restore (default data location, db names with backupsets) /// </summary> public RestoreConfigInfoResponse CreateConfigInfoResponse(RestoreConfigInfoRequestParams restoreConfigInfoRequest) { RestoreConfigInfoResponse response = new RestoreConfigInfoResponse(); RestoreDatabaseTaskDataObject restoreTaskObject = CreateRestoreForNewSession(restoreConfigInfoRequest.OwnerUri); if (restoreTaskObject != null) { // Default Data folder path in the target server response.ConfigInfo.Add(RestoreOptionsHelper.DataFileFolder, restoreTaskObject.DefaultDataFileFolder); // Default log folder path in the target server response.ConfigInfo.Add(RestoreOptionsHelper.LogFileFolder, restoreTaskObject.DefaultLogFileFolder); // The db names with backup set response.ConfigInfo.Add(RestoreOptionsHelper.SourceDatabaseNamesWithBackupSets, restoreTaskObject.GetDatabaseNamesWithBackupSets()); } return(response); }
/// <summary> /// Cancels existing restore plan /// </summary> public bool CancelRestorePlan(RestoreParams restoreParams) { RestoreDatabaseTaskDataObject restoreTaskObject = null; string sessionId = restoreParams.SessionId; if (!string.IsNullOrEmpty(sessionId) && sessions.TryGetValue(sessionId, out restoreTaskObject)) { ServerConnection connection = restoreTaskObject?.Server?.ConnectionContext; if (connection != null && connection.IsOpen) { connection.Disconnect(); } sessions.TryRemove(sessionId, out restoreTaskObject); return(true); } return(false); }
/// <summary> /// Create a restore data object that includes the plan to do the restore operation /// </summary> /// <param name="requestParam"></param> /// <returns></returns> private void UpdateRestorePlan(RestoreDatabaseTaskDataObject restoreDataObject) { if (!string.IsNullOrEmpty(restoreDataObject.RestoreParams.BackupFilePaths)) { restoreDataObject.AddFiles(restoreDataObject.RestoreParams.BackupFilePaths); } restoreDataObject.RestorePlanner.ReadHeaderFromMedia = !string.IsNullOrEmpty(restoreDataObject.RestoreParams.BackupFilePaths); if (string.IsNullOrWhiteSpace(restoreDataObject.RestoreParams.SourceDatabaseName)) { restoreDataObject.RestorePlanner.DatabaseName = restoreDataObject.DefaultDbName; } else { restoreDataObject.RestorePlanner.DatabaseName = restoreDataObject.RestoreParams.SourceDatabaseName; } restoreDataObject.TargetDatabase = restoreDataObject.RestoreParams.TargetDatabaseName; restoreDataObject.RestoreOptions.KeepReplication = restoreDataObject.RestoreParams.GetOptionValue <bool>(RestoreOptionsHelper.KeepReplication); restoreDataObject.RestoreOptions.ReplaceDatabase = restoreDataObject.RestoreParams.GetOptionValue <bool>(RestoreOptionsHelper.ReplaceDatabase); restoreDataObject.RestoreOptions.SetRestrictedUser = restoreDataObject.RestoreParams.GetOptionValue <bool>(RestoreOptionsHelper.SetRestrictedUser); string recoveryState = restoreDataObject.RestoreParams.GetOptionValue <string>(RestoreOptionsHelper.RecoveryState); object databaseRecoveryState; if (Enum.TryParse(typeof(DatabaseRecoveryState), recoveryState, out databaseRecoveryState)) { restoreDataObject.RestoreOptions.RecoveryState = (DatabaseRecoveryState)databaseRecoveryState; } bool isTailLogBackupPossible = restoreDataObject.IsTailLogBackupPossible(restoreDataObject.RestorePlanner.DatabaseName); if (isTailLogBackupPossible) { restoreDataObject.RestorePlanner.BackupTailLog = restoreDataObject.RestoreParams.GetOptionValue <bool>(RestoreOptionsHelper.BackupTailLog); restoreDataObject.TailLogBackupFile = restoreDataObject.RestoreParams.GetOptionValue <string>(RestoreOptionsHelper.TailLogBackupFile); restoreDataObject.TailLogWithNoRecovery = restoreDataObject.RestoreParams.GetOptionValue <bool>(RestoreOptionsHelper.TailLogWithNoRecovery); } else { restoreDataObject.RestorePlanner.BackupTailLog = false; } restoreDataObject.CloseExistingConnections = restoreDataObject.RestoreParams.GetOptionValue <bool>(RestoreOptionsHelper.CloseExistingConnections); restoreDataObject.UpdateRestorePlan(restoreDataObject.RestoreParams.RelocateDbFiles); }
/// <summary> /// Create a restore data object that includes the plan to do the restore operation /// </summary> /// <param name="requestParam"></param> /// <returns></returns> private void UpdateRestorePlan(RestoreDatabaseTaskDataObject restoreDataObject) { if (!string.IsNullOrEmpty(restoreDataObject.RestoreParams.BackupFilePath)) { restoreDataObject.AddFile(restoreDataObject.RestoreParams.BackupFilePath); } restoreDataObject.RestorePlanner.ReadHeaderFromMedia = !string.IsNullOrEmpty(restoreDataObject.RestoreParams.BackupFilePath); restoreDataObject.RestorePlanner.DatabaseName = restoreDataObject.DefaultDbName; restoreDataObject.TargetDatabase = restoreDataObject.RestoreParams.DatabaseName; //TODO: used for other types of restore /*bool isTailLogBackupPossible = restoreDataObject.RestorePlanner.IsTailLogBackupPossible(restoreDataObject.RestorePlanner.DatabaseName); * restoreDataObject.RestorePlanner.BackupTailLog = isTailLogBackupPossible; * restoreDataObject.TailLogBackupFile = restoreDataObject.Util.GetDefaultTailLogbackupFile(dbName); * restoreDataObject.RestorePlanner.TailLogBackupFile = restoreDataObject.TailLogBackupFile; */ restoreDataObject.UpdateRestorePlan(restoreDataObject.RestoreParams.RelocateDbFiles); }
/// <summary> /// Creates anew restore task object to do the restore operations /// </summary> /// <param name="restoreParams">Restore request parameters</param> /// <returns>Restore task object</returns> public RestoreDatabaseTaskDataObject CreateRestoreDatabaseTaskDataObject(RestoreParams restoreParams) { RestoreDatabaseTaskDataObject restoreTaskObject = null; if (!string.IsNullOrWhiteSpace(restoreParams.SessionId)) { this.restoreSessions.TryGetValue(restoreParams.SessionId, out restoreTaskObject); } if (restoreTaskObject == null) { restoreTaskObject = CreateRestoreForNewSession(restoreParams); string sessionId = string.IsNullOrWhiteSpace(restoreParams.SessionId) ? Guid.NewGuid().ToString() : restoreParams.SessionId; this.restoreSessions.AddOrUpdate(sessionId, restoreTaskObject, (key, oldSession) => restoreTaskObject); restoreTaskObject.SessionId = sessionId; } else { restoreTaskObject.RestoreParams = restoreParams; } return(restoreTaskObject); }
/// <summary> /// Executes the restore operation /// </summary> /// <param name="requestParam"></param> public void ExecuteRestore(RestoreDatabaseTaskDataObject restoreDataObject, SqlTask sqlTask = null) { // Restore Plan should be already created and updated at this point UpdateRestorePlan(restoreDataObject); if (restoreDataObject != null && CanRestore(restoreDataObject)) { try { restoreDataObject.SqlTask = sqlTask; restoreDataObject.Execute(); RestoreDatabaseTaskDataObject cachedRestoreDataObject; this.restoreSessions.TryRemove(restoreDataObject.SessionId, out cachedRestoreDataObject); } catch (Exception ex) { throw ex; } } else { throw new InvalidOperationException(SR.RestoreNotSupported); } }
private bool CanChangeTargetDatabase(RestoreDatabaseTaskDataObject restoreDataObject) { return(DatabaseUtils.IsSystemDatabaseConnection(restoreDataObject.Server.ConnectionContext.DatabaseName)); }
/// <summary> /// Returns true if the restoring the restoreDataObject is supported in the service /// </summary> private static bool CanRestore(RestoreDatabaseTaskDataObject restoreDataObject) { return(restoreDataObject != null && restoreDataObject.RestorePlan != null && restoreDataObject.RestorePlan.RestoreOperations != null && restoreDataObject.RestorePlan.RestoreOperations.Count > 0); }
/// <summary> /// Creates a restore plan, The result includes the information about the backup set, /// the files and the database to restore to /// </summary> /// <param name="requestParam">Restore request</param>s /// <returns>Restore plan</returns> public RestorePlanResponse CreateRestorePlanResponse(RestoreDatabaseTaskDataObject restoreDataObject) { RestorePlanResponse response = new RestorePlanResponse() { DatabaseName = restoreDataObject.RestoreParams.DatabaseName }; try { if (restoreDataObject != null && restoreDataObject.IsValid) { UpdateRestorePlan(restoreDataObject); if (restoreDataObject != null && restoreDataObject.IsValid) { response.DatabaseName = restoreDataObject.TargetDatabase; response.DbFiles = restoreDataObject.DbFiles.Select(x => new RestoreDatabaseFileInfo { FileType = x.DbFileType, LogicalFileName = x.LogicalName, OriginalFileName = x.PhysicalName, RestoreAsFileName = x.PhysicalNameRelocate }); response.CanRestore = CanRestore(restoreDataObject); if (!response.CanRestore) { response.ErrorMessage = SR.RestoreNotSupported; } response.RelocateFilesNeeded = !restoreDataObject.DbFilesLocationAreValid(); response.DefaultDataFolder = restoreDataObject.DefaultDataFileFolder; response.DefaultLogFolder = restoreDataObject.DefaultLogFileFolder; } else { if (restoreDataObject.ActiveException != null) { response.ErrorMessage = restoreDataObject.ActiveException.Message; } else { response.ErrorMessage = SR.RestorePlanFailed; } response.CanRestore = false; } } else { response.ErrorMessage = SR.RestorePlanFailed; } } catch (Exception ex) { response.ErrorMessage = ex.Message; if (ex.InnerException != null) { response.ErrorMessage += Environment.NewLine; response.ErrorMessage += ex.InnerException.Message; } } return(response); }
/// <summary> /// Creates a restore plan, The result includes the information about the backup set, /// the files and the database to restore to /// </summary> /// <param name="requestParam">Restore request</param>s /// <returns>Restore plan</returns> public RestorePlanResponse CreateRestorePlanResponse(RestoreDatabaseTaskDataObject restoreDataObject) { RestorePlanResponse response = new RestorePlanResponse() { DatabaseName = restoreDataObject.RestoreParams.TargetDatabaseName, PlanDetails = new System.Collections.Generic.Dictionary <string, RestorePlanDetailInfo>() }; try { if (restoreDataObject != null && restoreDataObject.IsValid) { restoreDataObject.UpdateRestoreTaskObject(); if (restoreDataObject != null && restoreDataObject.IsValid) { response.SessionId = restoreDataObject.SessionId; response.DatabaseName = restoreDataObject.TargetDatabaseName; response.PlanDetails.Add(RestoreOptionsHelper.TargetDatabaseName, RestoreOptionFactory.Instance.CreateAndValidate(RestoreOptionsHelper.TargetDatabaseName, restoreDataObject)); response.PlanDetails.Add(RestoreOptionsHelper.SourceDatabaseName, RestoreOptionFactory.Instance.CreateAndValidate(RestoreOptionsHelper.SourceDatabaseName, restoreDataObject)); response.PlanDetails.Add(RestoreOptionsHelper.ReadHeaderFromMedia, RestorePlanDetailInfo.Create( name: RestoreOptionsHelper.ReadHeaderFromMedia, currentValue: restoreDataObject.RestorePlanner.ReadHeaderFromMedia)); response.DbFiles = restoreDataObject.DbFiles.Select(x => new RestoreDatabaseFileInfo { FileType = x.DbFileType, LogicalFileName = x.LogicalName, OriginalFileName = x.PhysicalName, RestoreAsFileName = x.PhysicalNameRelocate }); response.CanRestore = CanRestore(restoreDataObject); response.PlanDetails.Add(LastBackupTaken, RestorePlanDetailInfo.Create(name: LastBackupTaken, currentValue: restoreDataObject.GetLastBackupTaken(), isReadOnly: true)); response.BackupSetsToRestore = restoreDataObject.GetSelectedBakupSets(); var dbNames = restoreDataObject.SourceDbNames; response.DatabaseNamesFromBackupSets = dbNames == null ? new string[] { } : dbNames.ToArray(); RestoreOptionsHelper.AddOptions(response, restoreDataObject); } else { if (restoreDataObject.ActiveException != null) { response.ErrorMessage = restoreDataObject.ActiveException.Message; } else { response.ErrorMessage = SR.RestorePlanFailed; } response.CanRestore = false; } } else { response.ErrorMessage = SR.RestorePlanFailed; } } catch (Exception ex) { response.ErrorMessage = ex.Message; if (ex.InnerException != null) { response.ErrorMessage += Environment.NewLine; response.ErrorMessage += ex.InnerException.Message; } Logger.Write(LogLevel.Normal, $"Failed to create restore plan. error: { response.ErrorMessage}"); } return(response); }
/// <summary> /// Creates a restore plan, The result includes the information about the backup set, /// the files and the database to restore to /// </summary> /// <param name="requestParam">Restore request</param>s /// <returns>Restore plan</returns> public RestorePlanResponse CreateRestorePlanResponse(RestoreDatabaseTaskDataObject restoreDataObject) { RestorePlanResponse response = new RestorePlanResponse() { DatabaseName = restoreDataObject.RestoreParams.TargetDatabaseName, PlanDetails = new System.Collections.Generic.Dictionary <string, object>() }; try { if (restoreDataObject != null && restoreDataObject.IsValid) { UpdateRestorePlan(restoreDataObject); if (restoreDataObject != null && restoreDataObject.IsValid) { response.SessionId = restoreDataObject.SessionId; response.DatabaseName = restoreDataObject.TargetDatabase; response.DbFiles = restoreDataObject.DbFiles.Select(x => new RestoreDatabaseFileInfo { FileType = x.DbFileType, LogicalFileName = x.LogicalName, OriginalFileName = x.PhysicalName, RestoreAsFileName = x.PhysicalNameRelocate }); response.CanRestore = CanRestore(restoreDataObject); if (!response.CanRestore) { response.ErrorMessage = SR.RestoreNotSupported; } response.PlanDetails.Add(LastBackupTaken, restoreDataObject.GetLastBackupTaken()); response.BackupSetsToRestore = restoreDataObject.GetSelectedBakupSets(); var dbNames = restoreDataObject.GetSourceDbNames(); response.DatabaseNamesFromBackupSets = dbNames == null ? new string[] { } : dbNames.ToArray(); // Adding the default values for some of the options in the plan details bool isTailLogBackupPossible = restoreDataObject.IsTailLogBackupPossible(restoreDataObject.RestorePlanner.DatabaseName); // Default backup tail-log. It's true when tail-log backup is possible for the source database response.PlanDetails.Add(RestoreOptionsHelper.DefaultBackupTailLog, isTailLogBackupPossible); // Default backup file for tail-log bacup when Tail-Log bachup is set to true response.PlanDetails.Add(RestoreOptionsHelper.DefaultTailLogBackupFile, restoreDataObject.Util.GetDefaultTailLogbackupFile(restoreDataObject.RestorePlan.DatabaseName)); // Default stand by file path for when RESTORE WITH STANDBY is selected response.PlanDetails.Add(RestoreOptionsHelper.DefaultStandbyFile, restoreDataObject.Util.GetDefaultStandbyFile(restoreDataObject.RestorePlan.DatabaseName)); // Default Data folder path in the target server response.PlanDetails.Add(RestoreOptionsHelper.DefaultDataFileFolder, restoreDataObject.DefaultDataFileFolder); // Default log folder path in the target server response.PlanDetails.Add(RestoreOptionsHelper.DefaultLogFileFolder, restoreDataObject.DefaultLogFileFolder); } else { if (restoreDataObject.ActiveException != null) { response.ErrorMessage = restoreDataObject.ActiveException.Message; } else { response.ErrorMessage = SR.RestorePlanFailed; } response.CanRestore = false; } } else { response.ErrorMessage = SR.RestorePlanFailed; } } catch (Exception ex) { response.ErrorMessage = ex.Message; if (ex.InnerException != null) { response.ErrorMessage += Environment.NewLine; response.ErrorMessage += ex.InnerException.Message; } } return(response); }