コード例 #1
0
 /// <summary>
 /// Sets restore plan properties
 /// </summary>
 private void SetRestorePlanProperties(RestorePlan rp)
 {
     if (rp == null || rp.RestoreOperations.Count < 1)
     {
         return;
     }
     rp.SetRestoreOptions(this.RestoreOptions);
     rp.CloseExistingConnections = this.CloseExistingConnections;
     if (this.targetDbName != null && !this.targetDbName.Equals(string.Empty))
     {
         rp.DatabaseName = targetDbName;
     }
     rp.RestoreOperations[0].RelocateFiles.Clear();
     foreach (DbFile dbFile in this.DbFiles)
     {
         // For XStore path, we don't want to try the getFullPath.
         string newPhysicalPath;
         Uri    pathUri;
         bool   uriCreated = Uri.TryCreate(dbFile.PhysicalNameRelocate, UriKind.Absolute, out pathUri);
         if (uriCreated && pathUri.Scheme == "https")
         {
             newPhysicalPath = dbFile.PhysicalNameRelocate;
         }
         else
         {
             newPhysicalPath = Path.GetFullPath(dbFile.PhysicalNameRelocate);
         }
         if (!dbFile.PhysicalName.Equals(newPhysicalPath))
         {
             RelocateFile relocFile = new RelocateFile(dbFile.LogicalName, dbFile.PhysicalNameRelocate);
             rp.RestoreOperations[0].RelocateFiles.Add(relocFile);
         }
     }
 }
コード例 #2
0
        internal RestorePlan CreateRestorePlan(DatabaseRestorePlanner planner, RestoreOptions restoreOptions)
        {
            this.CreateOrUpdateRestorePlanException = null;
            RestorePlan ret = null;

            try
            {
                ret = planner.CreateRestorePlan(restoreOptions);
                if (ret == null || ret.RestoreOperations.Count == 0)
                {
                    this.ActiveException = planner.GetBackupDeviceReadErrors();
                }
            }
            catch (Exception ex)
            {
                this.ActiveException = ex;
                this.CreateOrUpdateRestorePlanException = this.ActiveException;
            }
            finally
            {
            }


            return(ret);
        }
コード例 #3
0
        public void CreateNewRestorePlan()
        {
            this.ActiveException = null; //Clear any existing exceptions as the plan is getting recreated.
                                         //Clear any existing exceptions as new plan is getting recreated.
            this.CreateOrUpdateRestorePlanException = null;
            this.DbFiles.Clear();
            this.PlanUpdateRequired = false;
            this.restorePlan        = null;
            if (String.IsNullOrEmpty(this.RestorePlanner.DatabaseName))
            {
                this.RestorePlan = new RestorePlan(this.Server);
                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();

                    UpdateDBFilesPhysicalRelocate();
                }
            }
            if (this.restorePlan == null)
            {
                this.RestorePlan = new RestorePlan(this.Server);
                this.Util.AddCredentialNameForUrlBackupSet(this.RestorePlan, this.CredentialName);
            }
        }
コード例 #4
0
        /// <summary>
        /// Gets RestorePlan to perform restore and to script
        /// </summary>
        public RestorePlan GetRestorePlanForExecutionAndScript()
        {
            this.ActiveException = null; //Clear any existing exceptions as the plan is getting recreated.
                                         //Clear any existing exceptions as new plan is getting recreated.
            this.CreateOrUpdateRestorePlanException = null;
            bool tailLogBackup = this.RestorePlanner.BackupTailLog;

            if (this.planUpdateRequired)
            {
                this.RestorePlan = this.RestorePlanner.CreateRestorePlan(this.RestoreOptions);
                this.UpdateRestoreSelected();
                this.Util.AddCredentialNameForUrlBackupSet(this.RestorePlan, this.CredentialName);
            }
            RestorePlan rp = new RestorePlan(this.Server);

            rp.RestoreAction = RestoreActionType.Database;
            if (this.RestorePlan != null)
            {
                if (this.RestorePlan.TailLogBackupOperation != null && tailLogBackup)
                {
                    rp.TailLogBackupOperation = this.RestorePlan.TailLogBackupOperation;
                }
                int i = 0;
                foreach (Restore res in this.RestorePlan.RestoreOperations)
                {
                    if (this.RestoreSelected[i] == true)
                    {
                        rp.RestoreOperations.Add(res);
                    }
                    i++;
                }
            }
            this.SetRestorePlanProperties(rp);
            return(rp);
        }
