mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2025-01-20 07:19:18 +01:00
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:
commit
0184470ea3
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
164
XenAdmin/Wizards/PatchingWizard/PlanActions/HostPlanAction.cs
Normal file
164
XenAdmin/Wizards/PatchingWizard/PlanActions/HostPlanAction.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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" />
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user