diff --git a/XenAdmin/Wizards/PatchingWizard/PatchingWizard.cs b/XenAdmin/Wizards/PatchingWizard/PatchingWizard.cs index 28d5fb95d..ac4061ad1 100644 --- a/XenAdmin/Wizards/PatchingWizard/PatchingWizard.cs +++ b/XenAdmin/Wizards/PatchingWizard/PatchingWizard.cs @@ -104,13 +104,14 @@ namespace XenAdmin.Wizards.PatchingWizard if (prevPageType == typeof(PatchingWizard_SelectPatchPage)) { - var updateType = PatchingWizard_SelectPatchPage.SelectedUpdateType; - var newPatch = PatchingWizard_SelectPatchPage.SelectedNewPatch; - var existPatch = PatchingWizard_SelectPatchPage.SelectedExistingPatch; - var alertPatch = PatchingWizard_SelectPatchPage.SelectedUpdateAlert; - var fileFromDiskAlertPatch = PatchingWizard_SelectPatchPage.FileFromDiskAlert; var wizardModeAutomatic = PatchingWizard_SelectPatchPage.IsInAutomaticMode; + var updateType = wizardModeAutomatic ? UpdateType.NewRetail : PatchingWizard_SelectPatchPage.SelectedUpdateType; + var newPatch = wizardModeAutomatic ? null : PatchingWizard_SelectPatchPage.SelectedNewPatch; + var existPatch = wizardModeAutomatic ? null : PatchingWizard_SelectPatchPage.SelectedExistingPatch; + var alertPatch = wizardModeAutomatic ? null : PatchingWizard_SelectPatchPage.SelectedUpdateAlert; + var fileFromDiskAlertPatch = wizardModeAutomatic ? null : PatchingWizard_SelectPatchPage.FileFromDiskAlert; + PatchingWizard_SelectServers.IsInAutomaticMode = wizardModeAutomatic; PatchingWizard_SelectServers.SelectedUpdateType = updateType; PatchingWizard_SelectServers.Patch = existPatch; @@ -311,7 +312,20 @@ namespace XenAdmin.Wizards.PatchingWizard private void RemoveDownloadedPatches() { - foreach (string downloadedPatch in PatchingWizard_UploadPage.AllDownloadedPatches.Values) + var isInAutomaticMode = PatchingWizard_SelectPatchPage.IsInAutomaticMode; + + List listOfDownloadedFiles = new List(); + + if (isInAutomaticMode) + { + listOfDownloadedFiles.AddRange(PatchingWizard_AutoUpdatingPage.AllDownloadedPatches.Values); + } + else + { + listOfDownloadedFiles.AddRange(PatchingWizard_UploadPage.AllDownloadedPatches.Values); + } + + foreach (string downloadedPatch in listOfDownloadedFiles) { try { diff --git a/XenAdmin/Wizards/PatchingWizard/PatchingWizard_AutoUpdatingPage.cs b/XenAdmin/Wizards/PatchingWizard/PatchingWizard_AutoUpdatingPage.cs index 45bf739b2..2479dceb7 100644 --- a/XenAdmin/Wizards/PatchingWizard/PatchingWizard_AutoUpdatingPage.cs +++ b/XenAdmin/Wizards/PatchingWizard/PatchingWizard_AutoUpdatingPage.cs @@ -55,16 +55,16 @@ namespace XenAdmin.Wizards.PatchingWizard protected static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public XenAdmin.Core.Updates.UpgradeSequence UpgradeSequences { get; set; } - private bool _thisPageHasBeenCompleted = false; + private bool _thisPageIsCompleted = false; public List ProblemsResolvedPreCheck { private get; set; } public List SelectedMasters { private get; set; } private List patchMappings = new List(); - private Dictionary AllDownloadedPatches = new Dictionary(); + public Dictionary AllDownloadedPatches = new Dictionary(); - private List backgroundWorkers = new List(); + private List backgroundWorkers = new List(); public PatchingWizard_AutoUpdatingPage() { @@ -109,15 +109,28 @@ namespace XenAdmin.Wizards.PatchingWizard return _cancelEnabled; } + public override void PageCancelled() + { + if (!_thisPageIsCompleted) + { + backgroundWorkers.ForEach(bgw => bgw.CancelAsync()); + backgroundWorkers.Clear(); + } + + base.PageCancelled(); + } + + public override void PageLeave(PageLoadedDirection direction, ref bool cancel) + { + base.PageLeave(direction, ref cancel); + } + public override void PageLoaded(PageLoadedDirection direction) { base.PageLoaded(direction); - if (_thisPageHasBeenCompleted) - { - backgroundWorkers.ForEach(bgw => bgw.CancelAsync()); - backgroundWorkers.Clear(); - + if (_thisPageIsCompleted) + { return; } @@ -157,9 +170,11 @@ namespace XenAdmin.Wizards.PatchingWizard foreach (var host in hostsToApply) { if (host != master) + { planActionsByHost[host].Add(new ApplyXenServerPatchPlanAction(host, patch, patchMappings)); planActionsByHost[host].AddRange(GetMandatoryActionListForPatch(delayedActionsByHost[host], host, patch)); UpdateDelayedAfterPatchGuidanceActionListForHost(delayedActionsByHost[host], host, patch); + } } // now add all non-delayed actions to the pool action list @@ -202,7 +217,7 @@ namespace XenAdmin.Wizards.PatchingWizard if (backgroundWorkers.Count == 0) { - _thisPageHasBeenCompleted = true; + _thisPageIsCompleted = true; _nextEnabled = true; OnPageUpdated(); @@ -224,16 +239,19 @@ namespace XenAdmin.Wizards.PatchingWizard if (!actionsWorker.CancellationPending) { PlanAction action = (PlanAction)e.UserState; - if (e.ProgressPercentage == 0) + if (action != null) { - inProgressActions.Add(action); - } - else - { - doneActions.Add(action); - inProgressActions.Remove(action); + if (e.ProgressPercentage == 0) + { + inProgressActions.Add(action); + } + else + { + doneActions.Add(action); + inProgressActions.Remove(action); - progressBar.Value += (int)((float)e.ProgressPercentage / (float)backgroundWorkers.Count); //extend with error handling related numbers + progressBar.Value += (int)((float)e.ProgressPercentage / (float)backgroundWorkers.Count); //extend with error handling related numbers + } } UpdateStatusTextBox(); @@ -247,8 +265,11 @@ namespace XenAdmin.Wizards.PatchingWizard foreach (var pa in doneActions) { - sb.Append(pa); - sb.AppendLine(Messages.DONE); + if (pa.Visible) + { + sb.Append(pa); + sb.AppendLine(Messages.DONE); + } } foreach (var pa in errorActions) @@ -259,8 +280,11 @@ namespace XenAdmin.Wizards.PatchingWizard foreach (var pa in inProgressActions) { - sb.Append(pa); - sb.AppendLine(); + if (pa.Visible) + { + sb.Append(pa); + sb.AppendLine(Messages.DONE); + } } textBoxLog.Text = sb.ToString(); @@ -325,7 +349,7 @@ namespace XenAdmin.Wizards.PatchingWizard AllWorkersFinished(); ShowErrors(); - _thisPageHasBeenCompleted = true; + _thisPageIsCompleted = true; } _cancelEnabled = false; diff --git a/XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectServers.cs b/XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectServers.cs index bacd6d9d3..1c4bb40cc 100644 --- a/XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectServers.cs +++ b/XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectServers.cs @@ -100,24 +100,33 @@ namespace XenAdmin.Wizards.PatchingWizard xenConnections.Sort(); foreach (IXenConnection xenConnection in xenConnections) { - Pool pool = Helpers.GetPool(xenConnection); - bool hasPool = true; - if (pool != null) + if (IsInAutomaticMode) { - int index = dataGridViewHosts.Rows.Add(new PatchingHostsDataGridViewRow(pool)); - Host master = pool.Connection.Resolve(pool.master); - EnabledRow(master, SelectedUpdateType, index); + if (!xenConnection.IsConnected) + continue; + + var host = Helpers.GetMaster(xenConnection); + int index = dataGridViewHosts.Rows.Add(new PatchingHostsDataGridViewRow(host, false)); + EnabledRow(host, SelectedUpdateType, index); } else { - hasPool = false; - } - Host[] hosts = xenConnection.Cache.Hosts; - Array.Sort(hosts); - foreach (Host host in hosts) - { - int index = dataGridViewHosts.Rows.Add(new PatchingHostsDataGridViewRow(host, hasPool)); - EnabledRow(host, SelectedUpdateType, index); + Pool pool = Helpers.GetPool(xenConnection); + bool hasPool = pool != null; + if (hasPool) + { + int index = dataGridViewHosts.Rows.Add(new PatchingHostsDataGridViewRow(pool)); + Host master = pool.Connection.Resolve(pool.master); + EnabledRow(master, SelectedUpdateType, index); + } + + Host[] hosts = xenConnection.Cache.Hosts; + Array.Sort(hosts); + foreach (Host host in hosts) + { + int index = dataGridViewHosts.Rows.Add(new PatchingHostsDataGridViewRow(host, hasPool)); + EnabledRow(host, SelectedUpdateType, index); + } } } @@ -162,7 +171,7 @@ namespace XenAdmin.Wizards.PatchingWizard else { row.Enabled = false; - row.Cells[3].ToolTipText = Messages.PATCHINGWIZARD_SELECTSERVERPAGE_SERVER_NOT_AUTO_UPGRADABLE; + row.Cells[3].ToolTipText = Messages.PATCHINGWIZARD_SELECTSERVERPAGE_SERVER_NOT_AUTO_UPGRADABLE; } return; diff --git a/XenAdmin/Wizards/PatchingWizard/PlanActions/DownloadPatchPlanAction.cs b/XenAdmin/Wizards/PatchingWizard/PlanActions/DownloadPatchPlanAction.cs index f28608363..899565747 100644 --- a/XenAdmin/Wizards/PatchingWizard/PlanActions/DownloadPatchPlanAction.cs +++ b/XenAdmin/Wizards/PatchingWizard/PlanActions/DownloadPatchPlanAction.cs @@ -57,10 +57,16 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions protected override void RunWithSession(ref Session session) { + this.visible = false; + lock (patch) { + this.visible = true; this._title = string.Format(Messages.PATCHINGWIZARD_DOWNLOADUPDATE_ACTION_TITLE_DOWNLOADING, patch.Name); + if (Cancelling) + return; + //if it has not been already downloaded if (!AllDownloadedPatches.Any(dp => dp.Key == patch && !string.IsNullOrEmpty(dp.Value)) || !File.Exists(AllDownloadedPatches[patch])) @@ -69,6 +75,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions } else { + this.visible = false; this._title = string.Format(Messages.PATCHINGWIZARD_DOWNLOADUPDATE_ACTION_TITLE_SKIPPING, patch.Name); } } @@ -101,6 +108,9 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions if (action == null) return; + if (Cancelling) + action.Cancel(); + Program.Invoke(Program.MainWindow, () => { //UpdateActionProgress(action); diff --git a/XenAdmin/Wizards/PatchingWizard/PlanActions/PatchPrechecksOnMultipleHostsAction.cs b/XenAdmin/Wizards/PatchingWizard/PlanActions/PatchPrechecksOnMultipleHostsAction.cs index 692200b9b..ff287d720 100644 --- a/XenAdmin/Wizards/PatchingWizard/PlanActions/PatchPrechecksOnMultipleHostsAction.cs +++ b/XenAdmin/Wizards/PatchingWizard/PlanActions/PatchPrechecksOnMultipleHostsAction.cs @@ -60,9 +60,13 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions var mapping = mappings.Find(m => m.XenServerPatch == patch); if (mapping != null && mapping.Pool_patch != null) { - foreach (var host in hosts) { + if (Cancelling) + { + throw new CancelledException(); + } + try { var check = new PatchPrecheckCheck(host, mapping.Pool_patch); diff --git a/XenAdmin/Wizards/PatchingWizard/PlanActions/PlanAction.cs b/XenAdmin/Wizards/PatchingWizard/PlanActions/PlanAction.cs index 8b5a98eaf..8e5eb6485 100644 --- a/XenAdmin/Wizards/PatchingWizard/PlanActions/PlanAction.cs +++ b/XenAdmin/Wizards/PatchingWizard/PlanActions/PlanAction.cs @@ -35,6 +35,7 @@ using System.Threading; using log4net; using XenAdmin.Network; using XenAPI; +using System.Diagnostics; namespace XenAdmin.Wizards.PatchingWizard.PlanActions @@ -48,7 +49,17 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions public event EventHandler OnActionError; public event Action StatusChanged; public Exception Error; + protected bool Cancelling = false; + protected bool visible = true; + public bool Visible + { + get + { + return visible; + } + } + private string status; public string Status { @@ -230,6 +241,11 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions { return this.Title; } + + public virtual void Cancel() + { + Cancelling = true; + } } } diff --git a/XenAdmin/Wizards/PatchingWizard/PlanActions/RemoveUpdateFilesFromMaster.cs b/XenAdmin/Wizards/PatchingWizard/PlanActions/RemoveUpdateFilesFromMaster.cs index 95cd52211..e380a5ed6 100644 --- a/XenAdmin/Wizards/PatchingWizard/PlanActions/RemoveUpdateFilesFromMaster.cs +++ b/XenAdmin/Wizards/PatchingWizard/PlanActions/RemoveUpdateFilesFromMaster.cs @@ -32,7 +32,8 @@ using System.Collections.Generic; using XenAdmin.Core; using XenAPI; -using System.Linq; +using System.Linq; +using System; namespace XenAdmin.Wizards.PatchingWizard.PlanActions { @@ -52,14 +53,33 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions protected override void RunWithSession(ref Session session) { - var mapping = patchMappings.FirstOrDefault(pm => pm.Host == master && pm.XenServerPatch == patch); - - if (mapping != null) + try { - var task = Pool_patch.async_pool_clean(session, mapping.Pool_patch.opaque_ref); - PollTaskForResultAndDestroy(Connection, ref session, task); + Pool_patch poolPatch = null; - patchMappings.Remove(mapping); + var mapping = patchMappings.FirstOrDefault(pm => pm.Host == master && pm.XenServerPatch == patch); + + if (mapping != null || mapping.Pool_patch != null && mapping.Pool_patch.opaque_ref != null) + { + poolPatch = mapping.Pool_patch; + } + else + { + poolPatch = session.Connection.Cache.Pool_patches.FirstOrDefault(pp => string.Equals(pp.uuid, patch.Uuid, System.StringComparison.InvariantCultureIgnoreCase)); + } + + if (poolPatch != null && poolPatch.opaque_ref != null ) + { + var task = Pool_patch.async_pool_clean(session, mapping.Pool_patch.opaque_ref); + PollTaskForResultAndDestroy(Connection, ref session, task); + + patchMappings.Remove(mapping); + } + } + catch (Exception ex) + { + //best effort + log.Error("Failed to remove Pool_patch from the server.", ex); } } } diff --git a/XenAdmin/Wizards/PatchingWizard/PlanActions/UploadPatchToMasterPlanAction.cs b/XenAdmin/Wizards/PatchingWizard/PlanActions/UploadPatchToMasterPlanAction.cs index eab52868c..f7940da67 100644 --- a/XenAdmin/Wizards/PatchingWizard/PlanActions/UploadPatchToMasterPlanAction.cs +++ b/XenAdmin/Wizards/PatchingWizard/PlanActions/UploadPatchToMasterPlanAction.cs @@ -47,6 +47,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions private readonly List mappings; private Dictionary AllDownloadedPatches = new Dictionary(); private string tempFileName = null; + private AsyncAction inProgressAction = null; public UploadPatchToMasterPlanAction(IXenConnection connection, XenServerPatch patch, List mappings, Dictionary allDownloadedPatches) : base(connection, string.Format("Uploading update {0} to {1}...", patch.Name, connection.Name)) @@ -71,10 +72,12 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions try { var checkSpaceForUpload = new CheckDiskSpaceForPatchUploadAction(Helpers.GetMaster(conn), path, true); + inProgressAction = checkSpaceForUpload; checkSpaceForUpload.RunExternal(session); - var action = new UploadPatchAction(session.Connection, path, true, false); - action.RunExternal(session); + var uploadPatchAction = new UploadPatchAction(session.Connection, path, true, false); + inProgressAction = uploadPatchAction; + uploadPatchAction.RunExternal(session); var poolPatch = poolPatches.Find(p => string.Equals(p.uuid, patch.Uuid, StringComparison.OrdinalIgnoreCase)); if (poolPatch == null) @@ -126,6 +129,9 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions if (action == null) return; + if (Cancelling) + action.Cancel(); + Program.Invoke(Program.MainWindow, () => { //UpdateActionProgress(action); @@ -153,6 +159,14 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions } } + } + + public override void Cancel() + { + if (inProgressAction != null) + inProgressAction.Cancel(); + + base.Cancel(); } } } diff --git a/XenAdmin/Wizards/PatchingWizard/UpdateProgressBackgroundWorker.cs b/XenAdmin/Wizards/PatchingWizard/UpdateProgressBackgroundWorker.cs index 1696a86a8..7bd750555 100644 --- a/XenAdmin/Wizards/PatchingWizard/UpdateProgressBackgroundWorker.cs +++ b/XenAdmin/Wizards/PatchingWizard/UpdateProgressBackgroundWorker.cs @@ -18,6 +18,7 @@ namespace XenAdmin.Wizards.PatchingWizard public List FinsihedActions = new List(); public PlanAction FailedWithExceptionAction = null; public List doneActions = new List(); + public PlanAction InProgressAction { get; set; } public UpdateProgressBackgroundWorker(Host master, List planActions, List delayedActions) { @@ -49,5 +50,17 @@ namespace XenAdmin.Wizards.PatchingWizard return (int)(1.0 / (double)TotalNumberOfActions * (double)(FinsihedActions.Count)); } } + + public new void CancelAsync() + { + if (PlanActions != null) + PlanActions.ForEach(pa => + { + if (!pa.IsComplete) + pa.Cancel(); + }); + + base.CancelAsync(); + } } } diff --git a/XenModel/Actions/Updates/XenServerPatch.cs b/XenModel/Actions/Updates/XenServerPatch.cs index 3ee389843..fbadbf9cc 100644 --- a/XenModel/Actions/Updates/XenServerPatch.cs +++ b/XenModel/Actions/Updates/XenServerPatch.cs @@ -31,10 +31,12 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using XenAPI; namespace XenAdmin.Core { + [DebuggerDisplay("XenServerPatch (Name={Name}; Uuid={Uuid})")] public class XenServerPatch : IEquatable { private string _uuid; diff --git a/XenModel/Actions/Updates/XenServerVersion.cs b/XenModel/Actions/Updates/XenServerVersion.cs index 8825481df..f5567fc87 100644 --- a/XenModel/Actions/Updates/XenServerVersion.cs +++ b/XenModel/Actions/Updates/XenServerVersion.cs @@ -31,9 +31,11 @@ using System; using System.Collections.Generic; +using System.Diagnostics; namespace XenAdmin.Core { + [DebuggerDisplay("XenServerVersion (Name={Name}; Patches.Count={Patches.Count}; MinimalPatches.Count={MinimalPatches.Count})")] public class XenServerVersion { public Version Version; diff --git a/XenModel/Utils/Helpers.cs b/XenModel/Utils/Helpers.cs index 987a905be..ce24b9860 100755 --- a/XenModel/Utils/Helpers.cs +++ b/XenModel/Utils/Helpers.cs @@ -1410,6 +1410,9 @@ namespace XenAdmin.Core /// public static string OEMName(Host host) { + if (host.software_version == null) + return string.Empty; + if (!host.software_version.ContainsKey("oem_manufacturer")) return "";