Merge pull request #974 from GaborApatiNagy/master_batchupdate_new

REQ-156: Further Batch Update commits
This commit is contained in:
Mihaela Stoica 2016-05-04 13:54:12 +01:00
commit 318d28d4c1
21 changed files with 1029 additions and 137 deletions

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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="&gt;&gt;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="&gt;&gt;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="&gt;&gt;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="&gt;&gt;labelDownloadUpdate.Name" xml:space="preserve">
<value>labelDownloadUpdate</value>
</data>
<data name="&gt;&gt;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="&gt;&gt;labelDownloadUpdate.Parent" xml:space="preserve">
<value>panel1</value>
</data>
<data name="&gt;&gt;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="&gt;&gt;pictureBox2.Name" xml:space="preserve">
<value>pictureBox2</value>
</data>
<data name="&gt;&gt;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="&gt;&gt;pictureBox2.Parent" xml:space="preserve">
<value>panel1</value>
</data>
<data name="&gt;&gt;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="&gt;&gt;panel1.Name" xml:space="preserve">
<value>panel1</value>
</data>
<data name="&gt;&gt;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="&gt;&gt;panel1.Parent" xml:space="preserve">
<value>tableLayoutPanel1</value>
</data>
<data name="&gt;&gt;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>&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;TableLayoutSettings&gt;&lt;Controls&gt;&lt;Control Name="panel4" Row="5" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="panel2" Row="3" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="panel3" Row="4" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="panel1" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="label1" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="label2" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;/Controls&gt;&lt;Columns Styles="Percent,100" /&gt;&lt;Rows Styles="Absolute,30,Absolute,30,Absolute,40,Absolute,40,Absolute,40,Absolute,40" /&gt;&lt;/TableLayoutSettings&gt;</value>
<value>&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;TableLayoutSettings&gt;&lt;Controls&gt;&lt;Control Name="panel4" Row="5" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="panel2" Row="3" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="panel3" Row="4" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="label1" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="label2" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;/Controls&gt;&lt;Columns Styles="Percent,100" /&gt;&lt;Rows Styles="Absolute,30,Absolute,30,AutoSize,40,Absolute,40,Absolute,40,Absolute,40" /&gt;&lt;/TableLayoutSettings&gt;</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="&gt;&gt;$this.Type" xml:space="preserve">
<value>XenAdmin.Controls.XenTabPage, XenCenterMain, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</value>
</data>
</root>
</root>

View File

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

View File

@ -147,6 +147,9 @@
<data name="automaticOptionLabel.Text" xml:space="preserve">
<value>[XenCenter] will &amp;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="&gt;&gt;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="&gt;&gt;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>

View File

@ -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))

View File

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

View File

@ -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;
}
}
}
}
}

View File

@ -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;
}
}
}
}
}
}

View File

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

View File

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

View File

@ -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;
}
}
}
}
}

View File

@ -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">

View File

@ -126,6 +126,7 @@ namespace XenAdmin.Actions
protected override void Run()
{
SafeToExit = false;
foreach (Pool_patch patch in patches)
{
foreach (Host host in hosts)

View File

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

View File

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

View File

@ -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>

View File

@ -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>

View File

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