CP-36392: Refactored so that GetHashCode() does not reference mutable fields.

Signed-off-by: Konstantina Chremmou <konstantina.chremmou@citrix.com>
This commit is contained in:
Konstantina Chremmou 2022-04-05 21:16:52 +01:00
parent b3bc93f1f6
commit 177c47f79f
4 changed files with 92 additions and 69 deletions

View File

@ -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> task = null;

View File

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

View File

@ -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<Host, SR>(uploadIsoAction.SrsWithUploadedUpdatesPerHost)
};
var newMapping = new PoolUpdateMapping(xenServerPatch, poolUpdate, Helpers.GetCoordinator(conn),
new Dictionary<Host, SR>(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<Host, SR>(uploadIsoAction.SrsWithUploadedUpdatesPerHost),
SuppPackVdis = suppPackVdis
};
var newMapping = new SuppPackMapping(updateFilePath, poolUpdate, Helpers.GetCoordinator(conn),
new Dictionary<Host, SR>(uploadIsoAction.SrsWithUploadedUpdatesPerHost), suppPackVdis);
if (!mappings.Contains(newMapping))
mappings.Add(newMapping);

View File

@ -40,11 +40,12 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
public abstract class HostUpdateMapping
{
protected readonly Host CoordinatorHost;
public List<string> HostsThatNeedEvacuated = new List<string>();
public readonly List<string> HostsThatNeedEvacuation;
protected HostUpdateMapping(Host coordinatorHost)
protected HostUpdateMapping(Host coordinatorHost, List<string> hostsThatNeedEvacuation)
{
CoordinatorHost = coordinatorHost ?? throw new ArgumentNullException("coordinatorHost");
CoordinatorHost = coordinatorHost ?? throw new ArgumentNullException(nameof(coordinatorHost));
HostsThatNeedEvacuation = hostsThatNeedEvacuation ?? new List<string>();
}
protected bool Matches(Host coordinatorHost)
@ -64,7 +65,10 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
public abstract bool IsValid { get; }
public abstract void RefreshUpdate();
/// <summary>
/// Refresh the update/patch record based on uuid
/// </summary>
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<string> 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<string> 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<Host, SR> SrsWithUploadedUpdatesPerHost = new Dictionary<Host, SR>();
public readonly Pool_update Pool_update;
public readonly Dictionary<Host, SR> SrsWithUploadedUpdatesPerHost;
public PoolUpdateMapping(XenServerPatch xenServerPatch, Pool_update pool_update, Host coordinatorHost)
: base(xenServerPatch, coordinatorHost)
public PoolUpdateMapping(XenServerPatch xenServerPatch, Pool_update poolUpdate, Host coordinatorHost,
Dictionary<Host, SR> srsWithUploadedUpdatesPerHost, List<string> 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<Host, SR>();
}
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<string> 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<Host, SR> SrsWithUploadedUpdatesPerHost = new Dictionary<Host, SR>();
public Dictionary<Host, VDI> SuppPackVdis = new Dictionary<Host, VDI>();
public readonly Pool_update Pool_update;
public readonly Dictionary<Host, SR> SrsWithUploadedUpdatesPerHost;
public readonly Dictionary<Host, VDI> SuppPackVdis;
public SuppPackMapping(string path, Pool_update pool_update, Host coordinatorHost)
: base(coordinatorHost)
public SuppPackMapping(string path, Pool_update poolUpdate, Host coordinatorHost,
Dictionary<Host, SR> srsWithUploadedUpdatesPerHost, Dictionary<Host, VDI> suppPackVdis,
List<string> 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<Host, SR>();
SuppPackVdis = suppPackVdis ?? new Dictionary<Host, VDI>();
}
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;
}
}
}