CA-147163: Non-modal hotfix upload progress dialog

- Added new page to the patching wizard, called "Upload" which displays the upload actions for each server and the progress of these actions
- MultipleAction: added the functionality to optionally stop the action on first failure
- Fixed the error where an existing patch downloaded from another server and then uploaded to a new one was not deleted on cancelling the wizard [CA-156788]

Signed-off-by: Mihaela Stoica <mihaela.stoica@citrix.com>
This commit is contained in:
Mihaela Stoica 2015-01-09 12:54:12 +00:00
parent 13ac717a8d
commit 13c6d323c3
14 changed files with 629 additions and 109 deletions

View File

@ -1062,4 +1062,7 @@
<data name="MessageAlert_LICENSE_SERVER_VERSION_OBSOLETE" xml:space="preserve">
<value>7015</value>
</data>
<data name="PatchingWizard_UploadPatchPane" xml:space="preserve">
<value>6315</value>
</data>
</root>

View File

@ -50,6 +50,7 @@ namespace XenAdmin.Wizards.PatchingWizard
private readonly PatchingWizard_SelectPatchPage PatchingWizard_SelectPatchPage;
private readonly PatchingWizard_ModePage PatchingWizard_ModePage;
private readonly PatchingWizard_SelectServers PatchingWizard_SelectServers;
private readonly PatchingWizard_UploadPage PatchingWizard_UploadPage;
private readonly PatchingWizard_PrecheckPage PatchingWizard_PrecheckPage;
private readonly PatchingWizard_FirstPage PatchingWizard_FirstPage;
@ -61,12 +62,14 @@ namespace XenAdmin.Wizards.PatchingWizard
PatchingWizard_SelectPatchPage = new PatchingWizard_SelectPatchPage();
PatchingWizard_ModePage = new PatchingWizard_ModePage();
PatchingWizard_SelectServers = new PatchingWizard_SelectServers();
PatchingWizard_UploadPage = new PatchingWizard_UploadPage();
PatchingWizard_PrecheckPage = new PatchingWizard_PrecheckPage();
PatchingWizard_FirstPage = new PatchingWizard_FirstPage();
AddPage(PatchingWizard_FirstPage);
AddPage(PatchingWizard_SelectPatchPage);
AddPage(PatchingWizard_SelectServers);
AddPage(PatchingWizard_UploadPage);
// This gets enabled/disabled in the select patch step depending on if it is an OEM patch or not
AddPage(PatchingWizard_PrecheckPage);
AddPage(PatchingWizard_ModePage);
@ -97,8 +100,11 @@ namespace XenAdmin.Wizards.PatchingWizard
DisablePage(PatchingWizard_PrecheckPage, updateType == UpdateType.NewOem);
PatchingWizard_SelectServers.SelectedUpdateType = updateType;
PatchingWizard_SelectServers.SelectedExistingPatch = existPatch;
PatchingWizard_SelectServers.SelectedNewPatch = newPatch;
PatchingWizard_SelectServers.Patch = existPatch;
PatchingWizard_UploadPage.SelectedUpdateType = updateType;
PatchingWizard_UploadPage.SelectedExistingPatch = existPatch;
PatchingWizard_UploadPage.SelectedNewPatch = newPatch;
if (updateType == UpdateType.Existing)
{
@ -118,31 +124,34 @@ namespace XenAdmin.Wizards.PatchingWizard
else if (prevPageType == typeof(PatchingWizard_SelectServers))
{
var selectedServers = PatchingWizard_SelectServers.SelectedServers;
if (PatchingWizard_SelectPatchPage.SelectedUpdateType == UpdateType.NewRetail)
{
PatchingWizard_SelectPatchPage.SelectedUpdateType = UpdateType.Existing;
PatchingWizard_SelectPatchPage.SelectedExistingPatch = PatchingWizard_SelectServers.Patch;
PatchingWizard_SelectServers.SelectedUpdateType = UpdateType.Existing;
PatchingWizard_SelectServers.SelectedExistingPatch = PatchingWizard_SelectServers.Patch;
PatchingWizard_SelectServers.SelectedNewPatch = null;
PatchingWizard_PrecheckPage.Patch = PatchingWizard_SelectServers.Patch;
PatchingWizard_ModePage.Patch = PatchingWizard_SelectServers.Patch;
PatchingWizard_PatchingPage.Patch = PatchingWizard_SelectServers.Patch;
}
PatchingWizard_PrecheckPage.SelectedServers = selectedServers;
PatchingWizard_PrecheckPage.NewUploadedPatches = PatchingWizard_SelectServers.NewUploadedPatches;
//PatchingWizard_PrecheckPage.NewUploadedPatches = PatchingWizard_SelectServers.NewUploadedPatches;
PatchingWizard_ModePage.SelectedServers = selectedServers;
PatchingWizard_PatchingPage.SelectedMasters = PatchingWizard_SelectServers.SelectedMasters;
PatchingWizard_PatchingPage.SelectedServers = selectedServers;
PatchingWizard_PatchingPage.SelectedPools = PatchingWizard_SelectServers.SelectedPools;
PatchingWizard_UploadPage.SelectedMasters = PatchingWizard_SelectServers.SelectedMasters;
}
else if (prevPageType == typeof(PatchingWizard_UploadPage))
{
if (PatchingWizard_SelectPatchPage.SelectedUpdateType == UpdateType.NewRetail)
{
PatchingWizard_SelectPatchPage.SelectedUpdateType = UpdateType.Existing;
PatchingWizard_SelectPatchPage.SelectedExistingPatch = PatchingWizard_UploadPage.Patch;
PatchingWizard_SelectServers.SelectedUpdateType = UpdateType.Existing;
PatchingWizard_SelectServers.Patch = PatchingWizard_UploadPage.Patch;
PatchingWizard_PrecheckPage.Patch = PatchingWizard_UploadPage.Patch;
PatchingWizard_ModePage.Patch = PatchingWizard_UploadPage.Patch;
PatchingWizard_PatchingPage.Patch = PatchingWizard_UploadPage.Patch;
}
}
else if (prevPageType == typeof(PatchingWizard_ModePage))
{
@ -197,7 +206,7 @@ namespace XenAdmin.Wizards.PatchingWizard
private List<AsyncAction> GetRemovePatchActions()
{
return GetRemovePatchActions(PatchingWizard_SelectServers.NewUploadedPatches);
return GetRemovePatchActions(PatchingWizard_UploadPage.NewUploadedPatches);
}
private void RunMultipleActions(string title, string startDescription, string endDescription,
@ -231,11 +240,11 @@ namespace XenAdmin.Wizards.PatchingWizard
protected override void FinishWizard()
{
if (PatchingWizard_SelectServers.NewUploadedPatches != null)
if (PatchingWizard_UploadPage.NewUploadedPatches != null)
{
List<Pool_patch> patchesToRemove =
PatchingWizard_SelectServers.NewUploadedPatches.Where(
patch => patch.uuid != PatchingWizard_SelectServers.Patch.uuid).ToList();
PatchingWizard_UploadPage.NewUploadedPatches.Where(
patch => patch.uuid != PatchingWizard_UploadPage.Patch.uuid).ToList();
RemoveUnwantedPatches(patchesToRemove);
}

View File

@ -33,7 +33,6 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using XenAdmin.Actions;
using XenAdmin.Controls;
using XenAdmin.Controls.DataGridViewEx;
using XenAdmin.Core;
@ -88,9 +87,6 @@ namespace XenAdmin.Wizards.PatchingWizard
base.PageLoaded(direction);
try
{
if (SelectedUpdateType == UpdateType.Existing)
_patch = SelectedExistingPatch;
// catch selected servers, in order to restore selection after the dataGrid is reloaded
List<Host> selectedServers = SelectedServers;
@ -198,47 +194,6 @@ namespace XenAdmin.Wizards.PatchingWizard
return;
}
}
switch (SelectedUpdateType)
{
case UpdateType.NewRetail:
foreach (Host selectedServer in masters)
{
Host master = Helpers.GetMaster(selectedServer.Connection);
UploadPatchAction action = new UploadPatchAction(master.Connection, SelectedNewPatch);
new ActionProgressDialog(action, ProgressBarStyle.Blocks).ShowDialog();
if (action.Succeeded)
{
_patch = action.PatchRefs[master];
NewUploadedPatches.Add(_patch);
}
else
{
cancel = true;
break;
}
}
break;
case UpdateType.Existing:
foreach (Host selectedServer in masters)
{
List<Pool_patch> poolPatches = new List<Pool_patch>(selectedServer.Connection.Cache.Pool_patches);
if (poolPatches.Find(patch => patch.uuid == SelectedExistingPatch.uuid) == null)
{
//Download patch from server Upload in the selected server
var actionCopyPatch = new CopyPatchFromHostToOther(SelectedExistingPatch.Connection, selectedServer, SelectedExistingPatch);
new ActionProgressDialog(actionCopyPatch, ProgressBarStyle.Blocks).ShowDialog();
if (!actionCopyPatch.Succeeded)
{
cancel = true;
break;
}
}
}
break;
}
}
base.PageLeave(direction, ref cancel);
}
@ -302,13 +257,7 @@ namespace XenAdmin.Wizards.PatchingWizard
#region Accessors
public readonly List<Pool_patch> NewUploadedPatches = new List<Pool_patch>();
private Pool_patch _patch = null;
public Pool_patch Patch
{
get { return _patch; }
}
public Pool_patch Patch { private get; set; }
public List<Host> SelectedMasters
{
@ -371,10 +320,6 @@ namespace XenAdmin.Wizards.PatchingWizard
public UpdateType SelectedUpdateType { private get; set; }
public string SelectedNewPatch { private get; set; }
public Pool_patch SelectedExistingPatch { private get; set; }
public void SelectServers(List<Host> selectedServers)
{
if (selectedServers.Count > 0)

View File

@ -112,23 +112,23 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="label1.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Top</value>
</data>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="label1.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 0</value>
</data>
<data name="label1.Size" type="System.Drawing.Size, System.Drawing">
<value>608, 57</value>
<value>608, 37</value>
</data>
<assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="label1.TabIndex" type="System.Int32, mscorlib">
<value>1</value>
</data>
@ -140,7 +140,7 @@ Servers where the selected update cannot be applied appear disabled in this list
<value>label1</value>
</data>
<data name="&gt;&gt;label1.Type" xml:space="preserve">
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;label1.Parent" xml:space="preserve">
<value>$this</value>
@ -167,7 +167,7 @@ Servers where the selected update cannot be applied appear disabled in this list
<value>buttonSelectAll</value>
</data>
<data name="&gt;&gt;buttonSelectAll.Type" xml:space="preserve">
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;buttonSelectAll.Parent" xml:space="preserve">
<value>$this</value>
@ -194,7 +194,7 @@ Servers where the selected update cannot be applied appear disabled in this list
<value>buttonClearAll</value>
</data>
<data name="&gt;&gt;buttonClearAll.Type" xml:space="preserve">
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;buttonClearAll.Parent" xml:space="preserve">
<value>$this</value>
@ -205,7 +205,7 @@ Servers where the selected update cannot be applied appear disabled in this list
<data name="dataGridViewHosts.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Bottom, Left, Right</value>
</data>
<metadata name="ColumnPoolCheckBox.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="ColumnPoolCheckBox.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<data name="ColumnPoolCheckBox.HeaderText" xml:space="preserve">
@ -217,7 +217,7 @@ Servers where the selected update cannot be applied appear disabled in this list
<data name="ColumnPoolCheckBox.Width" type="System.Int32, mscorlib">
<value>16</value>
</data>
<metadata name="ColumnExpander.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="ColumnExpander.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<data name="ColumnExpander.HeaderText" xml:space="preserve">
@ -229,7 +229,7 @@ Servers where the selected update cannot be applied appear disabled in this list
<data name="ColumnExpander.Width" type="System.Int32, mscorlib">
<value>16</value>
</data>
<metadata name="ColumnPoolIconHostCheck.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="ColumnPoolIconHostCheck.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<data name="ColumnPoolIconHostCheck.HeaderText" xml:space="preserve">
@ -241,13 +241,13 @@ Servers where the selected update cannot be applied appear disabled in this list
<data name="ColumnPoolIconHostCheck.Width" type="System.Int32, mscorlib">
<value>16</value>
</data>
<metadata name="ColumnName.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="ColumnName.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<data name="ColumnName.HeaderText" xml:space="preserve">
<value>Name</value>
</data>
<metadata name="ColumnVersion.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="ColumnVersion.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<data name="ColumnVersion.HeaderText" xml:space="preserve">
@ -257,10 +257,10 @@ Servers where the selected update cannot be applied appear disabled in this list
<value>67</value>
</data>
<data name="dataGridViewHosts.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 60</value>
<value>0, 40</value>
</data>
<data name="dataGridViewHosts.Size" type="System.Drawing.Size, System.Drawing">
<value>605, 316</value>
<value>608, 336</value>
</data>
<data name="dataGridViewHosts.TabIndex" type="System.Int32, mscorlib">
<value>4</value>
@ -277,7 +277,7 @@ Servers where the selected update cannot be applied appear disabled in this list
<data name="&gt;&gt;dataGridViewHosts.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
@ -290,31 +290,31 @@ Servers where the selected update cannot be applied appear disabled in this list
<value>ColumnPoolCheckBox</value>
</data>
<data name="&gt;&gt;ColumnPoolCheckBox.Type" xml:space="preserve">
<value>System.Windows.Forms.DataGridViewCheckBoxColumn, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Windows.Forms.DataGridViewCheckBoxColumn, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;ColumnExpander.Name" xml:space="preserve">
<value>ColumnExpander</value>
</data>
<data name="&gt;&gt;ColumnExpander.Type" xml:space="preserve">
<value>System.Windows.Forms.DataGridViewImageColumn, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Windows.Forms.DataGridViewImageColumn, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;ColumnPoolIconHostCheck.Name" xml:space="preserve">
<value>ColumnPoolIconHostCheck</value>
</data>
<data name="&gt;&gt;ColumnPoolIconHostCheck.Type" xml:space="preserve">
<value>System.Windows.Forms.DataGridViewImageColumn, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Windows.Forms.DataGridViewImageColumn, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;ColumnName.Name" xml:space="preserve">
<value>ColumnName</value>
</data>
<data name="&gt;&gt;ColumnName.Type" xml:space="preserve">
<value>System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;ColumnVersion.Name" xml:space="preserve">
<value>ColumnVersion</value>
</data>
<data name="&gt;&gt;ColumnVersion.Type" xml:space="preserve">
<value>System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;$this.Name" xml:space="preserve">
<value>PatchingWizard_SelectServers</value>

View File

@ -0,0 +1,130 @@
namespace XenAdmin.Wizards.PatchingWizard
{
partial class PatchingWizard_UploadPage
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.label2 = new System.Windows.Forms.Label();
this.labelProgress = new System.Windows.Forms.Label();
this.progressBar1 = new System.Windows.Forms.ProgressBar();
this.flickerFreeListBox1 = new XenAdmin.Controls.FlickerFreeListBox();
this.tableLayoutPanel1.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 1;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Controls.Add(this.label2, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.labelProgress, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.progressBar1, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.flickerFreeListBox1, 0, 1);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 4;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(700, 397);
this.tableLayoutPanel1.TabIndex = 1;
//
// label2
//
this.label2.Dock = System.Windows.Forms.DockStyle.Top;
this.label2.ImeMode = System.Windows.Forms.ImeMode.NoControl;
this.label2.Location = new System.Drawing.Point(0, 0);
this.label2.Margin = new System.Windows.Forms.Padding(0);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(700, 37);
this.label2.TabIndex = 1;
this.label2.Text = "XenCenter is now uploading your update to the servers specified in the previous s" +
"tep.\r\nPlease wait for this operation to complete, then click Next to continue wi" +
"th the installation.";
//
// labelProgress
//
this.labelProgress.AutoSize = true;
this.labelProgress.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelProgress.ImeMode = System.Windows.Forms.ImeMode.NoControl;
this.labelProgress.Location = new System.Drawing.Point(3, 357);
this.labelProgress.Margin = new System.Windows.Forms.Padding(3);
this.labelProgress.Name = "labelProgress";
this.labelProgress.Padding = new System.Windows.Forms.Padding(1);
this.labelProgress.Size = new System.Drawing.Size(694, 15);
this.labelProgress.TabIndex = 0;
this.labelProgress.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// progressBar1
//
this.progressBar1.Dock = System.Windows.Forms.DockStyle.Fill;
this.progressBar1.ImeMode = System.Windows.Forms.ImeMode.NoControl;
this.progressBar1.Location = new System.Drawing.Point(3, 378);
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(694, 16);
this.progressBar1.TabIndex = 1;
//
// flickerFreeListBox1
//
this.flickerFreeListBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.flickerFreeListBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
this.flickerFreeListBox1.FormattingEnabled = true;
this.flickerFreeListBox1.IntegralHeight = false;
this.flickerFreeListBox1.ItemHeight = 18;
this.flickerFreeListBox1.Items.AddRange(new object[] {
"Nothing to upload"});
this.flickerFreeListBox1.Location = new System.Drawing.Point(3, 40);
this.flickerFreeListBox1.Name = "flickerFreeListBox1";
this.flickerFreeListBox1.Size = new System.Drawing.Size(694, 311);
this.flickerFreeListBox1.TabIndex = 2;
this.flickerFreeListBox1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.flickerFreeListBox1_DrawItem);
//
// PatchingWizard_UploadPage
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tableLayoutPanel1);
this.Name = "PatchingWizard_UploadPage";
this.Size = new System.Drawing.Size(700, 397);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label labelProgress;
private System.Windows.Forms.ProgressBar progressBar1;
private Controls.FlickerFreeListBox flickerFreeListBox1;
}
}

