mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-07 09:35:37 -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:
@@ -56,6 +56,32 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts
|
||||
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>
|
||||
/// Restore Plan Response
|
||||
/// </summary>
|
||||
@@ -79,7 +105,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts
|
||||
/// <summary>
|
||||
/// The db files included in the backup file
|
||||
/// </summary>
|
||||
public IEnumerable<string> DbFiles { get; set; }
|
||||
public IEnumerable<RestoreDatabaseFileInfo> DbFiles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Server name
|
||||
|
||||
@@ -141,8 +141,14 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
|
||||
if (restoreDataObject != null && restoreDataObject.IsValid)
|
||||
{
|
||||
response.DatabaseName = restoreDataObject.RestorePlanner.DatabaseName;
|
||||
response.DbFiles = restoreDataObject.DbFiles.Select(x => x.PhysicalName);
|
||||
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)
|
||||
@@ -234,9 +240,16 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
restoreDataObject.AddFile(restoreDataObject.RestoreParams.BackupFilePath);
|
||||
}
|
||||
restoreDataObject.RestorePlanner.ReadHeaderFromMedia = !string.IsNullOrEmpty(restoreDataObject.RestoreParams.BackupFilePath);
|
||||
var dbNames = restoreDataObject.GetSourceDbNames();
|
||||
string dbName = dbNames.First();
|
||||
restoreDataObject.RestorePlanner.DatabaseName = dbName;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,18 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
this.restoreOptions.PercentCompleteNotification = 5;
|
||||
}
|
||||
|
||||
public string TargetDatabase
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.IsNullOrEmpty(targetDbName) ? DefaultDbName : targetDbName;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.targetDbName = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsValid
|
||||
{
|
||||
get
|
||||
@@ -130,7 +142,14 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
/// </summary>
|
||||
public string DataFilesFolder
|
||||
{
|
||||
get { return this.dataFilesFolder; }
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.dataFilesFolder))
|
||||
{
|
||||
this.dataFilesFolder = this.DefaultDataFileFolder;
|
||||
}
|
||||
return this.dataFilesFolder;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (this.dataFilesFolder == null || !this.dataFilesFolder.Equals(value))
|
||||
@@ -158,7 +177,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
this.ActiveException = ex;
|
||||
}
|
||||
|
||||
this.RelocateDbFiles();
|
||||
this.UpdateDbFiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,7 +189,15 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
/// </summary>
|
||||
public string LogFilesFolder
|
||||
{
|
||||
get { return this.logFilesFolder; }
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.logFilesFolder))
|
||||
{
|
||||
this.logFilesFolder = this.DefaultLogFileFolder;
|
||||
}
|
||||
return this.logFilesFolder;
|
||||
|
||||
}
|
||||
set
|
||||
{
|
||||
if (this.logFilesFolder == null || !this.logFilesFolder.Equals(value))
|
||||
@@ -197,7 +224,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
{
|
||||
this.ActiveException = ex;
|
||||
}
|
||||
this.RelocateDbFiles();
|
||||
this.UpdateDbFiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,7 +237,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
/// </value>
|
||||
public bool PromptBeforeEachBackup { get; set; }
|
||||
|
||||
private void RelocateDbFiles()
|
||||
private void UpdateDbFiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -219,9 +246,9 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
string fileName = this.GetTargetDbFilePhysicalName(dbFile.PhysicalName);
|
||||
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
|
||||
{
|
||||
@@ -230,9 +257,9 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
}
|
||||
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
|
||||
{
|
||||
@@ -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>();
|
||||
|
||||
/// <summary>
|
||||
@@ -286,9 +344,17 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
public string targetDbName = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The database used to restore from
|
||||
/// The database from the backup file used to restore to by default
|
||||
/// </summary>
|
||||
public string sourceDbName = string.Empty;
|
||||
public string DefaultDbName
|
||||
{
|
||||
get
|
||||
{
|
||||
var dbNames = GetSourceDbNames();
|
||||
string dbName = dbNames.FirstOrDefault();
|
||||
return dbName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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)
|
||||
{
|
||||
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;
|
||||
fileName = sourceFilename.Replace(this.sourceDbName, this.targetDbName);
|
||||
fileName = sourceFilename.Replace(this.DefaultDbName, this.targetDbName);
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
@@ -503,20 +569,20 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
|
||||
if (String.IsNullOrEmpty(this.RestorePlanner.DatabaseName))
|
||||
{
|
||||
this.RestorePlan = new RestorePlan(this.Server);
|
||||
// this.LaunchAzureConnectToStorageDialog();
|
||||
this.Util.AddCredentialNameForUrlBackupSet(this.RestorePlan, this.CredentialName);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
this.RestorePlan = this.CreateRestorePlan(this.RestorePlanner, this.RestoreOptions);
|
||||
this.Util.AddCredentialNameForUrlBackupSet(this.restorePlan, this.CredentialName);
|
||||
if (this.ActiveException == null)
|
||||
{
|
||||
this.dbFiles = this.GetDbFiles();
|
||||
if(relocateAllFiles)
|
||||
UpdateDBFilesPhysicalRelocate();
|
||||
|
||||
if (relocateAllFiles)
|
||||
{
|
||||
RelocateDbFiles();
|
||||
UpdateDbFiles();
|
||||
}
|
||||
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.
|
||||
string newPhysicalPath;
|
||||
Uri pathUri;
|
||||
bool fUriCreated = Uri.TryCreate(dbFile.PhysicalNameRelocate, UriKind.Absolute, out pathUri);
|
||||
if (fUriCreated && pathUri.Scheme == "https")
|
||||
bool uriCreated = Uri.TryCreate(dbFile.PhysicalNameRelocate, UriKind.Absolute, out pathUri);
|
||||
if (uriCreated && pathUri.Scheme == "https")
|
||||
{
|
||||
newPhysicalPath = dbFile.PhysicalNameRelocate;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user