mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-12-23 08:56:02 +01:00
3f25c5868f
- fix all ThreeButtonDialog usages (and some other dialogs that I've came across) Signed-off-by: Mihaela Stoica <mihaela.stoica@citrix.com>
1035 lines
42 KiB
C#
1035 lines
42 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.Data;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using XenAdmin.Commands;
|
|
using XenAdmin.Model;
|
|
using XenAPI;
|
|
using XenAdmin.Core;
|
|
using XenAdmin.Wizards;
|
|
using XenAdmin.Actions;
|
|
using XenAdmin.Dialogs;
|
|
using XenAdmin.Controls.DataGridViewEx;
|
|
|
|
|
|
namespace XenAdmin.Controls.NetworkingTab
|
|
{
|
|
public partial class NetworkList : UserControl
|
|
{
|
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
|
|
public NetworkList()
|
|
{
|
|
InitializeComponent();
|
|
Properties.Settings.Default.PropertyChanged += Default_PropertyChanged;
|
|
}
|
|
|
|
private IXenObject _xenObject = null;
|
|
public IXenObject XenObject
|
|
{
|
|
get
|
|
{
|
|
Program.AssertOnEventThread();
|
|
return _xenObject;
|
|
}
|
|
set
|
|
{
|
|
Program.AssertOnEventThread();
|
|
|
|
// Remove all old property change listeners. They will get added back in the
|
|
// population of the DataGridView that follows (see BuildList).
|
|
DegregisterEventsOnXmo();
|
|
DeregisterEventsOnGridRows();
|
|
|
|
if (_xenObject is Host || _xenObject is Pool)
|
|
{
|
|
_xenObject.Connection.Cache.DeregisterBatchCollectionChanged<XenAPI.Network>(NetworkCollectionChanged);
|
|
_xenObject.Connection.Cache.DeregisterBatchCollectionChanged<PIF>(PIFCollectionChanged);
|
|
}
|
|
else if (_xenObject is VM)
|
|
{
|
|
_xenObject.Connection.Cache.DeregisterBatchCollectionChanged<VIF>(CollectionChanged);
|
|
_xenObject.Connection.Cache.DeregisterBatchCollectionChanged<VM_guest_metrics>(VM_guest_metrics_BatchCollectionChanged);
|
|
}
|
|
|
|
_xenObject = value;
|
|
|
|
if (_xenObject != null)
|
|
_xenObject.PropertyChanged += Server_PropertyChanged;
|
|
|
|
if (_xenObject is Host || _xenObject is Pool)
|
|
{
|
|
AddNetworkColumns();
|
|
|
|
_xenObject.Connection.Cache.RegisterBatchCollectionChanged<XenAPI.Network>(NetworkCollectionChanged);
|
|
_xenObject.Connection.Cache.RegisterBatchCollectionChanged<PIF>(PIFCollectionChanged);
|
|
|
|
AddNetworkButton.Text = Messages.HOST_NETWORK_TAB_ADD_BUTTON_LABEL;
|
|
EditNetworkButton.Text = Messages.HOST_NETWORK_TAB_EDIT_BUTTON_LABEL;
|
|
RemoveNetworkButton.Text = Messages.HOST_NETWORK_TAB_REMOVE_BUTTON_LABEL;
|
|
// This is the divider for the activate button, hide this as well as the button
|
|
groupBox1.Visible = false;
|
|
buttonActivateToggle.Visible = false;
|
|
}
|
|
else if (_xenObject is VM)
|
|
{
|
|
AddVifColumns();
|
|
|
|
_xenObject.Connection.Cache.RegisterBatchCollectionChanged<VIF>(CollectionChanged);
|
|
|
|
// update the list when we get new metrics
|
|
_xenObject.Connection.Cache.RegisterBatchCollectionChanged<VM_guest_metrics>(VM_guest_metrics_BatchCollectionChanged);
|
|
|
|
AddNetworkButton.Text = Messages.VM_NETWORK_TAB_ADD_BUTTON_LABEL;
|
|
EditNetworkButton.Text = Messages.VM_NETWORK_TAB_EDIT_BUTTON_LABEL;
|
|
RemoveNetworkButton.Text = Messages.VM_NETWORK_TAB_REMOVE_BUTTON_LABEL;
|
|
groupBox1.Visible = true;
|
|
buttonActivateToggle.Visible = true;
|
|
}
|
|
|
|
BuildList();
|
|
}
|
|
}
|
|
|
|
private void DegregisterEventsOnXmo()
|
|
{
|
|
if (XenObject == null)
|
|
return;
|
|
|
|
XenObject.PropertyChanged -= Server_PropertyChanged;
|
|
|
|
if (XenObject is VM)
|
|
{
|
|
VM vm = (VM)XenObject;
|
|
|
|
VM_guest_metrics vmGuestMetrics = vm.Connection.Resolve(vm.guest_metrics);
|
|
if (vmGuestMetrics != null)
|
|
vmGuestMetrics.PropertyChanged -= Server_PropertyChanged;
|
|
}
|
|
}
|
|
|
|
private void AddNetworkColumns()
|
|
{
|
|
// catch the sorting column and sorting order, so they could be restored after the columns are added to the grid (SCTX-501)
|
|
DataGridViewColumn previousSortColumn = NetworksGridView.SortedColumn;
|
|
SortOrder previousSortOrder = NetworksGridView.SortOrder == SortOrder.None ? SortOrder.Ascending : NetworksGridView.SortOrder;
|
|
|
|
try
|
|
{
|
|
NetworksGridView.SuspendLayout();
|
|
|
|
NetworksGridView.Columns.Clear();
|
|
NetworksGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
|
this.ImageColumn,
|
|
this.NameColumn,
|
|
this.DescriptionColumn,
|
|
this.NicColumn,
|
|
this.VlanColumn,
|
|
this.AutoColumn,
|
|
this.LinkStatusColumn,
|
|
this.NetworkMacColumn,
|
|
this.MtuColumn});
|
|
|
|
//CA-47050: the Description column should be autosized to Fill, but should not become smaller than a minimum
|
|
//width, which here is chosen to be the column header width. To find what this width is set temporarily the
|
|
//column's autosize mode to ColumnHeader.
|
|
this.DescriptionColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
|
|
int storedWidth = this.DescriptionColumn.Width;
|
|
this.DescriptionColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
|
|
this.DescriptionColumn.MinimumWidth = storedWidth;
|
|
}
|
|
finally
|
|
{
|
|
NetworksGridView.ResumeLayout();
|
|
}
|
|
|
|
// restore the sorting column (SCTX-501)
|
|
RestoreSortingColumn(previousSortColumn, previousSortOrder, NicColumn);
|
|
}
|
|
|
|
private void AddVifColumns()
|
|
{
|
|
// catch the sorting column and sorting order, so they could be restored after the columns are added to the grid (SCTX-501)
|
|
DataGridViewColumn previousSortColumn = NetworksGridView.SortedColumn;
|
|
SortOrder previousSortOrder = NetworksGridView.SortOrder == SortOrder.None ? SortOrder.Ascending : NetworksGridView.SortOrder;
|
|
|
|
NetworksGridView.Columns.Clear();
|
|
NetworksGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
|
this.ImageColumn,
|
|
this.DeviceColumn,
|
|
this.VifMacColumn,
|
|
this.LimitColumn,
|
|
this.NetworkColumn,
|
|
this.IpColumn,
|
|
this.ActiveColumn});
|
|
|
|
//the IP column should be autosized to Fill, but should not become smaller than a minimum
|
|
//width, which here is chosen to be the column header width. To find what this width is set temporarily the
|
|
//column's autosize mode to ColumnHeader.
|
|
this.IpColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
|
|
int storedWidth = this.DescriptionColumn.Width;
|
|
this.IpColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
|
|
this.IpColumn.MinimumWidth = storedWidth;
|
|
|
|
// restore the sorting column (SCTX-501)
|
|
RestoreSortingColumn(previousSortColumn, previousSortOrder, DeviceColumn);
|
|
}
|
|
|
|
private void RestoreSortingColumn(DataGridViewColumn previousSortColumn, SortOrder previousSortOrder, DataGridViewColumn defaultSortColumn)
|
|
{
|
|
// SCTX-501 preserve the sorting column
|
|
if ((previousSortColumn == null) || !NetworksGridView.Columns.Contains(previousSortColumn))
|
|
{
|
|
previousSortColumn = defaultSortColumn;
|
|
previousSortOrder = SortOrder.Ascending;
|
|
// try to get the old sort order from the SortGlyph
|
|
foreach (System.Windows.Forms.DataGridViewColumn column in NetworksGridView.Columns)
|
|
if (column.HeaderCell.SortGlyphDirection != SortOrder.None)
|
|
{
|
|
previousSortColumn = column;
|
|
previousSortOrder = column.HeaderCell.SortGlyphDirection;
|
|
break;
|
|
}
|
|
}
|
|
if (previousSortColumn != null)
|
|
{
|
|
// clear any old sort glyphs; this is necessary as a result of the
|
|
// change for CA-45643 (MTU column only added for Cowley or greater pools)
|
|
foreach (System.Windows.Forms.DataGridViewColumn column in NetworksGridView.Columns)
|
|
column.HeaderCell.SortGlyphDirection = SortOrder.None;
|
|
|
|
NetworksGridView.Sort(
|
|
previousSortColumn,
|
|
previousSortOrder == SortOrder.Ascending ? ListSortDirection.Ascending : ListSortDirection.Descending);
|
|
}
|
|
}
|
|
|
|
void VM_guest_metrics_BatchCollectionChanged(object sender, EventArgs e)
|
|
{
|
|
Program.Invoke(this, BuildList);
|
|
}
|
|
|
|
void Default_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
if (e.PropertyName == "ShowHiddenVMs")
|
|
{
|
|
BuildList();
|
|
}
|
|
}
|
|
|
|
public bool InBuildList = false;
|
|
public void BuildList()
|
|
{
|
|
Program.AssertOnEventThread();
|
|
if (!this.Visible)
|
|
return;
|
|
|
|
if (InBuildList)
|
|
return;
|
|
|
|
InBuildList = true;
|
|
|
|
try
|
|
{
|
|
if (XenObject == null || XenObject.Locked)
|
|
return;
|
|
|
|
if (!XenObject.Connection.CacheIsPopulated)
|
|
return;
|
|
|
|
if (XenObject is VM)
|
|
{
|
|
DeregisterEventsOnGridRows();
|
|
VIF selectedVIF = SelectedVif;
|
|
VM vm = XenObject as VM;
|
|
|
|
NetworksGridView.SuspendLayout();
|
|
NetworksGridView.Rows.Clear();
|
|
|
|
List<VIF> vifs = vm.Connection.ResolveAll(vm.VIFs);
|
|
vifs.Sort();
|
|
|
|
// CA-8981 - Listen for guest metric changes which is necessary for IP Address updates
|
|
VM_guest_metrics vmGuestMetrics = vm.Connection.Resolve(vm.guest_metrics);
|
|
if (vmGuestMetrics != null)
|
|
vmGuestMetrics.PropertyChanged += Server_PropertyChanged;
|
|
|
|
var vifRowsToAdd = new List<VifRow>();
|
|
foreach (var vif in vifs)
|
|
{
|
|
var network = vif.Connection.Resolve(vif.network);
|
|
if (network != null && network.IsGuestInstallerNetwork)
|
|
continue; // Don't show the guest installer network in the network tab (CA-73056)
|
|
vifRowsToAdd.Add(new VifRow(vif));
|
|
}
|
|
NetworksGridView.Rows.AddRange(vifRowsToAdd.ToArray());
|
|
|
|
bool selected = true;
|
|
|
|
if (selectedVIF != null)
|
|
{
|
|
foreach (VifRow row in NetworksGridView.Rows)
|
|
{
|
|
// Cannot compare opaque_ref as VIFs get destroyed / recreated on each edit.
|
|
if (row.Vif.device == selectedVIF.device)
|
|
{
|
|
row.Selected = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!selected && NetworksGridView.Rows.Count > 0)
|
|
{
|
|
NetworksGridView.Rows[0].Selected = true;
|
|
}
|
|
}
|
|
else if (XenObject is Host || XenObject is Pool)
|
|
{
|
|
DeregisterEventsOnGridRows();
|
|
XenAPI.Network selectedNetwork = SelectedNetwork;
|
|
|
|
NetworksGridView.SuspendLayout();
|
|
NetworksGridView.Rows.Clear();
|
|
|
|
XenAPI.Network[] networks = XenObject.Connection.Cache.Networks;
|
|
Array.Sort < XenAPI.Network>(networks);
|
|
|
|
List<NetworkRow> networkRowsToAdd = new List<NetworkRow>();
|
|
for (int i = 0; i < networks.Length; i++)
|
|
{
|
|
if (!networks[i].Show(XenAdmin.Properties.Settings.Default.ShowHiddenVMs))
|
|
continue;
|
|
networkRowsToAdd.Add(new NetworkRow(networks[i], XenObject));
|
|
}
|
|
NetworksGridView.Rows.AddRange(networkRowsToAdd.ToArray());
|
|
// The following update causes this to be a lot slower with many networks. Alot! CA-43944
|
|
//foreach(NetworkRow r in NetworksGridView.Rows)
|
|
//r.UpdateDefaultCellStyle(); // Has to be done again after adding to the grid view, even though it's already called in the constructor
|
|
|
|
if (selectedNetwork != null)
|
|
{
|
|
foreach (NetworkRow row in NetworksGridView.Rows)
|
|
{
|
|
if (row.Network.opaque_ref == selectedNetwork.opaque_ref && selectedNetwork.Show(XenAdmin.Properties.Settings.Default.ShowHiddenVMs))
|
|
{
|
|
row.Selected = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (NetworksGridView.SortedColumn != null)
|
|
{
|
|
NetworksGridView.Sort(
|
|
NetworksGridView.SortedColumn,
|
|
NetworksGridView.SortOrder == SortOrder.Ascending
|
|
? ListSortDirection.Ascending : ListSortDirection.Descending);
|
|
}
|
|
NetworksGridView.ResumeLayout();
|
|
InBuildList = false;
|
|
}
|
|
}
|
|
|
|
public void DeregisterEventsOnGridRows()
|
|
{
|
|
foreach (DataGridViewExRow row in NetworksGridView.Rows)
|
|
{
|
|
if (row is VifRow)
|
|
((VifRow)row).DeregisterEvents();
|
|
else if (row is NetworkRow)
|
|
((NetworkRow)row).DeregisterEvents();
|
|
}
|
|
}
|
|
|
|
|
|
private void NetworksGridView_SelectionChanged(object sender, EventArgs e)
|
|
{
|
|
UpdateEnablement();
|
|
}
|
|
|
|
private void UpdateEnablement()
|
|
{
|
|
bool locked = _xenObject.Locked;
|
|
|
|
if (SelectedNetwork != null)
|
|
{
|
|
XenAPI.Network TheNetwork = SelectedNetwork;
|
|
|
|
AddNetworkButton.Enabled = !locked;
|
|
EditNetworkButton.Enabled = !locked && !TheNetwork.Locked && !TheNetwork.IsSlave && !TheNetwork.CreateInProgress;
|
|
|
|
if (HasPhysicalNonBondNIC(TheNetwork))
|
|
{
|
|
RemoveNetworkButton.Enabled = false;
|
|
RemoveButtonContainer.SetToolTip(Messages.TOOLTIP_REMOVE_PIF);
|
|
}
|
|
else
|
|
{
|
|
RemoveNetworkButton.Enabled = !locked && !TheNetwork.Locked && !TheNetwork.IsSlave && !TheNetwork.CreateInProgress;
|
|
RemoveButtonContainer.SetToolTip("");
|
|
}
|
|
}
|
|
else if (SelectedVif != null)
|
|
{
|
|
VIF vif = SelectedVif;
|
|
AddNetworkButton.Enabled = !locked;
|
|
// In this case read vif.currently_attached as is-it-plugged
|
|
RemoveNetworkButton.Enabled = !locked && (vif.allowed_operations.Contains(vif_operations.unplug) || !vif.currently_attached);
|
|
EditNetworkButton.Enabled = !locked && (vif.allowed_operations.Contains(vif_operations.unplug) || !vif.currently_attached);
|
|
buttonActivateToggle.Enabled = !locked && (
|
|
vif.currently_attached && vif.allowed_operations.Contains(vif_operations.unplug)
|
|
|| !vif.currently_attached && vif.allowed_operations.Contains(vif_operations.plug));
|
|
|
|
buttonActivateToggle.Text = vif.currently_attached ? Messages.VM_NETWORK_TAB_DEACTIVATE_BUTTON_LABEL : Messages.VM_NETWORK_TAB_ACTIVATE_BUTTON_LABEL;
|
|
|
|
VM vm = (VM)XenObject;
|
|
if (vm.power_state == vm_power_state.Suspended)
|
|
{
|
|
RemoveButtonContainer.SetToolTip(Messages.TOOLTIP_REMOVE_NETWORK_SUSPENDED);
|
|
EditButtonContainer.SetToolTip(vm.HasNewVirtualisationStates ? Messages.TOOLTIP_EDIT_NETWORK_IO_DRIVERS : Messages.TOOLTIP_EDIT_NETWORK_TOOLS);
|
|
toolTipContainerActivateToggle.SetToolTip(vif.currently_attached
|
|
? Messages.TOOLTIP_DEACTIVATE_VIF_SUSPENDED : Messages.TOOLTIP_ACTIVATE_VIF_SUSPENDED);
|
|
}
|
|
else
|
|
{
|
|
if (vm.power_state == vm_power_state.Running && !vm.GetVirtualisationStatus.HasFlag(VM.VirtualisationStatus.IO_DRIVERS_INSTALLED))
|
|
{
|
|
RemoveButtonContainer.SetToolTip(vm.HasNewVirtualisationStates ? Messages.TOOLTIP_REMOVE_NETWORK_IO_DRIVERS : Messages.TOOLTIP_REMOVE_NETWORK_TOOLS);
|
|
EditButtonContainer.SetToolTip(vm.HasNewVirtualisationStates ? Messages.TOOLTIP_EDIT_NETWORK_IO_DRIVERS : Messages.TOOLTIP_EDIT_NETWORK_TOOLS);
|
|
toolTipContainerActivateToggle.SetToolTip(vif.currently_attached
|
|
? Messages.TOOLTIP_DEACTIVATE_VIF_TOOLS : Messages.TOOLTIP_ACTIVATE_VIF_TOOLS);
|
|
}
|
|
else
|
|
{
|
|
RemoveButtonContainer.RemoveAll();
|
|
EditButtonContainer.RemoveAll();
|
|
toolTipContainerActivateToggle.RemoveAll();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AddNetworkButton.Enabled = !locked;
|
|
RemoveNetworkButton.Enabled = false;
|
|
EditNetworkButton.Enabled = false;
|
|
buttonActivateToggle.Enabled = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return true if the given network has a PIF that represents a physical NIC -- i.e.
|
|
/// IsPhysical == true and IsBondNIC == false.
|
|
/// </summary>
|
|
/// <param name="network"></param>
|
|
/// <returns></returns>
|
|
private static bool HasPhysicalNonBondNIC(XenAPI.Network network)
|
|
{
|
|
foreach (PIF pif in network.Connection.ResolveAll(network.PIFs))
|
|
{
|
|
if (pif.IsPhysical && !pif.IsBondNIC)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void AddNetworkButton_Click(object sender, EventArgs e)
|
|
{
|
|
if (XenObject is VM)
|
|
{
|
|
VM vm = (VM)_xenObject;
|
|
|
|
if (NetworksGridView.Rows.Count >= vm.MaxVIFsAllowed)
|
|
{
|
|
using (var dlg = new ThreeButtonDialog(
|
|
new ThreeButtonDialog.Details(
|
|
SystemIcons.Error,
|
|
FriendlyErrorNames.VIFS_MAX_ALLOWED,
|
|
FriendlyErrorNames.VIFS_MAX_ALLOWED_TITLE)))
|
|
{
|
|
dlg.ShowDialog(Program.MainWindow);
|
|
}
|
|
return;
|
|
}
|
|
|
|
Host master = Helpers.GetMaster(vm.Connection);
|
|
if (master == null)
|
|
{
|
|
// Cache populating?
|
|
return;
|
|
}
|
|
VIFDialog d = new VIFDialog(vm.Connection, null, VIF.GetDeviceId(vm));
|
|
if (d.ShowDialog(this) != DialogResult.OK)
|
|
return;
|
|
|
|
Proxy_VIF pVif = d.GetNewSettings();
|
|
pVif.VM = vm.opaque_ref;
|
|
CreateVIFCommand action = new CreateVIFCommand(Program.MainWindow, vm, pVif);
|
|
action.Execute();
|
|
}
|
|
else if (XenObject is Host)
|
|
{
|
|
Host host = (Host)_xenObject;
|
|
Program.MainWindow.ShowPerConnectionWizard(_xenObject.Connection,
|
|
new NewNetworkWizard(_xenObject.Connection, null, host));
|
|
}
|
|
else if (XenObject is Pool)
|
|
{
|
|
Pool pool = (Pool)_xenObject;
|
|
Host host = pool.Connection.Resolve(pool.master);
|
|
if (host != null)
|
|
{
|
|
Program.MainWindow.ShowPerConnectionWizard(_xenObject.Connection,
|
|
new NewNetworkWizard(_xenObject.Connection, pool, host));
|
|
}
|
|
}
|
|
}
|
|
|
|
private XenAPI.Network SelectedNetwork
|
|
{
|
|
get
|
|
{
|
|
if (NetworksGridView.SelectedRows.Count == 0)
|
|
return null;
|
|
|
|
NetworkRow row = NetworksGridView.SelectedRows[0] as NetworkRow;
|
|
|
|
if (row == null)
|
|
return null;
|
|
|
|
return row.Network;
|
|
}
|
|
}
|
|
|
|
private VIF SelectedVif
|
|
{
|
|
get
|
|
{
|
|
if (NetworksGridView.SelectedRows.Count == 0)
|
|
return null;
|
|
|
|
VifRow row = NetworksGridView.SelectedRows[0] as VifRow;
|
|
|
|
if (row == null)
|
|
return null;
|
|
|
|
return row.Vif;
|
|
}
|
|
}
|
|
|
|
private void RemoveNetworkButton_Click(object sender, EventArgs e)
|
|
{
|
|
if (NetworksGridView.SelectedRows.Count == 0)
|
|
return;
|
|
|
|
XenAPI.Network network = SelectedNetwork;
|
|
if (network != null && network.IsBond)
|
|
{
|
|
var destroyBondCommand = new DestroyBondCommand(Program.MainWindow, network);
|
|
destroyBondCommand.Execute();
|
|
}
|
|
else
|
|
{
|
|
// Check and see if the system is running in automation test mode. If so, then
|
|
// do not launch the popup Y/N dialog.
|
|
DialogResult result;
|
|
if (Program.RunInAutomatedTestMode)
|
|
{
|
|
result = DialogResult.Yes;
|
|
}
|
|
else if (XenObject is VM)
|
|
{
|
|
// Deleting a VIF, not a Network.
|
|
using (var dlg = new ThreeButtonDialog(
|
|
new ThreeButtonDialog.Details(SystemIcons.Warning, Messages.MESSAGEBOX_VIF_DELETE, Messages.MESSAGEBOX_VIF_DELETE_TITLE),
|
|
ThreeButtonDialog.ButtonYes,
|
|
ThreeButtonDialog.ButtonNo))
|
|
{
|
|
result = dlg.ShowDialog(Program.MainWindow);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
using (var dlg = new ThreeButtonDialog(
|
|
new ThreeButtonDialog.Details(SystemIcons.Warning, Messages.MESSAGEBOX_NETWORK_DELETE, Messages.MESSAGEBOX_NETWORK_DELETE_TITLE),
|
|
ThreeButtonDialog.ButtonYes,
|
|
ThreeButtonDialog.ButtonNo))
|
|
{
|
|
result = dlg.ShowDialog(Program.MainWindow);
|
|
}
|
|
}
|
|
|
|
if (result == DialogResult.Yes)
|
|
{
|
|
DoRemoveNetwork();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DoRemoveNetwork()
|
|
{
|
|
if (SelectedVif != null)
|
|
{
|
|
VM vm = XenObject as VM;
|
|
|
|
var action = new DeleteVIFAction(SelectedVif);
|
|
action.Completed += action_Completed;
|
|
action.RunAsync();
|
|
}
|
|
else if(SelectedNetwork != null)
|
|
{
|
|
NetworkAction action = new NetworkAction(XenObject.Connection, SelectedNetwork,false);
|
|
action.Completed += action_Completed;
|
|
action.RunAsync();
|
|
}
|
|
}
|
|
|
|
private void buttonActivateToggle_Click(object sender, EventArgs e)
|
|
{
|
|
if (SelectedVif != null)
|
|
{
|
|
VM vm = XenObject as VM;
|
|
AsyncAction action;
|
|
if (SelectedVif.currently_attached)
|
|
action = new UnplugVIFAction(SelectedVif);
|
|
else
|
|
action = new PlugVIFAction(SelectedVif);
|
|
|
|
action.Completed += action_Completed;
|
|
action.RunAsync();
|
|
}
|
|
}
|
|
|
|
void NetworkCollectionChanged(object sender, EventArgs e)
|
|
{
|
|
Program.Invoke(this, BuildList);
|
|
}
|
|
|
|
void PIFCollectionChanged(object sender, EventArgs e)
|
|
{
|
|
Program.Invoke(this, BuildList);
|
|
}
|
|
|
|
void CollectionChanged(object sender, EventArgs e)
|
|
{
|
|
Program.Invoke(this, BuildList);
|
|
}
|
|
|
|
void action_Completed(ActionBase sender)
|
|
{
|
|
Program.Invoke(this, BuildList);
|
|
}
|
|
|
|
void Server_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
// JJN- Provide a temporary fix to the bug reported in CA-9322 where the
|
|
// editing of the MAC and Limit fields is barely usable due to the continuous
|
|
// reconstruction of the list within this view. Ensure the button enablement
|
|
// does not digress with this fix.
|
|
if (shouldRefreshBuildList(e))
|
|
{
|
|
Program.Invoke(this, RefreshAllItems);
|
|
}
|
|
}
|
|
|
|
private void RefreshAllItems()
|
|
{
|
|
foreach (DataGridViewExRow row in NetworksGridView.Rows)
|
|
{
|
|
if (row is VifRow)
|
|
((VifRow)row).UpdateDetails();
|
|
else if (row is NetworkRow)
|
|
((NetworkRow)row).UpdateDetails();
|
|
}
|
|
}
|
|
|
|
public static bool shouldRefreshBuildList(PropertyChangedEventArgs e)
|
|
{
|
|
return (e.PropertyName != "allowed_operations"
|
|
&& e.PropertyName != "current_operations"
|
|
&& e.PropertyName != "io_read_kbs"
|
|
&& e.PropertyName != "io_write_kbs"
|
|
&& e.PropertyName != "last_updated");
|
|
}
|
|
|
|
|
|
|
|
private void EditNetworkButton_Click(object sender, EventArgs e)
|
|
{
|
|
if (NetworksGridView.SelectedRows.Count > 0)
|
|
{
|
|
if (XenObject is VM)
|
|
{
|
|
launchVmNetworkSettingsDialog();
|
|
}
|
|
else
|
|
{
|
|
launchHostOrPoolNetworkSettingsDialog();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void launchVmNetworkSettingsDialog()
|
|
{
|
|
VM vm = XenObject as VM;
|
|
VIF vif = SelectedVif;
|
|
|
|
if (vm == null || vif == null)
|
|
return;
|
|
|
|
int device;
|
|
VIFDialog d;
|
|
if (int.TryParse(vif.device, out device))
|
|
{
|
|
d = new VIFDialog(vm.Connection, vif, device);
|
|
}
|
|
else
|
|
{
|
|
log.ErrorFormat("Aborting vif edit. Could not parse existing vif device to int. Value is: '{0}'", vif.device);
|
|
return;
|
|
}
|
|
|
|
if (d.ShowDialog() != DialogResult.OK)
|
|
return;
|
|
|
|
Proxy_VIF proxyVIF = d.GetNewSettings();
|
|
UpdateVIFCommand command = new UpdateVIFCommand(Program.MainWindow, vm, vif, proxyVIF);
|
|
InBuildList = true;
|
|
command.Completed += new EventHandler((s, f) => Program.Invoke(this, () =>
|
|
{
|
|
InBuildList = false;
|
|
BuildList();
|
|
}));
|
|
command.Execute();
|
|
}
|
|
|
|
|
|
private void launchHostOrPoolNetworkSettingsDialog()
|
|
{
|
|
XenAPI.Network network = SelectedNetwork;
|
|
if (network == null)
|
|
return;
|
|
|
|
new PropertiesDialog(network).ShowDialog(this);
|
|
}
|
|
|
|
private void EditMenuItemHandler(object sender, EventArgs e)
|
|
{
|
|
EditNetworkButton_Click(null, null);
|
|
}
|
|
|
|
private void AddMenuItemHandler(object sender, EventArgs e)
|
|
{
|
|
AddNetworkButton_Click(null, null);
|
|
}
|
|
|
|
private void RemoveMenuItemHandler(object sender, EventArgs e)
|
|
{
|
|
RemoveNetworkButton_Click(null, null);
|
|
}
|
|
|
|
private void NetworksGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
UpdateEnablement();
|
|
}
|
|
|
|
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
|
|
{
|
|
Point pt = NetworksGridView.PointToClient(new Point(contextMenuStrip1.Left, contextMenuStrip1.Top));
|
|
DataGridView.HitTestInfo info = NetworksGridView.HitTest(pt.X, pt.Y);
|
|
if (info != null && info.RowIndex >= 0 && info.RowIndex < NetworksGridView.Rows.Count)
|
|
{
|
|
DataGridViewRow row = NetworksGridView.Rows[info.RowIndex];
|
|
if (row != null)
|
|
{
|
|
row.Selected = true;
|
|
copyToolStripMenuItem.Visible = true;
|
|
addToolStripMenuItem.Visible = AddNetworkButton.Visible && AddNetworkButton.Enabled;
|
|
propertiesToolStripMenuItem.Visible = EditNetworkButton.Visible && EditNetworkButton.Enabled;
|
|
removeToolStripMenuItem.Visible = RemoveNetworkButton.Visible && RemoveNetworkButton.Enabled;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// else just show add button
|
|
copyToolStripMenuItem.Visible = false;
|
|
addToolStripMenuItem.Visible = AddNetworkButton.Visible && AddNetworkButton.Enabled;
|
|
propertiesToolStripMenuItem.Visible = false;
|
|
removeToolStripMenuItem.Visible = false;
|
|
}
|
|
|
|
private void copyToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
Point pt = NetworksGridView.PointToClient(new Point(contextMenuStrip1.Left, contextMenuStrip1.Top));
|
|
DataGridView.HitTestInfo info = NetworksGridView.HitTest(pt.X, pt.Y);
|
|
if (info != null && info.RowIndex >= 0 && info.RowIndex < NetworksGridView.Rows.Count)
|
|
{
|
|
DataGridViewRow row = NetworksGridView.Rows[info.RowIndex];
|
|
if (row != null)
|
|
{
|
|
string t = row.Cells[info.ColumnIndex].Value.ToString();
|
|
if (String.IsNullOrEmpty(t))
|
|
return;
|
|
|
|
Clipboard.SetText(t);
|
|
}
|
|
}
|
|
}
|
|
|
|
class VifRow : DataGridViewExRow
|
|
{
|
|
public VIF Vif;
|
|
private DataGridViewExImageCell ImageCell = new DataGridViewExImageCell();
|
|
private DataGridViewTextBoxCell DeviceCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell MacCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell LimitCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell NetworkCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell IpCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell AttachedCell = new DataGridViewTextBoxCell();
|
|
|
|
private VIF_metrics Metrics;
|
|
|
|
public VifRow(VIF vif)
|
|
{
|
|
Vif = vif;
|
|
|
|
Cells.AddRange(ImageCell,
|
|
DeviceCell,
|
|
MacCell,
|
|
LimitCell,
|
|
NetworkCell,
|
|
IpCell,
|
|
AttachedCell);
|
|
|
|
Vif.PropertyChanged += Server_PropertyChanged;
|
|
|
|
UpdateDetails();
|
|
}
|
|
|
|
public void UpdateDetails()
|
|
{
|
|
if(Metrics != null)
|
|
Metrics.PropertyChanged -= Server_PropertyChanged;
|
|
|
|
Metrics = Vif.Connection.Resolve(Vif.metrics);
|
|
|
|
if (Metrics != null)
|
|
Metrics.PropertyChanged += Server_PropertyChanged;
|
|
|
|
ImageCell.Value = Properties.Resources._000_Network_h32bit_16;
|
|
DeviceCell.Value = Vif.device;
|
|
MacCell.Value = Helpers.GetMacString(Vif.MAC);
|
|
LimitCell.Value = Vif.qos_algorithm_type != ""? Vif.LimitString:"";
|
|
NetworkCell.Value = Vif.NetworkName();
|
|
IpCell.Value = Vif.IPAddressesAsString();
|
|
AttachedCell.Value = Vif.currently_attached ? Messages.YES : Messages.NO;
|
|
}
|
|
|
|
public void DeregisterEvents()
|
|
{
|
|
Vif.PropertyChanged -= Server_PropertyChanged;
|
|
|
|
if (Metrics != null)
|
|
Metrics.PropertyChanged -= Server_PropertyChanged;
|
|
}
|
|
|
|
private void Server_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
if (NetworkList.shouldRefreshBuildList(e))
|
|
Program.Invoke(Program.MainWindow, UpdateDetails);
|
|
}
|
|
}
|
|
|
|
class NetworkRow : DataGridViewExRow
|
|
{
|
|
public XenAPI.Network Network;
|
|
private DataGridViewExImageCell ImageCell = new DataGridViewExImageCell();
|
|
private DataGridViewTextBoxCell NameCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell DescriptionCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell NicCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell VlanCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell AutoCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell LinkStatusCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell MacCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell MtuCell = new DataGridViewTextBoxCell();
|
|
private IXenObject Xmo;
|
|
PIF Pif;
|
|
|
|
public NetworkRow(XenAPI.Network network, IXenObject xmo)
|
|
{
|
|
Network = network;
|
|
Xmo = xmo;
|
|
|
|
Cells.AddRange(ImageCell,
|
|
NameCell,
|
|
DescriptionCell,
|
|
NicCell,
|
|
VlanCell,
|
|
AutoCell,
|
|
LinkStatusCell,
|
|
MacCell,
|
|
MtuCell);
|
|
|
|
Network.PropertyChanged += Server_PropertyChanged;
|
|
|
|
Program.Invoke(Program.MainWindow, UpdateDetails);
|
|
}
|
|
|
|
public void UpdateDetails()
|
|
{
|
|
Enabled = !Network.IsSlave;
|
|
|
|
DeregisterPifEvents();
|
|
|
|
Pif = Helpers.FindPIF(Network, Xmo as Host);
|
|
|
|
RegisterPifEvents();
|
|
|
|
ImageCell.Value = Properties.Resources._000_Network_h32bit_16;
|
|
NameCell.Value = NetworkName();
|
|
DescriptionCell.Value = Network.Description;
|
|
NicCell.Value = Helpers.GetName(Pif);
|
|
VlanCell.Value = Helpers.VlanString(Pif);
|
|
AutoCell.Value = Network.AutoPlug ? Messages.YES : Messages.NO;
|
|
LinkStatusCell.Value = Xmo is Pool ? Network.LinkStatusString :
|
|
Pif == null ? Messages.NONE : Pif.LinkStatusString;
|
|
MacCell.Value = Pif != null && Pif.IsPhysical ? Pif.MAC : Messages.SPACED_HYPHEN;
|
|
MtuCell.Value = Network.CanUseJumboFrames ? Network.MTU.ToString() : Messages.SPACED_HYPHEN;
|
|
}
|
|
|
|
public void DeregisterEvents()
|
|
{
|
|
Network.PropertyChanged -= Server_PropertyChanged;
|
|
|
|
DeregisterPifEvents();
|
|
}
|
|
|
|
private object NetworkName()
|
|
{
|
|
if (Network.Show(XenAdmin.Properties.Settings.Default.ShowHiddenVMs) && !Network.IsSlave)
|
|
return Helpers.GetName(Network);
|
|
else if (Network.IsSlave && Properties.Settings.Default.ShowHiddenVMs)
|
|
return string.Format(Messages.NIC_SLAVE, Helpers.GetName(Network));
|
|
else if (Properties.Settings.Default.ShowHiddenVMs)
|
|
return string.Format(Messages.NIC_HIDDEN, Helpers.GetName(Network));
|
|
else
|
|
return string.Empty;
|
|
}
|
|
|
|
private void Server_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
if(NetworkList.shouldRefreshBuildList(e))
|
|
Program.Invoke(Program.MainWindow, UpdateDetails);
|
|
}
|
|
|
|
private void RegisterPifEvents()
|
|
{
|
|
if (Pif != null)
|
|
{
|
|
Pif.PropertyChanged += Server_PropertyChanged;
|
|
|
|
// Listen for Tunnel and PIF_metrics changes which is necessary for Link Status updates (CA-46103)
|
|
if (Pif.IsTunnelAccessPIF)
|
|
{
|
|
Tunnel tunnel = Pif.Connection.Resolve(Pif.tunnel_access_PIF_of[0]);
|
|
if (tunnel != null)
|
|
tunnel.PropertyChanged += Pif_PropertyChanged;
|
|
}
|
|
else
|
|
{
|
|
PIF_metrics metrics = Pif.PIFMetrics;
|
|
if (metrics != null)
|
|
metrics.PropertyChanged += Pif_PropertyChanged;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DeregisterPifEvents()
|
|
{
|
|
if (Pif != null)
|
|
{
|
|
Pif.PropertyChanged -= Server_PropertyChanged;
|
|
|
|
// Remove Tunnel and PIF_metrics property change listeners (CA-46103)
|
|
if (Pif.IsTunnelAccessPIF)
|
|
{
|
|
Tunnel tunnel = Pif.Connection.Resolve(Pif.tunnel_access_PIF_of[0]);
|
|
if (tunnel != null)
|
|
tunnel.PropertyChanged -= Pif_PropertyChanged;
|
|
}
|
|
else
|
|
{
|
|
PIF_metrics metrics = Pif.PIFMetrics;
|
|
if (metrics != null)
|
|
metrics.PropertyChanged -= Pif_PropertyChanged;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Pif_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
// Tunnel.status or PIF_metrics.carrier (CA-46103)
|
|
if (e.PropertyName == "status" || e.PropertyName == "carrier")
|
|
Program.Invoke(Program.MainWindow, UpdateDetails);
|
|
}
|
|
}
|
|
|
|
private void NetworksGridView_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
|
|
{
|
|
if (XenObject != null && XenObject is VM && e.Column.Index == DeviceColumn.Index)
|
|
{
|
|
int val1 = 0;
|
|
int val2 = 0;
|
|
if (int.TryParse(e.CellValue1.ToString(), out val1)
|
|
&& int.TryParse(e.CellValue2.ToString(), out val2))
|
|
{
|
|
e.SortResult = val1.CompareTo(val2);
|
|
e.Handled = true;
|
|
return;
|
|
}
|
|
}
|
|
e.SortResult = StringUtility.NaturalCompare(e.CellValue1.ToString(), e.CellValue2.ToString());
|
|
e.Handled = true;
|
|
|
|
|
|
}
|
|
}
|
|
}
|