mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-11-25 06:16:37 +01:00
Merge pull request #974 from GaborApatiNagy/master_batchupdate_new
REQ-156: Further Batch Update commits
This commit is contained in:
commit
318d28d4c1
@ -39,7 +39,6 @@ using XenAdmin.Alerts;
|
||||
using XenAdmin.Network;
|
||||
using System.Diagnostics;
|
||||
|
||||
|
||||
namespace XenAdmin.Core
|
||||
{
|
||||
public class Updates
|
||||
@ -407,9 +406,9 @@ namespace XenAdmin.Core
|
||||
return alerts;
|
||||
}
|
||||
|
||||
public static UpgradeSequences GetUpgradeSequence(IXenConnection conn)
|
||||
public static UpgradeSequence GetUpgradeSequence(IXenConnection conn)
|
||||
{
|
||||
var uSeq = new UpgradeSequences();
|
||||
var uSeq = new UpgradeSequence();
|
||||
|
||||
Host master = Helpers.GetMaster(conn);
|
||||
List<Host> hosts = conn.Cache.Hosts.ToList();
|
||||
@ -457,8 +456,10 @@ namespace XenAdmin.Core
|
||||
var p = neededPatches[ii];
|
||||
|
||||
//checking requirements
|
||||
if (// no requirements
|
||||
p.RequiredPatches == null
|
||||
if (//not applied yet
|
||||
!appliedPatches.Any(ap => string.Equals(ap.uuid, p.Uuid, StringComparison.OrdinalIgnoreCase))
|
||||
// and either no requirements or they are meet
|
||||
&& (p.RequiredPatches == null
|
||||
|| p.RequiredPatches.Count == 0
|
||||
// all requirements met?
|
||||
|| p.RequiredPatches.All(
|
||||
@ -469,7 +470,7 @@ namespace XenAdmin.Core
|
||||
//the required-patch has already been applied
|
||||
|| (appliedPatches.Count != 0 && appliedPatches.Any(ap => string.Equals(ap.uuid, rp, StringComparison.OrdinalIgnoreCase)))
|
||||
)
|
||||
)
|
||||
))
|
||||
{
|
||||
// this patch can be added to the upgrade sequence now
|
||||
sequence.Add(p);
|
||||
@ -485,8 +486,26 @@ namespace XenAdmin.Core
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public class UpgradeSequences : Dictionary<Host, List<XenServerPatch>>
|
||||
public class UpgradeSequence : Dictionary<Host, List<XenServerPatch>>
|
||||
{
|
||||
private IEnumerable<XenServerPatch> AllPatches
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var patches in this.Values)
|
||||
foreach(var patch in patches)
|
||||
yield return patch;
|
||||
}
|
||||
}
|
||||
|
||||
public List<XenServerPatch> UniquePatches
|
||||
{
|
||||
get
|
||||
{
|
||||
return AllPatches.Distinct().ToList();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static XenServerVersionAlert NewXenServerVersionAlert(List<XenServerVersion> xenServerVersions)
|
||||
|
@ -165,6 +165,8 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
|
||||
PatchingWizard_UploadPage.SelectedMasters = PatchingWizard_SelectServers.SelectedMasters;
|
||||
PatchingWizard_UploadPage.SelectedServers = selectedServers;
|
||||
|
||||
PatchingWizard_AutoUpdatingPage.SelectedMasters = PatchingWizard_SelectServers.SelectedMasters;
|
||||
}
|
||||
else if (prevPageType == typeof(PatchingWizard_UploadPage))
|
||||
{
|
||||
@ -193,6 +195,7 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
else if (prevPageType == typeof(PatchingWizard_PrecheckPage))
|
||||
{
|
||||
PatchingWizard_PatchingPage.ProblemsResolvedPreCheck = PatchingWizard_PrecheckPage.ProblemsResolvedPreCheck;
|
||||
PatchingWizard_AutoUpdatingPage.ProblemsResolvedPreCheck = PatchingWizard_PrecheckPage.ProblemsResolvedPreCheck;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,9 @@ using XenAdmin.Dialogs;
|
||||
using XenAdmin.Wizards.PatchingWizard.PlanActions;
|
||||
using XenAPI;
|
||||
using XenAdmin.Actions;
|
||||
using System.Linq;
|
||||
using XenAdmin.Core;
|
||||
using XenAdmin.Network;
|
||||
|
||||
namespace XenAdmin.Wizards.PatchingWizard
|
||||
{
|
||||
@ -50,6 +53,17 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
{
|
||||
protected static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public XenAdmin.Core.Updates.UpgradeSequence UpgradeSequences { get; set; }
|
||||
private BackgroundWorker actionsWorker = null;
|
||||
private bool _thisPageHasBeenCompleted = false;
|
||||
|
||||
public List<Problem> ProblemsResolvedPreCheck { private get; set; }
|
||||
|
||||
public List<Host> SelectedMasters { private get; set; }
|
||||
|
||||
private List<PoolPatchMapping> patchMappings = new List<PoolPatchMapping>();
|
||||
private Dictionary<XenServerPatch, string> AllDownloadedPatches = new Dictionary<XenServerPatch, string>();
|
||||
|
||||
public PatchingWizard_AutoUpdatingPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
@ -96,7 +110,320 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
public override void PageLoaded(PageLoadedDirection direction)
|
||||
{
|
||||
base.PageLoaded(direction);
|
||||
|
||||
if (_thisPageHasBeenCompleted)
|
||||
{
|
||||
actionsWorker = null;
|
||||
return;
|
||||
}
|
||||
|
||||
Dictionary<Host, List<PlanAction>> planActionsPerPool = new Dictionary<Host, List<PlanAction>>();
|
||||
|
||||
foreach (var master in SelectedMasters)
|
||||
{
|
||||
Dictionary<Host, List<PlanAction>> planActionsByHost = new Dictionary<Host, List<PlanAction>>();
|
||||
Dictionary<Host, List<PlanAction>> delayedActionsByHost = new Dictionary<Host, List<PlanAction>>();
|
||||
|
||||
foreach (var host in master.Connection.Cache.Hosts)
|
||||
{
|
||||
planActionsByHost.Add(host, new List<PlanAction>());
|
||||
delayedActionsByHost.Add(host, new List<PlanAction>());
|
||||
}
|
||||
|
||||
//var master = Helpers.GetMaster(pool.Connection);
|
||||
var hosts = master.Connection.Cache.Hosts;
|
||||
|
||||
var us = Updates.GetUpgradeSequence(master.Connection);
|
||||
|
||||
foreach (var patch in us.UniquePatches)
|
||||
{
|
||||
var hostsToApply = us.Where(u => u.Value.Contains(patch)).Select(u => u.Key).ToList();
|
||||
|
||||
planActionsByHost[master].Add(new DownloadPatchPlanAction(master.Connection, patch, patchMappings, AllDownloadedPatches));
|
||||
planActionsByHost[master].Add(new UploadPatchToMasterPlanAction(master.Connection, patch, patchMappings, AllDownloadedPatches));
|
||||
planActionsByHost[master].Add(new PatchPrechecksOnMultipleHostsPlanAction(master.Connection, patch, hostsToApply, patchMappings));
|
||||
|
||||
if (hostsToApply.Contains(master))
|
||||
{
|
||||
planActionsByHost[master].Add(new ApplyXenServerPatchPlanAction(master, patch, patchMappings));
|
||||
planActionsByHost[master].AddRange(GetMandatoryActionListForPatch(delayedActionsByHost[master], master, patch));
|
||||
UpdateDelayedAfterPatchGuidanceActionListForHost(delayedActionsByHost[master], master, patch);
|
||||
}
|
||||
|
||||
foreach (var host in hostsToApply)
|
||||
{
|
||||
if (host != master)
|
||||
planActionsByHost[host].Add(new ApplyXenServerPatchPlanAction(host, patch, patchMappings));
|
||||
planActionsByHost[host].AddRange(GetMandatoryActionListForPatch(delayedActionsByHost[host], host, patch));
|
||||
UpdateDelayedAfterPatchGuidanceActionListForHost(delayedActionsByHost[host], host, patch);
|
||||
}
|
||||
|
||||
// now add all non-delayed actions to the pool action list
|
||||
|
||||
foreach (var kvp in planActionsByHost)
|
||||
{
|
||||
if (!planActionsPerPool.ContainsKey(master))
|
||||
{
|
||||
planActionsPerPool.Add(master, new List<PlanAction>());
|
||||
}
|
||||
|
||||
planActionsPerPool[master].AddRange(kvp.Value);
|
||||
kvp.Value.Clear();
|
||||
}
|
||||
|
||||
//clean up master at the end:
|
||||
planActionsPerPool[master].Add(new RemoveUpdateFileFromMasterPlanAction(master, patchMappings, patch));
|
||||
|
||||
}//patch
|
||||
|
||||
//add all delayed actions to the end of the actions, per host
|
||||
foreach (var kvp in delayedActionsByHost)
|
||||
{
|
||||
planActionsPerPool[master].AddRange(kvp.Value);
|
||||
}
|
||||
|
||||
} //foreach in SelectedMasters
|
||||
|
||||
|
||||
var planActions = new List<PlanAction>();
|
||||
|
||||
//actions list for serial execution
|
||||
foreach (var actionListPerPool in planActionsPerPool)
|
||||
{
|
||||
planActions.AddRange(actionListPerPool.Value);
|
||||
}
|
||||
|
||||
planActions.Add(new UnwindProblemsAction(ProblemsResolvedPreCheck));
|
||||
|
||||
actionsWorker = new BackgroundWorker();
|
||||
actionsWorker.DoWork += new DoWorkEventHandler(PatchingWizardAutomaticPatchWork);
|
||||
actionsWorker.WorkerReportsProgress = true;
|
||||
actionsWorker.ProgressChanged += new ProgressChangedEventHandler(actionsWorker_ProgressChanged);
|
||||
actionsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(actionsWorker_RunWorkerCompleted);
|
||||
actionsWorker.WorkerSupportsCancellation = true;
|
||||
actionsWorker.RunWorkerAsync(planActions);
|
||||
}
|
||||
|
||||
#region automatic_mode
|
||||
|
||||
private void actionsWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
|
||||
{
|
||||
if (!actionsWorker.CancellationPending)
|
||||
{
|
||||
PlanAction action = (PlanAction)e.UserState;
|
||||
if (e.ProgressPercentage == 0)
|
||||
textBoxLog.Text += action;
|
||||
else
|
||||
{
|
||||
textBoxLog.Text += string.Format("{0}\r\n", Messages.DONE);
|
||||
progressBar.Value += e.ProgressPercentage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void PatchingWizardAutomaticPatchWork(object obj, DoWorkEventArgs doWorkEventArgs)
|
||||
{
|
||||
List<PlanAction> actionList = (List<PlanAction>)doWorkEventArgs.Argument;
|
||||
foreach (PlanAction action in actionList)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (actionsWorker.CancellationPending)
|
||||
{
|
||||
doWorkEventArgs.Cancel = true;
|
||||
return;
|
||||
}
|
||||
this.actionsWorker.ReportProgress(0, action);
|
||||
action.Run();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
this.actionsWorker.ReportProgress((int)((1.0 / (double)actionList.Count) * 100), action);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
log.Error("Failed to carry out plan.", e);
|
||||
log.Debug(actionList);
|
||||
doWorkEventArgs.Result = new Exception(action.Title, e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void actionsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
if (!e.Cancelled)
|
||||
{
|
||||
Exception exception = e.Result as Exception;
|
||||
if (exception != null)
|
||||
{
|
||||
FinishedWithErrors(exception);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
FinishedSuccessfully();
|
||||
}
|
||||
|
||||
progressBar.Value = 100;
|
||||
_cancelEnabled = false;
|
||||
_nextEnabled = true;
|
||||
}
|
||||
OnPageUpdated();
|
||||
|
||||
_thisPageHasBeenCompleted = true;
|
||||
}
|
||||
|
||||
private void UpdateDelayedAfterPatchGuidanceActionListForHost(List<PlanAction> delayedGuidances, Host host, XenServerPatch patch)
|
||||
{
|
||||
List<PlanAction> actions = GetAfterApplyGuidanceActionsForPatch(host, patch);
|
||||
|
||||
if (!patch.GuidanceMandatory)
|
||||
{
|
||||
//not mandatory, so these actions will have to be run later
|
||||
//add the ones that are not yet there
|
||||
foreach (var ap in actions)
|
||||
if (!delayedGuidances.Any(da => da.GetType() == ap.GetType()))
|
||||
{
|
||||
//special rules
|
||||
//do not add restartXAPI if there is already a restartHost on the list
|
||||
if (delayedGuidances.Any(da => da is RebootHostPlanAction) && ap is RestartAgentPlanAction)
|
||||
continue;
|
||||
|
||||
delayedGuidances.Add(ap);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//remove delayed action of the same kind for this host (because it is mandatory and will run immediately)
|
||||
foreach (var mg in delayedGuidances)
|
||||
delayedGuidances.RemoveAll(a => a.GetType() == mg.GetType());
|
||||
|
||||
//if it is a restart, clean delayed list
|
||||
if (patch.after_apply_guidance == after_apply_guidance.restartHost)
|
||||
delayedGuidances.Clear();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static List<PlanAction> GetAfterApplyGuidanceActionsForPatch(Host host, XenServerPatch patch)
|
||||
{
|
||||
List<PlanAction> actions = new List<PlanAction>();
|
||||
|
||||
List<XenRef<VM>> runningVMs = RunningVMs(host);
|
||||
|
||||
if (patch.after_apply_guidance == after_apply_guidance.restartHost)
|
||||
{
|
||||
actions.Add(new EvacuateHostPlanAction(host));
|
||||
actions.Add(new RebootHostPlanAction(host));
|
||||
actions.Add(new BringBabiesBackAction(runningVMs, host, false));
|
||||
}
|
||||
|
||||
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 List<PlanAction> GetMandatoryActionListForPatch(List<PlanAction> delayedGuidances, Host host, XenServerPatch patch)
|
||||
{
|
||||
var actions = new List<PlanAction>();
|
||||
|
||||
if (!patch.GuidanceMandatory)
|
||||
return actions;
|
||||
|
||||
actions = GetAfterApplyGuidanceActionsForPatch(host, patch);
|
||||
|
||||
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 FinishedWithErrors(Exception exception)
|
||||
{
|
||||
//labelTitle.Text = string.Format(Messages.UPDATE_WAS_NOT_COMPLETED, GetUpdateName());
|
||||
|
||||
string errorMessage = null;
|
||||
|
||||
if (exception != null && exception.InnerException != null && exception.InnerException is Failure)
|
||||
{
|
||||
var innerEx = exception.InnerException as Failure;
|
||||
errorMessage = innerEx.Message;
|
||||
|
||||
if (innerEx.ErrorDescription != null && innerEx.ErrorDescription.Count > 0)
|
||||
log.Error(string.Concat(innerEx.ErrorDescription.ToArray()));
|
||||
}
|
||||
|
||||
labelError.Text = errorMessage ?? string.Format(Messages.PATCHING_WIZARD_ERROR, exception.Message);
|
||||
|
||||
log.ErrorFormat("Error message displayed: {0}", labelError.Text);
|
||||
|
||||
pictureBox1.Image = SystemIcons.Error.ToBitmap();
|
||||
if (exception.InnerException is SupplementalPackInstallFailedException)
|
||||
{
|
||||
errorLinkLabel.Visible = true;
|
||||
errorLinkLabel.Tag = exception.InnerException;
|
||||
}
|
||||
panel1.Visible = true;
|
||||
}
|
||||
|
||||
private void FinishedSuccessfully()
|
||||
{
|
||||
labelTitle.Text = Messages.PATCHINGWIZARD_UPDATES_DONE_AUTOMATIC_MODE;
|
||||
pictureBox1.Image = null;
|
||||
labelError.Text = Messages.CLOSE_WIZARD_CLICK_FINISH;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,9 +41,6 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
this.panel3 = new System.Windows.Forms.Panel();
|
||||
this.pictureBox4 = new System.Windows.Forms.PictureBox();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
this.labelDownloadUpdate = new System.Windows.Forms.Label();
|
||||
this.pictureBox2 = new System.Windows.Forms.PictureBox();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.panel4.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox5)).BeginInit();
|
||||
@ -51,8 +48,6 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).BeginInit();
|
||||
this.panel3.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox4)).BeginInit();
|
||||
this.panel1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// label1
|
||||
@ -71,7 +66,6 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
this.tableLayoutPanel1.Controls.Add(this.panel4, 0, 5);
|
||||
this.tableLayoutPanel1.Controls.Add(this.panel2, 0, 3);
|
||||
this.tableLayoutPanel1.Controls.Add(this.panel3, 0, 4);
|
||||
this.tableLayoutPanel1.Controls.Add(this.panel1, 0, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label2, 0, 1);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
@ -133,25 +127,6 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
resources.ApplyResources(this.label4, "label4");
|
||||
this.label4.Name = "label4";
|
||||
//
|
||||
// panel1
|
||||
//
|
||||
this.panel1.Controls.Add(this.labelDownloadUpdate);
|
||||
this.panel1.Controls.Add(this.pictureBox2);
|
||||
resources.ApplyResources(this.panel1, "panel1");
|
||||
this.panel1.Name = "panel1";
|
||||
//
|
||||
// labelDownloadUpdate
|
||||
//
|
||||
resources.ApplyResources(this.labelDownloadUpdate, "labelDownloadUpdate");
|
||||
this.labelDownloadUpdate.Name = "labelDownloadUpdate";
|
||||
//
|
||||
// pictureBox2
|
||||
//
|
||||
this.pictureBox2.Image = global::XenAdmin.Properties.Resources.homepage_bullet;
|
||||
resources.ApplyResources(this.pictureBox2, "pictureBox2");
|
||||
this.pictureBox2.Name = "pictureBox2";
|
||||
this.pictureBox2.TabStop = false;
|
||||
//
|
||||
// PatchingWizard_FirstPage
|
||||
//
|
||||
resources.ApplyResources(this, "$this");
|
||||
@ -166,8 +141,6 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).EndInit();
|
||||
this.panel3.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox4)).EndInit();
|
||||
this.panel1.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
@ -178,8 +151,6 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.Panel panel1;
|
||||
private System.Windows.Forms.PictureBox pictureBox2;
|
||||
private System.Windows.Forms.Panel panel4;
|
||||
private System.Windows.Forms.PictureBox pictureBox5;
|
||||
private System.Windows.Forms.Label label9;
|
||||
@ -189,7 +160,6 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
private System.Windows.Forms.Panel panel3;
|
||||
private System.Windows.Forms.PictureBox pictureBox4;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.Label labelDownloadUpdate;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +126,7 @@
|
||||
<value>3, 0</value>
|
||||
</data>
|
||||
<data name="label1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>363, 13</value>
|
||||
<value>369, 13</value>
|
||||
</data>
|
||||
<data name="label1.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>1</value>
|
||||
@ -145,7 +145,7 @@
|
||||
<value>tableLayoutPanel1</value>
|
||||
</data>
|
||||
<data name=">>label1.ZOrder" xml:space="preserve">
|
||||
<value>4</value>
|
||||
<value>3</value>
|
||||
</data>
|
||||
<data name="label2.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
@ -172,7 +172,7 @@
|
||||
<value>tableLayoutPanel1</value>
|
||||
</data>
|
||||
<data name=">>label2.ZOrder" xml:space="preserve">
|
||||
<value>5</value>
|
||||
<value>4</value>
|
||||
</data>
|
||||
<data name="tableLayoutPanel1.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
@ -245,7 +245,7 @@
|
||||
<value>Fill</value>
|
||||
</data>
|
||||
<data name="panel4.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>3, 183</value>
|
||||
<value>3, 143</value>
|
||||
</data>
|
||||
<data name="panel4.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>594, 34</value>
|
||||
@ -329,7 +329,7 @@
|
||||
<value>Fill</value>
|
||||
</data>
|
||||
<data name="panel2.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>3, 103</value>
|
||||
<value>3, 63</value>
|
||||
</data>
|
||||
<data name="panel2.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>594, 34</value>
|
||||
@ -413,7 +413,7 @@
|
||||
<value>Fill</value>
|
||||
</data>
|
||||
<data name="panel3.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>3, 143</value>
|
||||
<value>3, 103</value>
|
||||
</data>
|
||||
<data name="panel3.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>594, 34</value>
|
||||
@ -433,90 +433,6 @@
|
||||
<data name=">>panel3.ZOrder" xml:space="preserve">
|
||||
<value>2</value>
|
||||
</data>
|
||||
<data name="labelDownloadUpdate.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Left, Right</value>
|
||||
</data>
|
||||
<data name="labelDownloadUpdate.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>17, 0</value>
|
||||
</data>
|
||||
<data name="labelDownloadUpdate.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>20, 0, 3, 0</value>
|
||||
</data>
|
||||
<data name="labelDownloadUpdate.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>3, 0, 3, 0</value>
|
||||
</data>
|
||||
<data name="labelDownloadUpdate.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>577, 34</value>
|
||||
</data>
|
||||
<data name="labelDownloadUpdate.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>3</value>
|
||||
</data>
|
||||
<data name="labelDownloadUpdate.Text" xml:space="preserve">
|
||||
<value>Download the relevant update and ensure that you can access the update file from your computer.</value>
|
||||
</data>
|
||||
<data name="labelDownloadUpdate.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
|
||||
<value>MiddleLeft</value>
|
||||
</data>
|
||||
<data name=">>labelDownloadUpdate.Name" xml:space="preserve">
|
||||
<value>labelDownloadUpdate</value>
|
||||
</data>
|
||||
<data name=">>labelDownloadUpdate.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>labelDownloadUpdate.Parent" xml:space="preserve">
|
||||
<value>panel1</value>
|
||||
</data>
|
||||
<data name=">>labelDownloadUpdate.ZOrder" xml:space="preserve">
|
||||
<value>0</value>
|
||||
</data>
|
||||
<data name="pictureBox2.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>3, 15</value>
|
||||
</data>
|
||||
<data name="pictureBox2.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>0, 0, 0, 0</value>
|
||||
</data>
|
||||
<data name="pictureBox2.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>4, 4</value>
|
||||
</data>
|
||||
<data name="pictureBox2.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>6</value>
|
||||
</data>
|
||||
<data name=">>pictureBox2.Name" xml:space="preserve">
|
||||
<value>pictureBox2</value>
|
||||
</data>
|
||||
<data name=">>pictureBox2.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>pictureBox2.Parent" xml:space="preserve">
|
||||
<value>panel1</value>
|
||||
</data>
|
||||
<data name=">>pictureBox2.ZOrder" xml:space="preserve">
|
||||
<value>1</value>
|
||||
</data>
|
||||
<data name="panel1.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
|
||||
<value>Fill</value>
|
||||
</data>
|
||||
<data name="panel1.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>3, 63</value>
|
||||
</data>
|
||||
<data name="panel1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>594, 34</value>
|
||||
</data>
|
||||
<data name="panel1.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>7</value>
|
||||
</data>
|
||||
<data name=">>panel1.Name" xml:space="preserve">
|
||||
<value>panel1</value>
|
||||
</data>
|
||||
<data name=">>panel1.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>panel1.Parent" xml:space="preserve">
|
||||
<value>tableLayoutPanel1</value>
|
||||
</data>
|
||||
<data name=">>panel1.ZOrder" xml:space="preserve">
|
||||
<value>3</value>
|
||||
</data>
|
||||
<data name="tableLayoutPanel1.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
|
||||
<value>Top</value>
|
||||
</data>
|
||||
@ -527,7 +443,7 @@
|
||||
<value>6</value>
|
||||
</data>
|
||||
<data name="tableLayoutPanel1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>600, 220</value>
|
||||
<value>600, 180</value>
|
||||
</data>
|
||||
<data name="tableLayoutPanel1.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>3</value>
|
||||
@ -545,7 +461,7 @@
|
||||
<value>0</value>
|
||||
</data>
|
||||
<data name="tableLayoutPanel1.LayoutSettings" type="System.Windows.Forms.TableLayoutSettings, System.Windows.Forms">
|
||||
<value><?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="panel4" Row="5" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="panel2" Row="3" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="panel3" Row="4" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="panel1" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="label1" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="label2" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Percent,100" /><Rows Styles="Absolute,30,Absolute,30,Absolute,40,Absolute,40,Absolute,40,Absolute,40" /></TableLayoutSettings></value>
|
||||
<value><?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="panel4" Row="5" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="panel2" Row="3" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="panel3" Row="4" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="label1" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="label2" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Percent,100" /><Rows Styles="Absolute,30,Absolute,30,AutoSize,40,Absolute,40,Absolute,40,Absolute,40" /></TableLayoutSettings></value>
|
||||
</data>
|
||||
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
@ -562,4 +478,4 @@
|
||||
<data name=">>$this.Type" xml:space="preserve">
|
||||
<value>XenAdmin.Controls.XenTabPage, XenCenterMain, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
</root>
|
||||
</root>
|
@ -44,6 +44,7 @@ using System.IO;
|
||||
using XenAdmin.Dialogs;
|
||||
using System.Drawing;
|
||||
using XenAdmin.Alerts;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
namespace XenAdmin.Wizards.PatchingWizard
|
||||
@ -288,6 +289,11 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
private void UpdateEnablement()
|
||||
{
|
||||
dataGridViewPatches.HideSelection = !downloadUpdateRadioButton.Checked;
|
||||
|
||||
//if any connected host is licensed for automatic updating
|
||||
if (ConnectionsManager.XenConnectionsCopy.Any(c => c != null && c.Cache.Hosts.Any(h => !Host.RestrictBatchHotfixApply(h))))
|
||||
automaticOptionLabel.Visible = AutomaticRadioButton.Visible = true;
|
||||
|
||||
OnPageUpdated();
|
||||
}
|
||||
|
||||
|
@ -147,6 +147,9 @@
|
||||
<data name="automaticOptionLabel.Text" xml:space="preserve">
|
||||
<value>[XenCenter] will &automatically download and install all current updates from [Citrix], usually with only a single reboot at the end.</value>
|
||||
</data>
|
||||
<data name="automaticOptionLabel.Visible" type="System.Boolean, mscorlib">
|
||||
<value>False</value>
|
||||
</data>
|
||||
<data name=">>automaticOptionLabel.Name" xml:space="preserve">
|
||||
<value>automaticOptionLabel</value>
|
||||
</data>
|
||||
@ -186,6 +189,9 @@
|
||||
<data name="AutomaticRadioButton.Text" xml:space="preserve">
|
||||
<value>Automatic</value>
|
||||
</data>
|
||||
<data name="AutomaticRadioButton.Visible" type="System.Boolean, mscorlib">
|
||||
<value>False</value>
|
||||
</data>
|
||||
<data name=">>AutomaticRadioButton.Name" xml:space="preserve">
|
||||
<value>AutomaticRadioButton</value>
|
||||
</data>
|
||||
@ -457,7 +463,7 @@
|
||||
<value>80</value>
|
||||
</data>
|
||||
<data name="ColumnDate.Width" type="System.Int32, mscorlib">
|
||||
<value>55</value>
|
||||
<value>80</value>
|
||||
</data>
|
||||
<metadata name="webPageColumn.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
|
@ -118,7 +118,7 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
{
|
||||
int index = dataGridViewHosts.Rows.Add(new PatchingHostsDataGridViewRow(host, hasPool));
|
||||
EnabledRow(host, SelectedUpdateType, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// restore server selection
|
||||
@ -139,6 +139,16 @@ namespace XenAdmin.Wizards.PatchingWizard
|
||||
|
||||
if (IsInAutomaticMode)
|
||||
{
|
||||
//unlicensed servers are not enabled
|
||||
if (Host.RestrictBatchHotfixApply(host))
|
||||
{
|
||||
row.Enabled = false;
|
||||
row.Cells[3].ToolTipText = Messages.PATCHINGWIZARD_SELECTSERVERPAGE_HOST_UNLICENSED_FOR_BATCH_UPDATING;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//check updgrade sequences
|
||||
var us = Updates.GetUpgradeSequence(host.Connection);
|
||||
|
||||
if (us.ContainsKey(host))
|
||||
|
@ -0,0 +1,67 @@
|
||||
/* 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.Collections.Generic;
|
||||
using XenAdmin.Core;
|
||||
using XenAPI;
|
||||
|
||||
|
||||
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
|
||||
{
|
||||
public class ApplyXenServerPatchPlanAction : PlanActionWithSession
|
||||
{
|
||||
private readonly XenRef<Host> host;
|
||||
private readonly XenServerPatch xenServerPatch;
|
||||
private readonly List<PoolPatchMapping> mappings;
|
||||
|
||||
public ApplyXenServerPatchPlanAction(Host host, XenServerPatch xenServerPatch, List<PoolPatchMapping> mappings)
|
||||
: base(host.Connection, string.Format(Messages.UPDATES_WIZARD_APPLYING_UPDATE, xenServerPatch.Name, host.Name))
|
||||
{
|
||||
this.host = new XenRef<Host>(host);
|
||||
this.xenServerPatch = xenServerPatch;
|
||||
this.mappings = mappings;
|
||||
}
|
||||
|
||||
protected override void RunWithSession(ref Session session)
|
||||
{
|
||||
|
||||
var mapping = mappings.Find(m => m.XenServerPatch.Uuid == xenServerPatch.Uuid);
|
||||
if (mapping != null && mapping.Pool_patch != null)
|
||||
{
|
||||
var patchRef = mapping.Pool_patch;
|
||||
|
||||
XenRef<Task> task = Pool_patch.async_apply(session, patchRef.opaque_ref, host.opaque_ref);
|
||||
|
||||
PollTaskForResultAndDestroy(Connection, ref session, task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/* 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.Actions;
|
||||
using XenAdmin.Core;
|
||||
using XenAPI;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using XenAdmin.Network;
|
||||
|
||||
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
|
||||
{
|
||||
class DownloadPatchPlanAction : PlanActionWithSession
|
||||
{
|
||||
private readonly XenServerPatch patch;
|
||||
private readonly List<PoolPatchMapping> mappings;
|
||||
private Dictionary<XenServerPatch, string> AllDownloadedPatches = new Dictionary<XenServerPatch, string>();
|
||||
private string tempFileName = null;
|
||||
|
||||
public DownloadPatchPlanAction(IXenConnection connection, XenServerPatch patch, List<PoolPatchMapping> mappings, Dictionary<XenServerPatch, string> allDownloadedPatches)
|
||||
: base(connection, string.Format("Downloading update {0}...", patch.Name))
|
||||
{
|
||||
this.patch = patch;
|
||||
this.mappings = mappings;
|
||||
this.AllDownloadedPatches = allDownloadedPatches;
|
||||
}
|
||||
|
||||
protected override void RunWithSession(ref Session session)
|
||||
{
|
||||
lock (patch)
|
||||
{
|
||||
//if it has not been already downloaded
|
||||
if (!AllDownloadedPatches.Any(dp => dp.Key == patch && !string.IsNullOrEmpty(dp.Value))
|
||||
|| !File.Exists(AllDownloadedPatches[patch]))
|
||||
{
|
||||
DownloadFile(ref session);
|
||||
}
|
||||
else
|
||||
{
|
||||
//already downloaded
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void DownloadFile(ref Session session)
|
||||
{
|
||||
string patchUri = patch.PatchUrl;
|
||||
if (string.IsNullOrEmpty(patchUri))
|
||||
return;
|
||||
|
||||
Uri address = new Uri(patchUri);
|
||||
tempFileName = Path.GetTempFileName();
|
||||
|
||||
var downloadAction = new DownloadAndUnzipXenServerPatchAction(patch.Name, address, tempFileName, Branding.Update);
|
||||
|
||||
if (downloadAction != null)
|
||||
{
|
||||
downloadAction.Changed += downloadAndUnzipXenServerPatchAction_Changed;
|
||||
downloadAction.Completed += downloadAndUnzipXenServerPatchAction_Completed;
|
||||
}
|
||||
|
||||
downloadAction.RunExternal(session);
|
||||
}
|
||||
|
||||
private void downloadAndUnzipXenServerPatchAction_Changed(object sender)
|
||||
{
|
||||
var action = sender as AsyncAction;
|
||||
if (action == null)
|
||||
return;
|
||||
|
||||
Program.Invoke(Program.MainWindow, () =>
|
||||
{
|
||||
//UpdateActionProgress(action);
|
||||
//flickerFreeListBox1.Refresh();
|
||||
//OnPageUpdated();
|
||||
});
|
||||
}
|
||||
|
||||
private void downloadAndUnzipXenServerPatchAction_Completed(ActionBase sender)
|
||||
{
|
||||
var action = sender as AsyncAction;
|
||||
if (action == null)
|
||||
return;
|
||||
|
||||
action.Changed -= downloadAndUnzipXenServerPatchAction_Changed;
|
||||
action.Completed -= downloadAndUnzipXenServerPatchAction_Completed;
|
||||
|
||||
if (action.Succeeded)
|
||||
{
|
||||
if (action is DownloadAndUnzipXenServerPatchAction)
|
||||
{
|
||||
Host master = Helpers.GetMaster(action.Connection);
|
||||
|
||||
AllDownloadedPatches[patch] = (action as DownloadAndUnzipXenServerPatchAction).PatchPath;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/* 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.Actions;
|
||||
using XenAdmin.Core;
|
||||
using XenAPI;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using XenAdmin.Network;
|
||||
using XenAdmin.Diagnostics.Checks;
|
||||
|
||||
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
|
||||
{
|
||||
class PatchPrechecksOnMultipleHostsPlanAction : PlanActionWithSession
|
||||
{
|
||||
private readonly XenServerPatch patch;
|
||||
private readonly List<PoolPatchMapping> mappings;
|
||||
private List<Host> hosts = null;
|
||||
|
||||
public PatchPrechecksOnMultipleHostsPlanAction(IXenConnection connection, XenServerPatch patch, List<Host> hosts, List<PoolPatchMapping> mappings)
|
||||
: base(connection, string.Format("Checking free space for uploading and installing {0}...", patch.Name))
|
||||
{
|
||||
this.patch = patch;
|
||||
this.hosts = hosts;
|
||||
this.mappings = mappings;
|
||||
}
|
||||
|
||||
protected override void RunWithSession(ref Session session)
|
||||
{
|
||||
var mapping = mappings.Find(m => m.XenServerPatch == patch);
|
||||
if (mapping != null && mapping.Pool_patch != null)
|
||||
{
|
||||
|
||||
foreach (var host in hosts)
|
||||
{
|
||||
try
|
||||
{
|
||||
var check = new PatchPrecheckCheck(host, mapping.Pool_patch);
|
||||
var problem = check.RunCheck();
|
||||
|
||||
if (problem != null)
|
||||
{
|
||||
throw new Exception(problem.Title);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error(string.Format("Precheck failed on host {0}", host.Name), ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using XenAdmin.Core;
|
||||
using XenAPI;
|
||||
|
||||
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
|
||||
{
|
||||
public class PoolPatchMapping
|
||||
{
|
||||
public XenServerPatch XenServerPatch { get; set; }
|
||||
public Pool_patch Pool_patch { get; set; }
|
||||
public Host Host { get; set; }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is PoolPatchMapping))
|
||||
return false;
|
||||
|
||||
var that = obj as PoolPatchMapping;
|
||||
|
||||
return
|
||||
this.XenServerPatch == that.XenServerPatch
|
||||
&& this.Pool_patch == that.Pool_patch
|
||||
&& this.Host == that.Host;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return XenServerPatch.GetHashCode() ^ Pool_patch.GetHashCode() ^ Host.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/* 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.Collections.Generic;
|
||||
using XenAdmin.Core;
|
||||
using XenAPI;
|
||||
using System.Linq;
|
||||
|
||||
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
|
||||
{
|
||||
class RemoveUpdateFileFromMasterPlanAction : PlanActionWithSession
|
||||
{
|
||||
private readonly List<PoolPatchMapping> patchMappings = new List<PoolPatchMapping>();
|
||||
private readonly XenServerPatch patch = null;
|
||||
private readonly Host master = null;
|
||||
|
||||
public RemoveUpdateFileFromMasterPlanAction(Host master, List<PoolPatchMapping> patchMappings, XenServerPatch patch)
|
||||
: base(master.Connection, string.Format(Messages.UPDATES_WIZARD_REMOVING_UPDATES_FROM_POOL, master.Name))
|
||||
{
|
||||
this.patchMappings = patchMappings;
|
||||
this.patch = patch;
|
||||
this.master = master;
|
||||
}
|
||||
|
||||
protected override void RunWithSession(ref Session session)
|
||||
{
|
||||
var mapping = patchMappings.FirstOrDefault(pm => pm.Host == master && pm.XenServerPatch == patch);
|
||||
|
||||
if (mapping != null)
|
||||
{
|
||||
var task = Pool_patch.async_pool_clean(session, mapping.Pool_patch.opaque_ref);
|
||||
PollTaskForResultAndDestroy(Connection, ref session, task);
|
||||
|
||||
patchMappings.Remove(mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
/* 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.Actions;
|
||||
using XenAdmin.Core;
|
||||
using XenAPI;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using XenAdmin.Network;
|
||||
using XenAdmin.Diagnostics.Problems.HostProblem;
|
||||
|
||||
namespace XenAdmin.Wizards.PatchingWizard.PlanActions
|
||||
{
|
||||
class UploadPatchToMasterPlanAction : PlanActionWithSession
|
||||
{
|
||||
private readonly XenServerPatch patch;
|
||||
private readonly List<PoolPatchMapping> mappings;
|
||||
private Dictionary<XenServerPatch, string> AllDownloadedPatches = new Dictionary<XenServerPatch, string>();
|
||||
private string tempFileName = null;
|
||||
|
||||
public UploadPatchToMasterPlanAction(IXenConnection connection, XenServerPatch patch, List<PoolPatchMapping> mappings, Dictionary<XenServerPatch, string> allDownloadedPatches)
|
||||
: base(connection, string.Format("Uploading update {0} to {1}...", patch.Name, connection.Name))
|
||||
{
|
||||
this.patch = patch;
|
||||
this.mappings = mappings;
|
||||
this.AllDownloadedPatches = allDownloadedPatches;
|
||||
}
|
||||
|
||||
protected override void RunWithSession(ref Session session)
|
||||
{
|
||||
var path = AllDownloadedPatches[patch];
|
||||
|
||||
var poolPatches = new List<Pool_patch>(session.Connection.Cache.Pool_patches);
|
||||
var conn = session.Connection;
|
||||
|
||||
var existingMapping = mappings.Find(m => m.Host == Helpers.GetMaster(conn) && m.Pool_patch != null && m.XenServerPatch == patch);
|
||||
if (existingMapping == null
|
||||
|| !poolPatches.Any(p => string.Equals(p.uuid, existingMapping.Pool_patch.uuid, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
//free space check for upload:
|
||||
try
|
||||
{
|
||||
var checkSpaceForUpload = new CheckDiskSpaceForPatchUploadAction(Helpers.GetMaster(conn), path, true);
|
||||
checkSpaceForUpload.RunExternal(session);
|
||||
|
||||
var action = new UploadPatchAction(session.Connection, path, true, false);
|
||||
action.RunExternal(session);
|
||||
|
||||
var poolPatch = poolPatches.Find(p => string.Equals(p.uuid, patch.Uuid, StringComparison.OrdinalIgnoreCase));
|
||||
if (poolPatch == null)
|
||||
{
|
||||
//error
|
||||
}
|
||||
|
||||
var newMapping = new PoolPatchMapping()
|
||||
{
|
||||
Host = Helpers.GetMaster(session.Connection),
|
||||
XenServerPatch = patch,
|
||||
Pool_patch = poolPatch
|
||||
};
|
||||
|
||||
if (!mappings.Any(m => m.Host == newMapping.Host && m.Pool_patch == newMapping.Pool_patch && m.XenServerPatch == patch))
|
||||
mappings.Add(newMapping);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Error = ex;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DownloadFile(ref Session session)
|
||||
{
|
||||
string patchUri = patch.PatchUrl;
|
||||
if (string.IsNullOrEmpty(patchUri))
|
||||
return;
|
||||
|
||||
Uri address = new Uri(patchUri);
|
||||
tempFileName = Path.GetTempFileName();
|
||||
|
||||
var downloadAction = new DownloadAndUnzipXenServerPatchAction(patch.Name, address, tempFileName, Branding.Update);
|
||||
|
||||
if (downloadAction != null)
|
||||
{
|
||||
downloadAction.Changed += downloadAndUnzipXenServerPatchAction_Changed;
|
||||
downloadAction.Completed += downloadAndUnzipXenServerPatchAction_Completed;
|
||||
}
|
||||
|
||||
downloadAction.RunExternal(session);
|
||||
}
|
||||
|
||||
private void downloadAndUnzipXenServerPatchAction_Changed(object sender)
|
||||
{
|
||||
var action = sender as AsyncAction;
|
||||
if (action == null)
|
||||
return;
|
||||
|
||||
Program.Invoke(Program.MainWindow, () =>
|
||||
{
|
||||
//UpdateActionProgress(action);
|
||||
//flickerFreeListBox1.Refresh();
|
||||
//OnPageUpdated();
|
||||
});
|
||||
}
|
||||
|
||||
private void downloadAndUnzipXenServerPatchAction_Completed(ActionBase sender)
|
||||
{
|
||||
var action = sender as AsyncAction;
|
||||
if (action == null)
|
||||
return;
|
||||
|
||||
action.Changed -= downloadAndUnzipXenServerPatchAction_Changed;
|
||||
action.Completed -= downloadAndUnzipXenServerPatchAction_Completed;
|
||||
|
||||
if (action.Succeeded)
|
||||
{
|
||||
if (action is DownloadAndUnzipXenServerPatchAction)
|
||||
{
|
||||
Host master = Helpers.GetMaster(action.Connection);
|
||||
|
||||
AllDownloadedPatches[patch] = (action as DownloadAndUnzipXenServerPatchAction).PatchPath;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -860,6 +860,12 @@
|
||||
<Compile Include="Wizards\PatchingWizard\PatchingWizard_UploadPage.Designer.cs">
|
||||
<DependentUpon>PatchingWizard_UploadPage.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Wizards\PatchingWizard\PlanActions\ApplyXenServerPatchPlanAction.cs" />
|
||||
<Compile Include="Wizards\PatchingWizard\PlanActions\PatchPrechecksOnMultipleHostsAction.cs" />
|
||||
<Compile Include="Wizards\PatchingWizard\PlanActions\DownloadPatchPlanAction.cs" />
|
||||
<Compile Include="Wizards\PatchingWizard\PlanActions\UploadPatchToMasterPlanAction.cs" />
|
||||
<Compile Include="Wizards\PatchingWizard\PlanActions\PoolPatchMapping.cs" />
|
||||
<Compile Include="Wizards\PatchingWizard\PlanActions\RemoveUpdateFilesFromMaster.cs" />
|
||||
<Compile Include="Wizards\PatchingWizard\PlanActions\RemoveUpdateFile.cs" />
|
||||
<Compile Include="Wizards\PatchingWizard\PlanActions\InstallSupplementalPackPlanAction.cs" />
|
||||
<Compile Include="XenSearch\TreeNodeGroupAcceptor.cs">
|
||||
|
@ -126,6 +126,7 @@ namespace XenAdmin.Actions
|
||||
protected override void Run()
|
||||
{
|
||||
SafeToExit = false;
|
||||
|
||||
foreach (Pool_patch patch in patches)
|
||||
{
|
||||
foreach (Host host in hosts)
|
||||
|
@ -149,6 +149,7 @@ namespace XenAdmin.Actions
|
||||
string name = "";
|
||||
string description = "";
|
||||
string guidance = "";
|
||||
string guidance_mandatory = "";
|
||||
string patchVersion = "";
|
||||
string url = "";
|
||||
string patchUrl = "";
|
||||
@ -166,6 +167,8 @@ namespace XenAdmin.Actions
|
||||
description = attrib.Value;
|
||||
else if (attrib.Name == "after-apply-guidance")
|
||||
guidance = attrib.Value;
|
||||
else if (attrib.Name == "guidance-mandatory")
|
||||
guidance_mandatory = attrib.Value;
|
||||
else if (attrib.Name == "version")
|
||||
patchVersion = attrib.Value;
|
||||
else if (attrib.Name == "url")
|
||||
@ -183,7 +186,7 @@ namespace XenAdmin.Actions
|
||||
var conflictingPatches = GetPatchDependencies(version, ConflictingPatchesNode, ConflictingPatchNode);
|
||||
var requiredPatches = GetPatchDependencies(version, RequiredPatchesNode, RequiredPatchNode);
|
||||
|
||||
XenServerPatches.Add(new XenServerPatch(uuid, name, description, guidance, patchVersion, url,
|
||||
XenServerPatches.Add(new XenServerPatch(uuid, name, description, guidance, guidance_mandatory, patchVersion, url,
|
||||
patchUrl, timestamp, priority, installationSize, conflictingPatches, requiredPatches));
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using XenAPI;
|
||||
|
||||
namespace XenAdmin.Core
|
||||
{
|
||||
@ -40,6 +41,7 @@ namespace XenAdmin.Core
|
||||
public readonly string Name;
|
||||
public readonly string Description;
|
||||
public readonly string Guidance;
|
||||
public readonly string Guidance_mandatory;
|
||||
public readonly Version Version;
|
||||
public readonly string Url;
|
||||
public readonly string PatchUrl;
|
||||
@ -52,13 +54,14 @@ namespace XenAdmin.Core
|
||||
|
||||
private const int DEFAULT_PRIORITY = 2;
|
||||
|
||||
public XenServerPatch(string uuid, string name, string description, string guidance, string version, string url,
|
||||
public XenServerPatch(string uuid, string name, string description, string guidance, string guidance_mandatory , string version, string url,
|
||||
string patchUrl, string timestamp, string priority, string installationSize)
|
||||
{
|
||||
_uuid = uuid;
|
||||
Name = name;
|
||||
Description = description;
|
||||
Guidance = guidance;
|
||||
Guidance_mandatory = guidance_mandatory;
|
||||
Version = new Version(version);
|
||||
if (url.StartsWith("/XenServer"))
|
||||
url = XenServerVersion.UpdateRoot + url;
|
||||
@ -71,10 +74,11 @@ namespace XenAdmin.Core
|
||||
InstallationSize = 0;
|
||||
}
|
||||
|
||||
public XenServerPatch(string uuid, string name, string description, string guidance, string version, string url,
|
||||
public XenServerPatch(string uuid, string name, string description, string guidance, string guidance_mandatory, string version, string url,
|
||||
string patchUrl, string timestamp, string priority, string installationSize, List<string> conflictingPatches, List<string> requiredPatches)
|
||||
: this(uuid, name, description, guidance, version, url, patchUrl, timestamp, priority, installationSize)
|
||||
: this(uuid, name, description, guidance, guidance_mandatory, version, url, patchUrl, timestamp, priority, installationSize)
|
||||
{
|
||||
|
||||
ConflictingPatches = conflictingPatches;
|
||||
RequiredPatches = requiredPatches;
|
||||
}
|
||||
@ -89,5 +93,37 @@ namespace XenAdmin.Core
|
||||
return string.Equals(Uuid, other.Uuid, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public after_apply_guidance after_apply_guidance
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (Guidance)
|
||||
{
|
||||
case "restartHVM":
|
||||
return after_apply_guidance.restartHVM;
|
||||
|
||||
case "restartPV":
|
||||
return after_apply_guidance.restartPV;
|
||||
|
||||
case "restartHost":
|
||||
return after_apply_guidance.restartHost;
|
||||
|
||||
case "restartXAPI":
|
||||
return after_apply_guidance.restartXAPI;
|
||||
|
||||
default:
|
||||
return after_apply_guidance.unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool GuidanceMandatory
|
||||
{
|
||||
get
|
||||
{
|
||||
return !string.IsNullOrEmpty(Guidance_mandatory) && this.Guidance_mandatory.ToLowerInvariant().Contains("true");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
27
XenModel/Messages.Designer.cs
generated
27
XenModel/Messages.Designer.cs
generated
@ -25945,6 +25945,15 @@ namespace XenAdmin {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to a.
|
||||
/// </summary>
|
||||
public static string PATCHINGWIZARD_SELECTSERVERPAGE_HOST_UNLICENSED_FOR_BATCH_UPDATING {
|
||||
get {
|
||||
return ResourceManager.GetString("PATCHINGWIZARD_SELECTSERVERPAGE_HOST_UNLICENSED_FOR_BATCH_UPDATING", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Update already applied.
|
||||
/// </summary>
|
||||
@ -25981,6 +25990,15 @@ namespace XenAdmin {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Automatic update has finished..
|
||||
/// </summary>
|
||||
public static string PATCHINGWIZARD_UPDATES_DONE_AUTOMATIC_MODE {
|
||||
get {
|
||||
return ResourceManager.GetString("PATCHINGWIZARD_UPDATES_DONE_AUTOMATIC_MODE", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to [XenCenter] is now downloading your update and uploading it to the servers specified in the previous step.
|
||||
///Please wait for these operations to complete, then click Next to continue with the installation..
|
||||
@ -32749,6 +32767,15 @@ namespace XenAdmin {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Removing update files from {0}....
|
||||
/// </summary>
|
||||
public static string UPDATES_WIZARD_REMOVING_UPDATES_FROM_POOL {
|
||||
get {
|
||||
return ResourceManager.GetString("UPDATES_WIZARD_REMOVING_UPDATES_FROM_POOL", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Click here to repair.
|
||||
/// </summary>
|
||||
|
@ -8970,6 +8970,9 @@ However, there is not enough space to perform the repartitioning, so the current
|
||||
<data name="PATCHINGWIZARD_SELECTSERVERPAGE_HOST_UNLICENSED" xml:space="preserve">
|
||||
<value>Subscription Advantage required</value>
|
||||
</data>
|
||||
<data name="PATCHINGWIZARD_SELECTSERVERPAGE_HOST_UNLICENSED_FOR_BATCH_UPDATING" xml:space="preserve">
|
||||
<value>This server is not licensed for automatic updating</value>
|
||||
</data>
|
||||
<data name="PATCHINGWIZARD_SELECTSERVERPAGE_PATCH_ALREADY_APPLIED" xml:space="preserve">
|
||||
<value>Update already applied</value>
|
||||
</data>
|
||||
@ -8982,6 +8985,9 @@ However, there is not enough space to perform the repartitioning, so the current
|
||||
<data name="PATCHINGWIZARD_SELECTSERVERPAGE_TITLE" xml:space="preserve">
|
||||
<value>Select the servers you wish to update</value>
|
||||
</data>
|
||||
<data name="PATCHINGWIZARD_UPDATES_DONE_AUTOMATIC_MODE" xml:space="preserve">
|
||||
<value>Automatic update has finished.</value>
|
||||
</data>
|
||||
<data name="PATCHINGWIZARD_UPLOADPAGE_MESSAGE_DOWNLOAD_AND_UPLOAD" xml:space="preserve">
|
||||
<value>[XenCenter] is now downloading your update and uploading it to the servers specified in the previous step.
|
||||
Please wait for these operations to complete, then click Next to continue with the installation.</value>
|
||||
@ -11321,6 +11327,9 @@ Check your settings and try again.</value>
|
||||
<data name="UPDATES_WIZARD_REMOVING_UPDATE" xml:space="preserve">
|
||||
<value>Removing update {0} from {1}... </value>
|
||||
</data>
|
||||
<data name="UPDATES_WIZARD_REMOVING_UPDATES_FROM_POOL" xml:space="preserve">
|
||||
<value>Removing update files from {0}...</value>
|
||||
</data>
|
||||
<data name="UPDATES_WIZARD_REPAIR_SR" xml:space="preserve">
|
||||
<value>Click here to repair</value>
|
||||
</data>
|
||||
|
@ -246,6 +246,16 @@ namespace XenAPI
|
||||
return h._RestrictHotfixApply;
|
||||
}
|
||||
|
||||
private bool _RestrictBatchHotfixApply
|
||||
{
|
||||
get { return BoolKeyPreferTrue(license_params, "restrict_batch_hotfix_apply"); }
|
||||
}
|
||||
|
||||
public static bool RestrictBatchHotfixApply(Host h)
|
||||
{
|
||||
return h._RestrictBatchHotfixApply;
|
||||
}
|
||||
|
||||
private bool _RestrictCheckpoint
|
||||
{
|
||||
get { return BoolKeyPreferTrue(license_params, "restrict_checkpoint"); }
|
||||
|
Loading…
Reference in New Issue
Block a user