Merge pull request #1968 from kc284/master

CA-284125: Automated updates should prioritise a pending host restart to a mandatory xapi restart
This commit is contained in:
Mihaela Stoica 2018-03-08 15:54:39 +00:00 committed by GitHub
commit 0184470ea3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 546 additions and 724 deletions

View File

@ -33,19 +33,15 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Threading;
using log4net;
using XenAdmin.Controls;
using XenAdmin.Diagnostics.Problems;
using XenAdmin.Dialogs;
using XenAdmin.Wizards.PatchingWizard.PlanActions;
using XenAPI;
using XenAdmin.Actions;
using System.Linq;
using XenAdmin.Core;
using XenAdmin.Network;
using System.Text;
using System.Diagnostics;
using XenAdmin.Alerts;
@ -56,7 +52,6 @@ namespace XenAdmin.Wizards.PatchingWizard
{
protected static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public XenAdmin.Core.Updates.UpgradeSequence UpgradeSequences { get; set; }
private bool _thisPageIsCompleted = false;
public List<Problem> ProblemsResolvedPreCheck { private get; set; }
@ -127,11 +122,6 @@ namespace XenAdmin.Wizards.PatchingWizard
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);
@ -191,19 +181,28 @@ namespace XenAdmin.Wizards.PatchingWizard
{
planActions.Add(new ApplyXenServerPatchPlanAction(host, patch, patchMappings));
var actions = GetAfterApplyGuidanceActionsForPatch(host, patch);
if (patch.GuidanceMandatory)
{
planActions.AddRange(actions);
// remove all delayed actions of the same kind that have already been added
// (because these actions are guidance-mandatory=true, therefore
// they will run immediately, making delayed ones obsolete)
delayedActionsByHost[host].RemoveAll(dg => actions.Any(ma => ma.GetType() == dg.GetType()));
var action = patch.after_apply_guidance == after_apply_guidance.restartXAPI &&
delayedActionsByHost[host].Any(a => a is RestartHostPlanAction)
? new RestartHostPlanAction(host, host.GetRunningVMs(), restartAgentFallback:true)
: GetAfterApplyGuidanceAction(host, patch.after_apply_guidance);
if (action != null)
{
planActions.Add(action);
// remove all delayed actions of the same kind that has already been added
// (because this action is guidance-mandatory=true, therefore
// it will run immediately, making delayed ones obsolete)
delayedActionsByHost[host].RemoveAll(a => action.GetType() == a.GetType());
}
}
else
{
// add any action that is not already in the list
delayedActionsByHost[host].AddRange(actions.Where(a => !delayedActionsByHost[host].Any(dg => a.GetType() == dg.GetType())));
var action = GetAfterApplyGuidanceAction(host, patch.after_apply_guidance);
// add the action if it's not already in the list
if (action != null && !delayedActionsByHost[host].Any(a => a.GetType() == action.GetType()))
delayedActionsByHost[host].Add(action);
}
}
@ -222,7 +221,7 @@ namespace XenAdmin.Wizards.PatchingWizard
if (planActions.Count > 0)
{
var bgw = new UpdateProgressBackgroundWorker(master, planActions, delayedActionsByHost, finalActions);
var bgw = new UpdateProgressBackgroundWorker(planActions, delayedActionsByHost, finalActions);
backgroundWorkers.Add(bgw);
}
@ -273,7 +272,7 @@ namespace XenAdmin.Wizards.PatchingWizard
doneActions.Add(action);
inProgressActions.Remove(action);
progressBar.Value += (int)((float)e.ProgressPercentage / (float)backgroundWorkers.Count); //extend with error handling related numbers
progressBar.Value += e.ProgressPercentage/backgroundWorkers.Count; //extend with error handling related numbers
}
}
@ -319,6 +318,9 @@ namespace XenAdmin.Wizards.PatchingWizard
private void WorkerDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
var bgw = sender as UpdateProgressBackgroundWorker;
if (bgw == null)
return;
PlanAction action = null;
try
@ -345,9 +347,10 @@ namespace XenAdmin.Wizards.PatchingWizard
foreach (var h in hostsOrdered)
{
var actions = bgw.DelayedActionsByHost[h];
var restartActions = actions.Where(a => a is RestartHostPlanAction).ToList();
//run all restart-alike plan actions
foreach (var a in actions.Where(a => a.IsRestartRelatedPlanAction()))
foreach (var a in restartActions)
{
action = a;
@ -360,8 +363,10 @@ namespace XenAdmin.Wizards.PatchingWizard
RunPlanAction(bgw, action);
}
var otherActions = actions.Where(a => !(a is RestartHostPlanAction)).ToList();
//run the rest
foreach (var a in actions.Where(a => !a.IsRestartRelatedPlanAction()))
foreach (var a in otherActions)
{
action = a;
@ -372,19 +377,19 @@ namespace XenAdmin.Wizards.PatchingWizard
}
// any non-restart-alike delayed action needs to be run if:
// - this host is pre-Ely and there isn't any restart plan action among the delayed actions, or
// - this host is Ely or above and bgw.AvoidRestartHosts contains the host's uuid (shows that live patching must have succeeded) or there isn't any restart plan action among the delayed actions
if (!Helpers.ElyOrGreater(h) && !actions.Any(pa => pa.IsRestartRelatedPlanAction())
|| Helpers.ElyOrGreater(h) && (bgw.AvoidRestartHosts != null && bgw.AvoidRestartHosts.Contains(h.uuid) || !actions.Any(pa => pa.IsRestartRelatedPlanAction())))
// - this host is pre-Ely and there isn't any delayed restart plan action, or
// - this host is Ely or above and live patching must have succeeded or there isn't any delayed restart plan action
if ((!Helpers.ElyOrGreater(h) && restartActions.Count <= 0)
|| (Helpers.ElyOrGreater(h) && (h.Connection.TryResolveWithTimeout(new XenRef<Host>(h.opaque_ref)).updates_requiring_reboot.Count <= 0 || restartActions.Count <= 0)))
{
RunPlanAction(bgw, action);
}
else
{
//skip running it
//skip running it, but still need to report progress, mainly for the progress bar
action.Visible = false;
bgw.ReportProgress((int)((1.0 / (double)bgw.ActionsCount) * 100), action); //still need to report progress, mainly for the progress bar
bgw.ReportProgress(100/bgw.ActionsCount, action);
}
}
}
@ -405,7 +410,6 @@ namespace XenAdmin.Wizards.PatchingWizard
}
catch (Exception e)
{
bgw.FailedWithExceptionAction = action;
errorActions.Add(action);
inProgressActions.Remove(action);
@ -451,8 +455,6 @@ namespace XenAdmin.Wizards.PatchingWizard
private void RunPlanAction(UpdateProgressBackgroundWorker bgw, PlanAction action)
{
InitializePlanAction(bgw, action);
action.OnProgressChange += action_OnProgressChange;
bgw.ReportProgress(0, action);
@ -461,8 +463,7 @@ namespace XenAdmin.Wizards.PatchingWizard
Thread.Sleep(1000);
action.OnProgressChange -= action_OnProgressChange;
bgw.doneActions.Add(action);
bgw.ReportProgress((int)((1.0 / (double)bgw.ActionsCount) * 100), action);
bgw.ReportProgress(100/bgw.ActionsCount, action);
}
private void action_OnProgressChange(object sender, EventArgs e)
@ -470,15 +471,6 @@ namespace XenAdmin.Wizards.PatchingWizard
Program.Invoke(Program.MainWindow, UpdateStatusTextBox);
}
private static void InitializePlanAction(UpdateProgressBackgroundWorker bgw, PlanAction action)
{
if (action is IAvoidRestartHostsAware)
{
var avoidRestartAction = action as IAvoidRestartHostsAware;
avoidRestartAction.AvoidRestartHosts = bgw.AvoidRestartHosts;
}
}
private void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
var bgw = (UpdateProgressBackgroundWorker)sender;
@ -510,75 +502,23 @@ namespace XenAdmin.Wizards.PatchingWizard
OnPageUpdated();
}
private static List<PlanAction> GetAfterApplyGuidanceActionsForPatch(Host host, XenServerPatch patch)
private PlanAction GetAfterApplyGuidanceAction(Host host, after_apply_guidance guidance)
{
List<PlanAction> actions = new List<PlanAction>();
List<XenRef<VM>> runningVMs = RunningVMs(host);
if (patch.after_apply_guidance == after_apply_guidance.restartHost)
switch (guidance)
{
actions.Add(new EvacuateHostPlanAction(host));
actions.Add(new RebootHostPlanAction(host));
actions.Add(new BringBabiesBackAction(runningVMs, host, false));
case after_apply_guidance.restartHost:
return new RestartHostPlanAction(host, host.GetRunningVMs());
case after_apply_guidance.restartXAPI:
return new RestartAgentPlanAction(host);
case after_apply_guidance.restartHVM:
return new RebootVMsPlanAction(host, host.GetRunningHvmVMs());
case after_apply_guidance.restartPV:
return new RebootVMsPlanAction(host, host.GetRunningPvVMs());
default:
return null;
}
if (patch.after_apply_guidance == after_apply_guidance.restartXAPI)
{
actions.Add(new RestartAgentPlanAction(host));
}
if (patch.after_apply_guidance == after_apply_guidance.restartHVM)
{
actions.Add(new RebootVMsPlanAction(host, RunningHvmVMs(host)));
}
if (patch.after_apply_guidance == after_apply_guidance.restartPV)
{
actions.Add(new RebootVMsPlanAction(host, RunningPvVMs(host)));
}
return actions;
}
private static List<XenRef<VM>> RunningHvmVMs(Host host)
{
List<XenRef<VM>> vms = new List<XenRef<VM>>();
foreach (VM vm in host.Connection.ResolveAll(host.resident_VMs))
{
if (!vm.IsHVM() || !vm.is_a_real_vm())
continue;
vms.Add(new XenRef<VM>(vm.opaque_ref));
}
return vms;
}
private static List<XenRef<VM>> RunningPvVMs(Host host)
{
List<XenRef<VM>> vms = new List<XenRef<VM>>();
foreach (VM vm in host.Connection.ResolveAll(host.resident_VMs))
{
if (vm.IsHVM() || !vm.is_a_real_vm())
continue;
vms.Add(new XenRef<VM>(vm.opaque_ref));
}
return vms;
}
private static List<XenRef<VM>> RunningVMs(Host host)
{
List<XenRef<VM>> vms = new List<XenRef<VM>>();
foreach (VM vm in host.Connection.ResolveAll(host.resident_VMs))
{
if (!vm.is_a_real_vm())
continue;
vms.Add(new XenRef<VM>(vm.opaque_ref));
}
return vms;
}
#endregion
private void ShowErrors()
@ -652,14 +592,5 @@ namespace XenAdmin.Wizards.PatchingWizard
labelError.Text = Messages.CLOSE_WIZARD_CLICK_FINISH;
}
}
public static class Extensions
{
public static bool IsRestartRelatedPlanAction(this PlanAction a)
{
return
a is EvacuateHostPlanAction || a is RebootHostPlanAction || a is BringBabiesBackAction;
}
}
}