View File

@ -0,0 +1,244 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using XenAdmin.Actions;
using XenAdmin.Controls;
using XenAdmin.Core;
using XenAPI;
namespace XenAdmin.Wizards.PatchingWizard
{
public partial class PatchingWizard_UploadPage : XenTabPage
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public PatchingWizard_UploadPage()
{
InitializeComponent();
}
public override string Text { get { return Messages.PATCHINGWIZARD_UPLOADPAGE_TEXT; } }
public override string PageTitle { get { return Messages.PATCHINGWIZARD_UPLOADPAGE_TITLE; } }
public override string HelpID { get { return "UploadPatch"; } }
#region Accessors
public List<Host> SelectedMasters { private get; set; }
public UpdateType SelectedUpdateType { private get; set; }
public string SelectedNewPatch { private get; set; }
public Pool_patch SelectedExistingPatch { private get; set; }
public readonly List<Pool_patch> NewUploadedPatches = new List<Pool_patch>();
private Pool_patch _patch = null;
public Pool_patch Patch
{
get { return _patch; }
}
#endregion
public override void PageLoaded(PageLoadedDirection direction)
{
base.PageLoaded(direction);
if (SelectedUpdateType == UpdateType.Existing)
_patch = SelectedExistingPatch;
if (direction == PageLoadedDirection.Forward)
StartUploading();
}
public override void PageCancelled()
{
foreach (var action in uploadActions.Where(action => !action.IsCompleted))
{
CancelAction(action);
}
}
public override bool EnableNext()
{
return uploadActions.Count == 0 || uploadActions.All(action => action.Succeeded);
}
public override bool EnablePrevious()
{
return uploadActions.Count == 0 || uploadActions.All(action => action.IsCompleted);
}
private List<AsyncAction> uploadActions = new List<AsyncAction>();
private void StartUploading()
{
OnPageUpdated();
uploadActions.Clear();
//Upload the patches to the masters if it is necessary
List<Host> masters = SelectedMasters;
switch (SelectedUpdateType)
{
case UpdateType.NewRetail:
foreach (Host selectedServer in masters)
{
Host master = Helpers.GetMaster(selectedServer.Connection);
UploadPatchAction action = new UploadPatchAction(master.Connection, SelectedNewPatch, true);
action.Changed += singleAction_Changed;
action.Completed += singleAction_Completed;
uploadActions.Add(action);
}
break;
case UpdateType.Existing:
foreach (Host selectedServer in masters)
{
List<Pool_patch> poolPatches = new List<Pool_patch>(selectedServer.Connection.Cache.Pool_patches);
if (poolPatches.Find(patch => patch.uuid == SelectedExistingPatch.uuid) == null)
{
//Download patch from server Upload in the selected server
var action = new CopyPatchFromHostToOther(SelectedExistingPatch.Connection,
selectedServer, SelectedExistingPatch);
action.Changed += singleAction_Changed;
action.Completed += singleAction_Completed;
uploadActions.Add(action);
}
}
break;
}
if (uploadActions.Count > 0)
{
flickerFreeListBox1.Items.Clear();
labelProgress.Text = "";
progressBar1.Value = 0;
flickerFreeListBox1.Items.AddRange(uploadActions.ToArray());
}
flickerFreeListBox1.Refresh();
OnPageUpdated();
RunMultipleActions("Upload", "Uploading", "Update succesfully uploaded to selected server(s)", uploadActions);
}
private void RunMultipleActions(string title, string startDescription, string endDescription,
List<AsyncAction> subActions)
{
if (subActions.Count > 0)
{
using (var multipleAction = new MultipleAction(Connection, title, startDescription,
endDescription, subActions, true, true, true))
{
multipleAction.Completed += multipleAction_Completed;
multipleAction.RunAsync();
}
}
}
private static string GetActionDescription(AsyncAction action)
{
return !action.StartedRunning ? "" :
action.Exception == null
? action.Description
: action.Exception is CancelledException ? Messages.CANCELLED_BY_USER : action.Exception.Message;
}
private void CancelAction(AsyncAction action)
{
Program.AssertOnEventThread();
OnPageUpdated();
action.Changed -= singleAction_Changed;
action.Completed -= singleAction_Completed;
action.Cancel();
}
private void singleAction_Changed(object sender)
{
var action = sender as AsyncAction;
if (action == null)
return;
Program.Invoke(this, () =>
{
progressBar1.Value = action.PercentComplete;
labelProgress.Text = GetActionDescription(action);
flickerFreeListBox1.Refresh();
OnPageUpdated();
});
}
private void singleAction_Completed(ActionBase sender)
{
var action = sender as AsyncAction;
if (action == null)
return;
action.Changed -= singleAction_Changed;
action.Completed -= singleAction_Completed;
Program.Invoke(this, () =>
{
if (action.Succeeded)
{
Host master = Helpers.GetMaster(action.Connection);
if (action is UploadPatchAction)
_patch = (action as UploadPatchAction).PatchRefs[master];
if (action is CopyPatchFromHostToOther && action.Host != null)
_patch = action.Host.Connection.Cache.Resolve((action as CopyPatchFromHostToOther).NewPatchRef);
if (_patch != null && !NewUploadedPatches.Contains(_patch))
NewUploadedPatches.Add(_patch);
}
});
}
private void multipleAction_Completed(object sender)
{
var action = sender as AsyncAction;
if (action == null)
return;
labelProgress.Text = GetActionDescription(action);
action.Completed -= multipleAction_Completed;
}
private void flickerFreeListBox1_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index < 0)
return;
AsyncAction action = flickerFreeListBox1.Items[e.Index] as AsyncAction;
if (action == null)
{
Drawing.DrawText(e.Graphics, "Already uploaded to selected server(s)", flickerFreeListBox1.Font, new Rectangle(e.Bounds.Left, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height), Color.Green, flickerFreeListBox1.BackColor);
return;
}
Host host = action.Host;
if (host == null)
return;
using (SolidBrush backBrush = new SolidBrush(flickerFreeListBox1.BackColor))
{
e.Graphics.FillRectangle(backBrush, e.Bounds);
}
e.Graphics.DrawImage(Images.GetImage16For(action.Host), e.Bounds.Left, e.Bounds.Top);
string text = GetActionDescription(action);
int width = Drawing.MeasureText(text, flickerFreeListBox1.Font).Width;
Drawing.DrawText(e.Graphics, host.ToString(), flickerFreeListBox1.Font, new Rectangle(e.Bounds.Left + Properties.Resources._000_Server_h32bit_16.Width, e.Bounds.Top, e.Bounds.Right - (width + Properties.Resources._000_Server_h32bit_16.Width), e.Bounds.Height), flickerFreeListBox1.ForeColor, TextFormatFlags.Left | TextFormatFlags.EndEllipsis);
Color textColor;
if (!action.StartedRunning) // not started yet
textColor = flickerFreeListBox1.ForeColor;
else if (!action.IsCompleted) // in progress
textColor = Color.Blue;
else textColor = action.Succeeded ? Color.Green : Color.Red; // completed
Drawing.DrawText(e.Graphics, text, flickerFreeListBox1.Font, new Rectangle(e.Bounds.Right - width, e.Bounds.Top, width, e.Bounds.Height), textColor, flickerFreeListBox1.BackColor);
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -734,6 +734,12 @@
<DependentUpon>HAPage.cs</DependentUpon>
</Compile>
<Compile Include="Alerts\Types\XenCenterUpdateAlert.cs" />
<Compile Include="Wizards\PatchingWizard\PatchingWizard_UploadPage.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Wizards\PatchingWizard\PatchingWizard_UploadPage.Designer.cs">
<DependentUpon>PatchingWizard_UploadPage.cs</DependentUpon>
</Compile>
<Compile Include="XenSearch\TreeNodeGroupAcceptor.cs">
</Compile>
<Compile Include="Dialogs\FolderChangeDialog.cs">
@ -2067,6 +2073,9 @@
<SubType>Designer</SubType>
<DependentUpon>ConsolePanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Wizards\PatchingWizard\PatchingWizard_UploadPage.resx">
<DependentUpon>PatchingWizard_UploadPage.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Wizards\WizardProgress.resx">
<DependentUpon>WizardProgress.cs</DependentUpon>
<SubType>Designer</SubType>

