xenadmin/XenAdmin/Wizards/BugToolWizardFiles/BugToolPageSelectCapabilities.cs
Konstantina Chremmou ee648135f6 Since it is easy to forget calling the base class method at the beginning of the
PageLoaded override in derived classes, enforce it by wrapping the page specific
code in a new virtual method, which the derived classes can override and PageLoaded
can call after its own logic.

Signed-off-by: Konstantina Chremmou <konstantina.chremmou@citrix.com>
2018-03-09 11:22:26 +00:00

636 lines
22 KiB
C#

/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Xml;
using XenAdmin.Controls;
using XenAdmin.Core;
using XenAPI;
using XenAdmin.Actions;
using XenAdmin.Dialogs;
using XenCenterLib;
namespace XenAdmin.Wizards.BugToolWizardFiles
{
public partial class BugToolPageSelectCapabilities : XenTabPage
{
#region Private fields
private List<Host> _hostList = new List<Host>();
private List<Capability> _capabilities = new List<Capability>();
private Dictionary<Host, List<Capability>> hostCapabilities;
private List<GetSystemStatusCapabilities> actions;
private ActionProgressDialog dialog;
private bool cancelled;
#endregion
public BugToolPageSelectCapabilities()
{
InitializeComponent();
//set this here due to a framework bug
splitContainer1.Panel1MinSize = 250;
splitContainer1.Panel2MinSize = 200;
this.linkLabel1.Visible = !XenAdmin.Core.HiddenFeatures.LinkLabelHidden;
}
public override string Text{get { return Messages.BUGTOOL_PAGE_CAPABILITIES_TEXT; }}
public override string PageTitle { get { return Messages.BUGTOOL_PAGE_CAPABILITIES_PAGETITLE; } }
public override string HelpID { get { return "SelectReportContents"; } }
public override bool EnableNext()
{
return wizardCheckAnyChecked();
}
protected override void PageLoadedCore(PageLoadedDirection direction)
{
if (direction == PageLoadedDirection.Forward)
{
ClearButton.Enabled = wizardCheckAnyChecked();
SelectButton.Enabled = wizardCheckAnyUnchecked();
}
}
private bool wizardCheckAnyChecked()
{
foreach (DataGridViewRow row in dataGridViewItems.Rows)
{
var capRow = row as CapabilityRow;
if (capRow != null && capRow.Capability.Checked)
return true;
}
return false;
}
private bool wizardCheckAnyUnchecked()
{
foreach (DataGridViewRow row in dataGridViewItems.Rows)
{
var capRow = row as CapabilityRow;
if (capRow != null && !capRow.Capability.Checked)
return true;
}
return false;
}
/// <summary>
///
/// </summary>
/// <param name="HostList"></param>
/// <returns>If success of not - false with stop moving to next page</returns>
public bool GetCommonCapabilities(List<Host> HostList)
{
if (!cancelled && Helpers.ListsContentsEqual<Host>(_hostList, HostList))
return true;
_hostList = HostList;
dataGridViewItems.Rows.Clear();
if (dialog != null && dialog.Visible)
dialog.Close();
hostCapabilities = new Dictionary<Host, List<Capability>>();
actions = new List<GetSystemStatusCapabilities>();
cancelled = false;
dialog = new ActionProgressDialog(Messages.SERVER_STATUS_REPORT_GET_CAPABILITIES);
dialog.ShowCancel = true;
dialog.CancelClicked += new EventHandler(dialog_CancelClicked);
foreach (Host host in _hostList)
{
GetSystemStatusCapabilities action = new GetSystemStatusCapabilities(host);
actions.Add(action);
action.Completed += Common_action_Completed;
action.RunAsync();
}
if (_hostList.Count > 0)
dialog.ShowDialog(this);
return !cancelled;
}
private void dialog_CancelClicked(object sender, EventArgs e)
{
dialog.Close();
cancelled = true;
// Need to unhook events on current actions, to stop them
// interfeering when they return in 20mins
foreach (GetSystemStatusCapabilities action in actions)
action.Completed -= Common_action_Completed;
}
private void Common_action_Completed(ActionBase sender)
{
Program.Invoke(this, delegate()
{
if (cancelled)
return;
GetSystemStatusCapabilities caps = sender as GetSystemStatusCapabilities;
if (caps == null)
return;
hostCapabilities[caps.Host] =
caps.Succeeded ? parseXMLToList(caps) : null;
if (hostCapabilities.Count >= _hostList.Count)
{
dialog.Close();
CombineCapabilitiesLists();
}
});
}
private List<Capability> parseXMLToList(Actions.GetSystemStatusCapabilities action)
{
List<Capability> capabilities = new List<Capability>();
XmlDocument doc = new XmlDocument();
doc.LoadXml(action.Result);
foreach (XmlNode node in doc.GetElementsByTagName("capability"))
{
Capability c = new Capability();
foreach (XmlAttribute a in node.Attributes)
{
string name = a.Name;
string value = a.Value;
if (name == "content-type")
c.ContentType = value == "text/plain" ? ContentType.text_plain : ContentType.application_data;
else if (name == "default-checked")
c.DefaultChecked = value == "yes" ? true : false;
else if (name == "key")
c.Key = value;
else if (name == "max-size")
c.MaxSize = Int64.Parse(value);
else if (name == "min-size")
c.MinSize = Int64.Parse(value);
else if (name == "max-time")
c.MaxTime = Int64.Parse(value);
else if (name == "min-time")
c.MinTime = Int64.Parse(value);
else if (name == "pii")
c.PII = value == "yes" ? PrivateInformationIncluded.yes :
value == "no" ? PrivateInformationIncluded.no :
value == "maybe" ? PrivateInformationIncluded.maybe : PrivateInformationIncluded.customized;
}
capabilities.Add(c);
}
return capabilities;
}
private void CombineCapabilitiesLists()
{
List<Capability> combination = null;
foreach (List<Capability> capabilities in hostCapabilities.Values)
{
if (capabilities == null)
continue;
if (combination == null)
{
combination = capabilities;
continue;
}
combination = Helpers.ListsCommonItems<Capability>(combination, capabilities);
}
if (combination == null || combination.Count <= 0)
{
using (var dlg = new ThreeButtonDialog(
new ThreeButtonDialog.Details(
SystemIcons.Error,
Messages.SERVER_STATUS_REPORT_CAPABILITIES_FAILED,
Messages.SERVER_STATUS_REPORT)))
{
dlg.ShowDialog(this);
}
cancelled = true;
return;
}
_capabilities = combination;
_capabilities.Add(GetClientCapability());
Sort_capabilities();
buildList();
}
private Capability GetClientCapability()
{
Capability clientCap = new Capability();
clientCap.ContentType = ContentType.text_plain;
clientCap.DefaultChecked = true;
clientCap.Key = "client-logs";
clientCap.MaxSize = getLogSize();
clientCap.MinSize = clientCap.MaxSize;
clientCap.MaxTime = -1;
clientCap.MinTime = -1;
clientCap.PII = PrivateInformationIncluded.yes;
return clientCap;
}
private void Sort_capabilities()
{
_capabilities.Sort(new Comparison<Capability>(delegate(Capability obj1, Capability obj2)
{
int piicompare = obj1.PII.CompareTo(obj2.PII);
if (piicompare == 0)
return StringUtility.NaturalCompare(obj1.ToString(), obj2.ToString());
else
return piicompare;
}));
}
private void OnCheckedCapabilitiesChanged()
{
string totalSize, totalTime;
CalculateTotalSizeAndTime(out totalSize, out totalTime);
TotalSizeValue.Text = totalSize;
TotalTimeValue.Text = totalTime;
ClearButton.Enabled = wizardCheckAnyChecked();
SelectButton.Enabled = wizardCheckAnyUnchecked();
OnPageUpdated();
}
private void buildList()
{
try
{
dataGridViewItems.SuspendLayout();
dataGridViewItems.Rows.Clear();
var list = new List<DataGridViewRow>();
foreach (Capability c in _capabilities)
list.Add(new CapabilityRow(c));
dataGridViewItems.Rows.AddRange(list.ToArray());
}
finally
{
dataGridViewItems.ResumeLayout();
}
OnCheckedCapabilitiesChanged();
}
private long getLogSize()
{
String path = Program.GetLogFile_();
if (path != null)
{
// Size of XenCenter.log
FileInfo logFileInfo = new FileInfo(path);
long total = logFileInfo.Length;
// Add size of any XenCenter.log.x
DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(path));
Regex regex = new Regex(Regex.Escape(Path.GetFileName(path)) + @"\.\d+");
foreach (FileInfo file in di.GetFiles())
{
if (regex.IsMatch(file.Name))
total += file.Length;
}
return total;
}
else
{
return 50 * Util.BINARY_MEGA;
}
}
private void CalculateTotalSizeAndTime(out string totalSize, out string totalTime)
{
var sizeMinList = new List<long>();
var sizeMaxList = new List<long>();
var timeMinList = new List<long>();
var timeMaxList = new List<long>();
foreach (var row in dataGridViewItems.Rows)
{
var capRow = row as CapabilityRow;
if (capRow != null && capRow.Capability.Checked)
{
var c = capRow.Capability;
int m = c.Key == "client-logs" ? 1 : _hostList.Count;
sizeMinList.Add(c.MinSize * m);
sizeMaxList.Add(c.MaxSize * m);
timeMinList.Add(c.MinTime * m);
timeMaxList.Add(c.MaxTime * m);
}
}
totalSize = Helpers.StringFromMaxMinSizeList(sizeMinList, sizeMaxList);
totalTime = Helpers.StringFromMaxMinTimeList(timeMinList, timeMaxList);
}
public IEnumerable<Capability> Capabilities
{
get
{
return from DataGridViewRow row in dataGridViewItems.Rows
let capRow = row as CapabilityRow
where capRow != null && capRow.Capability.Checked
select capRow.Capability;
}
}
#region Control event handlers
private void dataGridViewItems_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
{
var row1 = dataGridViewItems.Rows[e.RowIndex1] as CapabilityRow;
var row2 = dataGridViewItems.Rows[e.RowIndex2] as CapabilityRow;
if (row1 != null && row2 != null && e.Column.Index == columnImage.Index)
{
e.SortResult = row1.Capability.PII.CompareTo(row2.Capability.PII);
e.Handled = true;
}
}
private void dataGridViewItems_SelectionChanged(object sender, EventArgs e)
{
if (dataGridViewItems.SelectedRows.Count > 0)
{
var row = dataGridViewItems.SelectedRows[0] as CapabilityRow;
if (row == null)
return;
DescriptionValue.Text = row.Capability.Description;
SizeValue.Text = row.Capability.EstimatedSize;
TimeValue.Text = row.Capability.EstimatedTime;
}
}
private void dataGridViewItems_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex != columnCheck.Index)
return;
if (e.RowIndex < 0 || e.RowIndex >= dataGridViewItems.RowCount)
return;
var row = dataGridViewItems.Rows[e.RowIndex] as CapabilityRow;
if (row == null)
return;
row.Capability.Checked = !row.Capability.Checked;
row.Update();
OnCheckedCapabilitiesChanged();
}
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
try
{
System.Diagnostics.Process.Start(InvisibleMessages.PRIVACY);
}
catch
{
using (var dlg = new ThreeButtonDialog(
new ThreeButtonDialog.Details(
SystemIcons.Error,
Messages.HOMEPAGE_ERROR_MESSAGE,
Messages.XENCENTER)))
{
dlg.ShowDialog(this);
}
}
}
private void SelectButton_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGridViewItems.Rows)
{
var capRow = row as CapabilityRow;
if (capRow != null && !capRow.Capability.Checked)
{
capRow.Capability.Checked = true;
capRow.Update();
}
}
OnCheckedCapabilitiesChanged();
}
private void ClearButton_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGridViewItems.Rows)
{
var capRow = row as CapabilityRow;
if (capRow != null && capRow.Capability.Checked)
{
capRow.Capability.Checked = false;
capRow.Update();
}
}
OnCheckedCapabilitiesChanged();
}
#endregion
private class CapabilityRow : DataGridViewRow
{
public readonly Capability Capability;
private readonly DataGridViewCheckBoxCell cellCheck = new DataGridViewCheckBoxCell();
private readonly DataGridViewTextBoxCell cellItem = new DataGridViewTextBoxCell();
private readonly DataGridViewImageCell cellImage = new DataGridViewImageCell();
public CapabilityRow(Capability capability)
{
Capability = capability;
Cells.AddRange(cellCheck, cellItem, cellImage);
Update();
}
public void Update()
{
cellCheck.Value = Capability.Checked;
cellItem.Value = Capability.Name;
switch(Capability.PII)
{
case PrivateInformationIncluded.maybe:
cellImage.Value = Properties.Resources.alert2_16;
break;
case PrivateInformationIncluded.customized:
cellImage.Value = Properties.Resources.alert3_16;
break;
case PrivateInformationIncluded.no:
cellImage.Value = Properties.Resources.alert4_16;
break;
case PrivateInformationIncluded.yes:
default:
cellImage.Value = Properties.Resources.alert1_16;
break;
}
cellImage.ToolTipText = Capability.PiiText;
}
}
}
public enum ContentType { text_plain, application_data };
public enum PrivateInformationIncluded { yes, maybe, customized, no};
public class Capability : IComparable<Capability>, IEquatable<Capability>
{
public ContentType ContentType;
bool _defaultChecked;
public long MaxSize;
public long MinSize;
public long MaxTime;
public long MinTime;
public PrivateInformationIncluded PII;
private string _key;
private string _name;
private string _description;
public bool Checked;
public bool DefaultChecked
{
get
{
return _defaultChecked;
}
set
{
_defaultChecked = value;
Checked = value;
}
}
public string PiiText
{
get
{
switch (PII)
{
case PrivateInformationIncluded.yes:
return Messages.PII_YES;
case PrivateInformationIncluded.maybe:
return Messages.PII_MAYBE;
case PrivateInformationIncluded.customized:
return Messages.PII_CUSTOMISED;
case PrivateInformationIncluded.no:
default:
return Messages.PII_NO;
}
}
}
public string Key
{
get
{
return _key;
}
set
{
_key = value;
_name = Core.PropertyManager.GetFriendlyName(string.Format("Label-host.system_status-{0}", _key));
if (string.IsNullOrEmpty(_name))
_name = _key;
_description = Core.PropertyManager.GetFriendlyName(string.Format("Description-host.system_status-{0}", _key));
}
}
public string Name
{
get { return _name; }
}
public string Description
{
get { return _description; }
}
public string EstimatedSize
{
get
{
return Helpers.StringFromMaxMinSize(MinSize, MaxSize);
}
}
public string EstimatedTime
{
get
{
return Helpers.StringFromMaxMinTime(MinTime, MaxTime);
}
}
public override string ToString()
{
return _name;
}
public int CompareTo(Capability other)
{
return StringUtility.NaturalCompare(this.Key, other.Key);
}
public bool Equals(Capability other)
{
return this.Key.Equals(other.Key);
}
}
}