2023-01-24 15:29:31 +01:00
/ * Copyright ( c ) Cloud Software Group , Inc .
2013-06-24 13:41:48 +02:00
*
* 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.Linq ;
using System.Windows.Forms ;
using XenAdmin.Controls ;
using XenAPI ;
using XenAdmin.Core ;
using XenAdmin.Actions ;
using XenAdmin.Help ;
2020-01-30 01:02:24 +01:00
using PifTuple = System . Tuple < XenAPI . PIF , bool > ;
2013-06-24 13:41:48 +02:00
namespace XenAdmin.Dialogs
{
public partial class NetworkingProperties : VerticallyTabbedDialog
{
private Host Host ;
private Pool Pool ;
private string ObjectName ;
private List < PIF > ShownPIFs ;
private List < PIF > AllPIFs ;
2017-01-24 03:22:35 +01:00
private bool AllowManagementOnVLAN ;
2013-06-24 13:41:48 +02:00
2020-01-30 01:02:24 +01:00
private readonly ToolTip toolTipRemove = new ToolTip ( ) ;
private bool tooltipVisible ;
2013-06-24 13:41:48 +02:00
public NetworkingProperties ( )
{
InitializeComponent ( ) ;
}
2019-10-10 18:15:16 +02:00
public NetworkingProperties ( Host host , PIF selectedPIF )
: base ( host . Connection )
2013-06-24 13:41:48 +02:00
{
2019-10-10 18:15:16 +02:00
InitializeComponent ( ) ;
2013-06-24 13:41:48 +02:00
Host = host ;
Pool = null ;
ObjectName = Helpers . GetName ( host ) ;
2017-01-24 03:22:35 +01:00
AllowManagementOnVLAN = ! Helpers . FeatureForbidden ( connection , Host . RestrictManagementOnVLAN ) ;
2013-06-24 13:41:48 +02:00
BlurbLabel . Text = string . Format ( Messages . NETWORKING_PROPERTIES_BLURB_HOST , ObjectName ) ;
Configure ( selectedPIF ) ;
}
2019-10-10 18:15:16 +02:00
public NetworkingProperties ( Pool pool , PIF selectedPIF )
: base ( pool . Connection )
2013-06-24 13:41:48 +02:00
{
2019-10-10 18:15:16 +02:00
InitializeComponent ( ) ;
2013-06-24 13:41:48 +02:00
Pool = pool ;
ObjectName = Helpers . GetName ( Pool ) ;
2017-01-24 03:22:35 +01:00
AllowManagementOnVLAN = ! Helpers . FeatureForbidden ( connection , Host . RestrictManagementOnVLAN ) ;
2013-06-24 13:41:48 +02:00
Host = connection . Resolve ( pool . master ) ;
if ( Host = = null )
2021-08-31 12:31:16 +02:00
throw new Failure ( Failure . INTERNAL_ERROR , "Could not resolve coordinator" ) ;
2013-06-24 13:41:48 +02:00
BlurbLabel . Text = string . Format ( Messages . NETWORKING_PROPERTIES_BLURB_POOL , ObjectName ) ;
Configure ( selectedPIF ) ;
}
private void Configure ( PIF selectedPIF )
{
Text = string . Format ( Messages . NETWORKING_PROPERTIES_TITLE , ObjectName ) ;
ShownPIFs = GetKnownPIFs ( false ) ;
AllPIFs = GetKnownPIFs ( true ) ;
2020-01-30 01:02:24 +01:00
PIF management_pif = AllPIFs . Find ( pif = > pif . management ) ;
2013-06-24 13:41:48 +02:00
if ( management_pif = = null )
{
// Cache has not been populated yet, or is being cleared.
return ;
}
bool ha = ( Pool ! = null & & Pool . ha_enabled ) ; // CA-24714
NetworkingPropertiesPage management_page = new NetworkingPropertiesPage ( ha ? NetworkingPropertiesPage . Type . PRIMARY_WITH_HA : NetworkingPropertiesPage . Type . PRIMARY ) ;
management_page . Purpose = Messages . MANAGEMENT ;
AddTabContents ( management_page ) ;
management_page . Tag = management_pif ;
foreach ( PIF pif in ShownPIFs )
{
if ( pif . opaque_ref ! = management_pif . opaque_ref & & pif . IsSecondaryManagementInterface ( true ) )
{
MakeSecondaryPage ( pif , Purpose ( pif ) ) ;
}
}
2020-01-30 01:02:24 +01:00
var inusemap = MakeProposedInUseMap ( ) ;
2013-06-24 13:41:48 +02:00
foreach ( NetworkingPropertiesPage page in verticalTabs . Items )
{
page . Pool = Pool ! = null ;
RefreshNetworkComboBox ( inusemap , page ) ;
}
foreach ( NetworkingPropertiesPage page in verticalTabs . Items )
{
ConfigurePage ( page , page . Tag as PIF ) ;
}
2020-01-30 01:02:24 +01:00
2013-06-24 13:41:48 +02:00
if ( selectedPIF ! = null )
{
foreach ( NetworkingPropertiesPage item in verticalTabs . Items )
{
if ( item . Tag = = selectedPIF )
{
verticalTabs . SelectedItem = item ;
2020-01-30 01:02:24 +01:00
break ;
2013-06-24 13:41:48 +02:00
}
}
}
else
verticalTabs . SelectedIndex = 0 ;
2020-01-30 01:02:24 +01:00
2013-06-24 13:41:48 +02:00
ResizeVerticalTabs ( verticalTabs . Items . Count ) ;
verticalTabs . AdjustItemTextBounds = GetItemTextBounds ;
}
private void ResizeVerticalTabs ( int itemCount )
{
int maxHeight = splitContainer . Panel1 . Height - AddButton . Height ;
verticalTabs . Height = Math . Min ( maxHeight , itemCount * verticalTabs . ItemHeight ) ;
AddButton . Top = verticalTabs . Top + verticalTabs . Height ;
}
/// <summary>
///
/// </summary>
/// <param name="page"></param>
/// <param name="pif">May be null, in which case the page is configured with reasonable defaults.</param>
private void ConfigurePage ( NetworkingPropertiesPage page , PIF pif )
{
if ( pif = = null )
{
page . SelectFirstUnusedNetwork ( ) ;
page . SubnetTextBox . Text = "" ;
page . GatewayTextBox . Text = "" ;
page . IPAddressTextBox . Text = "" ;
page . DHCPIPRadioButton . Checked = true ;
}
else
{
page . NetworkComboBox . SelectedItem = connection . Resolve ( pif . network ) ;
page . SubnetTextBox . Text = pif . netmask ;
page . GatewayTextBox . Text = pif . gateway ;
page . IPAddressTextBox . Text = pif . IP ;
page . DHCPIPRadioButton . Checked = pif . ip_configuration_mode = = ip_configuration_mode . DHCP ;
}
string [ ] addresses = pif = = null ? new string [ ] { "" } : pif . DNS . Split ( ',' ) ;
page . PreferredDNSTextBox . Text = addresses [ 0 ] ;
page . AlternateDNS1TextBox . Text = addresses . Length = = 1 ? "" : addresses [ 1 ] ;
page . AlternateDNS2TextBox . Text = addresses . Length < = 2 ? "" : addresses [ 2 ] ;
}
private void RefreshNetworkComboBox ( Dictionary < XenAPI . Network , List < NetworkingPropertiesPage > > InUseMap , NetworkingPropertiesPage page )
{
2017-01-24 03:22:35 +01:00
page . RefreshNetworkComboBox ( InUseMap , ManagementNetwork ( ) , AllowManagementOnVLAN ) ;
2013-06-24 13:41:48 +02:00
}
private List < PIF > GetKnownPIFs ( bool include_invisible )
{
List < PIF > result = new List < PIF > ( ) ;
foreach ( XenAPI . Network network in connection . Cache . Networks )
{
if ( network . Show ( include_invisible | | Properties . Settings . Default . ShowHiddenVMs ) )
{
PIF pif = FindPIFForThisHost ( network . PIFs ) ;
if ( pif ! = null )
result . Add ( pif ) ;
}
}
return result ;
}
private Dictionary < XenAPI . Network , List < NetworkingPropertiesPage > > MakeProposedInUseMap ( )
{
2020-01-30 01:02:24 +01:00
var inusemap = new Dictionary < XenAPI . Network , List < NetworkingPropertiesPage > > ( ) ;
2013-06-24 13:41:48 +02:00
foreach ( NetworkingPropertiesPage page in verticalTabs . Items )
{
XenAPI . Network network = ( XenAPI . Network ) page . NetworkComboBox . SelectedItem ;
if ( network = = null )
{
PIF pif = page . Tag as PIF ;
if ( pif = = null )
continue ;
network = pif . Connection . Resolve ( pif . network ) ;
if ( network = = null )
continue ;
}
if ( network . PIFs . Count = = 0 )
continue ;
if ( ! inusemap . ContainsKey ( network ) )
inusemap [ network ] = new List < NetworkingPropertiesPage > ( ) ;
inusemap [ network ] . Add ( page ) ;
}
foreach ( XenAPI . Network network in connection . Cache . Networks )
{
if ( network . Show ( Properties . Settings . Default . ShowHiddenVMs ) )
{
2017-09-03 04:33:29 +02:00
if ( connection . ResolveAll ( network . PIFs ) . Find ( p = > ! p . IsTunnelAccessPIF ( ) ) = = null ) // no PIFs, or all the PIFs are tunnel access PIFs so the network is a CHIN
2013-06-24 13:41:48 +02:00
continue ;
PIF pif = FindPIFForThisHost ( network . PIFs ) ;
2021-08-31 12:31:16 +02:00
if ( pif ! = null & & pif . IsInUseBondMember ( ) )
2013-06-24 13:41:48 +02:00
continue ;
if ( ! inusemap . ContainsKey ( network ) )
inusemap [ network ] = null ;
}
}
return inusemap ;
}
private void AddTabContents ( NetworkingPropertiesPage prop_page )
{
prop_page . HostCount = connection . Cache . HostCount ;
2020-01-30 01:02:24 +01:00
prop_page . ValidChanged + = prop_page_ValidChanged ;
prop_page . DeleteButtonClicked + = prop_page_DeleteButtonClicked ;
prop_page . NetworkComboBoxChanged + = prop_page_NetworkComboBoxChanged ;
2013-06-24 13:41:48 +02:00
prop_page . Parent = ContentPanel ;
prop_page . Dock = DockStyle . Fill ;
verticalTabs . Items . Add ( prop_page ) ;
RefreshButtons ( ) ;
}
void RefreshNetworkComboBoxes ( )
{
2020-01-30 01:02:24 +01:00
var inusemap = MakeProposedInUseMap ( ) ;
2013-06-24 13:41:48 +02:00
foreach ( NetworkingPropertiesPage page in verticalTabs . Items )
RefreshNetworkComboBox ( inusemap , page ) ;
}
void RefreshButtons ( )
{
foreach ( NetworkingPropertiesPage page in verticalTabs . Items )
2020-01-30 01:02:24 +01:00
page . RefreshButtons ( ) ;
2013-06-24 13:41:48 +02:00
okButton . Enabled = AllPagesValid ( ) ;
AddButton . Enabled = ShownPIFs . Count > verticalTabs . Items . Count ;
}
private bool AllPagesValid ( )
{
foreach ( NetworkingPropertiesPage page in verticalTabs . Items )
if ( ! page . Valid | | ! page . NameValid )
return false ;
return true ;
}
private void AddButton_Click ( object sender , EventArgs e )
{
ResizeVerticalTabs ( verticalTabs . Items . Count + 1 ) ;
verticalTabs . SelectedItem = MakeSecondaryPage ( null , AuxTabName ( ) ) ;
NetworkingPropertiesPage page = verticalTabs . SelectedItem as NetworkingPropertiesPage ;
RefreshNetworkComboBox ( MakeProposedInUseMap ( ) , page ) ;
ConfigurePage ( page , null ) ;
}
void prop_page_NetworkComboBoxChanged ( object sender , EventArgs e )
{
RefreshNetworkComboBoxes ( ) ;
}
void prop_page_DeleteButtonClicked ( object sender , EventArgs e )
{
NetworkingPropertiesPage prop_page = ( NetworkingPropertiesPage ) sender ;
int selectedIndex = verticalTabs . SelectedIndex ;
verticalTabs . Items . Remove ( prop_page ) ;
verticalTabs . SelectedIndex = selectedIndex < verticalTabs . Items . Count - 1 ? selectedIndex : verticalTabs . Items . Count - 1 ;
ContentPanel . Controls . Remove ( prop_page ) ;
RefreshNetworkComboBoxes ( ) ;
RefreshButtons ( ) ;
ResizeVerticalTabs ( verticalTabs . Items . Count ) ;
}
void prop_page_ValidChanged ( object sender , EventArgs e )
{
RefreshButtons ( ) ;
}
/// <summary>
///
/// </summary>
/// <param name="pif">May be null, in which case the page is configured with reasonable defaults.</param>
/// <param name="purpose"></param>
/// <returns></returns>
private NetworkingPropertiesPage MakeSecondaryPage ( PIF pif , string purpose )
{
NetworkingPropertiesPage prop_page = MakeSecondaryPage ( purpose ) ;
if ( pif ! = null )
prop_page . Tag = pif ;
if ( pif = = null )
prop_page . SelectName ( ) ;
return prop_page ;
}
private NetworkingPropertiesPage MakeSecondaryPage ( string purpose )
{
NetworkingPropertiesPage prop_page = new NetworkingPropertiesPage ( NetworkingPropertiesPage . Type . SECONDARY ) ;
prop_page . Pool = Pool ! = null ;
prop_page . Purpose = purpose ;
prop_page . PurposeTextBox . Text = purpose ;
prop_page . RefreshButtons ( ) ;
2020-01-30 01:02:24 +01:00
prop_page . PurposeTextBox . TextChanged + = ( sender , e ) = >
{
if ( sender is NetworkingPropertiesPage page )
page . Text = page . PurposeTextBox . Text ;
} ;
2013-06-24 13:41:48 +02:00
AddTabContents ( prop_page ) ;
return prop_page ;
}
private string Purpose ( PIF pif )
{
2017-09-05 03:15:38 +02:00
string purpose = pif . GetManagementPurpose ( ) ;
2013-06-24 13:41:48 +02:00
return string . IsNullOrEmpty ( purpose ) ? Messages . NETWORKING_PROPERTIES_PURPOSE_UNKNOWN : purpose ;
}
private string AuxTabName ( )
{
List < string > tabnames = GetTabNames ( ) ;
return Helpers . MakeUniqueNameFromPattern ( Messages . NETWORKING_PROPERTIES_AUX_TAB_NAME , tabnames , 1 ) ;
}
private List < string > GetTabNames ( )
{
List < string > result = new List < string > ( ) ;
foreach ( NetworkingPropertiesPage page in verticalTabs . Items )
{
result . Add ( page . Text ) ;
}
return result ;
}
private bool IPAddressSettingsChanged ( PIF pif1 , PIF pif2 )
{
return ! pif1 . IP . Equals ( pif2 . IP ) | |
! pif1 . netmask . Equals ( pif2 . netmask ) | |
! pif1 . gateway . Equals ( pif2 . gateway ) ;
}
private bool GetManagementInterfaceIPChanged ( PIF oldManagement , PIF newManagement )
{
if ( oldManagement = = null | | newManagement = = null )
throw new Failure ( Failure . INTERNAL_ERROR , "Management interface is null." ) ;
if ( oldManagement . ip_configuration_mode = = ip_configuration_mode . DHCP )
{
if ( newManagement . ip_configuration_mode = = ip_configuration_mode . DHCP )
return ! oldManagement . Equals ( newManagement ) ;
if ( newManagement . ip_configuration_mode = = ip_configuration_mode . Static )
return IPAddressSettingsChanged ( oldManagement , newManagement ) ;
}
else if ( oldManagement . ip_configuration_mode = = ip_configuration_mode . Static )
{
if ( newManagement . ip_configuration_mode = = ip_configuration_mode . Static )
return IPAddressSettingsChanged ( oldManagement , newManagement ) ;
if ( newManagement . ip_configuration_mode = = ip_configuration_mode . DHCP )
return true ;
}
throw new Failure ( Failure . INTERNAL_ERROR , "Unexpected IP configuration mode." ) ;
}
private void AcceptBtn_Click ( object sender , EventArgs e )
{
2020-01-30 01:02:24 +01:00
var newPIFs = new List < PifTuple > ( ) ;
var newNamePIFs = new List < PifTuple > ( ) ;
2013-06-24 13:41:48 +02:00
List < PIF > downPIFs = new List < PIF > ( ) ;
foreach ( PIF pif in AllPIFs )
{
if ( pif . IsManagementInterface ( XenAdmin . Properties . Settings . Default . ShowHiddenVMs ) )
downPIFs . Add ( pif ) ;
}
2020-01-30 01:02:24 +01:00
try
2013-06-24 13:41:48 +02:00
{
2020-01-30 01:02:24 +01:00
foreach ( NetworkingPropertiesPage page in verticalTabs . Items )
2018-08-21 13:29:03 +02:00
CollateChanges ( page , page . Tag as PIF , newPIFs , newNamePIFs ) ;
2020-01-30 01:02:24 +01:00
}
catch ( Failure )
{
2020-04-22 15:47:03 +02:00
using ( var dlg = new WarningDialog ( Messages . NETWORK_RECONFIG_CONNECTION_LOST ) )
2020-01-30 01:02:24 +01:00
dlg . ShowDialog ( this ) ;
this . Close ( ) ;
return ;
2013-06-24 13:41:48 +02:00
}
bool displayWarning = false ;
bool managementInterfaceIPChanged = false ;
2020-01-30 01:02:24 +01:00
PIF down_management = downPIFs . Find ( p = > p . management ) ;
PIF new_management = newPIFs . Select ( p = > p . Item1 ) . FirstOrDefault ( p = > p . management ) ;
2013-06-24 13:41:48 +02:00
if ( down_management ! = null )
{
if ( new_management = = null )
throw new Failure ( Failure . INTERNAL_ERROR , "Bringing down the management interface without bringing another one up is impossible!" ) ;
managementInterfaceIPChanged = GetManagementInterfaceIPChanged ( down_management , new_management ) ;
displayWarning = managementInterfaceIPChanged | |
( down_management . uuid ! = new_management . uuid | |
down_management . ip_configuration_mode ! = new_management . ip_configuration_mode ) ;
if ( down_management . Equals ( new_management ) )
{
// Management interface has not changed
down_management = null ;
}
}
// Any PIFs that are in downPIFs but also in newPIFs need to be removed from the former.
2017-06-20 15:29:22 +02:00
// downPIFs should contain all those that we no longer want to keep up.
2020-01-30 01:02:24 +01:00
downPIFs . RemoveAll ( p = > newPIFs . Any ( np = > np . Item1 . uuid = = p . uuid ) ) ;
2013-06-24 13:41:48 +02:00
// Remove any PIFs that haven't changed -- there's nothing to do for these ones. They are in this
// list originally so that they can be used as a filter against downPIFs.
2020-01-30 01:02:24 +01:00
newPIFs . RemoveAll ( p = > ! p . Item2 ) ;
2018-08-21 13:29:03 +02:00
2020-01-30 01:02:24 +01:00
newNamePIFs . RemoveAll ( p = > ! p . Item2 ) ;
2018-08-21 13:29:03 +02:00
if ( newNamePIFs . Count > 0 )
{
2020-01-30 01:02:24 +01:00
new SetSecondaryManagementPurposeAction ( connection , Pool , newNamePIFs . Select ( p = > p . Item1 ) . ToList ( ) ) . RunAsync ( ) ;
2018-08-21 13:29:03 +02:00
}
2013-06-24 13:41:48 +02:00
if ( newPIFs . Count > 0 | | downPIFs . Count > 0 )
{
if ( displayWarning )
{
2021-03-16 02:50:45 +01:00
string title = string . Format ( Pool = = null
? Messages . NETWORKING_PROPERTIES_WARNING_CHANGING_MANAGEMENT_HOST
: Messages . NETWORKING_PROPERTIES_WARNING_CHANGING_MANAGEMENT_POOL ,
BrandManager . BrandConsole ) ;
2013-06-24 13:41:48 +02:00
2016-06-20 11:49:12 +02:00
DialogResult dialogResult ;
2020-04-22 15:47:03 +02:00
using ( var dlg = new WarningDialog ( title ,
2013-06-24 13:41:48 +02:00
new ThreeButtonDialog . TBDButton ( Messages . NETWORKING_PROPERTIES_CHANGING_MANAGEMENT_CONTINUE , DialogResult . OK ) ,
2020-10-02 20:13:09 +02:00
ThreeButtonDialog . ButtonCancel ) { HelpNameSetter = "NetworkingPropertiesPMIWarning" } )
2016-06-20 11:49:12 +02:00
{
dialogResult = dlg . ShowDialog ( this ) ;
}
if ( DialogResult . OK ! = dialogResult )
2013-06-24 13:41:48 +02:00
{
2020-01-30 01:02:24 +01:00
DialogResult = DialogResult . None ;
2013-06-24 13:41:48 +02:00
return ;
}
}
if ( down_management = = null )
{
// We're actually just changing the IP address, not moving the management interface, so we just pass it in through newPIFs.
new_management = null ;
}
else
{
// We're switching the management interface over, so remove the old one from downPIFs -- it will be special-cased through
// down_management and new_management.
downPIFs . Remove ( down_management ) ;
}
// Reverse the lists so that the management interface is always last to be done. If something's going to go wrong, then we'd like
// the management interface to be the one that we don't break.
newPIFs . Reverse ( ) ;
downPIFs . Reverse ( ) ;
2020-01-30 01:02:24 +01:00
new ChangeNetworkingAction ( connection , Pool , Host , newPIFs . Select ( p = > p . Item1 ) . ToList ( ) , downPIFs ,
new_management , down_management , managementInterfaceIPChanged ) . RunAsync ( ) ;
2013-06-24 13:41:48 +02:00
}
Close ( ) ;
}
/// <summary>
/// Will throw an exception if the network has gone away.
/// </summary>
/// <param name="page"></param>
/// <param name="oldPIF"></param>
/// <param name="newPIFs"></param>
2018-08-21 13:29:03 +02:00
/// <param name="newNamePIFs"></param>
2020-01-30 01:02:24 +01:00
private void CollateChanges ( NetworkingPropertiesPage page , PIF oldPIF , List < PifTuple > newPIFs , List < PifTuple > newNamePIFs )
2013-06-24 13:41:48 +02:00
{
bool changed = false ;
2020-01-30 01:02:24 +01:00
bool changedName = false ;
2013-06-24 13:41:48 +02:00
if ( oldPIF = = null )
{
// This tab is newly created.
XenAPI . Network network = ( XenAPI . Network ) page . NetworkComboBox . SelectedItem ;
oldPIF = FindPIFForThisHost ( network . PIFs ) ;
if ( oldPIF = = null )
throw new Failure ( Failure . INTERNAL_ERROR , "Network has gone away" ) ;
changed = true ;
}
else
{
// This tab was populated when this dialog was launched.
XenAPI . Network network = connection . Resolve ( oldPIF . network ) ;
if ( ( XenAPI . Network ) page . NetworkComboBox . SelectedItem ! = network )
{
// The user has changed the network, so find the one we're using now.
XenAPI . Network new_network = ( XenAPI . Network ) page . NetworkComboBox . SelectedItem ;
oldPIF = FindPIFForThisHost ( new_network . PIFs ) ;
if ( oldPIF = = null )
throw new Failure ( Failure . INTERNAL_ERROR , "Network has gone away" ) ;
changed = true ;
}
}
PIF newPIF = ( PIF ) oldPIF . Clone ( ) ;
2020-01-30 01:02:24 +01:00
newPIF . PropertyChanged + = ( sender , e ) = > { changed = true ; } ;
2018-08-21 13:29:03 +02:00
PIF newNamePIF = ( PIF ) oldPIF . Clone ( ) ;
2020-01-30 01:02:24 +01:00
newNamePIF . PropertyChanged + = ( sender , e ) = > { changedName = true ; } ;
2013-06-24 13:41:48 +02:00
if ( page . DHCPIPRadioButton . Checked )
{
newPIF . ip_configuration_mode = ip_configuration_mode . DHCP ;
}
else
{
newPIF . ip_configuration_mode = ip_configuration_mode . Static ;
newPIF . netmask = page . SubnetTextBox . Text ;
newPIF . gateway = page . GatewayTextBox . Text ;
newPIF . IP = page . IPAddressTextBox . Text ;
2020-01-30 01:02:24 +01:00
2013-06-24 13:41:48 +02:00
List < string > dns = new List < string > ( ) ;
if ( page . PreferredDNSTextBox . Text . Length > 0 )
dns . Add ( page . PreferredDNSTextBox . Text ) ;
if ( page . AlternateDNS1TextBox . Text . Length > 0 )
dns . Add ( page . AlternateDNS1TextBox . Text ) ;
if ( page . AlternateDNS2TextBox . Text . Length > 0 )
dns . Add ( page . AlternateDNS2TextBox . Text ) ;
2020-01-30 01:02:24 +01:00
var newDns = string . Join ( "," , dns . ToArray ( ) ) ;
2013-06-24 13:41:48 +02:00
2020-01-30 01:02:24 +01:00
newPIF . DNS = newDns ;
2013-06-24 13:41:48 +02:00
}
2018-08-21 13:29:03 +02:00
newPIF . management = page . type ! = NetworkingPropertiesPage . Type . SECONDARY ;
2013-06-24 13:41:48 +02:00
if ( page . type = = NetworkingPropertiesPage . Type . SECONDARY )
{
2020-01-30 01:02:24 +01:00
if ( changed )
newPIF . SetManagementPurpose ( page . PurposeTextBox . Text ) ;
2018-08-21 13:29:03 +02:00
else
2020-01-30 01:02:24 +01:00
newNamePIF . SetManagementPurpose ( page . PurposeTextBox . Text ) ;
2013-06-24 13:41:48 +02:00
}
2020-01-30 01:02:24 +01:00
newPIFs . Add ( new PifTuple ( newPIF , changed ) ) ;
newNamePIFs . Add ( new PifTuple ( newNamePIF , changedName ) ) ;
2013-06-24 13:41:48 +02:00
}
private PIF FindPIFForThisHost ( List < XenRef < PIF > > pifs )
{
foreach ( PIF pif in connection . ResolveAll ( pifs ) )
{
if ( pif . host . opaque_ref = = Host . opaque_ref )
return pif ;
}
return null ;
}
private XenAPI . Network ManagementNetwork ( )
{
return ( XenAPI . Network ) ( ( NetworkingPropertiesPage ) verticalTabs . Items [ 0 ] ) . NetworkComboBox . SelectedItem ;
}
private void splitContainer_Panel1_Resize ( object sender , EventArgs e )
{
ResizeVerticalTabs ( verticalTabs . Items . Count ) ;
}
2020-01-30 01:02:24 +01:00
private Rectangle GetItemTextBounds ( Rectangle itemBounds )
2013-06-24 13:41:48 +02:00
{
return new Rectangle ( itemBounds . X , itemBounds . Y , itemBounds . Width - 20 , itemBounds . Height ) ;
}
private void verticalTabs_DrawItem ( object sender , DrawItemEventArgs e )
{
if ( e . Index < 0 | | e . Index > = verticalTabs . Items . Count )
return ;
NetworkingPropertiesPage page = verticalTabs . Items [ e . Index ] as NetworkingPropertiesPage ;
2017-12-15 12:09:26 +01:00
if ( page = = null | | page . type ! = NetworkingPropertiesPage . Type . SECONDARY | | page . ClusteringEnabled )
2013-06-24 13:41:48 +02:00
return ;
Graphics g = e . Graphics ;
Rectangle b = e . Bounds ;
// draw Delete icon
2020-06-18 02:20:29 +02:00
Image deleteIcon = Images . StaticImages . _000_Abort_h32bit_16 ;
2013-06-24 13:41:48 +02:00
if ( deleteIcon ! = null )
{
page . DeleteIconBounds = new Rectangle ( b . Right - deleteIcon . Width - ( ( 32 - deleteIcon . Width ) / 2 ) ,
b . Y + ( ( 32 - deleteIcon . Height ) / 2 ) , deleteIcon . Width , deleteIcon . Height ) ;
g . DrawImage ( deleteIcon , page . DeleteIconBounds ) ;
}
}
private bool MouseIsOnDeleteIcon ( Point mouseLocation )
{
int pageIndex = verticalTabs . IndexFromPoint ( mouseLocation ) ;
if ( pageIndex < 0 )
return false ;
NetworkingPropertiesPage page = verticalTabs . Items [ pageIndex ] as NetworkingPropertiesPage ;
if ( page = = null )
return false ;
var bounds = page . DeleteIconBounds ;
return bounds . Contains ( mouseLocation ) ;
}
private void verticalTabs_MouseMove ( object sender , MouseEventArgs e )
{
if ( MouseIsOnDeleteIcon ( e . Location ) )
ShowTooltip ( e . Location ) ;
else
HideTooltip ( ) ;
}
private void verticalTabs_MouseClick ( object sender , MouseEventArgs e )
{
int pageIndex = verticalTabs . IndexFromPoint ( e . Location ) ;
if ( pageIndex < 0 | | ! MouseIsOnDeleteIcon ( e . Location ) )
return ;
NetworkingPropertiesPage page = verticalTabs . Items [ pageIndex ] as NetworkingPropertiesPage ;
if ( page ! = null )
{
prop_page_DeleteButtonClicked ( page , new EventArgs ( ) ) ;
HideTooltip ( ) ;
}
}
private void linkLabelTellMeMore_LinkClicked ( object sender , LinkLabelLinkClickedEventArgs e )
{
HelpManager . Launch ( "NetworkingProperties" ) ;
}
private void ShowTooltip ( Point location )
{
if ( ! tooltipVisible )
{
toolTipRemove . Show ( Messages . NETWORKING_PROPERTIES_REMOVE_TOOLTIP , verticalTabs , location . X , location . Y + 20 ) ;
tooltipVisible = true ;
Cursor = Cursors . Hand ;
}
}
private void HideTooltip ( )
{
toolTipRemove . Hide ( verticalTabs ) ;
tooltipVisible = false ;
Cursor = Cursors . Default ;
}
2018-03-20 18:02:45 +01:00
protected override string GetTabTitle ( VerticalTabs . IVerticalTab verticalTab )
2013-06-24 13:41:48 +02:00
{
NetworkingPropertiesPage page = verticalTab as NetworkingPropertiesPage ;
if ( page ! = null )
{
return page . type = = NetworkingPropertiesPage . Type . SECONDARY ? page . Text : Messages . NETWORKING_PROPERTIES_TAB_TITLE_PRIMARY ;
}
return base . GetTabTitle ( verticalTab ) ;
}
}
}