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:
Leila Lali
2017-07-17 11:59:40 -07:00
committed by GitHub
parent 18977a89dc
commit 836847ce15
4 changed files with 1220 additions and 1115 deletions

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;
}