View File

@ -364,16 +364,12 @@ namespace XenAdmin.Wizards.PatchingWizard
if (patch == null)
return actions;
List<XenRef<VM>> runningVMs = RunningVMs(host, patch);
actions.Add(new ApplyPatchPlanAction(host, patch));
if (patch.after_apply_guidance.Contains(after_apply_guidance.restartHost)
&& !(LivePatchCodesByHost !=null && LivePatchCodesByHost.ContainsKey(host.uuid) && LivePatchCodesByHost[host.uuid] == livepatch_status.ok_livepatch_complete))
if (patch.after_apply_guidance.Contains(after_apply_guidance.restartHost)
&& !(LivePatchCodesByHost != null && LivePatchCodesByHost.ContainsKey(host.uuid) && LivePatchCodesByHost[host.uuid] == livepatch_status.ok_livepatch_complete))
{
actions.Add(new EvacuateHostPlanAction(host));
actions.Add(new RebootHostPlanAction(host));
actions.Add(new BringBabiesBackAction(runningVMs, host, false));
actions.Add(new RestartHostPlanAction(host, host.GetRunningVMs()));
}
if (patch.after_apply_guidance.Contains(after_apply_guidance.restartXAPI))
@ -383,67 +379,17 @@ namespace XenAdmin.Wizards.PatchingWizard
if (patch.after_apply_guidance.Contains(after_apply_guidance.restartHVM))
{
actions.Add(new RebootVMsPlanAction(host, RunningHvmVMs(host)));
actions.Add(new RebootVMsPlanAction(host, host.GetRunningHvmVMs()));
}
if (patch.after_apply_guidance.Contains(after_apply_guidance.restartPV))
{
actions.Add(new RebootVMsPlanAction(host, RunningPvVMs(host)));
actions.Add(new RebootVMsPlanAction(host, host.GetRunningPvVMs()));
}
return actions;
}
private static List<XenRef<VM>> RunningVMs(Host host, Pool_patch patch)
{
List<XenRef<VM>> vms = new List<XenRef<VM>>();
foreach (VM vm in patch.Connection.ResolveAll(host.resident_VMs))
{
if (!vm.is_a_real_vm())
continue;
vms.Add(new XenRef<VM>(vm.opaque_ref));
}
return vms;
}
private static List<XenRef<VM>> RunningHvmVMs(Host host)
{
List<XenRef<VM>> vms = new List<XenRef<VM>>();
foreach (VM vm in host.Connection.ResolveAll(host.resident_VMs))
{
if (!vm.IsHVM() || !vm.is_a_real_vm())
continue;
vms.Add(new XenRef<VM>(vm.opaque_ref));
}
return vms;
}
private static List<XenRef<VM>> RunningPvVMs(Host host)
{
List<XenRef<VM>> vms = new List<XenRef<VM>>();
foreach (VM vm in host.Connection.ResolveAll(host.resident_VMs))
{
if (vm.IsHVM() || !vm.is_a_real_vm())
continue;
vms.Add(new XenRef<VM>(vm.opaque_ref));
}
return vms;
}
private static List<XenRef<VM>> RunningVMs(Host host)
{
List<XenRef<VM>> vms = new List<XenRef<VM>>();
foreach (VM vm in host.Connection.ResolveAll(host.resident_VMs))
{
if (!vm.is_a_real_vm())
continue;
vms.Add(new XenRef<VM>(vm.opaque_ref));
}
return vms;
}
private List<PlanAction> CompileSuppPackActionList(Host host)
{
List<PlanAction> actions = new List<PlanAction>();
@ -451,14 +397,10 @@ namespace XenAdmin.Wizards.PatchingWizard
if (SelectedUpdateType != UpdateType.ISO || SuppPackVdis == null || !SuppPackVdis.ContainsKey(host))
return actions;
List<XenRef<VM>> runningVMs = RunningVMs(host);
actions.Add(new InstallSupplementalPackPlanAction(host, SuppPackVdis[host]));
// after_apply_guidance is restartHost
actions.Add(new EvacuateHostPlanAction(host));
actions.Add(new RebootHostPlanAction(host));
actions.Add(new BringBabiesBackAction(runningVMs, host, false));
actions.Add(new RestartHostPlanAction(host, host.GetRunningVMs()));
return actions;
}
@ -470,16 +412,12 @@ namespace XenAdmin.Wizards.PatchingWizard
if (SelectedUpdateType != UpdateType.ISO || poolUpdate == null)
return actions;
List<XenRef<VM>> runningVMs = RunningVMs(host);
actions.Add(new ApplyPoolUpdatePlanAction(host, poolUpdate));
if (poolUpdate.after_apply_guidance.Contains(update_after_apply_guidance.restartHost)
&& !(LivePatchCodesByHost != null && LivePatchCodesByHost.ContainsKey(host.uuid) && LivePatchCodesByHost[host.uuid] == livepatch_status.ok_livepatch_complete))
{
actions.Add(new EvacuateHostPlanAction(host));
actions.Add(new RebootHostPlanAction(host));
actions.Add(new BringBabiesBackAction(runningVMs, host, false));
actions.Add(new RestartHostPlanAction(host, host.GetRunningVMs()));
}
if (poolUpdate.after_apply_guidance.Contains(update_after_apply_guidance.restartXAPI))
@ -489,12 +427,12 @@ namespace XenAdmin.Wizards.PatchingWizard
if (poolUpdate.after_apply_guidance.Contains(update_after_apply_guidance.restartHVM))
{
actions.Add(new RebootVMsPlanAction(host, RunningHvmVMs(host)));
actions.Add(new RebootVMsPlanAction(host, host.GetRunningHvmVMs()));
}
if (poolUpdate.after_apply_guidance.Contains(update_after_apply_guidance.restartPV))
{
actions.Add(new RebootVMsPlanAction(host, RunningPvVMs(host)));
actions.Add(new RebootVMsPlanAction(host, host.GetRunningPvVMs()));
}
return actions;

View File