View File

@ -48,6 +48,7 @@ namespace XenAdmin.Actions
public bool ShowSubActionsDetails { get; private set; }
public string SubActionTitle { get; private set; }
public string SubActionDescription { get; private set; }
public bool StopOnFirstException { get; private set; }
public MultipleAction(IXenConnection connection, string title, string startDescription, string endDescription, List<AsyncAction> subActions, bool suppressHistory)
: base(connection, title, startDescription, suppressHistory)
@ -63,13 +64,20 @@ namespace XenAdmin.Actions
public MultipleAction(IXenConnection connection, string title, string startDescription, string endDescription,
List<AsyncAction> subActions, bool suppressHistory, bool showSubActionsDetails)
: this(connection, title, startDescription, endDescription, subActions)
: this(connection, title, startDescription, endDescription, subActions, suppressHistory)
{
ShowSubActionsDetails = showSubActionsDetails;
if (showSubActionsDetails)
RegisterEvents();
}
public MultipleAction(IXenConnection connection, string title, string startDescription, string endDescription,
List<AsyncAction> subActions, bool suppressHistory, bool showSubActionsDetails, bool stopOnFirstException)
: this(connection, title, startDescription, endDescription, subActions, suppressHistory, showSubActionsDetails)
{
StopOnFirstException = stopOnFirstException;
}
// The multiple action gets its ApiMethodsToRoleCheck by accumulating the lists from each of the subactions
public override RbacMethodList GetApiMethodsToRoleCheck
{
@ -143,6 +151,8 @@ namespace XenAdmin.Actions
// Record the first exception we come to. Though later if there are more than one we will replace this with non specific one.
if (Exception == null)
Exception = e;
if (StopOnFirstException)
break;
}
i++;
PercentComplete = 100 * i / subActions.Count;