コード例 #5
0
        /// <summary>
        /// Set credential name in the restore objects which have a backup set in Microsoft Azure
        /// From sql16, default credential is SAS credential so no explict credential needed for restore object.
        /// </summary>
        /// <param name="restorePlan">Restore plan created for the restore operation</param>
        /// <param name="credentialName">Sql server credential name</param>
        public void AddCredentialNameForUrlBackupSet(RestorePlan restorePlan, string credentialName)
        {
            if (string.IsNullOrEmpty(credentialName) || restorePlan == null || restorePlan.RestoreOperations == null)
            {
                return;
            }
            if (restorePlan.Server.VersionMajor >= 13) // for sql16, default backup/restore URL will use SAS
            {
                return;
            }
            // If any of the backup media in the restore object is in URL, we assign the credential name to the CredentialName property of the Restore object
            foreach (Restore res in restorePlan.RestoreOperations)
            {
                if (res.BackupSet != null && res.BackupSet.BackupMediaSet != null && res.BackupSet.BackupMediaSet.BackupMediaList != null)
                {
                    foreach (BackupMedia bkMedia in res.BackupSet.BackupMediaSet.BackupMediaList)
                    {
                        if (bkMedia != null && bkMedia.MediaType == DeviceType.Url)
                        {
                            res.CredentialName = credentialName;
                            break;
                        }
                    }
                }

                if (res.Devices != null)
                {
                    foreach (BackupDeviceItem bkDevice in res.Devices)
                    {
                        if (bkDevice.DeviceType == DeviceType.Url)
                        {
                            res.CredentialName = credentialName;
                            break;
                        }
                    }
                }
            }
            // If the backup file to which the tail log is going to be backed up is a file in Microsoft Azure,
            // we assign the credential name to the Credential Name property of the Backup object
            if (restorePlan.TailLogBackupOperation != null && restorePlan.TailLogBackupOperation.Devices != null)
            {
                foreach (BackupDeviceItem bkdevItem in restorePlan.TailLogBackupOperation.Devices)
                {
                    if (bkdevItem != null && bkdevItem.DeviceType == DeviceType.Url)
                    {
                        restorePlan.TailLogBackupOperation.CredentialName = credentialName;
                        break;
                    }
                }
            }
        }