@ -44,6 +44,8 @@ using XenAdmin.Diagnostics.Problems;
using XenAdmin.Diagnostics.Problems.HostProblem;
using XenAdmin.Dialogs;
using XenAPI;
using CheckGroup = System.Collections.Generic.KeyValuePair<string, System.Collections.Generic.List<XenAdmin.Diagnostics.Checks.Check>>;
namespace XenAdmin.Wizards.PatchingWizard
{
@ -276,9 +278,12 @@ namespace XenAdmin.Wizards.PatchingWizard
LivePatchCodesByHost = new Dictionary<string, livepatch_status>();
// Note: represent the groups as list so as to enforce the order of checks;
// a dictionary that looks sensible from a first look is not guranteed to
// keep the order, especially if items are removed (although not the case here)
var groups = update != null ? GenerateChecks(update) : GenerateChecks(patch); //patch is expected to be null for RPU
int totalChecks = groups.Values.Sum(c => c.Count);
int totalChecks = groups.Sum(c => c.Value == null ? 0 : c.Value.Count);
int doneCheckIndex = 0;
foreach (var group in groups)
@ -331,20 +336,20 @@ namespace XenAdmin.Wizards.PatchingWizard
set;
}
protected virtual Dictionary<string, List<Check>> GenerateCommonChecks(List<Host> applicableServers)
protected virtual List<CheckGroup> GenerateCommonChecks(List<Host> applicableServers)
{
var groups = new Dictionary<string, List<Check>>();
var groups = new List<CheckGroup>();
//XenCenter version check
if (UpdateAlert != null && UpdateAlert.NewServerVersion != null)
groups[Messages.CHECKING_XENCENTER_VERSION] = new List<Check> { new XenCenterVersionCheck(UpdateAlert.NewServerVersion) };
groups.Add(new CheckGroup(Messages.CHECKING_XENCENTER_VERSION, new List<Check> {new XenCenterVersionCheck(UpdateAlert.NewServerVersion)}));
//HostLivenessCheck checks
var livenessChecks = new List<Check>();
foreach (Host host in applicableServers)
livenessChecks.Add(new HostLivenessCheck(host));
groups[Messages.CHECKING_HOST_LIVENESS_STATUS] = livenessChecks;
groups.Add(new CheckGroup(Messages.CHECKING_HOST_LIVENESS_STATUS, livenessChecks));
//HA checks
@ -354,14 +359,14 @@ namespace XenAdmin.Wizards.PatchingWizard
if (Helpers.HostIsMaster(host))
haChecks.Add(new HAOffCheck(host));
}
groups[Messages.CHECKING_HA_STATUS] = haChecks;
groups.Add(new CheckGroup(Messages.CHECKING_HA_STATUS, haChecks));
//PBDsPluggedCheck
var pbdChecks = new List<Check>();
foreach (Host host in applicableServers)
pbdChecks.Add(new PBDsPluggedCheck(host));
groups[Messages.CHECKING_STORAGE_CONNECTIONS_STATUS] = pbdChecks;
groups.Add(new CheckGroup(Messages.CHECKING_STORAGE_CONNECTIONS_STATUS, pbdChecks));
//Disk space check for automated updates
@ -398,7 +403,7 @@ namespace XenAdmin.Wizards.PatchingWizard
));
}
}
groups[Messages.PATCHINGWIZARD_PRECHECKPAGE_CHECKING_DISK_SPACE] = diskChecks;
groups.Add(new CheckGroup(Messages.PATCHINGWIZARD_PRECHECKPAGE_CHECKING_DISK_SPACE, diskChecks));
}
//Checking reboot required and can evacuate host for version updates
@ -409,19 +414,19 @@ namespace XenAdmin.Wizards.PatchingWizard
var rebootChecks = new List<Check>();
foreach (var host in SelectedServers)
rebootChecks.Add(new HostNeedsRebootCheck(host, guidance, LivePatchCodesByHost));
groups[Messages.CHECKING_SERVER_NEEDS_REBOOT] = rebootChecks;
groups.Add(new CheckGroup(Messages.CHECKING_SERVER_NEEDS_REBOOT, rebootChecks));
var evacuateChecks = new List<Check>();
foreach (Host host in SelectedServers)
evacuateChecks.Add(new AssertCanEvacuateCheck(host, LivePatchCodesByHost));
groups[Messages.CHECKING_CANEVACUATE_STATUS] = evacuateChecks;
groups.Add(new CheckGroup(Messages.CHECKING_CANEVACUATE_STATUS, evacuateChecks));
}
return groups;
}
protected virtual Dictionary<string, List<Check>> GenerateChecks(Pool_patch patch)
protected virtual List<CheckGroup> GenerateChecks(Pool_patch patch)
{
List<Host> applicableServers = patch != null ? SelectedServers.Where(h => patch.AppliedOn(h) == DateTime.MaxValue).ToList() : SelectedServers;
@ -437,7 +442,7 @@ namespace XenAdmin.Wizards.PatchingWizard
Pool_patch poolPatchFromHost = poolPatches.Find(otherPatch => string.Equals(otherPatch.uuid, patch.uuid, StringComparison.OrdinalIgnoreCase));
serverChecks.Add(new PatchPrecheckCheck(host, poolPatchFromHost, LivePatchCodesByHost));
}
groups[Messages.CHECKING_SERVER_SIDE_STATUS] = serverChecks;
groups.Add(new CheckGroup(Messages.CHECKING_SERVER_SIDE_STATUS, serverChecks));
}
//Checking if the host needs a reboot
@ -451,7 +456,7 @@ namespace XenAdmin.Wizards.PatchingWizard
foreach (var host in applicableServers)
rebootChecks.Add(new HostNeedsRebootCheck(host, guidance, LivePatchCodesByHost));
groups[Messages.CHECKING_SERVER_NEEDS_REBOOT] = rebootChecks;
groups.Add(new CheckGroup(Messages.CHECKING_SERVER_NEEDS_REBOOT, rebootChecks));
}
//Checking can evacuate host
@ -463,7 +468,7 @@ namespace XenAdmin.Wizards.PatchingWizard
foreach (Host host in applicableServers)
evacuateChecks.Add(new AssertCanEvacuateCheck(host, LivePatchCodesByHost));
groups[Messages.CHECKING_CANEVACUATE_STATUS] = evacuateChecks;
groups.Add(new CheckGroup(Messages.CHECKING_CANEVACUATE_STATUS, evacuateChecks));
}
if (patch != null || WizardMode == WizardMode.AutomatedUpdates)
@ -472,13 +477,13 @@ namespace XenAdmin.Wizards.PatchingWizard
foreach (var pool in SelectedPools)
restartChecks.Add(new RestartHostOrToolstackPendingOnMasterCheck(pool, WizardMode == WizardMode.AutomatedUpdates ? null : patch.uuid));
groups[Messages.CHECKING_FOR_PENDING_RESTART] = restartChecks;
groups.Add(new CheckGroup(Messages.CHECKING_FOR_PENDING_RESTART, restartChecks));
}
return groups;
}
protected virtual Dictionary<string, List<Check>> GenerateChecks(Pool_update update)
protected virtual List<CheckGroup> GenerateChecks(Pool_update update)
{
List<Host> applicableServers = update != null ? SelectedServers.Where(h => !update.AppliedOn(h)).ToList() : SelectedServers;
var groups = GenerateCommonChecks(applicableServers);
@ -491,7 +496,7 @@ namespace XenAdmin.Wizards.PatchingWizard
homogeneityChecks.Add(new ServerSelectionCheck(pool, update, SelectedServers));
if (homogeneityChecks.Count > 0)
groups[Messages.CHECKING_SERVER_SELECTION] = homogeneityChecks;
groups.Add(new CheckGroup(Messages.CHECKING_SERVER_SELECTION, homogeneityChecks));
}
//Checking other things
@ -504,7 +509,7 @@ namespace XenAdmin.Wizards.PatchingWizard
Pool_update poolUpdateFromHost = updates.Find(otherPatch => string.Equals(otherPatch.uuid, update.uuid, StringComparison.OrdinalIgnoreCase));
serverChecks.Add(new PatchPrecheckCheck(host, poolUpdateFromHost, LivePatchCodesByHost));
}
groups[Messages.CHECKING_SERVER_SIDE_STATUS] = serverChecks;
groups.Add(new CheckGroup(Messages.CHECKING_SERVER_SIDE_STATUS, serverChecks));
}
//Checking if the host needs a reboot
@ -517,7 +522,7 @@ namespace XenAdmin.Wizards.PatchingWizard
foreach (var host in applicableServers)
rebootChecks.Add(new HostNeedsRebootCheck(host, guidance, LivePatchCodesByHost));
groups[Messages.CHECKING_SERVER_NEEDS_REBOOT] = rebootChecks;
groups.Add(new CheckGroup(Messages.CHECKING_SERVER_NEEDS_REBOOT, rebootChecks));
}
//Checking can evacuate host
@ -527,7 +532,7 @@ namespace XenAdmin.Wizards.PatchingWizard
foreach (Host host in applicableServers)
evacuateChecks.Add(new AssertCanEvacuateCheck(host, LivePatchCodesByHost));
groups[Messages.CHECKING_CANEVACUATE_STATUS] = evacuateChecks;
groups.Add(new CheckGroup(Messages.CHECKING_CANEVACUATE_STATUS, evacuateChecks));
}
if (update != null || WizardMode == WizardMode.AutomatedUpdates)
@ -537,7 +542,7 @@ namespace XenAdmin.Wizards.PatchingWizard
foreach (var pool in SelectedPools)
restartChecks.Add(new RestartHostOrToolstackPendingOnMasterCheck(pool, WizardMode == WizardMode.AutomatedUpdates ? null : update.uuid));
groups[Messages.CHECKING_FOR_PENDING_RESTART] = restartChecks;
groups.Add(new CheckGroup(Messages.CHECKING_FOR_PENDING_RESTART, restartChecks));
}
return groups;
@ -607,7 +612,7 @@ namespace XenAdmin.Wizards.PatchingWizard
labelProgress.Visible = actionInProgress || checkInProgress;
pictureBoxIssues.Visible = labelIssues.Visible = problemsFound && !actionInProgress && !checkInProgress;
return !IsCheckInProgress && !IsResolveActionInProgress && !problemsFound;
return !checkInProgress && !actionInProgress && !problemsFound;
}
public UpdateType SelectedUpdateType { private get; set; }

View File