View File

@ -93,6 +93,7 @@ namespace XenAdmin.Actions
{
Connection = null;
Session = null;
Description = String.Format(Messages.PATCH_UPLOADED, host.Name);
}
}
finally

View File

@ -41,17 +41,28 @@ namespace XenAdmin.Actions
{
private readonly Pool_patch _patchToCopy;
private readonly Host _hostDestiny;
private XenRef<Pool_patch> _newPatchRef;
public XenRef<Pool_patch> NewPatchRef
{
get
{
return _newPatchRef;
}
}
public CopyPatchFromHostToOther(IXenConnection connection, Host hostDestiny, Pool_patch patchToCopy)
: base(connection, Messages.UPLOADING_PATCH, true)
{
_hostDestiny = hostDestiny;
_patchToCopy = patchToCopy;
Host = _hostDestiny;
}
protected override void Run()
{
SafeToExit = false;
Result = BringPatchToPoolForHost(_hostDestiny, _patchToCopy);
_newPatchRef = BringPatchToPoolForHost(_hostDestiny, _patchToCopy);
Result = _newPatchRef;
}
}
}

View File

@ -31,8 +31,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using XenAdmin.Network;
using XenAdmin.Core;
@ -59,7 +57,11 @@ namespace XenAdmin.Actions
/// <param name="connection"></param>
/// <param name="path"></param>
public UploadPatchAction(IXenConnection connection, string path)
: base(connection, null, Messages.UPLOADING_PATCH)
: this(connection, path, false)
{}
public UploadPatchAction(IXenConnection connection, string path, bool suppressHistory)
: base(connection, null, Messages.UPLOADING_PATCH, suppressHistory)
{
Host master = Helpers.GetMaster(connection);
if (master == null)

View File

@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34209
// Runtime Version:4.0.30319.18444
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@ -24291,6 +24291,24 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Upload.
/// </summary>
public static string PATCHINGWIZARD_UPLOADPAGE_TEXT {
get {
return ResourceManager.GetString("PATCHINGWIZARD_UPLOADPAGE_TEXT", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Uploading selected file to your servers.
/// </summary>
public static string PATCHINGWIZARD_UPLOADPAGE_TITLE {
get {
return ResourceManager.GetString("PATCHINGWIZARD_UPLOADPAGE_TITLE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to XVA (*.xva)|*.xva|XVA Version 1 (ova.xml)|ova.xml.
/// </summary>
@ -31569,7 +31587,16 @@ namespace XenAdmin {
}
/// <summary>
/// Looks up a localized string similar to Uploading Update to Server &apos;{0}&apos;....
/// Looks up a localized string similar to Uploading - {0}%.
/// </summary>
public static string UPLOADING_PATCH_PROGRESS {
get {
return ResourceManager.GetString("UPLOADING_PATCH_PROGRESS", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Uploading to server &apos;{0}&apos;....
/// </summary>
public static string UPLOADING_PATCH_TO {
get {

View File

@ -10927,7 +10927,7 @@ Do you want to continue?</value>
<value>Uploading Update...</value>
</data>
<data name="UPLOADING_PATCH_TO" xml:space="preserve">
<value>Uploading Update to Server '{0}'...</value>
<value>Uploading to server '{0}'...</value>
</data>
<data name="UPSELL_BLURB_ALERTS" xml:space="preserve">
<value>Upgrade your XenServer license to enable Alerting and Reporting capabilities. Email based performance and error alerting will proactively notify administrators of error conditions or performance problems before they affect critical services.
@ -12252,4 +12252,13 @@ You will need to navigate to the Console on each of the selected VMs to complete
<data name="YOU_ARE_HERE" xml:space="preserve">
<value>You are here</value>
</data>
<data name="PATCHINGWIZARD_UPLOADPAGE_TEXT" xml:space="preserve">
<value>Upload</value>
</data>
<data name="PATCHINGWIZARD_UPLOADPAGE_TITLE" xml:space="preserve">
<value>Uploading selected file to your servers</value>
</data>
<data name="UPLOADING_PATCH_PROGRESS" xml:space="preserve">
<value>Uploading - {0}%</value>
</data>
</root>