コード例 #6
0
        /// <summary>
        /// Returns a default location for tail log backup
        /// If the first backup media is from Microsoft Azure, a Microsoft Azure url for the Tail log backup file is returned
        /// </summary>
        internal string GetDefaultTailLogbackupFile(string databaseName, RestorePlan restorePlan)
        {
            if (string.IsNullOrEmpty(databaseName) || restorePlan == null)
            {
                return(string.Empty);
            }
            if (restorePlan.TailLogBackupOperation != null && restorePlan.TailLogBackupOperation.Devices != null)
            {
                restorePlan.TailLogBackupOperation.Devices.Clear();
            }
            string      folderpath       = string.Empty;
            BackupMedia firstBackupMedia = this.GetFirstBackupMedia(restorePlan);
            string      filename         = this.SanitizeFileName(databaseName) + "_LogBackup_" + this.GetServerCurrentDateTime().ToString("yyyy-MM-dd_HH-mm-ss") + ".bak";

            if (firstBackupMedia != null && firstBackupMedia.MediaType == DeviceType.Url)
            {
                // the uri will use the same container as the container of the first backup media
                Uri uri;
                if (Uri.TryCreate(firstBackupMedia.MediaName, UriKind.Absolute, out uri))
                {
                    UriBuilder uriBuilder = new UriBuilder();
                    uriBuilder.Scheme = uri.Scheme;
                    uriBuilder.Host   = uri.Host;
                    if (uri.AbsolutePath.Length > 0)
                    {
                        string[] parts   = uri.AbsolutePath.Split('/');
                        string   newPath = string.Join("/", parts, 0, parts.Length - 1);
                        if (newPath.EndsWith("/"))
                        {
                            newPath = newPath.Substring(0, newPath.Length - 1);
                        }
                        uriBuilder.Host = uriBuilder.Host + newPath;
                    }
                    uriBuilder.Path = filename;
                    string urlFilename = uriBuilder.Uri.AbsoluteUri;
                    if (restorePlan.TailLogBackupOperation != null && restorePlan.TailLogBackupOperation.Devices != null)
                    {
                        restorePlan.TailLogBackupOperation.Devices.Add(new BackupDeviceItem(urlFilename, DeviceType.Url));
                    }
                    return(urlFilename);
                }
            }
            folderpath = this.GetDefaultBackupFolder();
            if (restorePlan.TailLogBackupOperation != null && restorePlan.TailLogBackupOperation.Devices != null)
            {
                restorePlan.TailLogBackupOperation.Devices.Add(new BackupDeviceItem(PathWrapper.Combine(folderpath, filename), DeviceType.File));
            }
            return(PathWrapper.Combine(folderpath, filename));
        }
コード例 #7
0
        //TODO: the code is moved from ssms and used for other typs of restore operation
        //Uncomment when restore operation for those types are supported

        /*
         * internal void MarkDuplicateSuspectPages(List<SuspectPageTaskDataObject> suspectPageObjList)
         * {
         *  List<SuspectPageTaskDataObject> newList = new List<SuspectPageTaskDataObject>(suspectPageObjList);
         *  newList.Sort();
         *  newList[0].IsDuplicate = false;
         *  for (int i = 1; i < newList.Count; i++)
         *  {
         *      if (newList[i].CompareTo(newList[i - 1]) == 0)
         *      {
         *          newList[i].IsDuplicate = true;
         *          newList[i - 1].IsDuplicate = true;
         *      }
         *      else
         *      {
         *          newList[i].IsDuplicate = false;
         *      }
         *  }
         * }
         */

        /*
         * internal void VerifyChecksumWorker(RestorePlan plan, IBackgroundOperationContext backgroundContext, EventHandler cancelEventHandler)
         * {
         * if (plan == null || plan.RestoreOperations.Count() == 0)
         * {
         *  return;
         * }
         * backgroundContext.IsCancelable = true;
         * backgroundContext.CancelRequested += cancelEventHandler;
         * try
         * {
         *  foreach (Restore res in plan.RestoreOperations)
         *  {
         *      if (!backgroundContext.IsCancelRequested && res.backupSet != null)
         *      {
         *          StringBuilder bkMediaNames = new StringBuilder();
         *          foreach (BackupDeviceItem item in res.Devices)
         *          {
         *              backgroundContext.Status = SR.Verifying + ":" + item.Name;
         *              try
         *              {
         *                  // Use the Restore public API to do the Restore VerifyOnly query
         *                  Restore restore = new Restore();
         *                  restore.CredentialName = res.CredentialName;
         *                  restore.Devices.Add(item);
         *                  if (!res.SqlVerify(this.server))
         *                  {
         *                      throw new Exception(SR.BackupDeviceItemVerificationFailed(item.Name));
         *                  }
         *              }
         *              catch (Exception ex)
         *              {
         *                  throw new Exception(SR.BackupDeviceItemVerificationFailed(item.Name), ex);
         *              }
         *          }
         *      }
         *  }
         * }
         * finally
         * {
         *  backgroundContext.CancelRequested -= cancelEventHandler;
         * }
         * }
         */

        private BackupMedia GetFirstBackupMedia(RestorePlan restorePlan)
        {
            /*
             * if (restorePlan == null || restorePlan.RestoreOperations == null || restorePlan.RestoreOperations.Count == 0)
             * {
             *  return null;
             * }
             * Restore res = restorePlan.RestoreOperations[0];
             * if (res == null || res.backupSet == null || res.backupSet.backupMediaSet == null || res.backupSet.backupMediaSet.BackupMediaList == null || res.backupSet.backupMediaSet.BackupMediaList.ToList().Count == 0)
             * {
             *  return null;
             * }
             * return res.backupSet.backupMediaSet.BackupMediaList.ToList()[0];
             */
            return(null);
        }
