mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 10:58:30 -05:00
fixed the bugs related to relocating db files for restore (#414)
* fixed the bugs related to relocating db files for restore
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -56,6 +56,32 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts
|
|||||||
public string ErrorMessage { get; set; }
|
public string ErrorMessage { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Database file info
|
||||||
|
/// </summary>
|
||||||
|
public class RestoreDatabaseFileInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// File type (Rows Data, Log ...)
|
||||||
|
/// </summary>
|
||||||
|
public string FileType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logical Name
|
||||||
|
/// </summary>
|
||||||
|
public string LogicalFileName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Original location of the file to restore to
|
||||||
|
/// </summary>
|
||||||
|
public string OriginalFileName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The file to restore to
|
||||||
|
/// </summary>
|
||||||
|
public string RestoreAsFileName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Restore Plan Response
|
/// Restore Plan Response
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -79,7 +105,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The db files included in the backup file
|
/// The db files included in the backup file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<string> DbFiles { get; set; }
|
public IEnumerable<RestoreDatabaseFileInfo> DbFiles { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Server name
|
/// Server name
|
||||||
|
|||||||
@@ -141,8 +141,14 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
|
|
||||||
if (restoreDataObject != null && restoreDataObject.IsValid)
|
if (restoreDataObject != null && restoreDataObject.IsValid)
|
||||||
{
|
{
|
||||||
response.DatabaseName = restoreDataObject.RestorePlanner.DatabaseName;
|
response.DatabaseName = restoreDataObject.TargetDatabase;
|
||||||
response.DbFiles = restoreDataObject.DbFiles.Select(x => x.PhysicalName);
|
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.CanRestore = CanRestore(restoreDataObject);
|
||||||
|
|
||||||
if (!response.CanRestore)
|
if (!response.CanRestore)
|
||||||
@@ -234,9 +240,16 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
restoreDataObject.AddFile(restoreDataObject.RestoreParams.BackupFilePath);
|
restoreDataObject.AddFile(restoreDataObject.RestoreParams.BackupFilePath);
|
||||||
}
|
}
|
||||||
restoreDataObject.RestorePlanner.ReadHeaderFromMedia = !string.IsNullOrEmpty(restoreDataObject.RestoreParams.BackupFilePath);
|
restoreDataObject.RestorePlanner.ReadHeaderFromMedia = !string.IsNullOrEmpty(restoreDataObject.RestoreParams.BackupFilePath);
|
||||||
var dbNames = restoreDataObject.GetSourceDbNames();
|
|
||||||
string dbName = dbNames.First();
|
restoreDataObject.RestorePlanner.DatabaseName = restoreDataObject.DefaultDbName;
|
||||||
restoreDataObject.RestorePlanner.DatabaseName = dbName;
|
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);
|
restoreDataObject.UpdateRestorePlan(restoreDataObject.RestoreParams.RelocateDbFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,18 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
this.restoreOptions.PercentCompleteNotification = 5;
|
this.restoreOptions.PercentCompleteNotification = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string TargetDatabase
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(targetDbName) ? DefaultDbName : targetDbName;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.targetDbName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsValid
|
public bool IsValid
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -130,7 +142,14 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string DataFilesFolder
|
public string DataFilesFolder
|
||||||
{
|
{
|
||||||
get { return this.dataFilesFolder; }
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(this.dataFilesFolder))
|
||||||
|
{
|
||||||
|
this.dataFilesFolder = this.DefaultDataFileFolder;
|
||||||
|
}
|
||||||
|
return this.dataFilesFolder;
|
||||||
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (this.dataFilesFolder == null || !this.dataFilesFolder.Equals(value))
|
if (this.dataFilesFolder == null || !this.dataFilesFolder.Equals(value))
|
||||||
@@ -158,7 +177,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
this.ActiveException = ex;
|
this.ActiveException = ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.RelocateDbFiles();
|
this.UpdateDbFiles();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,7 +189,15 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string LogFilesFolder
|
public string LogFilesFolder
|
||||||
{
|
{
|
||||||
get { return this.logFilesFolder; }
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(this.logFilesFolder))
|
||||||
|
{
|
||||||
|
this.logFilesFolder = this.DefaultLogFileFolder;
|
||||||
|
}
|
||||||
|
return this.logFilesFolder;
|
||||||
|
|
||||||
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (this.logFilesFolder == null || !this.logFilesFolder.Equals(value))
|
if (this.logFilesFolder == null || !this.logFilesFolder.Equals(value))
|
||||||
@@ -197,7 +224,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
{
|
{
|
||||||
this.ActiveException = ex;
|
this.ActiveException = ex;
|
||||||
}
|
}
|
||||||
this.RelocateDbFiles();
|
this.UpdateDbFiles();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,7 +237,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
/// </value>
|
/// </value>
|
||||||
public bool PromptBeforeEachBackup { get; set; }
|
public bool PromptBeforeEachBackup { get; set; }
|
||||||
|
|
||||||
private void RelocateDbFiles()
|
private void UpdateDbFiles()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -219,9 +246,9 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
string fileName = this.GetTargetDbFilePhysicalName(dbFile.PhysicalName);
|
string fileName = this.GetTargetDbFilePhysicalName(dbFile.PhysicalName);
|
||||||
if (!dbFile.DbFileType.Equals("Log"))
|
if (!dbFile.DbFileType.Equals("Log"))
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(this.dataFilesFolder))
|
if (!string.IsNullOrEmpty(this.DataFilesFolder))
|
||||||
{
|
{
|
||||||
dbFile.PhysicalNameRelocate = PathWrapper.Combine(this.dataFilesFolder, fileName);
|
dbFile.PhysicalNameRelocate = PathWrapper.Combine(this.DataFilesFolder, fileName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -230,9 +257,9 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(this.logFilesFolder))
|
if (!string.IsNullOrEmpty(this.LogFilesFolder))
|
||||||
{
|
{
|
||||||
dbFile.PhysicalNameRelocate = PathWrapper.Combine(this.logFilesFolder, fileName);
|
dbFile.PhysicalNameRelocate = PathWrapper.Combine(this.LogFilesFolder, fileName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -247,6 +274,37 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the Restore folder location of those db files whose orginal directory location
|
||||||
|
/// is not present in the destination computer.
|
||||||
|
/// </summary>
|
||||||
|
internal void UpdateDBFilesPhysicalRelocate()
|
||||||
|
{
|
||||||
|
foreach (DbFile item in DbFiles)
|
||||||
|
{
|
||||||
|
string fileName = this.GetTargetDbFilePhysicalName(item.PhysicalName);
|
||||||
|
item.PhysicalNameRelocate = PathWrapper.Combine(PathWrapper.GetDirectoryName(item.PhysicalName),
|
||||||
|
fileName);
|
||||||
|
Uri pathUri;
|
||||||
|
bool fUriCreated = Uri.TryCreate(item.PhysicalNameRelocate, UriKind.Absolute, out pathUri);
|
||||||
|
if ((!fUriCreated || pathUri.Scheme != Uri.UriSchemeHttps) &&
|
||||||
|
!Directory.Exists(Path.GetDirectoryName(item.PhysicalNameRelocate)))
|
||||||
|
{
|
||||||
|
string directoryPath = string.Empty;
|
||||||
|
if (string.Compare(item.DbFileType, SR.Log, StringComparison.OrdinalIgnoreCase) == 0)
|
||||||
|
{
|
||||||
|
directoryPath = Util.GetDefaultLogFileFolder();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
directoryPath = Util.GetDefaultDataFileFolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
item.PhysicalNameRelocate = PathWrapper.Combine(directoryPath, fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<DbFile> dbFiles = new List<DbFile>();
|
private List<DbFile> dbFiles = new List<DbFile>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -286,9 +344,17 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
public string targetDbName = string.Empty;
|
public string targetDbName = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The database used to restore from
|
/// The database from the backup file used to restore to by default
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string sourceDbName = string.Empty;
|
public string DefaultDbName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var dbNames = GetSourceDbNames();
|
||||||
|
string dbName = dbNames.FirstOrDefault();
|
||||||
|
return dbName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether [close existing connections].
|
/// Gets or sets a value indicating whether [close existing connections].
|
||||||
@@ -393,10 +459,10 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
private string GetTargetDbFilePhysicalName(string sourceDbFilePhysicalLocation)
|
private string GetTargetDbFilePhysicalName(string sourceDbFilePhysicalLocation)
|
||||||
{
|
{
|
||||||
string fileName = Path.GetFileName(sourceDbFilePhysicalLocation);
|
string fileName = Path.GetFileName(sourceDbFilePhysicalLocation);
|
||||||
if (!string.IsNullOrEmpty(this.sourceDbName) && !string.IsNullOrEmpty(this.targetDbName))
|
if (!string.IsNullOrEmpty(this.DefaultDbName) && !string.IsNullOrEmpty(this.targetDbName))
|
||||||
{
|
{
|
||||||
string sourceFilename = fileName;
|
string sourceFilename = fileName;
|
||||||
fileName = sourceFilename.Replace(this.sourceDbName, this.targetDbName);
|
fileName = sourceFilename.Replace(this.DefaultDbName, this.targetDbName);
|
||||||
}
|
}
|
||||||
return fileName;
|
return fileName;
|
||||||
}
|
}
|
||||||
@@ -503,20 +569,20 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
if (String.IsNullOrEmpty(this.RestorePlanner.DatabaseName))
|
if (String.IsNullOrEmpty(this.RestorePlanner.DatabaseName))
|
||||||
{
|
{
|
||||||
this.RestorePlan = new RestorePlan(this.Server);
|
this.RestorePlan = new RestorePlan(this.Server);
|
||||||
// this.LaunchAzureConnectToStorageDialog();
|
|
||||||
this.Util.AddCredentialNameForUrlBackupSet(this.RestorePlan, this.CredentialName);
|
this.Util.AddCredentialNameForUrlBackupSet(this.RestorePlan, this.CredentialName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
this.RestorePlan = this.CreateRestorePlan(this.RestorePlanner, this.RestoreOptions);
|
this.RestorePlan = this.CreateRestorePlan(this.RestorePlanner, this.RestoreOptions);
|
||||||
this.Util.AddCredentialNameForUrlBackupSet(this.restorePlan, this.CredentialName);
|
this.Util.AddCredentialNameForUrlBackupSet(this.restorePlan, this.CredentialName);
|
||||||
if (this.ActiveException == null)
|
if (this.ActiveException == null)
|
||||||
{
|
{
|
||||||
this.dbFiles = this.GetDbFiles();
|
this.dbFiles = this.GetDbFiles();
|
||||||
if(relocateAllFiles)
|
UpdateDBFilesPhysicalRelocate();
|
||||||
|
|
||||||
|
if (relocateAllFiles)
|
||||||
{
|
{
|
||||||
RelocateDbFiles();
|
UpdateDbFiles();
|
||||||
}
|
}
|
||||||
this.SetRestorePlanProperties(this.restorePlan);
|
this.SetRestorePlanProperties(this.restorePlan);
|
||||||
}
|
}
|
||||||
@@ -569,8 +635,8 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
|||||||
// For XStore path, we don't want to try the getFullPath.
|
// For XStore path, we don't want to try the getFullPath.
|
||||||
string newPhysicalPath;
|
string newPhysicalPath;
|
||||||
Uri pathUri;
|
Uri pathUri;
|
||||||
bool fUriCreated = Uri.TryCreate(dbFile.PhysicalNameRelocate, UriKind.Absolute, out pathUri);
|
bool uriCreated = Uri.TryCreate(dbFile.PhysicalNameRelocate, UriKind.Absolute, out pathUri);
|
||||||
if (fUriCreated && pathUri.Scheme == "https")
|
if (uriCreated && pathUri.Scheme == "https")
|
||||||
{
|
{
|
||||||
newPhysicalPath = dbFile.PhysicalNameRelocate;
|
newPhysicalPath = dbFile.PhysicalNameRelocate;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user