mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-11-25 06:16:37 +01:00
4b0b83245f
* CA-34231: Replace negative language with `block list` in code and references Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `stop` in code and references Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `freezing` in code Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `run/ran` in code comments Some paramater mentions have been renamed, as they will be renamed in future commits. Excluded mentions in XenAPI/Host.cs and XenAPI/VM.cs since code is autogenerated. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # CFUValidator/CommandLineOptions/CFUCommandLineOptionManager.cs # XenAdmin/Controls/Wlb/WlbOptModeScheduler.cs # XenAdmin/Dialogs/Wlb/WorkloadReports.cs * CA-34231: Replace negative language with `run` in Command.cs Run method Used Resharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/TabPages/GeneralTabPage.cs * CA-34231: Replace negative language with `run` in Command.cs CanRun method Used Resharper rename utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `run` in Command.cs CanRunCore method Used ReSharper rename utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Commands/DRConfigureCommand.cs # XenAdmin/Commands/DRDryrunCommand.cs # XenAdmin/Commands/DRFailbackCommand.cs # XenAdmin/Commands/DRFailoverCommand.cs # XenAdmin/Commands/DisasterRecoveryCommand.cs # XenAdmin/Commands/VMGroupCommand.cs * CA-34231: Replace negative language with `run` in Command.cs RunCore method Used ReSharper rename utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `run` in Command.cs GetCantExecuteReasonCore method Used ReSharper rename utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `run` in Command.cs GetCantRunReasons method Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace remaining negative language with `run` in Command.cs Also applied to related symbols. Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `run` in methods named CanRun Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `run` in methods in CrossPoolMigrateCommand.cs Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Commands/CrossPoolMigrateCommand.cs * CA-34231: Replace negative language with `run` in remaining Run methods Also updated negative language in `DeleteVMCommand` Also updated in comment in `CrossPoolMigrateCommand` Also renamed missed instances of `CanRun` Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `run` in `CanRunCore` and `RunCore` Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace remaining negative language with `run` in Commands folder Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace remaining negative language with `run` in XenAdmin/Controls folder Used ReSharper renaming utility. Had to rename `WlbReportView.xs:RunReport()` to `WlbReportView.xs:StartRunReport()` to resolve conflict with change from `WlbReportView:ExecuteReport()` to `WlbReportView:RunReport()` Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Controls/Wlb/WlbOptModeScheduler.cs # XenAdmin/Dialogs/Wlb/WorkloadReports.cs # XenAdminTests/UnitTests/WlbTests/WlbScheduledTaskTests.cs * CA-34231: Replace all remaining negative language with `run` in code Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Commands/Controls/WlbRecommendations.cs # XenAdminTests/UnitTests/WlbTests/WlbScheduledTaskTests.cs # XenModel/WLB/WlbScheduledTask.cs * CA-34231: Replace negative language with `supporter` or `bond member` in code strings Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `supporter` or `bond member` in Messages string Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/MainWindow.cs # XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectServers.cs # XenModel/Messages.Designer.cs # XenModel/Messages.resx * CA-34231: Replace remaining negative language with `supporter` in .resx files Used ReSharper renaming utility. FriendlyErrorNames.resx has been excluded. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `supporter` or `bond member` in XenAdmin code Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Dialogs/NewPoolDialog.cs * CA-34231: Replace negative language with `supporter` or `bond member` in XenModel code Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `coordinator` in CFUValidator code Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # CFUValidator/CFUValidator.cs * CA-34231: Replace negative language with `coordinator` in solution's comments and hardcoded strings Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `coordinator` in `Helpers:GetCoordinator` method Used ReSharper renaming utility. also renamed similarly named method in `ObjectChange.cs` Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Alerts/Types/HotfixEligibilityAlert.cs # XenAdmin/Controls/CustomDataGraph/ArchiveMaintainer.cs * CA-34231: Replace negative language with `coordinator` in `EvacuateHostDialog.resx` Used ReSharper renaming utility. Excluded jp and zh resources Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Dialogs/EvacuateHostDialog.resx * CA-34231: Replace negative language with `coordinator` in `EvacuateHostDialog.resx` Used ReSharper renaming utility. Excluded jp and zh resource files. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Dialogs/NewPoolDialog.resx * CA-34231: Rename missing language references for change to `coordinator` Misc files were not saved before last commits. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `coordinator` in `Messages.resx`'s code Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Commands/HACommand.cs # XenAdmin/TabPages/AdPage.cs # XenModel/Actions/Network/CreateBondAction.cs # XenModel/Actions/Network/NetworkAction.cs # XenModel/Messages.Designer.cs # XenModel/Messages.resx * CA-34231: Replace negative language with `coordinator` in `ExternalPluginAction.cs` Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `coordinator` in `XenAdmin/Commands` Used ReSharper renaming utility. Also replace negative language in missed comment in `ExternalPluginAction.cs` Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Commands/AddHostToPoolCommand.cs # XenAdmin/Commands/HACommand.cs * CA-34231: Replace negative language with `coordinator` in `Helpers.cs` Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `coordinator` in `NetworkingHelper.cs` Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `coordinator` in `PoolJoinRules.cs` Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Dialogs/NewPoolDialog.cs * CA-34231: Replace negative language with `coordinator` in `XenAdmin/Commands`, `Controls`, and `Core` Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Commands/AddHostToPoolCommand.cs * CA-34231: Replace negative language with `coordinator` in `XenAdmin/Diagnostics` Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `coordinator` in `XenAdmin/Dialogs` Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Dialogs/NewPoolDialog.cs * CA-34231: Replace remaining negative language with `coordinator` in `XenAdmin` Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/MainWindow.cs # XenAdmin/TabPages/GeneralTabPage.cs # XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectServers.cs # XenAdmin/Wizards/RollingUpgradeWizard/RollingUpgradeExtrasPage.cs # XenAdmin/Wizards/RollingUpgradeWizard/RollingUpgradeWizard.cs # XenAdmin/Wizards/RollingUpgradeWizard/RollingUpgradeWizardPrecheckPage.cs # XenAdmin/XenSearch/Columns.cs * CA-34231: Replace remaining negative language with `coordinator` in `XenModel\Actions` Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenModel/Actions/Network/CreateBondAction.cs * CA-34231: Replace remaining negative language with `coordinator` in `XenModel` Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace remaining negative strings with `main` in `Messages.resx` Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenModel/Messages.Designer.cs # XenModel/Messages.resx * CA-34231: Replace remaining negative string names with `main` in `Messages.resx` Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Dialogs/OptionsPages/SaveAndRestoreOptionsPage.cs # XenModel/Messages.resx * CA-34231: Rename dialogs to replace negative connotations with `main` Used ReSharper renaming utility Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `main` in `SaveAndResoreOptionsPage.cs` Also updated its resx file. Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> # Conflicts: # XenAdmin/Dialogs/OptionsPages/SaveAndRestoreOptionsPage.cs * CA-34231: Fix invalid reference in `SaveAndRestoreOptionsPage.Designer.cs` after renaming Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `main` in `EnterMainPasswordDialog.cs` Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `main` in `ChangeMainPasswordDialog.cs` Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Fix invalid reference not changed after renaming `EnterMainPasswordDialog.cs` Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace remaining negative language with `main` in `XenAdmin/Dialogs` Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Update class names in HelpManager.resx Following renaming of main password dialog. Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace negative language with `main` in `Metadata.cs` Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Remove remaning negative language with `coordinator` from `Messages.resx` Used ReSharper renaming Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Remove remaning negative language with `other pool member` from `Messages.resx` Used ReSharper Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CA-34231: Replace remaining negative language in solution Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Remove commented out code in VNCGraphicsClient.cs Code has only been improved partially as it's not strictly relevant to the PR Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Amend negative word replacement in XSVNCScreen.cs Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Simplify debug call formatting in NewPoolDialog.cs Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Add code mistakenly removed in MainWindow.cs Removed as part of `f155f9c8` Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Revert renaming of constant related to Windows' API Considered external to CH Center Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Amend hotkey for Coordinator field in `NewPoolDialog` Previous ALT+<key> hotkey was conflicting with CreatePool Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Remove unecessary whitespace in EvacuateHostDialog.cs Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Update if block to exclude unecessary else in DRFailoverWizard.cs Not relevant to the PR, but the change is small enought to no need extra testing Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Amend typo in PoolJoinRules.cs supporer -> supporter Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Replace missing negative language with `coordinator` in `XenAPI-Extensions/Pool.cs` Variables and methods XenAPI-Extensions were mistakenly skipped Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Replace negative language in `XenApi-Extensions` with `coordinator/interface` Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Replace negative language in `XenApi-Extensions` with `supporter/member` Used ReSharper renaming utility. Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Replace remaining negative language in `XenServerHealthCheckBugTool.cs` This is only used to format the string Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Change line-endings to CRLF in `Page_CloudConfigParamters.cs` Done in order to fix merge conflict into master Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com> * CP-34231: Amend misc negative language renaming typos `XenServerHealthCheckBugTool` and `XenServerHealthCheckService` Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>
897 lines
37 KiB
C#
897 lines
37 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.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using XenAdmin.Core;
|
|
using XenAdmin.Wlb;
|
|
using XenAPI;
|
|
using XenAdmin.Actions;
|
|
using XenAdmin.Actions.Wlb;
|
|
using XenAdmin.Commands;
|
|
|
|
|
|
namespace XenAdmin.Controls.Wlb
|
|
{
|
|
public partial class WlbOptimizePool : UserControl
|
|
{
|
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
private readonly ListViewColumnSorter columnSorter = new ListViewColumnSorter();
|
|
|
|
private IXenObject _xenObject;
|
|
private Pool _pool;
|
|
private Dictionary<VM, WlbOptimizationRecommendation> _vmOptList = new Dictionary<VM, WlbOptimizationRecommendation>();
|
|
private Dictionary<XenRef<VM>, string[]> _recommendations = new Dictionary<XenRef<VM>, string[]>();
|
|
private string _optId = String.Empty;
|
|
private bool _autoOptEnabled = false;
|
|
private bool _powerManagementEnabled = false;
|
|
|
|
// TODO: change to proper report file name
|
|
private readonly string ReportFile = "pool_optimization_history";
|
|
|
|
// All used in the listview.
|
|
private readonly Font OperationTextFont;
|
|
private readonly Color OperationTextColor;
|
|
private readonly Color ShadedRowColor;
|
|
private readonly Color DisabledShadedRowColor;
|
|
|
|
// Listview minimum column widths
|
|
private int[] minimumColumnWidths = { 0, 25, 25, 25 };
|
|
|
|
/// <summary>
|
|
/// Initialize optimize pool listview
|
|
/// </summary>
|
|
public WlbOptimizePool()
|
|
{
|
|
InitializeComponent();
|
|
Host_CollectionChangedWithInvoke += Program.ProgramInvokeHandler(Host_CollectionChanged);
|
|
VM_CollectionChangedWithInvoke=Program.ProgramInvokeHandler(VM_CollectionChanged);
|
|
OperationTextFont = new Font(this.Font, FontStyle.Bold);
|
|
OperationTextColor = Color.Black;
|
|
ShadedRowColor = Color.FromArgb(230, 240, 255);
|
|
DisabledShadedRowColor = Color.FromArgb(224, 222, 205);
|
|
|
|
optimizePoolListView.SmallImageList = Images.ImageList16;
|
|
optimizePoolListView.ListViewItemSorter = columnSorter;
|
|
|
|
recommendationUpdateTimer = new System.Threading.Timer(TimerCallback, null, 0, 0);
|
|
StartTimer();
|
|
}
|
|
|
|
#region public methods
|
|
|
|
/// <summary>
|
|
/// Set XenModelOpject and populate optimize pool listview properly
|
|
/// </summary>
|
|
public IXenObject XenObject
|
|
{
|
|
set
|
|
{
|
|
Program.AssertOnEventThread();
|
|
|
|
if (_xenObject != null)
|
|
{
|
|
if (_xenObject is Pool)
|
|
{
|
|
this._pool.PropertyChanged -= Pool_PropertyChanged;
|
|
|
|
_pool.Connection.Cache.DeregisterCollectionChanged<XenAPI.Host>(Host_CollectionChangedWithInvoke);
|
|
foreach (Host host in _pool.Connection.Cache.Hosts)
|
|
{
|
|
host.PropertyChanged -= Host_PropertyChanged;
|
|
|
|
host.Connection.Cache.DeregisterCollectionChanged<VM>(VM_CollectionChangedWithInvoke);
|
|
foreach (VM vm in host.Connection.Cache.VMs)
|
|
{
|
|
vm.PropertyChanged -= VM_PropertyChanged;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_xenObject = value;
|
|
_pool = null;
|
|
|
|
if (_xenObject != null)
|
|
{
|
|
if (_xenObject is Pool)
|
|
{
|
|
_pool = (Pool)_xenObject;
|
|
|
|
this._pool.PropertyChanged += Pool_PropertyChanged;
|
|
|
|
_pool.Connection.Cache.RegisterCollectionChanged<XenAPI.Host>(Host_CollectionChangedWithInvoke);
|
|
foreach (Host host in _pool.Connection.Cache.Hosts)
|
|
{
|
|
host.PropertyChanged -= Host_PropertyChanged;
|
|
host.PropertyChanged += Host_PropertyChanged;
|
|
|
|
host.Connection.Cache.RegisterCollectionChanged<VM>(VM_CollectionChangedWithInvoke);
|
|
foreach (VM vm in host.Connection.Cache.VMs)
|
|
{
|
|
vm.PropertyChanged -= VM_PropertyChanged;
|
|
vm.PropertyChanged += VM_PropertyChanged;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BuildRecList();
|
|
}
|
|
}
|
|
|
|
public void SetOptControlProperties(bool autoOptEnabled, bool powerManagementEnabled)
|
|
{
|
|
_autoOptEnabled = autoOptEnabled;
|
|
_powerManagementEnabled = powerManagementEnabled;
|
|
|
|
this.SuspendLayout();
|
|
if (WlbServerState.GetState(_pool) == WlbServerState.ServerState.Enabled)
|
|
{
|
|
// Update listView VM/Host header text
|
|
this.optimizePoolListView.BeginUpdate();
|
|
this.columnHeader1.Text = Messages.WLB_OPT_HEADER_VMHOST;
|
|
this.optimizePoolListView.EndUpdate();
|
|
}
|
|
else
|
|
{
|
|
// Update listView VM/Host header text
|
|
this.optimizePoolListView.BeginUpdate();
|
|
this.columnHeader1.Text = Messages.WLB_OPT_HEADER_VM;
|
|
this.optimizePoolListView.EndUpdate();
|
|
}
|
|
|
|
this.ResumeLayout();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called from wlb page, used to disable/enable optimize pool controls properly when WLB is Enabled/Disabled
|
|
/// </summary>
|
|
/// <param name="disable">disable controls if it's true, else enable controls</param>
|
|
public void WLBOptDisable(bool disable)
|
|
{
|
|
optimizePoolListView.BeginUpdate();
|
|
if (disable)
|
|
{
|
|
this.statusLabel.Visible = false;
|
|
this.optimizePoolListView.Items.Clear();
|
|
this.optimizePoolListView.Visible = true;
|
|
this.optimizePoolListView.Enabled = false;
|
|
this.applyButton.Visible = true;
|
|
this.applyButton.Enabled = false;
|
|
}
|
|
else
|
|
{
|
|
if (!this.optimizePoolListView.Visible)
|
|
{
|
|
this.statusLabel.Visible = true;
|
|
this.optimizePoolListView.Items.Clear();
|
|
this.optimizePoolListView.Visible = true;
|
|
this.applyButton.Visible = true;
|
|
this.applyButton.Enabled = false;
|
|
}
|
|
else
|
|
{
|
|
this.optimizePoolListView.Enabled = true;
|
|
if (this.optimizePoolListView.Items.Count > 0)
|
|
this.applyButton.Enabled = true;
|
|
else
|
|
this.statusLabel.Visible = true;
|
|
}
|
|
}
|
|
optimizePoolListView.EndUpdate();
|
|
}
|
|
#endregion
|
|
|
|
#region Event Handlers
|
|
|
|
/// <summary>
|
|
/// Triggered when pool wlb enabled/disabled and optimize pool
|
|
/// </summary>
|
|
/// <param name="sender">XenObject<Pool></param>
|
|
/// <param name="e">PropertyChangedEventArgs</param>
|
|
private void Pool_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
Program.Invoke(this, delegate
|
|
{
|
|
if (_xenObject != null && Program.MainWindow.TheTabControl.SelectedTab == Program.MainWindow.TabPageWLB)
|
|
{
|
|
if (e.PropertyName == "wlb_enabled")
|
|
{
|
|
// enable/disble controls and display message properly
|
|
WLBOptDisable(!Helpers.WlbEnabled(((Pool)sender).Connection));
|
|
}
|
|
|
|
if (e.PropertyName == "other_config")
|
|
{
|
|
// check whether it's optimize pool event
|
|
if (((Pool)sender).other_config.ContainsKey(WlbOptimizationRecommendation.OPTIMIZINGPOOL))
|
|
{
|
|
BuildRecList();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Triggered when hosts leave/join pool
|
|
/// </summary>
|
|
/// <param name="sender">object</param>
|
|
/// <param name="e">CollectionChangeEventArgs</param>
|
|
private void Host_CollectionChanged(object sender, CollectionChangeEventArgs e)
|
|
{
|
|
switch (e.Action)
|
|
{
|
|
case CollectionChangeAction.Add:
|
|
((Host)e.Element).PropertyChanged -= Host_PropertyChanged;
|
|
((Host)e.Element).PropertyChanged += Host_PropertyChanged;
|
|
break;
|
|
case CollectionChangeAction.Remove:
|
|
((Host)e.Element).PropertyChanged -= Host_PropertyChanged;
|
|
break;
|
|
}
|
|
// It's not necessary to call BuildRecList here
|
|
// because Remove/add Hosts also triger VM_CollectionChange,
|
|
}
|
|
|
|
/// <summary>
|
|
/// respond to host name change and vms leaving/joining the host.
|
|
/// </summary>
|
|
/// <param name="sender">XenObject<Host></param>
|
|
/// <param name="e">PropertyChangedEventArgs</param>
|
|
private void Host_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
if (_pool != null &&
|
|
Helpers.WlbEnabled(_pool.Connection) &&
|
|
applyButton.Enabled &&
|
|
IsHostOnListView(((Host)sender), false))
|
|
{
|
|
if (e.PropertyName == "name_label")
|
|
{
|
|
optimizePoolListView.BeginUpdate();
|
|
foreach (ListViewItem item in optimizePoolListView.Items)
|
|
{
|
|
UpdateRow(item);
|
|
}
|
|
optimizePoolListView.EndUpdate();
|
|
}
|
|
|
|
if ((e.PropertyName == "resident_VMs" && IsHostOnListView(((Host)sender), true))
|
|
|| (e.PropertyName == "enabled" && !((Host)sender).enabled))
|
|
{
|
|
Program.Invoke(this, delegate()
|
|
{
|
|
BuildRecList();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check whether Host property change relates to optimize pool list view. Will return true if the host is on the list view.
|
|
/// Must be called on the event thread.
|
|
/// </summary>
|
|
/// <param name="host">XenObject<Host></param>
|
|
/// <param name="checkVMHost">Whether to check VM host</param>
|
|
/// <returns>True if host is on the optimize pool list view, else return false</returns>
|
|
private bool IsHostOnListView(Host host, bool checkVMHost)
|
|
{
|
|
Program.AssertOnEventThread();
|
|
|
|
bool onList = false;
|
|
|
|
// should find if any vms that not on host but in listview
|
|
foreach (ListViewItem item in optimizePoolListView.Items)
|
|
{
|
|
Host fromHost = ((WlbOptimizationRecommendation)item.Tag).fromHost;
|
|
Host toHost = ((WlbOptimizationRecommendation)item.Tag).toHost;
|
|
VM vm = ((WlbOptimizationRecommendation)item.Tag).vm;
|
|
|
|
// whether check vm's host changes
|
|
if (checkVMHost)
|
|
{
|
|
// update optimize pool listview if vm from host is to move to host
|
|
if (vm.Connection.Resolve(vm.resident_on) == toHost)
|
|
{
|
|
onList = true;
|
|
}
|
|
}
|
|
// whether host is related to optimize pool listview
|
|
else if ((fromHost != null && fromHost == host)
|
|
|| (toHost != null && toHost== host))
|
|
{
|
|
onList = true;
|
|
}
|
|
}
|
|
return onList;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Triggered when vm collection is changed, pool is connected and optimize pool listview is visiable.
|
|
/// </summary>
|
|
/// <param name="sender">object</param>
|
|
/// <param name="e">CollectionChangeEventArgs</param>
|
|
private void VM_CollectionChanged(object sender, CollectionChangeEventArgs e)
|
|
{
|
|
Program.AssertOnEventThread();
|
|
|
|
switch (e.Action)
|
|
{
|
|
case CollectionChangeAction.Add:
|
|
((VM)e.Element).PropertyChanged -= VM_PropertyChanged;
|
|
((VM)e.Element).PropertyChanged += VM_PropertyChanged;
|
|
break;
|
|
case CollectionChangeAction.Remove:
|
|
((VM)e.Element).PropertyChanged -= VM_PropertyChanged;
|
|
break;
|
|
}
|
|
|
|
// only continue if pool is connect and pool is not null
|
|
if (_xenObject == null || !_xenObject.Connection.IsConnected)
|
|
return;
|
|
|
|
// only update recommendation listview if applyButton is enabled and a vm has been removed from collection
|
|
if (applyButton.Enabled && e.Action == CollectionChangeAction.Remove)
|
|
BuildRecList();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Triggered when vm state is changed
|
|
/// </summary>
|
|
/// <param name="sender">XenObject<VM></param>
|
|
/// <param name="e">PropertyChangedEventArgs</param>
|
|
private void VM_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
Program.Invoke(Program.MainWindow, () =>
|
|
{
|
|
|
|
// Find row for VM
|
|
ListViewItem item = FindItemFromVM((VM) sender);
|
|
if (item != null)
|
|
{
|
|
optimizePoolListView.BeginUpdate();
|
|
try
|
|
{
|
|
UpdateRow(item);
|
|
}
|
|
finally
|
|
{
|
|
optimizePoolListView.EndUpdate();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Finds the ListViewItem for the given VM. Will return null if no corresponding item could be found.
|
|
/// Must be called on the event thread.
|
|
/// </summary>
|
|
/// <param name="vm">XenObject<VM></param>
|
|
/// <returns>Return the listview item when found, null if nothing is found</returns>
|
|
private ListViewItem FindItemFromVM(VM vm)
|
|
{
|
|
Program.AssertOnEventThread();
|
|
|
|
foreach (ListViewItem item in optimizePoolListView.Items)
|
|
{
|
|
if (((WlbOptimizationRecommendation)item.Tag).vm == vm)
|
|
{
|
|
return item;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Apply optimization to a pool
|
|
/// </summary>
|
|
/// <param name="sender">object</param>
|
|
/// <param name="e">EventArgs</param>
|
|
private void ButtonApply_Click(object sender, EventArgs e)
|
|
{
|
|
if (this._pool == null)
|
|
return;
|
|
|
|
applyButton.Enabled = false;
|
|
|
|
action = HelpersGUI.FindActiveOptAction(_xenObject.Connection);
|
|
if ((action != null && action.GetType() != typeof(WlbOptimizePoolAction)) || action == null)
|
|
{
|
|
new WlbOptimizePoolAction(_pool, _vmOptList, _optId).RunAsync();
|
|
Program.MainWindow.UpdateToolbars();
|
|
}
|
|
}
|
|
|
|
private void linkLabelReportHistory_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
|
{
|
|
new ViewWorkloadReportsCommand(Program.MainWindow, _pool, ReportFile, true).Run();
|
|
}
|
|
|
|
private static void UpdateRow(ListViewItem row)
|
|
{
|
|
|
|
try // In try block to fix CA-40197
|
|
{
|
|
|
|
Program.AssertOnEventThread();
|
|
|
|
WlbOptimizationRecommendation optVMmSetting = (WlbOptimizationRecommendation)row.Tag;
|
|
|
|
if (String.IsNullOrEmpty(optVMmSetting.toHost.name_label) || String.IsNullOrEmpty(optVMmSetting.fromHost.name_label))
|
|
{
|
|
row.ImageIndex = (int)Images.GetIconFor(optVMmSetting.toHost ?? optVMmSetting.fromHost);
|
|
row.SubItems[1].Text = Helpers.GetName(optVMmSetting.toHost ?? optVMmSetting.fromHost);
|
|
row.SubItems[2].Text = optVMmSetting.toHost != null ? Messages.WLB_OPT_OPERATION_HOST_POWERON : Messages.WLB_OPT_REASON_POWEROFF;
|
|
}
|
|
else
|
|
{
|
|
row.ImageIndex = (int)Images.GetIconFor(optVMmSetting.vm);
|
|
row.SubItems[1].Text = optVMmSetting.vm.name_label;
|
|
row.SubItems[2].Text = String.Format(Messages.WLB_OPT_OPERATION_VM, optVMmSetting.fromHost.name_label, optVMmSetting.toHost.name_label);
|
|
}
|
|
|
|
row.SubItems[3].Text = optVMmSetting.reason;
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
log.Error(ex, ex);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Refresh Timer
|
|
private System.Threading.Timer recommendationUpdateTimer;
|
|
private const int RECOMMENDATION_INITIAL_INTERVAL = 1000 * 5; // 5 seconds interval
|
|
// Default to 2 minutes due to Kirkwood recommendation is generated every 2 minutes
|
|
private const int RECOMMENDATION_UPDATE_INTERVAL = 1000 * 30; // 30 seconds interval
|
|
AsyncAction action = null;
|
|
|
|
/// <summary>
|
|
/// start timer with 5 seconds interval
|
|
/// </summary>
|
|
private void StartTimer()
|
|
{
|
|
recommendationUpdateTimer.Change(RECOMMENDATION_INITIAL_INTERVAL, 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Timer call back, used to refresh optimize pool listview.
|
|
/// Dispose if program exits, do nothing if wlb tab is not focused
|
|
/// </summary>
|
|
/// <param name="o">object</param>
|
|
private void TimerCallback(object o)
|
|
{
|
|
if (recommendationUpdateTimer == null)
|
|
return;
|
|
|
|
if (Program.Exiting)
|
|
{
|
|
recommendationUpdateTimer.Dispose();
|
|
return;
|
|
}
|
|
|
|
if (Program.MainWindow != null && Program.MainWindow.WlbPage != null)
|
|
{
|
|
Program.Invoke(Program.MainWindow, delegate()
|
|
{
|
|
if (_xenObject != null && Program.MainWindow.TheTabControl.SelectedTab == Program.MainWindow.TabPageWLB
|
|
&& _pool != null &&_pool.Connection.IsConnected && _pool.Connection.Session != null)
|
|
{
|
|
BuildRecList();
|
|
}
|
|
});
|
|
}
|
|
recommendationUpdateTimer.Change(RECOMMENDATION_UPDATE_INTERVAL, 0);
|
|
}
|
|
#endregion
|
|
|
|
|
|
#region load optimizePoolListView properly
|
|
/// <summary>
|
|
/// Build optimize pool list view properly
|
|
/// </summary>
|
|
private void BuildRecList()
|
|
{
|
|
Program.AssertOnEventThread();
|
|
|
|
if(_xenObject == null)
|
|
return;
|
|
|
|
if (Helpers.WlbEnabled(_xenObject.Connection))
|
|
{
|
|
try
|
|
{
|
|
if (_xenObject is Pool)
|
|
{
|
|
_pool = (Pool)_xenObject;
|
|
|
|
// get any active WLB action
|
|
action = HelpersGUI.FindActiveWLBAction(_xenObject.Connection);
|
|
|
|
// make sure we are not initializing, starting or stopping WLB
|
|
if (action is DisableWLBAction || action is EnableWLBAction || action is InitializeWLBAction)
|
|
return;
|
|
|
|
optimizePoolListView.BeginUpdate();
|
|
|
|
// check whether optimize pool is running before load optimize pool listview
|
|
if ((action != null && action is WlbOptimizePoolAction)
|
|
|| (action == null && _pool.other_config.ContainsKey(WlbOptimizationRecommendation.OPTIMIZINGPOOL)
|
|
&& _pool.other_config[WlbOptimizationRecommendation.OPTIMIZINGPOOL] == Messages.IN_PROGRESS))
|
|
{
|
|
//statusLabel.Text = Messages.WLB_OPT_OPTIMIZING;
|
|
this.applyButton.Text = Messages.WLB_OPT_OPTIMIZING;
|
|
EnableControls(false, false);
|
|
}
|
|
else if (action as WlbRetrieveRecommendationsAction == null)
|
|
{
|
|
this.applyButton.Text = Messages.WLB_OPT_APPLY_RECOMMENDATIONS;
|
|
// retrieve recommendations, and load optimize pool listview properly
|
|
var optAction = new WlbRetrieveRecommendationsAction(_pool);
|
|
optAction.Completed += this.OptRecRetrieveAction_Completed;
|
|
optAction.RunAsync();
|
|
}
|
|
}
|
|
}
|
|
catch (Failure f)
|
|
{
|
|
statusLabel.Text = Messages.WLB_OPT_LOADING_ERROR;
|
|
log.Error(f, f);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
statusLabel.Text = Messages.WLB_OPT_LOADING_ERROR;
|
|
log.Error($"There was an error calling retrieve_wlb_recommendations on pool {_pool.name_label}.", e);
|
|
}
|
|
|
|
finally
|
|
{
|
|
optimizePoolListView.EndUpdate();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.WLBOptDisable(true);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve wlb optimize pool recommendation action complete handler.
|
|
/// Populate optimize pool listview and enable controls properly.
|
|
/// </summary>
|
|
protected void OptRecRetrieveAction_Completed(ActionBase sender)
|
|
{
|
|
AsyncAction action = (AsyncAction)sender;
|
|
if (action.IsCompleted)
|
|
{
|
|
action.Completed -= OptRecRetrieveAction_Completed;
|
|
|
|
if (action is WlbRetrieveRecommendationsAction thisAction)
|
|
{
|
|
_recommendations = thisAction.Recommendations;
|
|
|
|
if (_recommendations != null && IsGoodRecommendation(_recommendations) && _xenObject.Connection == action.Connection)
|
|
{
|
|
Program.Invoke(this, delegate()
|
|
{
|
|
PopulateData(_recommendations);
|
|
|
|
// In case optimizePoolListView is empty
|
|
if (optimizePoolListView.Items.Count == 0)
|
|
{
|
|
statusLabel.Text = Messages.WLB_OPT_POOL_NO_RECOMMENDATION;
|
|
EnableControls(true, false);
|
|
}
|
|
else
|
|
EnableControls(false, true);
|
|
});
|
|
}
|
|
else
|
|
{
|
|
Program.Invoke(this, delegate()
|
|
{
|
|
statusLabel.Text = Messages.WLB_OPT_POOL_NO_RECOMMENDATION;
|
|
EnableControls(true, false);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if there are recommendations and verify if recommendations are valid and good;
|
|
/// return false if no valid recommendations
|
|
/// </summary>
|
|
/// <param name="recommendations">Optimize pool recommendations</param>
|
|
/// <returns>true if recommendations are valid, else return false</returns>
|
|
private bool IsGoodRecommendation(Dictionary<XenRef<VM>, string[]> recommendations)
|
|
{
|
|
bool goodRec = false;
|
|
|
|
if (recommendations != null)
|
|
{
|
|
foreach (KeyValuePair<XenRef<VM>, string[]> rec in recommendations)
|
|
{
|
|
// make sure at least one recommendation is good
|
|
if (rec.Value[(int)RecProperties.WLB].Trim().ToLower() == "wlb")
|
|
{
|
|
// get opt id from new recommendations
|
|
_optId = rec.Value[(int)RecProperties.OptId];
|
|
|
|
// get opt id of the most recent optimized action from pool's other configuration property
|
|
string optimizeId = String.Empty;
|
|
(Helpers.GetOtherConfig(this._pool)).TryGetValue(WlbOptimizationRecommendation.OPTIMIZINGPOOL, out optimizeId);
|
|
|
|
// make sure pool's recommendations are not old/just optimized recommendations
|
|
if (optimizeId != _optId)
|
|
{
|
|
goodRec = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return goodRec;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks to see if all the wlb recommendations are for PowerOff or PowerOn operations
|
|
/// </summary>
|
|
/// <param name="recommendations"></param>
|
|
/// <returns></returns>
|
|
private bool IsPowerOnlyRecommendation(Dictionary<XenRef<VM>, string[]> recommendations)
|
|
{
|
|
bool powerOnly = true;
|
|
|
|
if (recommendations != null)
|
|
{
|
|
foreach (KeyValuePair<XenRef<VM>, string[]> rec in recommendations)
|
|
{
|
|
if (rec.Value[(int)RecProperties.WLB].Trim().ToLower() == "wlb" &&
|
|
!(rec.Value[(int)RecProperties.Reason].Trim().ToLower().StartsWith("power")))
|
|
{
|
|
powerOnly = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return powerOnly;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Populate optimize pool listview properly
|
|
/// </summary>
|
|
/// <param name="recommendations">optimize pool recommendations</param>
|
|
private void PopulateData(Dictionary<XenRef<VM>, string[]> recommendations)
|
|
{
|
|
Program.AssertOnEventThread();
|
|
|
|
optimizePoolListView.BeginUpdate();
|
|
try
|
|
{
|
|
if (_vmOptList != null)
|
|
_vmOptList.Clear();
|
|
|
|
optimizePoolListView.Items.Clear();
|
|
List<ListViewItem> newItems = new List<ListViewItem>();
|
|
|
|
WlbOptimizationRecommendationCollection sortedRecommendations = new WlbOptimizationRecommendationCollection(_pool, recommendations);
|
|
|
|
// WLB: recommendation return string format ["WLB"; vm/vm dom0; optId; recID; reason]
|
|
|
|
foreach (WlbOptimizationRecommendation optVmSetting in sortedRecommendations)
|
|
{
|
|
_optId = optVmSetting.optId.ToString();
|
|
_vmOptList.Add(optVmSetting.vm, optVmSetting);
|
|
|
|
ListViewItem row = new ListViewItem();
|
|
row.Tag = optVmSetting;
|
|
newItems.Add(row);
|
|
|
|
row.SubItems.Add(new ListViewItem.ListViewSubItem());
|
|
row.SubItems.Add(new ListViewItem.ListViewSubItem());
|
|
row.SubItems.Add(new ListViewItem.ListViewSubItem());
|
|
row.SubItems.Add(new ListViewItem.ListViewSubItem());
|
|
|
|
// Power on/off hosts
|
|
if (optVmSetting.toHost == null)
|
|
{
|
|
row.ImageIndex = (int)Images.GetIconFor(optVmSetting.toHost != null ? optVmSetting.toHost : optVmSetting.fromHost);
|
|
row.SubItems[1].Text = Helpers.GetName(optVmSetting.toHost != null ? optVmSetting.toHost : optVmSetting.fromHost);
|
|
row.SubItems[2].Text = optVmSetting.powerOperation;
|
|
}
|
|
else // VMs
|
|
{
|
|
row.ImageIndex = (int)Images.GetIconFor(optVmSetting.vm);
|
|
row.SubItems[1].Text = Helpers.GetName(optVmSetting.vm);
|
|
row.SubItems[2].Text = String.Format(Messages.WLB_OPT_OPERATION_VM, Helpers.GetName(optVmSetting.fromHost), Helpers.GetName(optVmSetting.toHost));
|
|
}
|
|
row.SubItems[3].Text = optVmSetting.reason;
|
|
}
|
|
|
|
optimizePoolListView.Items.AddRange(newItems.ToArray());
|
|
}
|
|
finally
|
|
{
|
|
optimizePoolListView.EndUpdate();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enable optimize pool controls properly
|
|
/// </summary>
|
|
private void EnableControls(bool enableLabel, bool enableButton)
|
|
{
|
|
// Rules for enabling the button:
|
|
// Passed RBAC checks, and
|
|
// If we are not in automatic mode, or
|
|
// ( We are in automatic mode, and
|
|
// We are in automated mode but PowerManagement is not enabled, and
|
|
// All recommdations are power-related)
|
|
|
|
if (enableLabel)
|
|
{
|
|
optimizePoolListView.Items.Clear();
|
|
}
|
|
optimizePoolListView.Visible = true;
|
|
optimizePoolListView.Enabled = PassedRbacChecks();
|
|
|
|
statusLabel.Visible = enableLabel;
|
|
|
|
applyButton.Visible = true;
|
|
if (PassedRbacChecks() &&
|
|
(!_autoOptEnabled ||
|
|
(_autoOptEnabled && !_powerManagementEnabled && IsPowerOnlyRecommendation(_recommendations))))
|
|
{
|
|
applyButton.Enabled = enableButton;
|
|
}
|
|
else
|
|
{
|
|
applyButton.Enabled = false;
|
|
}
|
|
|
|
}
|
|
|
|
private RbacMethodList WLB_PERMISSION_CHECKS = new RbacMethodList(
|
|
"pool.initialize_wlb",
|
|
"pool.set_wlb_enabled",
|
|
"pool.send_wlb_configuration"
|
|
);
|
|
|
|
private readonly CollectionChangeEventHandler Host_CollectionChangedWithInvoke;
|
|
private readonly CollectionChangeEventHandler VM_CollectionChangedWithInvoke;
|
|
|
|
private bool PassedRbacChecks()
|
|
{
|
|
return Role.CanPerform(WLB_PERMISSION_CHECKS, this._pool.Connection);
|
|
}
|
|
#endregion
|
|
|
|
|
|
#region OptimizePoolListView item drawing event and colum event handlers
|
|
/// <summary>
|
|
/// Draw default column header
|
|
/// </summary>
|
|
/// <param name="sender">object</param>
|
|
/// <param name="e">DrawListViewColumnHeaderEventArgs</param>
|
|
private void OptimizePoolListView_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
|
|
{
|
|
// Draw default column header
|
|
e.DrawDefault = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draw items on optimize pool listview properly
|
|
/// </summary>
|
|
/// <param name="sender">object</param>
|
|
/// <param name="e">DrawListViewItemEventArgs</param>
|
|
private void OptimizePoolListView_DrawItem(object sender, DrawListViewItemEventArgs e)
|
|
{
|
|
// Fill the full width of the control, not just to the end of the column headers.
|
|
Rectangle r = e.Bounds;
|
|
int i = 0;
|
|
foreach (ColumnHeader col in optimizePoolListView.Columns)
|
|
{
|
|
i += col.Width;
|
|
}
|
|
// Fill from the right of the rightmost item to the end of the control
|
|
r.Width = Math.Max(i, optimizePoolListView.ClientSize.Width);
|
|
r.X = i;
|
|
|
|
using (Brush backBrush = new SolidBrush(e.Item.Index % 2 == 1 ? ShadedRowColor : SystemColors.Window))
|
|
e.Graphics.FillRectangle(backBrush, r);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draw sub items in optimize pool list view
|
|
/// </summary>
|
|
/// <param name="sender">object</param>
|
|
/// <param name="e">DrawListViewSubItemEventArgs</param>
|
|
private void OptimizePoolListView_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
|
|
{
|
|
Rectangle rect = e.Bounds;
|
|
using (Brush backBrush = new SolidBrush(e.Item.Index % 2 == 1 ? ShadedRowColor : SystemColors.Window))
|
|
e.Graphics.FillRectangle(backBrush, rect);
|
|
|
|
Color fontColor = Color.Black;
|
|
|
|
if (e.ColumnIndex == 2)
|
|
{
|
|
TextRenderer.DrawText(e.Graphics, e.Item.SubItems[e.ColumnIndex].Text, OperationTextFont, e.Bounds, OperationTextColor, TextFormatFlags.EndEllipsis);
|
|
}
|
|
else if (e.ColumnIndex == 3)
|
|
{
|
|
TextRenderer.DrawText(e.Graphics, e.Item.SubItems[e.ColumnIndex].Text, this.Font, e.Bounds, fontColor, TextFormatFlags.EndEllipsis);
|
|
}
|
|
else
|
|
{
|
|
DrawSubItem1(fontColor, e);
|
|
}
|
|
}
|
|
|
|
|
|
private void DrawSubItem1(Color fontColor, DrawListViewSubItemEventArgs e)
|
|
{
|
|
Image icon = e.Item.ImageList.Images[e.Item.ImageIndex];
|
|
Point p = new Point(e.Bounds.Left, e.Bounds.Top + (e.Bounds.Height - icon.Height) / 2);
|
|
|
|
// Draw normally
|
|
e.Graphics.DrawImageUnscaled(icon, p);
|
|
|
|
Point p2 = new Point(p.X + icon.Width + 2, p.Y);
|
|
Rectangle r = new Rectangle(p2.X, p2.Y, e.Bounds.Right - p2.X, e.Bounds.Height);
|
|
TextRenderer.DrawText(e.Graphics, e.Item.SubItems[e.ColumnIndex].Text, this.Font, r, fontColor, TextFormatFlags.EndEllipsis);
|
|
}
|
|
|
|
private void optimizePoolListView_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
|
|
{
|
|
//Maintain a minimum column widths
|
|
|
|
|
|
if (minimumColumnWidths.Length>=e.ColumnIndex &&
|
|
optimizePoolListView.Columns[e.ColumnIndex].Width < minimumColumnWidths[e.ColumnIndex])
|
|
{
|
|
optimizePoolListView.Columns[e.ColumnIndex].Width = minimumColumnWidths[e.ColumnIndex];
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
|
|
|
|
}
|
|
}
|