コード例 #8
0
        /// <summary>
        /// Updates restore plan
        /// </summary>
        public void UpdateRestorePlan(bool relocateAllFiles = false)
        {
            this.ActiveException = null; //Clear any existing exceptions as the plan is getting recreated.
                                         //Clear any existing exceptions as new plan is getting recreated.
            this.CreateOrUpdateRestorePlanException = null;
            this.DbFiles.Clear();
            this.planUpdateRequired = false;
            this.restorePlan        = null;
            if (String.IsNullOrEmpty(this.RestorePlanner.DatabaseName))
            {
                this.RestorePlan = new RestorePlan(this.Server);
                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();
                    UpdateDBFilesPhysicalRelocate();

                    if (relocateAllFiles)
                    {
                        UpdateDbFiles();
                    }
                    this.SetRestorePlanProperties(this.restorePlan);
                }
            }
            if (this.restorePlan != null)
            {
                this.RestoreSelected = new bool[this.restorePlan.RestoreOperations.Count];
                for (int i = 0; i < this.restorePlan.RestoreOperations.Count; i++)
                {
                    this.RestoreSelected[i] = true;
                }
            }
            else
            {
                this.RestorePlan = new RestorePlan(this.Server);
                this.Util.AddCredentialNameForUrlBackupSet(this.RestorePlan, this.CredentialName);
                this.RestoreSelected = new bool[0];
            }
        }
コード例 #9
0
        /// <summary>
        /// Gets RestorePlan to perform restore and to script
        /// </summary>
        public RestorePlan GetRestorePlanForExecutionAndScript()
        {
            // One of the reasons the existing plan is not used and a new plan is created to execute is the order of the backupsets and
            // the last backupset is important. User can choose specific backupset in the plan to restore and
            // if the last backup set is not selected from the list, it means the item before that should be the real last item
            // with simply removing the item from the list, the order won't work correctlly. Smo considered the last item removed and
            // doesn't consider the previous item as the last item. Creating a new list and adding backpsets is the only way to make it work
            // and the reason the last backup set is important is that it has to restore with recovery mode while the others are restored with no recovery

            this.ActiveException = null; //Clear any existing exceptions as the plan is getting recreated.
            //Clear any existing exceptions as new plan is getting recreated.
            this.CreateOrUpdateRestorePlanException = null;
            bool tailLogBackup = this.RestorePlanner.BackupTailLog;

            if (this.PlanUpdateRequired)
            {
                this.RestorePlan = this.RestorePlanner.CreateRestorePlan(this.RestoreOptions);

                this.Util.AddCredentialNameForUrlBackupSet(this.RestorePlan, this.CredentialName);
            }
            RestorePlan rp = new RestorePlan(this.Server);

            rp.RestoreAction = RestoreActionType.Database;
            if (this.RestorePlan != null)
            {
                if (this.RestorePlan.TailLogBackupOperation != null && tailLogBackup)
                {
                    rp.TailLogBackupOperation = this.RestorePlan.TailLogBackupOperation;
                }
                int i = 0;
                foreach (Restore res in this.RestorePlan.RestoreOperations)
                {
                    if (this.backupSetsFilterInfo.IsBackupSetSelected(res.BackupSet))
                    {
                        rp.RestoreOperations.Add(res);
                    }
                    i++;
                }
            }
            this.SetRestorePlanProperties(rp);
            RestorePlanToExecute = rp;
            return(rp);
        }