@ -32,132 +32,29 @@
using System;
using System.Collections.Generic;
using System.Threading;
using XenAdmin.Core;
using XenAPI;
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
{
public class BringBabiesBackAction : PlanActionWithSession, IAvoidRestartHostsAware
public class BringBabiesBackAction : HostPlanAction
{
private readonly XenRef<Host> _host;
private readonly Host currentHost;
private readonly List<XenRef<VM>> _vms;
private readonly bool _enableOnly = false;
public List<string> AvoidRestartHosts { private get; set; }
private readonly bool _enableOnly;
public BringBabiesBackAction(List<XenRef<VM>> vms, Host host, bool enableOnly)
: base(host.Connection, string.Format(Messages.UPDATES_WIZARD_EXITING_MAINTENANCE_MODE, host.Name()))
: base(host, string.Format(Messages.UPDATES_WIZARD_EXITING_MAINTENANCE_MODE, host.Name()))
{
base.TitlePlan = string.Format(Messages.EXIT_SERVER_FROM_MAINTENANCE_MODE, host.Name());
this._host = new XenRef<Host>(host);
this._vms = vms;
this._enableOnly = enableOnly;
currentHost = host;
visible = false;
}
protected override Host CurrentHost
{
get { return currentHost; }
TitlePlan = string.Format(Messages.EXIT_SERVER_FROM_MAINTENANCE_MODE, host.Name());
_vms = vms;
_enableOnly = enableOnly;
Visible = false;
}
protected override void RunWithSession(ref Session session)
{
// If there are no patches that require reboot, we skip the evacuate-reboot-bringbabiesback sequence
if (Helpers.ElyOrGreater(currentHost) && AvoidRestartHosts != null && AvoidRestartHosts.Contains(currentHost.uuid))
{
log.Debug("Skipped scheduled restart (livepatching succeeded), BringBabiesBackAction is skipped.");
return;
}
visible = true;
Status = Messages.PLAN_ACTION_STATUS_RECONNECTING_STORAGE;
PBD.CheckAndBestEffortPlugPBDsFor(Connection, _vms);
//
// CA-17428: Apply hotfixes to a pool of hosts through XenCenter fails.
//
// Host do reenable themselves anyway, so just wait 1 min for that,
// occasionally poking it.
//
int retries = 0;
Status = Messages.PLAN_ACTION_STATUS_REENABLING_HOST;
while (!Host.get_enabled(session, _host.opaque_ref))
{
retries++;
Thread.Sleep(5000);
try
{
Host.enable(session, _host.opaque_ref);
}
catch (Exception e)
{
if (retries > 60)
throw;
log.Debug(string.Format("Cannot enable host {0}. Retrying in 5 sec.", _host.opaque_ref), e);
}
}
if(_enableOnly)
return;
int vmCount = _vms.Count;
int vmNumber = 0;
foreach (VM vm in Connection.ResolveAll(_vms))
{
int tries = 0;
if(vm.power_state != vm_power_state.Running)
continue; // vm may have been shutdown or suspended.
do
{
tries++;
try
{
Status = string.Format(Messages.PLAN_ACTION_STATUS_MIGRATING_VM_X_OF_Y, vmNumber + 1, vmCount);
log.DebugFormat("Migrating VM '{0}' back to Host '{1}'", Helpers.GetName(vm),
Helpers.GetName(Connection.Resolve(_host)));
PollTaskForResultAndDestroy(Connection, ref session,
VM.async_live_migrate(session, vm.opaque_ref, _host.opaque_ref),
(vmNumber * 100) / vmCount, ((vmNumber + 1) * 100) / vmCount);
vmNumber++;
}
catch (Failure e)
{
// When trying to put the first vm back, we get all sorts
// of errors ie storage not plugged yet etc. Just ignore them for now
if (vmNumber > 0 || tries > 24)
throw;
log.Debug(string.Format("Error migrating VM '{0}' back to Host '{1}'",
Helpers.GetName(vm), Helpers.GetName(Connection.Resolve(_host))), e);
Thread.Sleep(5000);
}
} while (vmNumber == 0);
}
Host hostModelObject = Connection.Resolve(_host);
if (hostModelObject != null)
{
log.DebugFormat("Cleaning up evacuated VMs from Host '{0}'", hostModelObject.Name());
hostModelObject.ClearEvacuatedVMs(session);
}
Visible = true;
BringBabiesBack(ref session, _vms, _enableOnly);
}
}
}

View File

