diff --git a/XenAdmin/Wizards/PatchingWizard/PlanActions/ApplyXenServerPatchPlanAction.cs b/XenAdmin/Wizards/PatchingWizard/PlanActions/ApplyXenServerPatchPlanAction.cs index b03dfb51c..a23989156 100644 --- a/XenAdmin/Wizards/PatchingWizard/PlanActions/ApplyXenServerPatchPlanAction.cs +++ b/XenAdmin/Wizards/PatchingWizard/PlanActions/ApplyXenServerPatchPlanAction.cs @@ -53,7 +53,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions protected override void RunWithSession(ref Session session) { var coordinator = Helpers.GetCoordinator(Connection); - var mapping = (from HostUpdateMapping hum in mappings + HostUpdateMapping mapping = (from HostUpdateMapping hum in mappings let xpm = hum as XenServerPatchMapping where xpm != null && xpm.Matches(coordinator, xenServerPatch) select xpm).FirstOrDefault(); @@ -70,13 +70,16 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions try { // evacuate the host, if needed, before applying the update - if (mapping.HostsThatNeedEvacuated.Contains(host.uuid)) + if (mapping.HostsThatNeedEvacuation.Contains(host.uuid)) EvacuateHost(ref session); AddProgressStep(string.Format(Messages.UPDATES_WIZARD_APPLYING_UPDATE, xenServerPatch.Name, host.Name())); - PatchPrecheckOnHostPlanAction.RefreshUpdate(host, mapping, session); + if (mapping is PoolUpdateMapping pum) + PatchPrecheckOnHostPlanAction.ReIntroducePoolUpdate(host, pum.Pool_update, session); + + mapping = mapping.RefreshUpdate(); XenRef task = null; diff --git a/XenAdmin/Wizards/PatchingWizard/PlanActions/PatchPrecheckOnHostPlanAction.cs b/XenAdmin/Wizards/PatchingWizard/PlanActions/PatchPrecheckOnHostPlanAction.cs index 33daf50b8..8df1368e2 100644 --- a/XenAdmin/Wizards/PatchingWizard/PlanActions/PatchPrecheckOnHostPlanAction.cs +++ b/XenAdmin/Wizards/PatchingWizard/PlanActions/PatchPrecheckOnHostPlanAction.cs @@ -63,7 +63,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions { var coordinator = Helpers.GetCoordinator(Connection); - var mapping = (from HostUpdateMapping hum in mappings + HostUpdateMapping mapping = (from HostUpdateMapping hum in mappings let xpm = hum as XenServerPatchMapping where xpm != null && xpm.Matches(coordinator, xenServerPatch) select xpm).FirstOrDefault(); @@ -82,7 +82,10 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions { AddProgressStep(string.Format(Messages.UPDATES_WIZARD_RUNNING_PRECHECK, xenServerPatch.Name, host.Name())); - RefreshUpdate(host, mapping, session); + if (mapping is PoolUpdateMapping pum) + ReIntroducePoolUpdate(host, pum.Pool_update, session); + + mapping = mapping.RefreshUpdate(); List problems = null; @@ -115,8 +118,8 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions if(updateRequiresHostReboot && !hostsThatWillRequireReboot.Contains(host.uuid)) hostsThatWillRequireReboot.Add(host.uuid); - if (updateRequiresHostReboot && !mapping.HostsThatNeedEvacuated.Contains(host.uuid)) - mapping.HostsThatNeedEvacuated.Add(host.uuid); + if (updateRequiresHostReboot && !mapping.HostsThatNeedEvacuation.Contains(host.uuid)) + mapping.HostsThatNeedEvacuation.Add(host.uuid); if (livePatchStatus.ContainsKey(host.uuid) && livePatchStatus[host.uuid] == livepatch_status.ok_livepatch_complete) { if (!livePatchAttempts.ContainsKey(host.uuid) || livePatchAttempts[host.uuid] == null) @@ -125,25 +128,25 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions } } - public static void RefreshUpdate(Host host, HostUpdateMapping mapping, Session session) + + public static void ReIntroducePoolUpdate(Host host, Pool_update poolUpdate, Session session) { - // re-introduce pool_update if needed - if (mapping is PoolUpdateMapping poolUpdateMapping - && session.Connection.Cache.Pool_updates.FirstOrDefault(u => string.Equals(u.uuid, poolUpdateMapping.Pool_update.uuid, StringComparison.OrdinalIgnoreCase)) == null) + if (session.Connection.Cache.Pool_updates.FirstOrDefault(u => string.Equals(u.uuid, poolUpdate.uuid, StringComparison.OrdinalIgnoreCase)) == null) { log.InfoFormat("Re-introduce update on '{0}'. Update = '{1}' (uuid = '{2}'; old opaque_ref = '{3}')", - host.Name(), poolUpdateMapping.Pool_update.Name(), poolUpdateMapping.Pool_update.uuid, - poolUpdateMapping.Pool_update.opaque_ref); + host.Name(), poolUpdate.Name(), poolUpdate.uuid, + poolUpdate.opaque_ref); + try { - var newUpdateRef = Pool_update.introduce(session, poolUpdateMapping.Pool_update.vdi.opaque_ref); + var newUpdateRef = Pool_update.introduce(session, poolUpdate.vdi.opaque_ref); session.Connection.WaitForCache(newUpdateRef); } catch (Exception e) { if (e is Failure failure && failure.ErrorDescription != null && failure.ErrorDescription.Count > 1 && failure.ErrorDescription[0] == Failure.UPDATE_ALREADY_EXISTS) { - log.InfoFormat("Update '{0}' already exists", poolUpdateMapping.Pool_update.Name()); + log.InfoFormat("Update '{0}' already exists", poolUpdate.Name()); } else { @@ -152,9 +155,6 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions } } } - - // refresh the update/patch record based on uuid - mapping.RefreshUpdate(); } } } diff --git a/XenAdmin/Wizards/PatchingWizard/PlanActions/UploadPatchToCoordinatorPlanAction.cs b/XenAdmin/Wizards/PatchingWizard/PlanActions/UploadPatchToCoordinatorPlanAction.cs index 159cd2307..c3e484529 100644 --- a/XenAdmin/Wizards/PatchingWizard/PlanActions/UploadPatchToCoordinatorPlanAction.cs +++ b/XenAdmin/Wizards/PatchingWizard/PlanActions/UploadPatchToCoordinatorPlanAction.cs @@ -189,10 +189,8 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions throw new Exception(Messages.ACTION_UPLOADPATCHTOCOORDINATORPLANACTION_FAILED); } - var newMapping = new PoolUpdateMapping(xenServerPatch, poolUpdate, Helpers.GetCoordinator(conn)) - { - SrsWithUploadedUpdatesPerHost = new Dictionary(uploadIsoAction.SrsWithUploadedUpdatesPerHost) - }; + var newMapping = new PoolUpdateMapping(xenServerPatch, poolUpdate, Helpers.GetCoordinator(conn), + new Dictionary(uploadIsoAction.SrsWithUploadedUpdatesPerHost)); if (!mappings.Contains(newMapping)) mappings.Add(newMapping); @@ -263,11 +261,8 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions suppPackVdis.Add(kvp.Key, vdi); } - var newMapping = new SuppPackMapping(updateFilePath, poolUpdate, Helpers.GetCoordinator(conn)) - { - SrsWithUploadedUpdatesPerHost = new Dictionary(uploadIsoAction.SrsWithUploadedUpdatesPerHost), - SuppPackVdis = suppPackVdis - }; + var newMapping = new SuppPackMapping(updateFilePath, poolUpdate, Helpers.GetCoordinator(conn), + new Dictionary(uploadIsoAction.SrsWithUploadedUpdatesPerHost), suppPackVdis); if (!mappings.Contains(newMapping)) mappings.Add(newMapping); diff --git a/XenAdmin/Wizards/PatchingWizard/PlanActions/XenServerPatchMapping.cs b/XenAdmin/Wizards/PatchingWizard/PlanActions/XenServerPatchMapping.cs index fd5e992ff..4a44b7577 100644 --- a/XenAdmin/Wizards/PatchingWizard/PlanActions/XenServerPatchMapping.cs +++ b/XenAdmin/Wizards/PatchingWizard/PlanActions/XenServerPatchMapping.cs @@ -40,11 +40,12 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions public abstract class HostUpdateMapping { protected readonly Host CoordinatorHost; - public List HostsThatNeedEvacuated = new List(); + public readonly List HostsThatNeedEvacuation; - protected HostUpdateMapping(Host coordinatorHost) + protected HostUpdateMapping(Host coordinatorHost, List hostsThatNeedEvacuation) { - CoordinatorHost = coordinatorHost ?? throw new ArgumentNullException("coordinatorHost"); + CoordinatorHost = coordinatorHost ?? throw new ArgumentNullException(nameof(coordinatorHost)); + HostsThatNeedEvacuation = hostsThatNeedEvacuation ?? new List(); } protected bool Matches(Host coordinatorHost) @@ -64,7 +65,10 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions public abstract bool IsValid { get; } - public abstract void RefreshUpdate(); + /// + /// Refresh the update/patch record based on uuid + /// + public abstract HostUpdateMapping RefreshUpdate(); } @@ -72,10 +76,10 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions { public readonly XenServerPatch XenServerPatch; - protected XenServerPatchMapping(XenServerPatch xenServerPatch, Host coordinatorHost) - : base(coordinatorHost) + protected XenServerPatchMapping(XenServerPatch xenServerPatch, Host coordinatorHost, List hostsThatNeedEvacuation) + : base(coordinatorHost, hostsThatNeedEvacuation) { - XenServerPatch = xenServerPatch ?? throw new ArgumentNullException("xenServerPatch"); + XenServerPatch = xenServerPatch ?? throw new ArgumentNullException(nameof(xenServerPatch)); } public bool Matches(Host coordinatorHost, XenServerPatch xenServerPatch) @@ -97,12 +101,12 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions public class PoolPatchMapping : XenServerPatchMapping { - public Pool_patch Pool_patch; + public readonly Pool_patch Pool_patch; - public PoolPatchMapping(XenServerPatch xenServerPatch, Pool_patch pool_patch, Host coordinatorHost) - : base(xenServerPatch, coordinatorHost) + public PoolPatchMapping(XenServerPatch xenServerPatch, Pool_patch poolPatch, Host coordinatorHost, List hostsThatNeedEvacuation = null) + : base(xenServerPatch, coordinatorHost, hostsThatNeedEvacuation) { - Pool_patch = pool_patch ?? throw new ArgumentNullException("pool_patch"); + Pool_patch = poolPatch ?? throw new ArgumentNullException(nameof(poolPatch)); } public bool Matches(Host coordinatorHost, XenServerPatch xenServerPatch, Pool_patch patch ) @@ -126,27 +130,33 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions get { return Pool_patch != null && Pool_patch.opaque_ref != null; } } - public override void RefreshUpdate() + public override HostUpdateMapping RefreshUpdate() { if (Pool_patch != null) { - var patch = CoordinatorHost.Connection?.Cache.Pool_patches.FirstOrDefault(u => string.Equals(u.uuid, Pool_patch.uuid, StringComparison.OrdinalIgnoreCase)); + var patch = CoordinatorHost.Connection?.Cache.Pool_patches.FirstOrDefault(u => + string.Equals(u.uuid, Pool_patch.uuid, StringComparison.OrdinalIgnoreCase)); + if (patch != null && patch.opaque_ref != Pool_patch.opaque_ref) - Pool_patch = patch; + return new PoolPatchMapping(XenServerPatch, patch, CoordinatorHost, HostsThatNeedEvacuation); } + + return this; } } public class PoolUpdateMapping : XenServerPatchMapping { - public Pool_update Pool_update; - public Dictionary SrsWithUploadedUpdatesPerHost = new Dictionary(); + public readonly Pool_update Pool_update; + public readonly Dictionary SrsWithUploadedUpdatesPerHost; - public PoolUpdateMapping(XenServerPatch xenServerPatch, Pool_update pool_update, Host coordinatorHost) - : base(xenServerPatch, coordinatorHost) + public PoolUpdateMapping(XenServerPatch xenServerPatch, Pool_update poolUpdate, Host coordinatorHost, + Dictionary srsWithUploadedUpdatesPerHost, List hostsThatNeedEvacuation = null) + : base(xenServerPatch, coordinatorHost, hostsThatNeedEvacuation) { - Pool_update = pool_update ?? throw new ArgumentNullException("pool_update"); + Pool_update = poolUpdate ?? throw new ArgumentNullException(nameof(poolUpdate)); + SrsWithUploadedUpdatesPerHost = srsWithUploadedUpdatesPerHost ?? new Dictionary(); } public bool Matches(Host coordinatorHost, XenServerPatch xenServerPatch, Pool_update update) @@ -170,17 +180,19 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions get { return Pool_update != null && Pool_update.opaque_ref != null; } } - public override void RefreshUpdate() + public override HostUpdateMapping RefreshUpdate() { if (Pool_update != null) { - var update = Pool_update.Connection?.Cache.Pool_updates.FirstOrDefault(u => string.Equals(u.uuid, Pool_update.uuid, StringComparison.OrdinalIgnoreCase)); + var update = Pool_update.Connection?.Cache.Pool_updates.FirstOrDefault(u => + string.Equals(u.uuid, Pool_update.uuid, StringComparison.OrdinalIgnoreCase)); + if (update != null && update.opaque_ref != Pool_update.opaque_ref) - { - Pool_update = update; - } + return new PoolUpdateMapping(XenServerPatch, update, CoordinatorHost, + SrsWithUploadedUpdatesPerHost, HostsThatNeedEvacuation); } - + + return this; } } @@ -188,12 +200,12 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions public class OtherLegacyMapping : HostUpdateMapping { public readonly string Path; - public Pool_patch Pool_patch; + public readonly Pool_patch Pool_patch; - public OtherLegacyMapping(string path, Pool_patch pool_patch, Host coordinatorHost) - : base(coordinatorHost) + public OtherLegacyMapping(string path, Pool_patch pool_patch, Host coordinatorHost, List hostsThatNeedEvacuation = null) + : base(coordinatorHost, hostsThatNeedEvacuation) { - Path = !string.IsNullOrEmpty(path) ? path : throw new ArgumentNullException("path"); + Path = !string.IsNullOrEmpty(path) ? path : throw new ArgumentNullException(nameof(path)); Pool_patch = pool_patch; } @@ -230,14 +242,18 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions } } - public override void RefreshUpdate() + public override HostUpdateMapping RefreshUpdate() { if (Pool_patch != null) { - var patch = CoordinatorHost.Connection?.Cache.Pool_patches.FirstOrDefault(u => string.Equals(u.uuid, Pool_patch.uuid, StringComparison.OrdinalIgnoreCase)); + var patch = CoordinatorHost.Connection?.Cache.Pool_patches.FirstOrDefault(u => + string.Equals(u.uuid, Pool_patch.uuid, StringComparison.OrdinalIgnoreCase)); + if (patch != null && patch.opaque_ref != Pool_patch.opaque_ref) - Pool_patch = patch; + return new OtherLegacyMapping(Path, patch, CoordinatorHost, HostsThatNeedEvacuation); } + + return this; } } @@ -245,15 +261,19 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions public class SuppPackMapping : HostUpdateMapping { public readonly string Path; - public Pool_update Pool_update; - public Dictionary SrsWithUploadedUpdatesPerHost = new Dictionary(); - public Dictionary SuppPackVdis = new Dictionary(); + public readonly Pool_update Pool_update; + public readonly Dictionary SrsWithUploadedUpdatesPerHost; + public readonly Dictionary SuppPackVdis; - public SuppPackMapping(string path, Pool_update pool_update, Host coordinatorHost) - : base(coordinatorHost) + public SuppPackMapping(string path, Pool_update poolUpdate, Host coordinatorHost, + Dictionary srsWithUploadedUpdatesPerHost, Dictionary suppPackVdis, + List hostsThatNeedEvacuation = null) + : base(coordinatorHost, hostsThatNeedEvacuation) { - Path = !string.IsNullOrEmpty(path) ? path : throw new ArgumentNullException("path"); - Pool_update = pool_update; + Path = !string.IsNullOrEmpty(path) ? path : throw new ArgumentNullException(nameof(path)); + Pool_update = poolUpdate; + SrsWithUploadedUpdatesPerHost = srsWithUploadedUpdatesPerHost ?? new Dictionary(); + SuppPackVdis = suppPackVdis ?? new Dictionary(); } public bool Matches(Host coordinatorHost, string path, Pool_update update = null) @@ -289,14 +309,19 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions } } - public override void RefreshUpdate() + public override HostUpdateMapping RefreshUpdate() { if (Pool_update != null) { - var update = CoordinatorHost.Connection?.Cache.Pool_updates.FirstOrDefault(u => string.Equals(u.uuid, Pool_update.uuid, StringComparison.OrdinalIgnoreCase)); + var update = CoordinatorHost.Connection?.Cache.Pool_updates.FirstOrDefault(u => + string.Equals(u.uuid, Pool_update.uuid, StringComparison.OrdinalIgnoreCase)); + if (update != null && update.opaque_ref != Pool_update.opaque_ref) - Pool_update = update; + return new SuppPackMapping(Path, update, CoordinatorHost, SrsWithUploadedUpdatesPerHost, + SuppPackVdis, HostsThatNeedEvacuation); } + + return this; } } }