コード例 #10
0
        /// <summary>
        /// Executes the restore operations
        /// </summary>
        public void Execute()
        {
            RestorePlan restorePlan = GetRestorePlanForExecutionAndScript();

            // ssms creates a new restore plan by calling GetRestorePlanForExecutionAndScript and
            // Doens't use the plan already created here. not sure why, using the existing restore plan doesn't make
            // any issue so far so keeping in it for now but we might want to double check later
            if (restorePlan != null && restorePlan.RestoreOperations.Count > 0)
            {
                restorePlan.PercentComplete += (object sender, PercentCompleteEventArgs e) =>
                {
                    if (SqlTask != null)
                    {
                        SqlTask.AddMessage($"{e.Percent}%", SqlTaskStatus.InProgress);
                    }
                };
                restorePlan.Execute();
            }
        }
コード例 #11
0
        /// <summary>
        /// Executes the restore operations
        /// </summary>
        public override void Execute()
        {
            if (IsValid && RestorePlan.RestoreOperations != null && RestorePlan.RestoreOperations.Any())
            {
                // Restore Plan should be already created and updated at this point

                RestorePlan restorePlan = GetRestorePlanForExecutionAndScript();

                if (restorePlan != null && restorePlan.RestoreOperations.Count > 0)
                {
                    restorePlan.PercentComplete += (object sender, PercentCompleteEventArgs e) =>
                    {
                        OnMessageAdded(new TaskMessage {
                            Description = $"{e.Percent}%", Status = SqlTaskStatus.InProgress
                        });
                    };
                    restorePlan.Execute();
                }
            }
            else
            {
                throw new InvalidOperationException(SR.RestoreNotSupported);
            }
        }
コード例 #12
0
        public void ToggleSelectRestore(int index)
        {
            RestorePlan rp = this.restorePlan;

            if (rp == null || rp.RestoreOperations.Count <= index)
            {
                return;
            }
            //the last index - this will include tail-Log restore operation if present
            if (index == rp.RestoreOperations.Count - 1)
            {
                if (this.RestoreSelected[index])
                {
                    this.RestoreSelected[index] = false;
                }
                else
                {
                    for (int i = 0; i <= index; i++)
                    {
                        this.RestoreSelected[i] = true;
                    }
                }
                return;
            }
            if (index == 0)
            {
                if (!this.RestoreSelected[index])
                {
                    this.RestoreSelected[index] = true;
                }
                else
                {
                    for (int i = index; i < rp.RestoreOperations.Count; i++)
                    {
                        this.RestoreSelected[i] = false;
                    }
                }
                return;
            }

            if (index == 1 && rp.RestoreOperations[index].BackupSet.BackupSetType == BackupSetType.Differential)
            {
                if (!this.RestoreSelected[index])
                {
                    this.RestoreSelected[0]     = true;
                    this.RestoreSelected[index] = true;
                }
                else if (rp.RestoreOperations[2].BackupSet == null)
                {
                    this.RestoreSelected[index] = false;
                    this.RestoreSelected[2]     = false;
                }
                else if (this.Server.Version.Major < 9 || BackupSet.IsBackupSetsInSequence(rp.RestoreOperations[0].BackupSet, rp.RestoreOperations[2].BackupSet))
                {
                    this.RestoreSelected[index] = false;
                }
                else
                {
                    for (int i = index; i < rp.RestoreOperations.Count; i++)
                    {
                        this.RestoreSelected[i] = false;
                    }
                }
                return;
            }
            if (rp.RestoreOperations[index].BackupSet.BackupSetType == BackupSetType.Log)
            {
                if (this.RestoreSelected[index])
                {
                    for (int i = index; i < rp.RestoreOperations.Count; i++)
                    {
                        this.RestoreSelected[i] = false;
                    }
                    return;
                }
                else
                {
                    for (int i = 0; i <= index; i++)
                    {
                        this.RestoreSelected[i] = true;
                    }
                    return;
                }
            }
        }
コード例 #13
0
 public DefaultRestoreScanner(RestorePlan plan, CancellationToken cancellationToken)
 {
     CancellationToken = cancellationToken;
     Plan = plan;
 }