Merge pull request #1029 from GaborApatiNagy/master_batch_new2

CP-17699, CA-213232: Batch Updates fixes and improvements
This commit is contained in:
Mihaela Stoica 2016-06-17 15:15:11 +01:00 committed by GitHub
commit 7273f8a886
12 changed files with 184 additions and 53 deletions

View File

@ -104,13 +104,14 @@ namespace XenAdmin.Wizards.PatchingWizard
if (prevPageType == typeof(PatchingWizard_SelectPatchPage)) 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 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.IsInAutomaticMode = wizardModeAutomatic;
PatchingWizard_SelectServers.SelectedUpdateType = updateType; PatchingWizard_SelectServers.SelectedUpdateType = updateType;
PatchingWizard_SelectServers.Patch = existPatch; PatchingWizard_SelectServers.Patch = existPatch;
@ -311,7 +312,20 @@ namespace XenAdmin.Wizards.PatchingWizard
private void RemoveDownloadedPatches() private void RemoveDownloadedPatches()
{ {
foreach (string downloadedPatch in PatchingWizard_UploadPage.AllDownloadedPatches.Values) var isInAutomaticMode = PatchingWizard_SelectPatchPage.IsInAutomaticMode;
List<string> listOfDownloadedFiles = new List<string>();
if (isInAutomaticMode)
{
listOfDownloadedFiles.AddRange(PatchingWizard_AutoUpdatingPage.AllDownloadedPatches.Values);
}
else
{
listOfDownloadedFiles.AddRange(PatchingWizard_UploadPage.AllDownloadedPatches.Values);
}
foreach (string downloadedPatch in listOfDownloadedFiles)
{ {
try try
{ {

View File

@ -55,16 +55,16 @@ namespace XenAdmin.Wizards.PatchingWizard
protected static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public XenAdmin.Core.Updates.UpgradeSequence UpgradeSequences { get; set; } public XenAdmin.Core.Updates.UpgradeSequence UpgradeSequences { get; set; }
private bool _thisPageHasBeenCompleted = false; private bool _thisPageIsCompleted = false;
public List<Problem> ProblemsResolvedPreCheck { private get; set; } public List<Problem> ProblemsResolvedPreCheck { private get; set; }
public List<Host> SelectedMasters { private get; set; } public List<Host> SelectedMasters { private get; set; }
private List<PoolPatchMapping> patchMappings = new List<PoolPatchMapping>(); private List<PoolPatchMapping> patchMappings = new List<PoolPatchMapping>();
private Dictionary<XenServerPatch, string> AllDownloadedPatches = new Dictionary<XenServerPatch, string>(); public Dictionary<XenServerPatch, string> AllDownloadedPatches = new Dictionary<XenServerPatch, string>();
private List<BackgroundWorker> backgroundWorkers = new List<BackgroundWorker>(); private List<UpdateProgressBackgroundWorker> backgroundWorkers = new List<UpdateProgressBackgroundWorker>();
public PatchingWizard_AutoUpdatingPage() public PatchingWizard_AutoUpdatingPage()
{ {
@ -109,15 +109,28 @@ namespace XenAdmin.Wizards.PatchingWizard
return _cancelEnabled; 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) public override void PageLoaded(PageLoadedDirection direction)
{ {
base.PageLoaded(direction); base.PageLoaded(direction);
if (_thisPageHasBeenCompleted) if (_thisPageIsCompleted)
{ {
backgroundWorkers.ForEach(bgw => bgw.CancelAsync());
backgroundWorkers.Clear();
return; return;
} }
@ -157,9 +170,11 @@ namespace XenAdmin.Wizards.PatchingWizard
foreach (var host in hostsToApply) foreach (var host in hostsToApply)
{ {
if (host != master) if (host != master)
{
planActionsByHost[host].Add(new ApplyXenServerPatchPlanAction(host, patch, patchMappings)); planActionsByHost[host].Add(new ApplyXenServerPatchPlanAction(host, patch, patchMappings));
planActionsByHost[host].AddRange(GetMandatoryActionListForPatch(delayedActionsByHost[host], host, patch)); planActionsByHost[host].AddRange(GetMandatoryActionListForPatch(delayedActionsByHost[host], host, patch));
UpdateDelayedAfterPatchGuidanceActionListForHost(delayedActionsByHost[host], host, patch); UpdateDelayedAfterPatchGuidanceActionListForHost(delayedActionsByHost[host], host, patch);
}
} }
// now add all non-delayed actions to the pool action list // now add all non-delayed actions to the pool action list
@ -202,7 +217,7 @@ namespace XenAdmin.Wizards.PatchingWizard
if (backgroundWorkers.Count == 0) if (backgroundWorkers.Count == 0)
{ {
_thisPageHasBeenCompleted = true; _thisPageIsCompleted = true;
_nextEnabled = true; _nextEnabled = true;
OnPageUpdated(); OnPageUpdated();
@ -224,16 +239,19 @@ namespace XenAdmin.Wizards.PatchingWizard
if (!actionsWorker.CancellationPending) if (!actionsWorker.CancellationPending)
{ {
PlanAction action = (PlanAction)e.UserState; PlanAction action = (PlanAction)e.UserState;
if (e.ProgressPercentage == 0) if (action != null)
{ {
inProgressActions.Add(action); if (e.ProgressPercentage == 0)
} {
else inProgressActions.Add(action);
{ }
doneActions.Add(action); else
inProgressActions.Remove(action); {
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(); UpdateStatusTextBox();
@ -247,8 +265,11 @@ namespace XenAdmin.Wizards.PatchingWizard
foreach (var pa in doneActions) foreach (var pa in doneActions)
{ {
sb.Append(pa); if (pa.Visible)
sb.AppendLine(Messages.DONE); {
sb.Append(pa);
sb.AppendLine(Messages.DONE);
}
} }
foreach (var pa in errorActions) foreach (var pa in errorActions)
@ -259,8 +280,11 @@ namespace XenAdmin.Wizards.PatchingWizard
foreach (var pa in inProgressActions) foreach (var pa in inProgressActions)
{ {
sb.Append(pa); if (pa.Visible)
sb.AppendLine(); {
sb.Append(pa);
sb.AppendLine(Messages.DONE);
}
} }
textBoxLog.Text = sb.ToString(); textBoxLog.Text = sb.ToString();
@ -325,7 +349,7 @@ namespace XenAdmin.Wizards.PatchingWizard
AllWorkersFinished(); AllWorkersFinished();
ShowErrors(); ShowErrors();
_thisPageHasBeenCompleted = true; _thisPageIsCompleted = true;
} }
_cancelEnabled = false; _cancelEnabled = false;

View File

@ -100,24 +100,33 @@ namespace XenAdmin.Wizards.PatchingWizard
xenConnections.Sort(); xenConnections.Sort();
foreach (IXenConnection xenConnection in xenConnections) foreach (IXenConnection xenConnection in xenConnections)
{ {
Pool pool = Helpers.GetPool(xenConnection); if (IsInAutomaticMode)
bool hasPool = true;
if (pool != null)
{ {
int index = dataGridViewHosts.Rows.Add(new PatchingHostsDataGridViewRow(pool)); if (!xenConnection.IsConnected)
Host master = pool.Connection.Resolve(pool.master); continue;
EnabledRow(master, SelectedUpdateType, index);
var host = Helpers.GetMaster(xenConnection);
int index = dataGridViewHosts.Rows.Add(new PatchingHostsDataGridViewRow(host, false));
EnabledRow(host, SelectedUpdateType, index);
} }
else else
{ {
hasPool = false; Pool pool = Helpers.GetPool(xenConnection);
} bool hasPool = pool != null;
Host[] hosts = xenConnection.Cache.Hosts; if (hasPool)
Array.Sort(hosts); {
foreach (Host host in hosts) int index = dataGridViewHosts.Rows.Add(new PatchingHostsDataGridViewRow(pool));
{ Host master = pool.Connection.Resolve(pool.master);
int index = dataGridViewHosts.Rows.Add(new PatchingHostsDataGridViewRow(host, hasPool)); EnabledRow(master, SelectedUpdateType, index);
EnabledRow(host, 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);
}
} }
} }

View File

@ -57,10 +57,16 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
protected override void RunWithSession(ref Session session) protected override void RunWithSession(ref Session session)
{ {
this.visible = false;
lock (patch) lock (patch)
{ {
this.visible = true;
this._title = string.Format(Messages.PATCHINGWIZARD_DOWNLOADUPDATE_ACTION_TITLE_DOWNLOADING, patch.Name); this._title = string.Format(Messages.PATCHINGWIZARD_DOWNLOADUPDATE_ACTION_TITLE_DOWNLOADING, patch.Name);
if (Cancelling)
return;
//if it has not been already downloaded //if it has not been already downloaded
if (!AllDownloadedPatches.Any(dp => dp.Key == patch && !string.IsNullOrEmpty(dp.Value)) if (!AllDownloadedPatches.Any(dp => dp.Key == patch && !string.IsNullOrEmpty(dp.Value))
|| !File.Exists(AllDownloadedPatches[patch])) || !File.Exists(AllDownloadedPatches[patch]))
@ -69,6 +75,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
} }
else else
{ {
this.visible = false;
this._title = string.Format(Messages.PATCHINGWIZARD_DOWNLOADUPDATE_ACTION_TITLE_SKIPPING, patch.Name); this._title = string.Format(Messages.PATCHINGWIZARD_DOWNLOADUPDATE_ACTION_TITLE_SKIPPING, patch.Name);
} }
} }
@ -101,6 +108,9 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
if (action == null) if (action == null)
return; return;
if (Cancelling)
action.Cancel();
Program.Invoke(Program.MainWindow, () => Program.Invoke(Program.MainWindow, () =>
{ {
//UpdateActionProgress(action); //UpdateActionProgress(action);

View File

@ -60,9 +60,13 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
var mapping = mappings.Find(m => m.XenServerPatch == patch); var mapping = mappings.Find(m => m.XenServerPatch == patch);
if (mapping != null && mapping.Pool_patch != null) if (mapping != null && mapping.Pool_patch != null)
{ {
foreach (var host in hosts) foreach (var host in hosts)
{ {
if (Cancelling)
{
throw new CancelledException();
}
try try
{ {
var check = new PatchPrecheckCheck(host, mapping.Pool_patch); var check = new PatchPrecheckCheck(host, mapping.Pool_patch);

View File

@ -35,6 +35,7 @@ using System.Threading;
using log4net; using log4net;
using XenAdmin.Network; using XenAdmin.Network;
using XenAPI; using XenAPI;
using System.Diagnostics;
namespace XenAdmin.Wizards.PatchingWizard.PlanActions namespace XenAdmin.Wizards.PatchingWizard.PlanActions
@ -48,6 +49,16 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
public event EventHandler OnActionError; public event EventHandler OnActionError;
public event Action<PlanAction, Host> StatusChanged; public event Action<PlanAction, Host> StatusChanged;
public Exception Error; public Exception Error;
protected bool Cancelling = false;
protected bool visible = true;
public bool Visible
{
get
{
return visible;
}
}
private string status; private string status;
public string Status public string Status
@ -230,6 +241,11 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
{ {
return this.Title; return this.Title;
} }
public virtual void Cancel()
{
Cancelling = true;
}
} }
} }

View File

@ -33,6 +33,7 @@ using System.Collections.Generic;
using XenAdmin.Core; using XenAdmin.Core;
using XenAPI; using XenAPI;
using System.Linq; using System.Linq;
using System;
namespace XenAdmin.Wizards.PatchingWizard.PlanActions namespace XenAdmin.Wizards.PatchingWizard.PlanActions
{ {
@ -52,14 +53,33 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
protected override void RunWithSession(ref Session session) protected override void RunWithSession(ref Session session)
{ {
var mapping = patchMappings.FirstOrDefault(pm => pm.Host == master && pm.XenServerPatch == patch); try
if (mapping != null)
{ {
var task = Pool_patch.async_pool_clean(session, mapping.Pool_patch.opaque_ref); Pool_patch poolPatch = null;
PollTaskForResultAndDestroy(Connection, ref session, task);
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);
} }
} }
} }

View File

@ -47,6 +47,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
private readonly List<PoolPatchMapping> mappings; private readonly List<PoolPatchMapping> mappings;
private Dictionary<XenServerPatch, string> AllDownloadedPatches = new Dictionary<XenServerPatch, string>(); private Dictionary<XenServerPatch, string> AllDownloadedPatches = new Dictionary<XenServerPatch, string>();
private string tempFileName = null; private string tempFileName = null;
private AsyncAction inProgressAction = null;
public UploadPatchToMasterPlanAction(IXenConnection connection, XenServerPatch patch, List<PoolPatchMapping> mappings, Dictionary<XenServerPatch, string> allDownloadedPatches) public UploadPatchToMasterPlanAction(IXenConnection connection, XenServerPatch patch, List<PoolPatchMapping> mappings, Dictionary<XenServerPatch, string> allDownloadedPatches)
: base(connection, string.Format("Uploading update {0} to {1}...", patch.Name, connection.Name)) : base(connection, string.Format("Uploading update {0} to {1}...", patch.Name, connection.Name))
@ -71,10 +72,12 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
try try
{ {
var checkSpaceForUpload = new CheckDiskSpaceForPatchUploadAction(Helpers.GetMaster(conn), path, true); var checkSpaceForUpload = new CheckDiskSpaceForPatchUploadAction(Helpers.GetMaster(conn), path, true);
inProgressAction = checkSpaceForUpload;
checkSpaceForUpload.RunExternal(session); checkSpaceForUpload.RunExternal(session);
var action = new UploadPatchAction(session.Connection, path, true, false); var uploadPatchAction = new UploadPatchAction(session.Connection, path, true, false);
action.RunExternal(session); inProgressAction = uploadPatchAction;
uploadPatchAction.RunExternal(session);
var poolPatch = poolPatches.Find(p => string.Equals(p.uuid, patch.Uuid, StringComparison.OrdinalIgnoreCase)); var poolPatch = poolPatches.Find(p => string.Equals(p.uuid, patch.Uuid, StringComparison.OrdinalIgnoreCase));
if (poolPatch == null) if (poolPatch == null)
@ -126,6 +129,9 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
if (action == null) if (action == null)
return; return;
if (Cancelling)
action.Cancel();
Program.Invoke(Program.MainWindow, () => Program.Invoke(Program.MainWindow, () =>
{ {
//UpdateActionProgress(action); //UpdateActionProgress(action);
@ -154,5 +160,13 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
} }
} }
public override void Cancel()
{
if (inProgressAction != null)
inProgressAction.Cancel();
base.Cancel();
}
} }
} }

View File

@ -18,6 +18,7 @@ namespace XenAdmin.Wizards.PatchingWizard
public List<PlanAction> FinsihedActions = new List<PlanAction>(); public List<PlanAction> FinsihedActions = new List<PlanAction>();
public PlanAction FailedWithExceptionAction = null; public PlanAction FailedWithExceptionAction = null;
public List<PlanAction> doneActions = new List<PlanAction>(); public List<PlanAction> doneActions = new List<PlanAction>();
public PlanAction InProgressAction { get; set; }
public UpdateProgressBackgroundWorker(Host master, List<PlanAction> planActions, List<PlanAction> delayedActions) public UpdateProgressBackgroundWorker(Host master, List<PlanAction> planActions, List<PlanAction> delayedActions)
{ {
@ -49,5 +50,17 @@ namespace XenAdmin.Wizards.PatchingWizard
return (int)(1.0 / (double)TotalNumberOfActions * (double)(FinsihedActions.Count)); 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();
}
} }
} }

View File

@ -31,10 +31,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using XenAPI; using XenAPI;
namespace XenAdmin.Core namespace XenAdmin.Core
{ {
[DebuggerDisplay("XenServerPatch (Name={Name}; Uuid={Uuid})")]
public class XenServerPatch : IEquatable<XenServerPatch> public class XenServerPatch : IEquatable<XenServerPatch>
{ {
private string _uuid; private string _uuid;

View File

@ -31,9 +31,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
namespace XenAdmin.Core namespace XenAdmin.Core
{ {
[DebuggerDisplay("XenServerVersion (Name={Name}; Patches.Count={Patches.Count}; MinimalPatches.Count={MinimalPatches.Count})")]
public class XenServerVersion public class XenServerVersion
{ {
public Version Version; public Version Version;

View File

@ -1410,6 +1410,9 @@ namespace XenAdmin.Core
/// </summary> /// </summary>
public static string OEMName(Host host) public static string OEMName(Host host)
{ {
if (host.software_version == null)
return string.Empty;
if (!host.software_version.ContainsKey("oem_manufacturer")) if (!host.software_version.ContainsKey("oem_manufacturer"))
return ""; return "";