@ -57,12 +57,12 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
protected override void RunWithSession(ref Session session)
{
this.visible = false;
this.Visible = false;
lock (patch)
{
this.visible = true;
this._title = string.Format(Messages.PATCHINGWIZARD_DOWNLOADUPDATE_ACTION_TITLE_DOWNLOADING, patch.Name);
this.Visible = true;
Title = string.Format(Messages.PATCHINGWIZARD_DOWNLOADUPDATE_ACTION_TITLE_DOWNLOADING, patch.Name);
if (Cancelling)
return;
@ -71,8 +71,8 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
if ((AllDownloadedPatches.ContainsKey(patch) && File.Exists(AllDownloadedPatches[patch]))
|| (patchFromDisk.Key == patch && File.Exists(patchFromDisk.Value)))
{
this.visible = false;
this._title = string.Format(Messages.PATCHINGWIZARD_DOWNLOADUPDATE_ACTION_TITLE_SKIPPING, patch.Name);
this.Visible = false;
Title = string.Format(Messages.PATCHINGWIZARD_DOWNLOADUPDATE_ACTION_TITLE_SKIPPING, patch.Name);
}
else
{

View File

@ -30,71 +30,24 @@
*/
using System.Collections.Generic;
using XenAdmin.Core;
using XenAPI;
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
{
public class EvacuateHostPlanAction : PlanActionWithSession, IAvoidRestartHostsAware
{
private readonly XenRef<Host> _host;
private readonly Host currentHost;
public List<string> AvoidRestartHosts { private get; set; }
public class EvacuateHostPlanAction : HostPlanAction
{
public EvacuateHostPlanAction(Host host)
: base(host.Connection, string.Format(Messages.PLANACTION_VMS_MIGRATING, host.Name()))
: base(host, string.Format(Messages.PLANACTION_VMS_MIGRATING, host.Name()))
{
base.TitlePlan = string.Format(Messages.MIGRATE_VMS_OFF_SERVER, host.Name());
this._host = new XenRef<Host>(host);
currentHost = host;
visible = false;
}
protected override Host CurrentHost
{
get { return currentHost; }
TitlePlan = string.Format(Messages.MIGRATE_VMS_OFF_SERVER, host.Name());
Visible = false;
}
protected override void RunWithSession(ref Session session)
{
Host hostObject = TryResolveWithTimeout(_host);
// If there are no patches that require reboot, we skip the evacuate-reboot-bringbabiesback sequence
// But we only do this if we indicated that host restart should be avoided (by initializing the AvoidRestartHosts property)
if (Helpers.ElyOrGreater(hostObject) && AvoidRestartHosts != null)
{
log.DebugFormat("Checking host.patches_requiring_reboot now on '{0}'...", hostObject);
if (hostObject.updates_requiring_reboot.Count > 0)
{
AvoidRestartHosts.Remove(hostObject.uuid);
log.DebugFormat("Restart is needed now (hostObject.updates_requiring_reboot has {0} items in it). Evacuating now. Will restart after.", hostObject.updates_requiring_reboot.Count);
}
else
{
if (!AvoidRestartHosts.Contains(hostObject.uuid))
AvoidRestartHosts.Add(hostObject.uuid);
log.Debug("Will skip scheduled restart (livepatching succeeded), because hostObject.patches_requiring_reboot is empty.");
return;
}
}
visible = true;
PBD.CheckAndPlugPBDsFor(Connection.ResolveAll(hostObject.resident_VMs));
log.DebugFormat("Disabling host {0}", hostObject.Name());
Host.disable(session, _host.opaque_ref);
Status = Messages.PLAN_ACTION_STATUS_MIGRATING_VMS_FROM_HOST;
log.DebugFormat("Migrating VMs from host {0}", hostObject.Name());
XenRef<Task> task = Host.async_evacuate(session, _host.opaque_ref);
PollTaskForResultAndDestroy(Connection, ref session, task);
Visible = true;
EvacuateHost(ref session);
}
}
}

View File

@ -0,0 +1,164 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using XenAdmin.Core;
using XenAPI;
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
{
public abstract class HostPlanAction : PlanActionWithSession
{
private readonly Host _currentHost;
protected readonly XenRef<Host> HostXenRef;
protected HostPlanAction(Host host, string description)
: base(host.Connection, description)
{
HostXenRef = new XenRef<Host>(host);
}
protected override Host CurrentHost
{
get { return _currentHost; }
}
public Host GetResolvedHost()
{
return Connection.TryResolveWithTimeout(HostXenRef);
}
protected void EvacuateHost(ref Session session)
{
var hostObj = GetResolvedHost();
Title = string.Format(Messages.PLANACTION_VMS_MIGRATING, hostObj.Name());
PBD.CheckAndPlugPBDsFor(Connection.ResolveAll(hostObj.resident_VMs));
log.DebugFormat("Disabling host {0}", hostObj.Name());
Host.disable(session, HostXenRef.opaque_ref);
Status = Messages.PLAN_ACTION_STATUS_MIGRATING_VMS_FROM_HOST;
log.DebugFormat("Migrating VMs from host {0}", hostObj.Name());
XenRef<Task> task = Host.async_evacuate(session, HostXenRef.opaque_ref);
PollTaskForResultAndDestroy(Connection, ref session, task);
}
protected void BringBabiesBack(ref Session session, List<XenRef<VM>> vmrefs, bool enableOnly)
{
Status = Messages.PLAN_ACTION_STATUS_RECONNECTING_STORAGE;
PBD.CheckAndBestEffortPlugPBDsFor(Connection, vmrefs);
//
// CA-17428: Apply hotfixes to a pool of hosts through XenCenter fails.
//
// Hosts do reenable themselves anyway, so just wait 1 min for that,
// occasionally poking it.
//
Status = Messages.PLAN_ACTION_STATUS_REENABLING_HOST;
int retries = 0;
while (!Host.get_enabled(session, HostXenRef.opaque_ref))
{
retries++;
Thread.Sleep(5000);
try
{
Host.enable(session, HostXenRef.opaque_ref);
}
catch (Exception e)
{
if (retries > 60)
throw;
log.Debug(string.Format("Cannot enable host {0}. Retrying in 5 sec.", HostXenRef.opaque_ref), e);
}
}
if (enableOnly)
return;
int vmCount = vmrefs.Count;
int vmNumber = 0;
var hostObj = GetResolvedHost();
foreach (VM vm in Connection.ResolveAll(vmrefs))
{
int tries = 0;
if (vm.power_state != vm_power_state.Running)
continue; // vm may have been shutdown or suspended.
do
{
tries++;
try
{
Status = string.Format(Messages.PLAN_ACTION_STATUS_MIGRATING_VM_X_OF_Y, vmNumber + 1, vmCount);
log.DebugFormat("Migrating VM '{0}' back to Host '{1}'", vm.Name(), hostObj.Name());
PollTaskForResultAndDestroy(Connection, ref session,
VM.async_live_migrate(session, vm.opaque_ref, HostXenRef.opaque_ref),
(vmNumber * 100) / vmCount, ((vmNumber + 1) * 100) / vmCount);
vmNumber++;
}
catch (Failure e)
{
// When trying to put the first vm back, we get all sorts
// of errors ie storage not plugged yet etc. Just ignore them for now
if (vmNumber > 0 || tries > 24)
throw;
log.Debug(string.Format("Error migrating VM '{0}' back to Host '{1}'", vm.Name(), hostObj.Name()), e);
Thread.Sleep(5000);
}
} while (vmNumber == 0);
}
log.DebugFormat("Cleaning up evacuated VMs from Host '{0}'", hostObj.Name());
Host.ClearEvacuatedVMs(session, HostXenRef);
}
}
}

View File

@ -1,43 +0,0 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
{
interface IAvoidRestartHostsAware
{
List<string> AvoidRestartHosts { set; }
}
}

View File

@ -35,7 +35,6 @@ using System.Threading;
using log4net;
using XenAdmin.Network;
using XenAPI;
using System.Diagnostics;
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
@ -51,18 +50,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
public Exception Error;
protected bool Cancelling = false;
protected bool visible = true;
public bool Visible
{
get
{
return visible;
}
set
{
visible = value;
}
}
public bool Visible { get; set; }
private string status;
public string Status
@ -96,40 +84,15 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
}
}
protected string _title;
public string Title
{
get
{
return _title;
}
}
public string Title { get; protected set; }
public string TitlePlan { get; set; }
private bool _showProgressBar = false;
public event EventHandler OnShowProgressBarChange;
public virtual bool ShowProgressBar
{
get
{
return _showProgressBar;
}
set
{
_showProgressBar = value;
if (OnShowProgressBarChange != null)
OnShowProgressBarChange(this, new EventArgs());
}
}
protected PlanAction(string title)
{
Visible = true;
_percentComplete = 0;
_title = title;
Title = title;
}
protected abstract void _Run();
@ -172,8 +135,6 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
}
protected delegate void UpdateProgressDelegate(int progress);
private void UpdateProgress(int progress)
{
this.PercentComplete = progress;
@ -197,13 +158,13 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
}
protected static string PollTaskForResult(IXenConnection connection, ref Session session,
XenRef<Task> task, UpdateProgressDelegate updateProgressDelegate)
XenRef<Task> task, Action<int> updateProgressDelegate)
{
return PollTaskForResult(connection, ref session, task, updateProgressDelegate, 0, 100);
}
protected static String PollTaskForResult(IXenConnection connection, ref Session session,
XenRef<Task> task, UpdateProgressDelegate updateProgressDelegate, int min, int max)
XenRef<Task> task, Action<int> updateProgressDelegate, int min, int max)
{
Program.AssertOffEventThread();

View File

@ -31,7 +31,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using XenAdmin.Network;
using XenAPI;
@ -41,37 +40,12 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
{
protected readonly IXenConnection Connection;
protected PlanActionWithSession(IXenConnection connection, String description, int offset)
protected PlanActionWithSession(IXenConnection connection, string description)
: base(description)
{
if(connection==null)
throw new ArgumentException(this.GetType().Name+" connection null");
this.Connection = connection;
}
protected PlanActionWithSession(IXenConnection connection, String description)
: this(connection, description, 1)
{
}
protected T TryResolveWithTimeout<T>(XenRef<T> t) where T : XenObject<T>
{
log.DebugFormat("Resolving {0} {1}", t, t.opaque_ref);
int timeout = 120; // two minutes;
while (timeout > 0)
{
T obj = Connection.Resolve(t);
if (obj != null)
return obj;
Thread.Sleep(1000);
timeout = timeout - 1;
}
if (typeof(T) == typeof(Host))
throw new Failure(Failure.HOST_OFFLINE);
throw new Failure(Failure.HANDLE_INVALID, typeof(T).Name, t.opaque_ref);
Connection = connection;
}
protected abstract void RunWithSession(ref Session session);

View File

@ -30,54 +30,23 @@
*/
using System.Collections.Generic;
using XenAdmin.Core;
using XenAdmin.Network;
using XenAPI;
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
{
public class RebootHostPlanAction : RebootPlanAction, IAvoidRestartHostsAware
public class RebootHostPlanAction : RebootPlanAction
{
private readonly Host _host;
public List<string> AvoidRestartHosts { private get; set; }
public RebootHostPlanAction(Host host)
: base(host.Connection, new XenRef<Host>(host.opaque_ref), string.Format(Messages.UPDATES_WIZARD_REBOOTING, host))
: base(host, string.Format(Messages.UPDATES_WIZARD_REBOOTING, host))
{
_host = host;
visible = false;
Visible = false;
}
protected override void RunWithSession(ref Session session)
{
// If there are no patches that require reboot, we skip the evacuate-reboot-bringbabiesback sequence
if (Helpers.ElyOrGreater(_host) && AvoidRestartHosts != null && AvoidRestartHosts.Contains(_host.uuid))
{
log.Debug("Skipping scheduled restart (livepatching succeeded). RebootHostPlanAction is skipped.");
return;
}
visible = true;
_host.Connection.ExpectDisruption = true;
try
{
base.WaitForReboot(ref session, _session => XenAPI.Host.async_reboot(_session, Host.opaque_ref));
foreach (var host in _host.Connection.Cache.Hosts)
host.CheckAndPlugPBDs(); // Wait for PBDs to become plugged on all hosts
}
finally
{
_host.Connection.ExpectDisruption = false;
}
}
internal void RunExternal(Session session)
{
RunWithSession(ref session);
Visible = true;
RebootHost(ref session);
}
}
}

View File

@ -31,79 +31,19 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using XenAdmin.Network;
using XenAPI;
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
{
// TODO COWLEY: This code is used more widely and the common parts should move into HostAction.
public abstract class RebootPlanAction : PlanActionWithSession
public abstract class RebootPlanAction : HostPlanAction
{
protected readonly XenRef<Host> Host;
private bool _cancelled = false;
protected RebootPlanAction(IXenConnection connection, XenRef<Host> host, String title)
: base(connection, title)
protected RebootPlanAction(Host host, string title)
: base(host, title)
{
this.Host = host;
}
protected delegate double MetricDelegate(Session session);
protected delegate void DelegateWithSession(Session session);
protected void WaitForReboot(ref Session session, DelegateWithSession methodInvoker)
{
Host host = TryResolveWithTimeout(this.Host);
_WaitForReboot(host.IsMaster(), ref session, GetHostBootTime, methodInvoker);
}
protected void WaitForAgent(ref Session session, DelegateWithSession methodInvoker)
{
Host host = TryResolveWithTimeout(this.Host);
_WaitForReboot(host.IsMaster(), ref session, GetAgentStartTime, methodInvoker);
}
private double GetAgentStartTime(Session session)
{
Dictionary<String, String> other_config = XenAPI.Host.get_other_config(session, Host);
if (other_config == null)
return 0.0;
if (!other_config.ContainsKey(XenAPI.Host.AGENT_START_TIME))
return 0.0;
double agentStartTime;
if (!double.TryParse(other_config[XenAPI.Host.AGENT_START_TIME], NumberStyles.Number,
CultureInfo.InvariantCulture, out agentStartTime))
return 0.0;
return agentStartTime;
}
private double GetHostBootTime(Session session)
{
Dictionary<String, String> other_config = XenAPI.Host.get_other_config(session, Host);
if (other_config == null)
return 0.0;
if (!other_config.ContainsKey(XenAPI.Host.BOOT_TIME))
return 0.0;
double agentStartTime;
if (!double.TryParse(other_config[XenAPI.Host.BOOT_TIME], NumberStyles.Number,
CultureInfo.InvariantCulture, out agentStartTime))
return 0.0;
return agentStartTime;
}
public override void Cancel()
@ -127,10 +67,29 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
Connection.ConnectionLost -= connection_ConnectionLost;
}
private void _WaitForReboot(bool master, ref Session session, MetricDelegate metricDelegate, DelegateWithSession methodInvoker)
protected void RebootHost(ref Session session)
{
var hostObj = GetResolvedHost();
Title = string.Format(Messages.UPDATES_WIZARD_REBOOTING, hostObj.Name());
Connection.ExpectDisruption = true;
try
{
WaitForReboot(ref session, Host.BootTime, s => Host.async_reboot(s, HostXenRef.opaque_ref));
foreach (var host in Connection.Cache.Hosts)
host.CheckAndPlugPBDs(); // Wait for PBDs to become plugged on all hosts
}
finally
{
Connection.ExpectDisruption = false;
}
}
protected void WaitForReboot(ref Session session, Func<Session, string, double> metricDelegate, Action<Session> methodInvoker)
{
bool master = GetResolvedHost().IsMaster();
_cancelled = false;
double metric = metricDelegate(session);
double metric = metricDelegate(session, HostXenRef.opaque_ref);
log.DebugFormat("{0}._WaitForReboot(master='{1}', metric='{2}')", GetType().Name, master, metric);
@ -153,8 +112,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
}
}
private Session WaitForHostToStart(bool master, Session session, MetricDelegate metricDelegate, double metric)
private Session WaitForHostToStart(bool master, Session session, Func<Session, string, double> metricDelegate, double metric)
{
Connection.ExpectDisruption = true;
@ -214,7 +172,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
Thread.Sleep(1000);
}
private void WaitForBootTimeToBeGreaterThanBefore(bool master, Session session, MetricDelegate metricDelegate, double metric)
private void WaitForBootTimeToBeGreaterThanBefore(bool master, Session session, Func<Session, string, double> metricDelegate, double metric)
{
DateTime waitForMetric = DateTime.Now;
@ -225,7 +183,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
double currentMetric;
do
{
currentMetric = metricDelegate(session);
currentMetric = metricDelegate(session, HostXenRef.opaque_ref);
if (_cancelled)
throw new CancelledException();

View File

@ -29,7 +29,6 @@
* SUCH DAMAGE.
*/
using XenAdmin.Network;
using XenAPI;
@ -37,21 +36,14 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
{
public class RestartAgentPlanAction : RebootPlanAction
{
/// <summary>
///
/// </summary>
/// <param name="connection"></param>
/// <param name="host"></param>
/// <param name="owner">The Form in front of which any connecting dialogs will be shown. May be null.</param>
public RestartAgentPlanAction(Host host)
: base(host.Connection, new XenRef<Host>(host), string.Format(Messages.UPDATES_WIZARD_RESTARTING_AGENT, host.Name()))
: base(host, string.Format(Messages.UPDATES_WIZARD_RESTARTING_AGENT, host.Name()))
{
}
protected override void RunWithSession(ref Session session)
{
base.WaitForAgent(ref session, _session => XenAPI.Host.async_restart_agent(_session, Host.opaque_ref));
WaitForReboot(ref session, Host.AgentStartTime, s => Host.async_restart_agent(s, HostXenRef.opaque_ref));
}
}
}

View File

@ -0,0 +1,91 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using XenAdmin.Core;
using XenAPI;
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
{
public class RestartHostPlanAction : RebootPlanAction
{
private readonly List<XenRef<VM>> _vms;
private readonly bool _enableOnly;
private readonly bool _restartAgentFallback;
public RestartHostPlanAction(Host host, List<XenRef<VM>> vms, bool enableOnly = false, bool restartAgentFallback = false)
: base(host, string.Empty)
{
_vms = vms;
Visible = false;
_enableOnly = enableOnly;
_restartAgentFallback = restartAgentFallback;
}
protected override void RunWithSession(ref Session session)
{
Visible = true;
var hostObj = GetResolvedHost();
if (Helpers.ElyOrGreater(hostObj))
{
log.DebugFormat("Checking host.patches_requiring_reboot now on '{0}'.", hostObj);
if (hostObj.updates_requiring_reboot.Count > 0)
{
log.DebugFormat("Found {0} patches requiring reboot (live patching failed)."
+ "Initiating evacuate-reboot-bringbabiesback process.",
hostObj.updates_requiring_reboot.Count);
}
else if (_restartAgentFallback)
{
log.Debug("Live patching succeeded. Restarting agent.");
Title = string.Format(Messages.UPDATES_WIZARD_RESTARTING_AGENT, hostObj.Name());
WaitForReboot(ref session, Host.AgentStartTime, s => Host.async_restart_agent(s, HostXenRef.opaque_ref));
return;
}
else
{
log.Debug("Did not find patches requiring reboot (live patching succeeded)."
+ " Skipping scheduled restart.");
return;
}
}
EvacuateHost(ref session);
RebootHost(ref session);
BringBabiesBack(ref session, _vms, _enableOnly);
}
}
}

View File

@ -52,7 +52,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
{
List<VM> vmObjs = new List<VM>();
foreach (XenRef<VM> vm in _vms)
vmObjs.Add(TryResolveWithTimeout(vm));
vmObjs.Add(Connection.TryResolveWithTimeout(vm));
PBD.CheckAndPlugPBDsFor(vmObjs);

View File

@ -33,8 +33,6 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XenAdmin.Wizards.PatchingWizard.PlanActions;
using XenAPI;
@ -42,46 +40,24 @@ namespace XenAdmin.Wizards.PatchingWizard
{
class UpdateProgressBackgroundWorker : BackgroundWorker
{
private readonly int _actionsCount;
public List<PlanAction> PlanActions { get; private set; }
public Dictionary<Host, List<PlanAction>> DelayedActionsByHost {get; private set; }
public List<PlanAction> FinalActions { get; private set; }
private Host master;
public List<PlanAction> FinsihedActions = new List<PlanAction>();
public PlanAction FailedWithExceptionAction = null;
public List<PlanAction> doneActions = new List<PlanAction>();
public PlanAction InProgressAction { get; set; }
private readonly List<string> avoidRestartHosts = new List<string>();
/// <summary>
/// This list lists uuids of hosts that does not need to be restarted
/// </summary>
public List<string> AvoidRestartHosts
public UpdateProgressBackgroundWorker(List<PlanAction> planActions,
Dictionary<Host, List<PlanAction>> delayedActionsByHost, List<PlanAction> finalActions)
{
get
{
return avoidRestartHosts;
}
}
public UpdateProgressBackgroundWorker(Host master, List<PlanAction> planActions, Dictionary<Host, List<PlanAction>> delayedActionsByHost,
List<PlanAction> finalActions)
{
this.master = master;
this.PlanActions = planActions;
this.DelayedActionsByHost = delayedActionsByHost;
this.FinalActions = finalActions;
PlanActions = planActions;
DelayedActionsByHost = delayedActionsByHost;
FinalActions = finalActions;
_actionsCount = PlanActions.Count + DelayedActionsByHost.Sum(kvp => kvp.Value.Count) + FinalActions.Count;
}
public int ActionsCount
{
get
{
return PlanActions.Count + DelayedActionsByHost.Sum(kvp => kvp.Value.Count) + FinalActions.Count;
}
get { return _actionsCount; }
}
public new void CancelAsync()

View File

@ -79,10 +79,11 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
if (_cancel)
return;
if (planAction is UpgradeHostPlanAction)
var upgradeAction = planAction as UpgradeHostPlanAction;
if (upgradeAction != null)
{
Host hostAfterReboot = (planAction as UpgradeHostPlanAction).Host;
Host hostAfterReboot = upgradeAction.GetResolvedHost();
if (hostAfterReboot != null && Helpers.SameServerVersion(hostAfterReboot, hostVersion))
{
log.ErrorFormat("Host '{0}' rebooted with the same version '{1}'", hostAfterReboot.Name(), hostAfterReboot.LongProductVersion());

View File

@ -130,15 +130,14 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
try
{
if (planAction is UpgradeManualHostPlanAction)
{
var upgradeAction = (UpgradeManualHostPlanAction)planAction;
var upgradeAction = planAction as UpgradeManualHostPlanAction;
if (upgradeAction != null)
{
if (ManageSemiAutomaticPlanAction != null)
ManageSemiAutomaticPlanAction(upgradeAction);
if (host.IsMaster())
poolHigherProductVersion = upgradeAction.Host.LongProductVersion();
poolHigherProductVersion = upgradeAction.GetResolvedHost().LongProductVersion();
}
else
planAction.Run();

View File

@ -33,13 +33,12 @@ using System;
using System.Collections.Generic;
using XenAPI;
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
{
class UpgradeHostPlanAction : UpgradeManualHostPlanAction
{
private readonly Dictionary<string, string> _arguments = new Dictionary<string, string>();
private Dictionary<string, string> _arguments = new Dictionary<string, string>();
public UpgradeHostPlanAction(Host host, Dictionary<string, string> arguments)
: base(host)
{
@ -49,7 +48,7 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
protected override void RunWithSession(ref Session session)
{
string value = XenAPI.Host.call_plugin(session, Host.opaque_ref, "prepare_host_upgrade.py", "main", _arguments);
string value = Host.call_plugin(session, HostXenRef.opaque_ref, "prepare_host_upgrade.py", "main", _arguments);
if (value.ToLower() == "true")
base.RunWithSession(ref session);
else

View File

@ -32,34 +32,25 @@
using XenAPI;
using System;
using System.Timers;
using XenAdmin.Wizards.PatchingWizard.PlanActions;
using Timer = System.Timers.Timer;
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
namespace XenAdmin.Wizards.RollingUpgradeWizard.PlanActions
{
public class UpgradeManualHostPlanAction : RebootPlanAction
{
private readonly Host _host;
public Timer timer = new Timer();
public UpgradeManualHostPlanAction(Host host)
: base(host.Connection, new XenRef<Host>(host.opaque_ref), string.Format(Messages.UPGRADING_SERVER, host))
: base(host, string.Format(Messages.UPGRADING_SERVER, host))
{
TitlePlan = Messages.UPGRADING;
_host = host;
timer.Interval = 20 * 60000;
timer.AutoReset = true;
timer.Elapsed += timer_Elapsed;
}
protected override Host CurrentHost
{
get { return _host; }
}
public new Host Host { get { return TryResolveWithTimeout(base.Host); } }
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (rebooting && Timeout != null)
@ -77,43 +68,39 @@ namespace XenAdmin.Wizards.PatchingWizard.PlanActions
{
try
{
Status = Messages.PLAN_ACTION_STATUS_DISABLING_HOST_SERVER;
var hostObj = GetResolvedHost();
if (Host.enabled)
if (hostObj.enabled)
{
log.DebugFormat("Disabling host {0}", _host.Name());
XenAPI.Host.disable(session, Host.opaque_ref);
Status = Messages.PLAN_ACTION_STATUS_DISABLING_HOST_SERVER;
log.DebugFormat("Disabling host {0}", hostObj.Name());
Host.disable(session, HostXenRef.opaque_ref);
}
timer.Start();
rebooting = true;
log.DebugFormat("Upgrading host {0}", _host.Name());
log.DebugFormat("Upgrading host {0}", hostObj.Name());
Status = Messages.PLAN_ACTION_STATUS_INSTALLING_XENSERVER;
log.DebugFormat("Waiting for host {0} to reboot", _host.Name());
WaitForReboot(ref session, _session => XenAPI.Host.async_reboot(_session, Host.opaque_ref));
log.DebugFormat("Waiting for host {0} to reboot", hostObj.Name());
WaitForReboot(ref session, Host.BootTime, s => Host.async_reboot(s, HostXenRef.opaque_ref));
Status = Messages.PLAN_ACTION_STATUS_RECONNECTING_STORAGE;
foreach (var host in _host.Connection.Cache.Hosts)
foreach (var host in Connection.Cache.Hosts)
host.CheckAndPlugPBDs(); // Wait for PBDs to become plugged on all hosts
rebooting = false;
log.DebugFormat("Host {0} rebooted", _host.Name());
log.DebugFormat("Host {0} rebooted", hostObj.Name());
Status = Messages.PLAN_ACTION_STATUS_HOST_UPGRADED;
log.DebugFormat("Upgraded host {0}", _host.Name());
log.DebugFormat("Upgraded host {0}", hostObj.Name());
}
finally
{
_host.Connection.ExpectDisruption = false;
Connection.ExpectDisruption = false;
timer.Stop();
}
}
internal void RunExternal(Session session)
{
RunWithSession(ref session);
}
}
}

View File

@ -260,7 +260,7 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
var upgradeHostPlanAction = planAction;
//Show dialog prepare host boot from CD or PXE boot and click OK to reboot
string msg = string.Format(Messages.ROLLING_UPGRADE_REBOOT_MESSAGE, planAction.Host.Name());
string msg = string.Format(Messages.ROLLING_UPGRADE_REBOOT_MESSAGE, planAction.GetResolvedHost().Name());
UpgradeManualHostPlanAction action = upgradeHostPlanAction;
@ -273,16 +273,16 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
if (Dialog.DialogResult != DialogResult.OK) // Cancel or Unknown
{
completedTitleLabel = Messages.ROLLING_UPGRADE_UPGRADE_NOT_COMPLETED;
if(action.Host.IsMaster())
if (action.GetResolvedHost().IsMaster())
throw new ApplicationException(Messages.EXCEPTION_USER_CANCELLED_MASTER);
throw new ApplicationException(Messages.EXCEPTION_USER_CANCELLED);
}
}
});
string beforeRebootProductVersion = upgradeHostPlanAction.Host.LongProductVersion();
string hostName = upgradeHostPlanAction.Host.Name();
upgradeHostPlanAction.Timeout += new EventHandler(upgradeHostPlanAction_Timeout);
string beforeRebootProductVersion = upgradeHostPlanAction.GetResolvedHost().LongProductVersion();
string hostName = upgradeHostPlanAction.GetResolvedHost().Name();
upgradeHostPlanAction.Timeout += upgradeHostPlanAction_Timeout;
try
{
do
@ -294,7 +294,7 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
upgradeHostPlanAction.Run();
//if comes back and does not have a different product version
if (Helpers.SameServerVersion(upgradeHostPlanAction.Host, beforeRebootProductVersion))
if (Helpers.SameServerVersion(upgradeHostPlanAction.GetResolvedHost(), beforeRebootProductVersion))
{
using (var dialog = new NotModalThreeButtonDialog(SystemIcons.Exclamation,
string.Format(Messages.ROLLING_UPGRADE_REBOOT_AGAIN_MESSAGE, hostName)
@ -304,15 +304,15 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
if (dialog.DialogResult != DialogResult.OK) // Cancel or Unknown
throw new Exception(Messages.HOST_REBOOTED_SAME_VERSION);
else
upgradeHostPlanAction = new UpgradeManualHostPlanAction(upgradeHostPlanAction.Host);
upgradeHostPlanAction = new UpgradeManualHostPlanAction(upgradeHostPlanAction.GetResolvedHost());
}
}
} while (Helpers.SameServerVersion(upgradeHostPlanAction.Host, beforeRebootProductVersion));
} while (Helpers.SameServerVersion(upgradeHostPlanAction.GetResolvedHost(), beforeRebootProductVersion));
}
finally
{
upgradeHostPlanAction.Timeout -= new EventHandler(upgradeHostPlanAction_Timeout);
upgradeHostPlanAction.Timeout -= upgradeHostPlanAction_Timeout;
}
}
@ -436,20 +436,18 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
private List<PlanAction> GetSubTasksFor(Host host)
{
List<XenRef<VM>> runningVMs = RunningVMs(host);
if (ManualModeSelected)
return new List<PlanAction>
{
new EvacuateHostPlanAction(host),
new UpgradeManualHostPlanAction(host),
new BringBabiesBackAction(runningVMs, host, true)
};
var runningVMs = RunningVMs(host);
var upgradeAction = ManualModeSelected
? new UpgradeManualHostPlanAction(host)
: new UpgradeHostPlanAction(host, InstallMethodConfig);
return new List<PlanAction>
{
new EvacuateHostPlanAction(host),
new UpgradeHostPlanAction(host, InstallMethodConfig),
new BringBabiesBackAction(runningVMs, host, true)
};
{
new EvacuateHostPlanAction(host),
upgradeAction,
new BringBabiesBackAction(runningVMs, host, true)
};
}
private static List<XenRef<VM>> RunningVMs(Host host)

View File

@ -39,6 +39,8 @@ using XenAdmin.Diagnostics.Hotfixing;
using XenAdmin.Wizards.PatchingWizard;
using XenAPI;
using System.Linq;
using CheckGroup = System.Collections.Generic.KeyValuePair<string, System.Collections.Generic.List<XenAdmin.Diagnostics.Checks.Check>>;
namespace XenAdmin.Wizards.RollingUpgradeWizard
{
@ -138,16 +140,16 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
get { return "Upgradeprechecks"; }
}
protected override Dictionary<string, List<Check>> GenerateChecks(Pool_patch patch)
protected override List<CheckGroup> GenerateChecks(Pool_patch patch)
{
var groups = new Dictionary<string, List<Check>>();
var groups = new List<CheckGroup>();
//XenCenter version check (if any of the selected server version is not the latest)
var latestCrVersion = Updates.XenServerVersions.FindAll(item => item.LatestCr).OrderByDescending(v => v.Version).FirstOrDefault();
if (latestCrVersion != null &&
SelectedServers.Any(host => new Version(Helpers.HostProductVersion(host)) < latestCrVersion.Version))
{
groups[Messages.CHECKING_XENCENTER_VERSION] = new List<Check> {new XenCenterVersionCheck(null)};
groups.Add(new CheckGroup(Messages.CHECKING_XENCENTER_VERSION, new List<Check> {new XenCenterVersionCheck(null)}));
}
//HostMaintenanceModeCheck checks
@ -155,7 +157,7 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
foreach (Host host in SelectedServers)
livenessChecks.Add(new HostMaintenanceModeCheck(host));
groups[Messages.CHECKING_HOST_LIVENESS_STATUS] = livenessChecks;
groups.Add(new CheckGroup(Messages.CHECKING_HOST_LIVENESS_STATUS, livenessChecks));
//HA checks
var haChecks = new List<Check>();
@ -168,20 +170,20 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
haChecks.Add(new HAOffCheck(host));
}
groups[Messages.CHECKING_HA_STATUS] = haChecks;
groups.Add(new CheckGroup(Messages.CHECKING_HA_STATUS, haChecks));
//Checking can evacuate host
var evacuateChecks = new List<Check>();
foreach (Host host in SelectedServers)
evacuateChecks.Add(new AssertCanEvacuateUpgradeCheck(host));
groups[Messages.CHECKING_CANEVACUATE_STATUS] = evacuateChecks;
groups.Add(new CheckGroup(Messages.CHECKING_CANEVACUATE_STATUS, evacuateChecks));
//PBDsPluggedCheck
var pbdChecks = new List<Check>();
foreach (Host host in SelectedServers)
pbdChecks.Add(new PBDsPluggedCheck(host));
groups[Messages.CHECKING_STORAGE_CONNECTIONS_STATUS] = pbdChecks;
groups.Add(new CheckGroup(Messages.CHECKING_STORAGE_CONNECTIONS_STATUS, pbdChecks));
//HotfixesCheck required for MNR, Cowley, Boston and Sanibel
@ -192,7 +194,7 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
hotfixChecks.Add(new HostHasHotfixCheck(host));
}
if (hotfixChecks.Count > 0)
groups[Messages.CHECKING_UPGRADE_HOTFIX_STATUS] = hotfixChecks;
groups.Add(new CheckGroup(Messages.CHECKING_UPGRADE_HOTFIX_STATUS, hotfixChecks));
//iSL (StorageLink) check - CA-223486: only for pre-Creedence
@ -202,7 +204,7 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
var srLinkChecks = new List<Check>();
foreach (Host host in preCreedenceServers)
srLinkChecks.Add(new HostHasUnsupportedStorageLinkSRCheck(host));
groups[Messages.CHECKING_STORAGELINK_STATUS] = srLinkChecks;
groups.Add(new CheckGroup(Messages.CHECKING_STORAGELINK_STATUS, srLinkChecks));
}
//SafeToUpgradeCheck - in automatic mode only
@ -212,7 +214,7 @@ namespace XenAdmin.Wizards.RollingUpgradeWizard
foreach (Host host in SelectedServers)
upgradeChecks.Add(new SafeToUpgradeCheck(host));
groups[Messages.CHECKING_SAFE_TO_UPGRADE] = upgradeChecks;
groups.Add(new CheckGroup(Messages.CHECKING_SAFE_TO_UPGRADE, upgradeChecks));
}
return groups;

View File

@ -964,9 +964,10 @@
</Compile>
<Compile Include="Wizards\PatchingWizard\PlanActions\ApplyPoolUpdatePlanAction.cs" />
<Compile Include="Wizards\PatchingWizard\PlanActions\ApplyXenServerPatchPlanAction.cs" />
<Compile Include="Wizards\PatchingWizard\PlanActions\IAvoidRestartCapable.cs" />
<Compile Include="Wizards\PatchingWizard\PlanActions\HostPlanAction.cs" />
<Compile Include="Wizards\PatchingWizard\PlanActions\PatchPrechecksOnMultipleHostsAction.cs" />
<Compile Include="Wizards\PatchingWizard\PlanActions\DownloadPatchPlanAction.cs" />
<Compile Include="Wizards\PatchingWizard\PlanActions\RestartHostPlanAction.cs" />
<Compile Include="Wizards\PatchingWizard\PlanActions\UploadPatchToMasterPlanAction.cs" />
<Compile Include="Wizards\PatchingWizard\PlanActions\PoolPatchMapping.cs" />
<Compile Include="Wizards\PatchingWizard\PlanActions\RemoveUpdateFilesFromMaster.cs" />

View File

@ -31,9 +31,9 @@
using System;
using XenAPI;
using XenAdmin.Core;
using System.Collections.Generic;
namespace XenAdmin.Network
{
public interface IXenConnection : IComparable<IXenConnection>, IDisposable
@ -74,6 +74,7 @@ namespace XenAdmin.Network
bool IsConnected { get; }
string Name { get; }
Session ElevatedSession(string username, string password);
T TryResolveWithTimeout<T>(XenRef<T> t) where T : XenObject<T>;
T Resolve<T>(XenRef<T> xenRef) where T : XenObject<T>;
List<T> ResolveAll<T>(IEnumerable<XenRef<T>> xenRefs) where T : XenObject<T>;
List<VDI> ResolveAllShownXenModelObjects(List<XenRef<VDI>> xenRefs, bool showHiddenObjects);

View File

@ -1872,6 +1872,26 @@ namespace XenAdmin.Network
});
}
public T TryResolveWithTimeout<T>(XenRef<T> t) where T : XenObject<T>
{
log.DebugFormat("Resolving {0} {1}", t, t.opaque_ref);
int timeout = 120; // two minutes;
while (timeout > 0)
{
T obj = Resolve(t);
if (obj != null)
return obj;
Thread.Sleep(1000);
timeout = timeout - 1;
}
if (typeof(T) == typeof(Host))
throw new Failure(Failure.HOST_OFFLINE);
throw new Failure(Failure.HANDLE_INVALID, typeof(T).Name, t.opaque_ref);
}
/// <summary>
/// Stub to Cache.Resolve
/// </summary>

View File

@ -705,7 +705,7 @@ namespace XenAPI
return BoolKey(other_config, MAINTENANCE_MODE);
}
public const string BOOT_TIME = "boot_time";
private const string BOOT_TIME = "boot_time";
public double BootTime()
{
@ -724,6 +724,12 @@ namespace XenAPI
return bootTime;
}
public static double BootTime(Session session, string hostOpaqueRef)
{
var host = get_record(session, hostOpaqueRef);
return host.BootTime();
}
public PrettyTimeSpan Uptime()
{
double bootTime = BootTime();
@ -732,7 +738,7 @@ namespace XenAPI
return new PrettyTimeSpan(DateTime.UtcNow - Util.FromUnixTime(bootTime) - Connection.ServerTimeOffset);
}
public const string AGENT_START_TIME = "agent_start_time";
private const string AGENT_START_TIME = "agent_start_time";
public double AgentStartTime()
{
@ -750,6 +756,12 @@ namespace XenAPI
return agentStartTime;
}
public static double AgentStartTime(Session session, string hostOpaqueRef)
{
var host = get_record(session, hostOpaqueRef);
return host.AgentStartTime();
}
public PrettyTimeSpan AgentUptime()
{
double startTime = AgentStartTime();
@ -776,6 +788,37 @@ namespace XenAPI
return resident_VMs != null && resident_VMs.Count >= 2;
}
public List<XenRef<VM>> GetRunningPvVMs()
{
var vms = from XenRef<VM> vmref in resident_VMs
let vm = Connection.Resolve(vmref)
where vm != null && vm.is_a_real_vm() && !vm.IsHVM()
select vmref;
return vms.ToList();
}
public List<XenRef<VM>> GetRunningHvmVMs()
{
var vms = from XenRef<VM> vmref in resident_VMs
let vm = Connection.Resolve(vmref)
where vm != null && vm.is_a_real_vm() && vm.IsHVM()
select vmref;
return vms.ToList();
}
public List<XenRef<VM>> GetRunningVMs()
{
var vms = from XenRef<VM> vmref in resident_VMs
let vm = Connection.Resolve(vmref)
where vm != null && vm.is_a_real_vm()
select vmref;
return vms.ToList();
}
#region Save Evacuated VMs for later
public const String MAINTENANCE_MODE_EVACUATED_VMS_MIGRATED = "MAINTENANCE_MODE_EVACUATED_VMS_MIGRATED";
@ -887,10 +930,15 @@ namespace XenAPI
public void ClearEvacuatedVMs(Session session)
{
XenRef<Host> serverOpaqueRef1 = get_by_uuid(session, uuid);
remove_from_other_config(session, serverOpaqueRef1, MAINTENANCE_MODE_EVACUATED_VMS_MIGRATED);
remove_from_other_config(session, serverOpaqueRef1, MAINTENANCE_MODE_EVACUATED_VMS_HALTED);
remove_from_other_config(session, serverOpaqueRef1, MAINTENANCE_MODE_EVACUATED_VMS_SUSPENDED);
var hostRef = get_by_uuid(session, uuid);
ClearEvacuatedVMs(session, hostRef);
}
public static void ClearEvacuatedVMs(Session session, XenRef<Host> hostRef)
{
remove_from_other_config(session, hostRef, MAINTENANCE_MODE_EVACUATED_VMS_MIGRATED);
remove_from_other_config(session, hostRef, MAINTENANCE_MODE_EVACUATED_VMS_HALTED);
remove_from_other_config(session, hostRef, MAINTENANCE_MODE_EVACUATED_VMS_SUSPENDED);
}
public List<VM> GetMigratedEvacuatedVMs()