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 ;
2014-01-22 13:39:32 +01:00
using System.Collections.ObjectModel ;
2013-06-24 13:41:48 +02:00
using System.ComponentModel ;
using System.Configuration ;
using System.Diagnostics ;
using System.Drawing ;
2023-05-09 16:12:04 +02:00
using System.IO ;
2013-06-24 13:41:48 +02:00
using System.Runtime.InteropServices ;
using System.Security.Permissions ;
using System.Text ;
using System.Threading ;
using System.Windows.Forms ;
using System.Xml ;
using XenAdmin.Actions.GUIActions ;
2013-08-30 14:35:32 +02:00
using XenAdmin.Controls.MainWindowControls ;
2013-06-24 13:41:48 +02:00
using XenAdmin.Wizards.ImportWizard ;
using XenAPI ;
using XenAdmin.Actions ;
using XenAdmin.Alerts ;
using XenAdmin.Commands ;
using XenAdmin.Controls ;
using XenAdmin.Core ;
using XenAdmin.Dialogs ;
using XenAdmin.Model ;
using XenAdmin.Network ;
using XenAdmin.TabPages ;
using XenAdmin.XenSearch ;
using XenAdmin.Plugins ;
2017-11-17 02:04:45 +01:00
using XenCenterLib ;
2013-06-24 13:41:48 +02:00
using System.Linq ;
2021-04-30 18:39:57 +02:00
using XenAdmin.Controls.GradientPanel ;
2023-07-22 16:52:32 +02:00
using XenAdmin.Dialogs.ServerUpdates ;
2018-12-21 12:15:59 +01:00
using XenAdmin.Help ;
2013-06-24 13:41:48 +02:00
namespace XenAdmin
{
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
[ComVisibleAttribute(true)]
2019-09-13 18:47:27 +02:00
public partial class MainWindow : Form , ISynchronizeInvoke , IMainWindow , IFormWithHelp
2013-06-24 13:41:48 +02:00
{
private static readonly log4net . ILog log = log4net . LogManager . GetLogger ( System . Reflection . MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
/// <summary>
/// A mapping between objects in the tree and the associated selected tab.
/// </summary>
private Dictionary < object , TabPage > selectedTabs = new Dictionary < object , TabPage > ( ) ;
/// <summary>
/// The selected tab for the overview node.
/// </summary>
2022-11-08 12:18:35 +01:00
private TabPage selectedOverviewTab ;
2013-06-24 13:41:48 +02:00
internal readonly PerformancePage PerformancePage = new PerformancePage ( ) ;
internal readonly GeneralTabPage GeneralPage = new GeneralTabPage ( ) ;
internal readonly BallooningPage BallooningPage = new BallooningPage ( ) ;
internal readonly ConsolePanel ConsolePanel = new ConsolePanel ( ) ;
2016-07-05 09:14:13 +02:00
internal readonly CvmConsolePanel CvmConsolePanel = new CvmConsolePanel ( ) ;
2013-06-24 13:41:48 +02:00
internal readonly HAPage HAPage = new HAPage ( ) ;
internal readonly HAUpsellPage HAUpsellPage = new HAUpsellPage ( ) ;
internal readonly HomePage HomePage = new HomePage ( ) ;
internal readonly SearchPage SearchPage = new SearchPage ( ) ;
internal readonly NetworkPage NetworkPage = new NetworkPage ( ) ;
internal readonly NICPage NICPage = new NICPage ( ) ;
internal readonly WlbPage WlbPage = new WlbPage ( ) ;
internal readonly WLBUpsellPage WLBUpsellPage = new WLBUpsellPage ( ) ;
internal readonly SrStoragePage SrStoragePage = new SrStoragePage ( ) ;
internal readonly PhysicalStoragePage PhysicalStoragePage = new PhysicalStoragePage ( ) ;
internal readonly VMStoragePage VMStoragePage = new VMStoragePage ( ) ;
internal readonly AdPage AdPage = new AdPage ( ) ;
2016-05-20 14:01:51 +02:00
internal readonly ADUpsellPage AdUpsellPage = new ADUpsellPage ( ) ;
2013-11-14 12:06:50 +01:00
internal readonly GpuPage GpuPage = new GpuPage ( ) ;
2016-07-13 14:36:49 +02:00
internal readonly PvsPage PvsPage = new PvsPage ( ) ;
2015-02-06 11:03:42 +01:00
internal readonly DockerProcessPage DockerProcessPage = new DockerProcessPage ( ) ;
2015-02-09 08:42:00 +01:00
internal readonly DockerDetailsPage DockerDetailsPage = new DockerDetailsPage ( ) ;
2017-09-27 14:37:17 +02:00
internal readonly UsbPage UsbPage = new UsbPage ( ) ;
2013-06-24 13:41:48 +02:00
2023-07-22 17:43:02 +02:00
private readonly NotificationsBasePage [ ] _notificationPages ;
2022-11-08 12:18:35 +01:00
private ActionBase statusBarAction ;
2018-10-01 17:08:15 +02:00
2022-11-08 12:18:35 +01:00
private bool IgnoreTabChanges ;
2013-06-24 13:41:48 +02:00
2017-02-27 19:00:46 +01:00
/// <summary>
/// Helper boolean to only trigger Resize_End when window is really resized by dragging edges
/// Without this Resize_End is triggered even when window is moved around and not resized
/// </summary>
2022-11-08 12:18:35 +01:00
private bool mainWindowResized ;
2017-02-27 19:00:46 +01:00
2013-06-24 13:41:48 +02:00
private readonly Dictionary < IXenConnection , IList < Form > > activePoolWizards = new Dictionary < IXenConnection , IList < Form > > ( ) ;
2022-11-10 18:36:27 +01:00
private string [ ] _commandLineArgs ;
2013-06-24 13:41:48 +02:00
private static readonly System . Windows . Forms . Timer CheckForUpdatesTimer = new System . Windows . Forms . Timer ( ) ;
2021-11-29 16:18:38 +01:00
public readonly PluginManager PluginManager ;
2013-06-24 13:41:48 +02:00
private readonly ContextMenuBuilder contextMenuBuilder ;
private readonly LicenseManagerLauncher licenseManagerLauncher ;
private readonly LicenseTimer licenseTimer ;
private Dictionary < ToolStripMenuItem , int > pluginMenuItemStartIndexes = new Dictionary < ToolStripMenuItem , int > ( ) ;
2016-01-29 15:38:58 +01:00
private bool expandTreeNodesOnStartup ;
private int connectionsInProgressOnStartup ;
2022-02-01 14:42:11 +01:00
private ClientUpdateAlert updateAlert ;
2022-01-07 16:49:18 +01:00
2018-03-06 09:19:41 +01:00
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern uint RegisterApplicationRestart ( string pszCommandline , uint dwFlags ) ;
2022-11-08 12:18:35 +01:00
public event Action CloseSplashRequested ;
2022-11-10 18:36:27 +01:00
public MainWindow ( string [ ] args )
2013-06-24 13:41:48 +02:00
{
2022-11-10 18:36:27 +01:00
_commandLineArgs = args ;
2013-06-24 13:41:48 +02:00
licenseManagerLauncher = new LicenseManagerLauncher ( Program . MainWindow ) ;
InvokeHelper . Initialize ( this ) ;
2022-11-11 17:33:04 +01:00
ConnectionsManager . XenConnections . Clear ( ) ;
ConnectionsManager . History . Clear ( ) ;
Search . InitSearch ( ) ;
2013-06-24 13:41:48 +02:00
InitializeComponent ( ) ;
SetMenuItemStartIndexes ( ) ;
Icon = Properties . Resources . AppIcon ;
2013-11-23 17:03:21 +01:00
2018-03-06 09:19:41 +01:00
//CA-270999: Add registration to RestartManager
RegisterApplicationRestart ( null , 0 ) ;
2013-11-23 17:03:21 +01:00
#region Add Tab pages
2013-06-24 13:41:48 +02:00
components . Add ( NICPage ) ;
components . Add ( VMStoragePage ) ;
components . Add ( SrStoragePage ) ;
components . Add ( PerformancePage ) ;
components . Add ( GeneralPage ) ;
components . Add ( BallooningPage ) ;
components . Add ( ConsolePanel ) ;
2016-07-05 09:14:13 +02:00
components . Add ( CvmConsolePanel ) ;
2013-06-24 13:41:48 +02:00
components . Add ( NetworkPage ) ;
components . Add ( HAPage ) ;
components . Add ( HomePage ) ;
components . Add ( WlbPage ) ;
components . Add ( AdPage ) ;
2013-11-14 12:06:50 +01:00
components . Add ( GpuPage ) ;
2016-07-13 14:36:49 +02:00
components . Add ( PvsPage ) ;
2013-10-01 16:35:57 +02:00
components . Add ( SearchPage ) ;
2015-02-06 11:03:42 +01:00
components . Add ( DockerProcessPage ) ;
2015-02-09 08:42:00 +01:00
components . Add ( DockerDetailsPage ) ;
2017-09-27 14:37:17 +02:00
components . Add ( UsbPage ) ;
2013-06-24 13:41:48 +02:00
AddTabContents ( VMStoragePage , TabPageStorage ) ;
AddTabContents ( SrStoragePage , TabPageSR ) ;
AddTabContents ( NICPage , TabPageNICs ) ;
AddTabContents ( PerformancePage , TabPagePeformance ) ;
AddTabContents ( GeneralPage , TabPageGeneral ) ;
AddTabContents ( BallooningPage , TabPageBallooning ) ;
AddTabContents ( ConsolePanel , TabPageConsole ) ;
2016-07-05 09:14:13 +02:00
AddTabContents ( CvmConsolePanel , TabPageCvmConsole ) ;
2013-06-24 13:41:48 +02:00
AddTabContents ( NetworkPage , TabPageNetwork ) ;
AddTabContents ( HAPage , TabPageHA ) ;
AddTabContents ( HAUpsellPage , TabPageHAUpsell ) ;
AddTabContents ( HomePage , TabPageHome ) ;
AddTabContents ( WlbPage , TabPageWLB ) ;
AddTabContents ( WLBUpsellPage , TabPageWLBUpsell ) ;
AddTabContents ( PhysicalStoragePage , TabPagePhysicalStorage ) ;
AddTabContents ( AdPage , TabPageAD ) ;
2016-05-20 14:01:51 +02:00
AddTabContents ( AdUpsellPage , TabPageADUpsell ) ;
2013-11-14 12:06:50 +01:00
AddTabContents ( GpuPage , TabPageGPU ) ;
2016-07-13 14:36:49 +02:00
AddTabContents ( PvsPage , TabPagePvs ) ;
2013-10-01 16:35:57 +02:00
AddTabContents ( SearchPage , TabPageSearch ) ;
2015-02-06 11:03:42 +01:00
AddTabContents ( DockerProcessPage , TabPageDockerProcess ) ;
2015-02-09 08:42:00 +01:00
AddTabContents ( DockerDetailsPage , TabPageDockerDetails ) ;
2017-09-27 14:37:17 +02:00
AddTabContents ( UsbPage , TabPageUSB ) ;
2013-06-24 13:41:48 +02:00
2013-11-23 17:03:21 +01:00
#endregion
2023-07-22 17:43:02 +02:00
_notificationPages = new NotificationsBasePage [ ] { alertPage , updatesPage , cdnUpdatesPage , eventsPage } ;
2013-06-24 13:41:48 +02:00
PoolCollectionChangedWithInvoke = Program . ProgramInvokeHandler ( CollectionChanged < Pool > ) ;
MessageCollectionChangedWithInvoke = Program . ProgramInvokeHandler ( MessageCollectionChanged ) ;
HostCollectionChangedWithInvoke = Program . ProgramInvokeHandler ( CollectionChanged < Host > ) ;
VMCollectionChangedWithInvoke = Program . ProgramInvokeHandler ( CollectionChanged < VM > ) ;
SRCollectionChangedWithInvoke = Program . ProgramInvokeHandler ( CollectionChanged < SR > ) ;
FolderCollectionChangedWithInvoke = Program . ProgramInvokeHandler ( CollectionChanged < Folder > ) ;
TaskCollectionChangedWithInvoke = Program . ProgramInvokeHandler ( MeddlingActionManager . TaskCollectionChanged ) ;
2020-07-26 15:05:58 +02:00
RegisterEvents ( ) ;
2013-06-24 13:41:48 +02:00
2021-11-29 16:18:38 +01:00
PluginManager = new PluginManager ( ) ;
PluginManager . PluginsChanged + = pluginManager_PluginsChanged ;
PluginManager . LoadPlugins ( ) ;
contextMenuBuilder = new ContextMenuBuilder ( PluginManager , this ) ;
( ( WinformsXenAdminConfigProvider ) XenAdminConfigManager . Provider ) . PluginManager = PluginManager ;
2013-06-24 13:41:48 +02:00
FormFontFixer . Fix ( this ) ;
Folders . InitFolders ( ) ;
2015-02-04 10:48:32 +01:00
DockerContainers . InitDockerContainers ( ) ;
2013-06-24 13:41:48 +02:00
// Fix colour of text on gradient panels
2021-04-30 18:39:57 +02:00
TitleLabel . ForeColor = VerticalGradientPanel . TextColor ;
loggedInLabel1 . SetTextColor ( VerticalGradientPanel . TextColor ) ;
2013-06-24 13:41:48 +02:00
2013-11-12 13:44:19 +01:00
statusProgressBar . Visible = false ;
2014-01-22 13:39:32 +01:00
SelectionManager . BindTo ( MainMenuBar . Items , this ) ;
SelectionManager . BindTo ( ToolStrip . Items , this ) ;
2013-06-24 13:41:48 +02:00
licenseTimer = new LicenseTimer ( licenseManagerLauncher ) ;
GeneralPage . LicenseLauncher = licenseManagerLauncher ;
2016-01-22 10:01:36 +01:00
2022-02-21 16:28:40 +01:00
updateClientToolStripMenuItem . Visible = false ;
2021-03-16 02:50:45 +01:00
xenSourceOnTheWebToolStripMenuItem . Text = string . Format ( xenSourceOnTheWebToolStripMenuItem . Text ,
BrandManager . ProductBrand ) ;
viewApplicationLogToolStripMenuItem . Text = string . Format ( viewApplicationLogToolStripMenuItem . Text , BrandManager . BrandConsole ) ;
xenCenterPluginsOnlineToolStripMenuItem . Text = string . Format ( xenCenterPluginsOnlineToolStripMenuItem . Text , BrandManager . BrandConsole ) ;
aboutXenSourceAdminToolStripMenuItem . Text = string . Format ( aboutXenSourceAdminToolStripMenuItem . Text , BrandManager . BrandConsole ) ;
templatesToolStripMenuItem1 . Text = string . Format ( templatesToolStripMenuItem1 . Text , BrandManager . ProductBrand ) ;
2022-05-11 10:39:02 +02:00
updateClientToolStripMenuItem . Text = string . Format ( updateClientToolStripMenuItem . Text , BrandManager . BrandConsole ) ;
2023-05-11 22:17:57 +02:00
toolStripMenuItemCfu . Text = string . Format ( toolStripMenuItemCfu . Text , BrandManager . BrandConsole ) ;
2021-03-16 02:50:45 +01:00
2016-01-28 22:43:15 +01:00
toolStripSeparator7 . Visible = xenSourceOnTheWebToolStripMenuItem . Visible = xenCenterPluginsOnlineToolStripMenuItem . Visible = ! HiddenFeatures . ToolStripMenuItemHidden ;
2020-03-24 03:07:15 +01:00
2023-07-22 17:43:02 +02:00
statusButtonAlerts . Visible = statusButtonUpdates . Visible = statusButtonCdnUpdates . Visible = statusButtonProgress . Visible = statusButtonErrors . Visible = false ;
statusButtonUpdates . ToolTipText = string . Format ( statusButtonUpdates . ToolTipText , BrandManager . ProductVersion821 ) ;
statusButtonCdnUpdates . ToolTipText = string . Format ( statusButtonCdnUpdates . ToolTipText , BrandManager . ProductBrand , BrandManager . ProductVersionPost82 ) ;
2013-06-24 13:41:48 +02:00
}
2020-07-26 15:05:58 +02:00
private void RegisterEvents ( )
{
//ClipboardViewer is registered in OnHandleCreated
OtherConfigAndTagsWatcher . RegisterEventHandlers ( ) ;
Alert . RegisterAlertCollectionChanged ( XenCenterAlerts_CollectionChanged ) ;
2020-07-26 15:54:52 +02:00
Updates . UpdateAlertCollectionChanged + = Updates_CollectionChanged ;
2023-07-03 21:50:12 +02:00
Updates . CdnUpdateInfoChanged + = Cdn_UpdateInfoChanged ;
2023-05-11 22:17:57 +02:00
Updates . CheckForClientUpdatesStarted + = ClientUpdatesCheck_Started ;
Updates . CheckForClientUpdatesCompleted + = ClientUpdatesCheck_Completed ;
2020-07-26 15:05:58 +02:00
ConnectionsManager . History . CollectionChanged + = History_CollectionChanged ;
//ConnectionsManager.XenConnections.CollectionChanged is registered in OnShown
Properties . Settings . Default . SettingChanging + = Default_SettingChanging ;
eventsPage . GoToXenObjectRequested + = eventsPage_GoToXenObjectRequested ;
SearchPage . SearchChanged + = SearchPanel_SearchChanged ;
}
private void UnRegisterEvents ( )
{
Clip . UnregisterClipboardViewer ( ) ;
OtherConfigAndTagsWatcher . DeregisterEventHandlers ( ) ;
Alert . DeregisterAlertCollectionChanged ( XenCenterAlerts_CollectionChanged ) ;
2020-07-26 15:54:52 +02:00
Updates . UpdateAlertCollectionChanged - = Updates_CollectionChanged ;
2023-07-03 21:50:12 +02:00
Updates . CdnUpdateInfoChanged - = Cdn_UpdateInfoChanged ;
2023-05-11 22:17:57 +02:00
Updates . CheckForClientUpdatesStarted - = ClientUpdatesCheck_Started ;
Updates . CheckForClientUpdatesCompleted - = ClientUpdatesCheck_Completed ;
2020-07-26 15:05:58 +02:00
ConnectionsManager . History . CollectionChanged - = History_CollectionChanged ;
ConnectionsManager . XenConnections . CollectionChanged - = XenConnection_CollectionChanged ;
Properties . Settings . Default . SettingChanging - = Default_SettingChanging ;
eventsPage . GoToXenObjectRequested - = eventsPage_GoToXenObjectRequested ;
SearchPage . SearchChanged - = SearchPanel_SearchChanged ;
}
2013-08-22 18:25:12 +02:00
private void Default_SettingChanging ( object sender , SettingChangingEventArgs e )
2013-06-24 13:41:48 +02:00
{
if ( e = = null )
return ;
if ( e . SettingName = = "AutoSwitchToRDP" | | e . SettingName = = "EnableRDPPolling" )
{
ConsolePanel . ResetAllViews ( ) ;
2013-08-22 18:25:12 +02:00
if ( SelectionManager . Selection . FirstIsRealVM )
2022-01-31 12:37:34 +01:00
ConsolePanel . SetCurrentSource ( ( VM ) SelectionManager . Selection . First ) ;
2016-10-14 13:21:59 +02:00
else if ( SelectionManager . Selection . FirstIs < Host > ( ) )
2022-01-31 12:37:34 +01:00
ConsolePanel . SetCurrentSource ( ( Host ) SelectionManager . Selection . First ) ;
2013-06-24 13:41:48 +02:00
2022-02-02 18:24:20 +01:00
ConsolePanel . UnpauseActiveView ( sender = = TheTabControl ) ;
2013-06-24 13:41:48 +02:00
}
}
private void SetMenuItemStartIndexes ( )
{
foreach ( ToolStripMenuItem menu in MainMenuBar . Items )
{
foreach ( ToolStripItem item in menu . DropDownItems )
{
if ( item ! = null & & item . Text = = "PluginItemsPlaceHolder" )
{
pluginMenuItemStartIndexes . Add ( menu , menu . DropDownItems . IndexOf ( item ) ) ;
menu . DropDownItems . Remove ( item ) ;
break ;
}
}
}
}
internal SelectionBroadcaster SelectionManager
{
get
{
2013-08-26 12:42:32 +02:00
return navigationPane . SelectionManager ;
2013-06-24 13:41:48 +02:00
}
}
internal ContextMenuBuilder ContextMenuBuilder
{
get
{
return contextMenuBuilder ;
}
}
protected override void OnLoad ( EventArgs e )
{
Program . AssertOnEventThread ( ) ;
History . EnableHistoryButtons ( ) ;
History . NewHistoryItem ( new XenModelObjectHistoryItem ( null , TabPageHome ) ) ;
2021-03-16 02:50:45 +01:00
Text = BrandManager . BrandConsole ;
2013-06-24 13:41:48 +02:00
/ *
* Resume window size and location
* /
try
{
// Bring in previous version user setting for the first time.
if ( Properties . Settings . Default . DoUpgrade )
{
Properties . Settings . Default . Upgrade ( ) ;
Properties . Settings . Default . DoUpgrade = false ;
XenAdmin . Settings . TrySaveSettings ( ) ;
}
Point savedLocation = Properties . Settings . Default . WindowLocation ;
Size savedSize = Properties . Settings . Default . WindowSize ;
if ( HelpersGUI . WindowIsOnScreen ( savedLocation , savedSize ) )
{
this . Location = savedLocation ;
this . Size = savedSize ;
}
}
catch
{
2021-09-10 15:19:08 +02:00
// ignored
2013-06-24 13:41:48 +02:00
}
// Using the Load event ensures that the handle has been
// created:
base . OnLoad ( e ) ;
2013-08-24 18:00:32 +02:00
}
2013-06-24 13:41:48 +02:00
2013-08-24 18:00:32 +02:00
protected override void OnShown ( EventArgs e )
{
base . OnShown ( e ) ;
2013-11-05 15:40:16 +01:00
TheTabControl . Visible = true ;
2023-07-28 16:21:31 +02:00
foreach ( var page in _notificationPages )
{
page . Visible = false ;
page . FiltersChanged + = NotificationsPage_FiltersChanged ;
}
2023-05-11 17:34:21 +02:00
SetFiltersLabel ( ) ;
2013-08-26 12:42:32 +02:00
navigationPane . FocusTreeView ( ) ;
2013-06-24 13:41:48 +02:00
}
protected override void OnHandleCreated ( EventArgs e )
{
base . OnHandleCreated ( e ) ;
Clip . RegisterClipboardViewer ( ) ;
}
protected override void WndProc ( ref System . Windows . Forms . Message e )
{
//System.Console.WriteLine(Win32.GetWindowsMessageName(e.Msg));
switch ( e . Msg )
{
case Win32 . WM_CHANGECBCHAIN : // Clipboard chain has changed.
Clip . ProcessWMChangeCBChain ( e ) ;
break ;
case Win32 . WM_DRAWCLIPBOARD : // Content of clipboard has changed.
Clip . ProcessWMDrawClipboard ( e ) ;
break ;
case Win32 . WM_DESTROY :
Clip . UnregisterClipboardViewer ( ) ;
base . WndProc ( ref e ) ;
break ;
default :
base . WndProc ( ref e ) ;
break ;
}
}
private void AddTabContents ( Control contents , TabPage TabPage )
{
contents . Location = new Point ( 0 , 0 ) ;
contents . Size = TabPage . Size ;
contents . Anchor = AnchorStyles . Left | AnchorStyles . Bottom | AnchorStyles . Top | AnchorStyles . Right ;
TabPage . Controls . Add ( contents ) ;
}
2020-10-25 14:01:56 +01:00
private void History_CollectionChanged ( object sender , CollectionChangeEventArgs e )
2013-06-24 13:41:48 +02:00
{
if ( Program . Exiting )
return ;
2020-10-25 14:01:56 +01:00
switch ( e . Action )
2013-11-19 16:42:47 +01:00
{
2020-10-25 14:01:56 +01:00
case CollectionChangeAction . Add :
if ( e . Element is ActionBase action )
{
if ( ! ( action is MeddlingAction ) )
2013-11-19 16:42:47 +01:00
{
2020-10-25 14:01:56 +01:00
Program . Invoke ( this , ( ) = >
2013-11-19 16:42:47 +01:00
{
SetStatusBar ( null , null ) ;
statusBarAction = action ;
2020-10-25 14:01:56 +01:00
} ) ;
2013-11-19 16:42:47 +01:00
}
2020-10-25 14:01:56 +01:00
action . Changed + = actionChanged ;
action . Completed + = actionCompleted ;
actionChanged ( action ) ;
}
break ;
case CollectionChangeAction . Remove :
if ( e . Element is ActionBase actionB )
{
actionB . Changed - = actionChanged ;
actionB . Completed - = actionCompleted ;
}
else if ( e . Element is List < ActionBase > range )
{
foreach ( var a in range )
2013-11-19 16:42:47 +01:00
{
2020-10-25 14:01:56 +01:00
a . Changed - = actionChanged ;
a . Completed - = actionCompleted ;
2013-11-19 16:42:47 +01:00
}
2020-10-25 14:01:56 +01:00
}
else
return ;
2023-07-22 17:43:02 +02:00
UpdateErrorStatusButton ( ) ;
2020-10-25 14:01:56 +01:00
break ;
}
2013-06-24 13:41:48 +02:00
}
2018-10-12 14:36:44 +02:00
private void actionCompleted ( ActionBase action )
2017-03-24 11:30:34 +01:00
{
2020-10-25 14:01:56 +01:00
action . Changed - = actionChanged ;
action . Completed - = actionCompleted ;
2017-03-24 11:30:34 +01:00
actionChanged ( action ) ;
2020-10-25 14:01:56 +01:00
2023-03-23 23:25:13 +01:00
if ( action is ISrAction )
2017-03-24 11:30:34 +01:00
Program . Invoke ( this , UpdateToolbars ) ;
}
2018-10-12 14:36:44 +02:00
private void actionChanged ( ActionBase action )
2013-06-24 13:41:48 +02:00
{
if ( Program . Exiting )
return ;
2013-08-05 15:28:21 +02:00
2020-10-25 14:01:56 +01:00
Program . Invoke ( this , ( ) = >
{
UpdateStatusProgressBar ( action ) ;
2023-07-22 17:43:02 +02:00
UpdateErrorStatusButton ( ) ;
2020-10-25 14:01:56 +01:00
} ) ;
2013-06-24 13:41:48 +02:00
}
2020-10-25 14:01:56 +01:00
private void UpdateStatusProgressBar ( ActionBase action )
2013-06-24 13:41:48 +02:00
{
2020-10-25 14:01:56 +01:00
if ( statusBarAction ! = action )
2017-03-16 14:31:51 +01:00
return ;
2013-11-12 13:44:19 +01:00
2020-10-25 14:01:56 +01:00
statusProgressBar . Visible = action . ShowProgress & & ! action . IsCompleted ;
2018-10-12 14:36:44 +02:00
var percentage = action . PercentComplete ;
Debug . Assert ( 0 < = percentage & & percentage < = 100 ,
"PercentComplete is out of range, the reporting action needs to be fixed." ) ; //CA-8517
2013-06-24 13:41:48 +02:00
2020-10-25 14:01:56 +01:00
if ( percentage < 0 )
percentage = 0 ;
else if ( percentage > 100 )
percentage = 100 ;
statusProgressBar . Value = percentage ;
2018-10-12 14:36:44 +02:00
2020-10-25 14:01:56 +01:00
// Don't show cancelled exception
if ( action . Exception ! = null & & ! ( action . Exception is CancelledException ) )
{
SetStatusBar ( Images . StaticImages . _000_error_h32bit_16 , action . Exception . Message ) ;
2013-11-12 13:44:19 +01:00
}
2020-10-25 14:01:56 +01:00
else
{
SetStatusBar ( null , action . IsCompleted
? null
: ! string . IsNullOrEmpty ( action . Description )
? action . Description
: ! string . IsNullOrEmpty ( action . Title )
? action . Title
: null ) ;
}
}
2013-11-19 16:42:47 +01:00
2023-07-22 17:43:02 +02:00
private void UpdateErrorStatusButton ( )
2020-10-25 14:01:56 +01:00
{
2023-07-22 17:43:02 +02:00
int progressCount = ConnectionsManager . History . Count ( a = > ! a . IsCompleted ) ;
statusButtonProgress . Text = progressCount . ToString ( ) ;
statusButtonProgress . Visible = progressCount > 0 ;
2020-10-25 14:01:56 +01:00
int errorCount = ConnectionsManager . History . Count ( a = >
a . IsCompleted & & ! a . Succeeded & & ! ( a is CancellingAction ca & & ca . Cancelled ) ) ;
2020-03-24 03:07:15 +01:00
navigationPane . UpdateNotificationsButton ( NotificationsSubMode . Events , errorCount ) ;
2023-07-22 17:43:02 +02:00
statusButtonErrors . Text = errorCount . ToString ( ) ;
statusButtonErrors . Visible = errorCount > 0 ;
2013-11-19 16:42:47 +01:00
if ( eventsPage . Visible )
{
2020-03-24 03:07:15 +01:00
TitleLabel . Text = NotificationsSubModeItem . GetText ( NotificationsSubMode . Events , errorCount ) ;
TitleIcon . Image = NotificationsSubModeItem . GetImage ( NotificationsSubMode . Events , errorCount ) ;
2013-11-19 16:42:47 +01:00
}
2013-11-12 13:44:19 +01:00
}
2018-10-12 14:36:44 +02:00
private void SetStatusBar ( Image image , string message )
2013-11-12 13:44:19 +01:00
{
statusLabel . Image = image ;
statusLabel . Text = Helpers . FirstLine ( message ) ;
}
2022-11-08 12:18:35 +01:00
public void CloseSplashScreen ( )
{
ThreadPool . QueueUserWorkItem ( delegate
{
// Sleep a short time before closing the splash
Thread . Sleep ( 500 ) ;
Program . Invoke ( Program . MainWindow , ( ) = > CloseSplashRequested ? . Invoke ( ) ) ;
} ) ;
}
2013-06-24 13:41:48 +02:00
private void MainWindow_Shown ( object sender , EventArgs e )
{
MainMenuBar . Location = new Point ( 0 , 0 ) ;
2018-09-28 18:58:49 +02:00
var rendProf = ToolStrip . Renderer as ToolStripProfessionalRenderer ;
if ( rendProf ! = null )
rendProf . RoundedEdges = false ;
2013-06-24 13:41:48 +02:00
RequestRefreshTreeView ( ) ;
2022-05-04 15:23:04 +02:00
ConnectionsManager . XenConnections . CollectionChanged + = XenConnection_CollectionChanged ;
//no need to catch ConfigurationErrorsException as the settings have already been loaded
Settings . RestoreSession ( ) ;
2016-01-29 15:38:58 +01:00
// if there are fewer than 30 connections, then expand the tree nodes.
expandTreeNodesOnStartup = ConnectionsManager . XenConnectionsCopy . Count < 30 ;
connectionsInProgressOnStartup = 0 ;
2013-06-24 13:41:48 +02:00
// kick-off connections for all the loaded server list
foreach ( IXenConnection connection in ConnectionsManager . XenConnectionsCopy )
{
if ( ! connection . SaveDisconnected )
{
2016-01-29 15:38:58 +01:00
connectionsInProgressOnStartup + + ;
connection . ConnectionStateChanged + = Connection_ConnectionStateChangedOnStartup ;
connection . CachePopulated + = connection_CachePopulatedOnStartup ;
2013-06-24 13:41:48 +02:00
XenConnectionUI . BeginConnect ( connection , true , this , true ) ;
}
}
2022-11-08 12:18:35 +01:00
CloseSplashScreen ( ) ;
2013-06-24 13:41:48 +02:00
if ( ! Program . RunInAutomatedTestMode & & ! Helpers . CommonCriteriaCertificationRelease )
{
if ( ! Properties . Settings . Default . SeenAllowUpdatesDialog )
2023-05-11 22:17:57 +02:00
using ( var dlg = new NoIconDialog ( string . Format ( Messages . ALLOWED_UPDATES_DIALOG_MESSAGE , BrandManager . BrandConsole , BrandManager . ProductBrand ) ,
2021-02-26 04:31:05 +01:00
ThreeButtonDialog . ButtonYes , ThreeButtonDialog . ButtonNo )
{
HelpButton = true ,
HelpNameSetter = "AllowUpdatesDialog" ,
ShowCheckbox = true ,
CheckboxCaption = Messages . ALLOWED_UPDATES_DIALOG_CHECKBOX
} )
{
var result = dlg . ShowDialog ( this ) = = DialogResult . Yes ;
Properties . Settings . Default . AllowXenCenterUpdates = result ;
Properties . Settings . Default . SeenAllowUpdatesDialog = true ;
if ( result & & dlg . IsCheckBoxChecked )
{
2021-11-29 16:18:38 +01:00
using ( var dialog = new OptionsDialog ( PluginManager ) )
2021-02-26 04:31:05 +01:00
{
dialog . SelectConnectionOptionsPage ( ) ;
dialog . ShowDialog ( this ) ;
}
}
Settings . TrySaveSettings ( ) ;
}
2013-06-24 13:41:48 +02:00
// start checkforupdates thread
CheckForUpdatesTimer . Interval = 1000 * 60 * 60 * 24 ; // 24 hours
2013-11-21 15:11:29 +01:00
CheckForUpdatesTimer . Tick + = CheckForUpdatesTimer_Tick ;
2013-06-24 13:41:48 +02:00
CheckForUpdatesTimer . Start ( ) ;
2023-05-11 22:17:57 +02:00
Updates . CheckForClientUpdates ( ) ;
Updates . CheckForServerUpdates ( ) ;
2013-06-24 13:41:48 +02:00
}
2015-08-27 01:30:02 +02:00
2022-11-10 18:36:27 +01:00
ProcessCommand ( _commandLineArgs ) ;
2013-06-24 13:41:48 +02:00
}
2013-11-21 15:11:29 +01:00
private void CheckForUpdatesTimer_Tick ( object sender , EventArgs e )
{
2023-05-11 22:17:57 +02:00
Updates . CheckForClientUpdates ( ) ;
Updates . CheckForServerUpdates ( ) ;
2013-11-21 15:11:29 +01:00
}
2013-06-24 13:41:48 +02:00
private void LoadTasksAsMeddlingActions ( IXenConnection connection )
{
if ( ! connection . IsConnected | | connection . Session = = null )
return ;
Dictionary < XenRef < Task > , Task > tasks = Task . get_all_records ( connection . Session ) ;
foreach ( KeyValuePair < XenRef < Task > , Task > pair in tasks )
{
pair . Value . Connection = connection ;
pair . Value . opaque_ref = pair . Key ;
MeddlingActionManager . ForceAddTask ( pair . Value ) ;
}
}
2019-10-27 16:52:15 +01:00
private void connection_CachePopulatedOnStartup ( IXenConnection c )
2013-06-24 13:41:48 +02:00
{
c . CachePopulated - = connection_CachePopulatedOnStartup ;
2016-01-29 15:38:58 +01:00
if ( expandTreeNodesOnStartup )
TrySelectNewNode ( c , false , true , false ) ;
Program . Invoke ( this , ShowAboutDialogOnStartup ) ;
}
2019-10-27 16:52:15 +01:00
private void Connection_ConnectionStateChangedOnStartup ( IXenConnection c )
2016-01-29 15:38:58 +01:00
{
2016-02-04 10:54:42 +01:00
c . ConnectionStateChanged - = Connection_ConnectionStateChangedOnStartup ;
2016-01-29 15:38:58 +01:00
Program . Invoke ( Program . MainWindow , delegate
{
connectionsInProgressOnStartup - - ;
// show the About dialog if this was the last connection in progress and the connection failed
if ( ! c . IsConnected )
ShowAboutDialogOnStartup ( ) ;
} ) ;
}
/// <summary>
/// Show the About dialog after all conncections kicked-off on startup have finished the connection phase (cache populated)
/// Must be called on the event thread.
/// </summary>
private void ShowAboutDialogOnStartup ( )
{
Program . AssertOnEventThread ( ) ;
if ( connectionsInProgressOnStartup > 0 )
return ;
2016-02-29 15:54:26 +01:00
if ( Properties . Settings . Default . ShowAboutDialog & & HiddenFeatures . LicenseNagVisible )
2016-01-29 15:38:58 +01:00
ShowForm ( typeof ( AboutDialog ) ) ;
2013-06-24 13:41:48 +02:00
}
2022-11-10 18:36:27 +01:00
#region Commnad line args processing
internal void ProcessCommand ( params string [ ] args )
2013-06-24 13:41:48 +02:00
{
2022-11-10 18:36:27 +01:00
if ( args ! = null & & args . Length > 1 )
2013-06-24 13:41:48 +02:00
{
2022-11-10 18:36:27 +01:00
switch ( args [ 0 ] )
{
case "import" :
log . DebugFormat ( "CLI: Importing VM export from {0}" , args [ 1 ] ) ;
OpenGlobalImportWizard ( args [ 1 ] ) ;
break ;
case "license" :
log . DebugFormat ( "CLI: Installing license from {0}" , args [ 1 ] ) ;
LaunchLicensePicker ( args [ 1 ] ) ;
break ;
case "restore" :
log . DebugFormat ( "CLI: Restoring host backup from {0}" , args [ 1 ] ) ;
new RestoreHostFromBackupCommand ( this , null , args [ 1 ] ) . Run ( ) ;
break ;
case "search" :
log . DebugFormat ( "CLI: Importing saved XenSearch from '{0}'" , args [ 1 ] ) ;
new ImportSearchCommand ( this , args [ 1 ] ) . Run ( ) ;
break ;
case "connect" :
log . DebugFormat ( "CLI: Connecting to server '{0}'" , args [ 1 ] ) ;
2019-10-03 10:18:20 +02:00
2022-11-10 18:36:27 +01:00
var connection = new XenConnection
{
Hostname = args [ 1 ] ,
Port = ConnectionsManager . DEFAULT_XEN_PORT ,
Username = args . Length > 2 ? args [ 2 ] : "" ,
Password = args . Length > 3 ? args [ 3 ] : ""
} ;
2019-10-03 10:18:20 +02:00
2023-05-09 16:12:04 +02:00
if ( File . Exists ( args [ 1 ] ) )
XenConnectionUI . ConnectToXapiDatabase ( connection , this ) ;
else
XenConnectionUI . BeginConnect ( connection , true , this , false ) ;
2022-11-10 18:36:27 +01:00
break ;
default :
log . Warn ( "CLI: Wrong syntax or unknown command line options." ) ;
break ;
}
2013-06-24 13:41:48 +02:00
}
2022-11-10 18:36:27 +01:00
2023-05-09 16:12:04 +02:00
HelpersGUI . BringFormToFront ( this ) ;
2013-06-24 13:41:48 +02:00
}
2022-11-10 18:36:27 +01:00
#endregion
/// <summary>
/// Manages UI and network updates whenever hosts are added and removed
/// </summary>
private void XenConnection_CollectionChanged ( object sender , CollectionChangeEventArgs e )
2013-06-24 13:41:48 +02:00
{
if ( Program . Exiting )
return ;
//Program.AssertOnEventThread();
Program . BeginInvoke ( Program . MainWindow , ( ) = > XenConnectionCollectionChanged ( e ) ) ;
}
2022-11-10 18:36:27 +01:00
2013-06-24 13:41:48 +02:00
private readonly CollectionChangeEventHandler PoolCollectionChangedWithInvoke = null ;
private readonly CollectionChangeEventHandler MessageCollectionChangedWithInvoke = null ;
private readonly CollectionChangeEventHandler HostCollectionChangedWithInvoke = null ;
private readonly CollectionChangeEventHandler VMCollectionChangedWithInvoke = null ;
private readonly CollectionChangeEventHandler SRCollectionChangedWithInvoke = null ;
private readonly CollectionChangeEventHandler FolderCollectionChangedWithInvoke = null ;
private readonly CollectionChangeEventHandler TaskCollectionChangedWithInvoke = null ;
private void XenConnectionCollectionChanged ( CollectionChangeEventArgs e )
{
try
{
2017-07-14 19:08:54 +02:00
IXenConnection connection = e . Element as IXenConnection ;
2013-06-24 13:41:48 +02:00
2013-08-26 12:42:32 +02:00
navigationPane . XenConnectionCollectionChanged ( e ) ;
2013-08-25 13:42:38 +02:00
2013-06-24 13:41:48 +02:00
if ( e . Action = = CollectionChangeAction . Add )
{
2017-07-14 19:08:54 +02:00
if ( connection = = null )
return ;
2013-06-24 13:41:48 +02:00
connection . ClearingCache + = connection_ClearingCache ;
connection . ConnectionResult + = Connection_ConnectionResult ;
connection . ConnectionLost + = Connection_ConnectionLost ;
connection . ConnectionClosed + = Connection_ConnectionClosed ;
connection . ConnectionReconnecting + = connection_ConnectionReconnecting ;
connection . XenObjectsUpdated + = Connection_XenObjectsUpdated ;
connection . Cache . RegisterCollectionChanged < XenAPI . Message > ( MessageCollectionChangedWithInvoke ) ;
connection . Cache . RegisterCollectionChanged < Pool > ( PoolCollectionChangedWithInvoke ) ;
connection . Cache . RegisterCollectionChanged < Host > ( HostCollectionChangedWithInvoke ) ;
connection . Cache . RegisterCollectionChanged < VM > ( VMCollectionChangedWithInvoke ) ;
connection . Cache . RegisterCollectionChanged < SR > ( SRCollectionChangedWithInvoke ) ;
connection . Cache . RegisterCollectionChanged < Folder > ( FolderCollectionChangedWithInvoke ) ;
connection . Cache . RegisterCollectionChanged < Task > ( TaskCollectionChangedWithInvoke ) ;
connection . CachePopulated + = connection_CachePopulated ;
}
else if ( e . Action = = CollectionChangeAction . Remove )
{
2017-07-14 19:08:54 +02:00
var range = new List < IXenConnection > ( ) ;
if ( connection ! = null )
2013-06-24 13:41:48 +02:00
{
2017-07-14 19:08:54 +02:00
range . Add ( connection ) ;
}
else
{
var r = e . Element as List < IXenConnection > ;
if ( r ! = null )
range = r ;
else
return ;
2013-06-24 13:41:48 +02:00
}
2017-07-14 19:08:54 +02:00
foreach ( var con in range )
2016-07-05 09:14:13 +02:00
{
2017-07-14 19:08:54 +02:00
con . ClearingCache - = connection_ClearingCache ;
con . ConnectionResult - = Connection_ConnectionResult ;
con . ConnectionLost - = Connection_ConnectionLost ;
con . ConnectionClosed - = Connection_ConnectionClosed ;
con . ConnectionReconnecting - = connection_ConnectionReconnecting ;
con . XenObjectsUpdated - = Connection_XenObjectsUpdated ;
con . Cache . DeregisterCollectionChanged < XenAPI . Message > ( MessageCollectionChangedWithInvoke ) ;
con . Cache . DeregisterCollectionChanged < Pool > ( PoolCollectionChangedWithInvoke ) ;
con . Cache . DeregisterCollectionChanged < Host > ( HostCollectionChangedWithInvoke ) ;
con . Cache . DeregisterCollectionChanged < VM > ( VMCollectionChangedWithInvoke ) ;
con . Cache . DeregisterCollectionChanged < SR > ( SRCollectionChangedWithInvoke ) ;
con . Cache . DeregisterCollectionChanged < Folder > ( FolderCollectionChangedWithInvoke ) ;
con . Cache . DeregisterCollectionChanged < Task > ( TaskCollectionChangedWithInvoke ) ;
con . CachePopulated - = connection_CachePopulated ;
foreach ( VM vm in con . Cache . VMs )
{
2022-01-31 12:37:34 +01:00
ConsolePanel . CloseVncForSource ( vm ) ;
2017-07-14 19:08:54 +02:00
}
2013-06-24 13:41:48 +02:00
2017-07-14 19:08:54 +02:00
foreach ( Host host in con . Cache . Hosts )
{
2022-01-31 12:37:34 +01:00
ConsolePanel . CloseVncForSource ( host . ControlDomainZero ( ) ) ;
2013-06-24 13:41:48 +02:00
2017-09-03 04:33:29 +02:00
foreach ( VM vm in host . OtherControlDomains ( ) )
2022-01-31 12:37:34 +01:00
CvmConsolePanel . CloseVncForSource ( vm ) ;
2017-07-14 19:08:54 +02:00
}
2013-06-24 13:41:48 +02:00
2017-07-14 19:08:54 +02:00
con . EndConnect ( ) ;
}
2018-10-03 12:05:41 +02:00
2013-06-24 13:41:48 +02:00
//CA-41228 refresh submenu items when there are no connections
2013-08-22 18:25:12 +02:00
SelectionManager . RefreshSelection ( ) ;
2013-06-24 13:41:48 +02:00
}
}
catch ( Exception exn )
{
log . Error ( exn , exn ) ;
// Can't do any more about this.
}
}
/// <summary>
/// Closes any wizards for this connection. Must be done before we clear the cache so that per-VM wizards are closed.
/// In many cases this is already covered (e.g. if the user explicitly disconnects). This method ensures we also
/// do it when we unexpectedly lose the connection.
/// </summary>
2019-10-27 16:52:15 +01:00
private void connection_ClearingCache ( IXenConnection connection )
2013-06-24 13:41:48 +02:00
{
2014-01-22 13:39:32 +01:00
CloseActiveWizards ( connection ) ;
2013-11-21 12:57:57 +01:00
Alert . RemoveAlert ( alert = > alert . Connection ! = null & & alert . Connection . Equals ( connection ) ) ;
2023-07-22 17:16:46 +02:00
if ( Helpers . CloudOrGreater ( connection ) )
Updates . RemoveCdnInfoForConnection ( connection ) ;
else
Updates . RefreshUpdateAlerts ( Updates . UpdateType . ServerPatches | Updates . UpdateType . ServerVersion ) ;
2014-10-08 18:16:45 +02:00
RequestRefreshTreeView ( ) ;
2013-06-24 13:41:48 +02:00
}
2021-04-13 14:36:30 +02:00
private void connection_CachePopulated ( IXenConnection connection )
2013-06-24 13:41:48 +02:00
{
2021-08-31 12:31:16 +02:00
Host coordinator = Helpers . GetCoordinator ( connection ) ;
if ( coordinator = = null )
2013-06-24 13:41:48 +02:00
return ;
2021-05-26 01:32:59 +02:00
log . InfoFormat ( "Connected to {0} (version {1}, build {2}.{3}) with {4} {5}" ,
2021-08-31 12:31:16 +02:00
Helpers . GetName ( coordinator ) , Helpers . HostProductVersionText ( coordinator ) , Helpers . HostProductVersion ( coordinator ) ,
coordinator . BuildNumberRaw ( ) , BrandManager . BrandConsole , Program . Version ) ;
2013-06-24 13:41:48 +02:00
2015-11-18 17:52:43 +01:00
// Check the PRODUCT_BRAND
2021-08-31 12:31:16 +02:00
if ( ! Program . RunInAutomatedTestMode & & ! SameProductBrand ( coordinator ) )
2015-11-18 17:52:43 +01:00
{
connection . EndConnect ( ) ;
2018-10-03 10:12:11 +02:00
Program . Invoke ( Program . MainWindow , delegate
2015-11-18 17:52:43 +01:00
{
2021-08-31 12:31:16 +02:00
var title = string . Format ( Messages . CONNECTION_REFUSED_TITLE , Helpers . GetName ( coordinator ) . Ellipsise ( 80 ) ) ;
2022-04-11 22:44:27 +02:00
new DummyAction ( title , "" , string . Format ( Messages . INCOMPATIBLE_PRODUCTS , BrandManager . BrandConsole ) ) . Run ( ) ;
2015-11-18 17:52:43 +01:00
2021-03-16 02:50:45 +01:00
using ( var dlog = new ErrorDialog ( string . Format ( Messages . INCOMPATIBLE_PRODUCTS , BrandManager . BrandConsole ) )
{ WindowTitle = title } )
2015-11-18 17:52:43 +01:00
dlog . ShowDialog ( this ) ;
} ) ;
return ;
}
2021-08-31 12:31:16 +02:00
//check the pool has no supporters earlier than the lowest supported version
2019-02-01 14:25:44 +01:00
//(could happen if trying to connect to a partially upgraded pool where
//the newest hosts have been upgraded using a earlier XenCenter)
2021-08-31 12:31:16 +02:00
var supporters = connection . Cache . Hosts . Where ( h = > h . opaque_ref ! = coordinator . opaque_ref ) ;
foreach ( var supporter in supporters )
2019-02-01 14:25:44 +01:00
{
2023-07-11 12:23:36 +02:00
if ( Helpers . NaplesOrGreater ( supporter ) )
2019-02-01 14:25:44 +01:00
continue ;
connection . EndConnect ( ) ;
Program . Invoke ( Program . MainWindow , ( ) = >
{
2021-08-31 12:31:16 +02:00
var title = string . Format ( Messages . CONNECTION_REFUSED_TITLE , Helpers . GetName ( coordinator ) . Ellipsise ( 80 ) ) ;
2023-05-10 16:22:46 +02:00
var msg = string . Format ( Messages . SUPPORTER_TOO_OLD , BrandManager . ProductVersion712 , BrandManager . BrandConsole ) ;
2022-04-11 22:44:27 +02:00
new DummyAction ( title , "" , msg ) . Run ( ) ;
2019-02-01 14:25:44 +01:00
2021-03-16 02:50:45 +01:00
using ( var dlg = new ErrorDialog ( msg , ThreeButtonDialog . ButtonOK )
{ WindowTitle = Messages . CONNECT_TO_SERVER } )
2019-02-01 14:25:44 +01:00
{
dlg . ShowDialog ( this ) ;
}
} ) ;
return ;
}
2013-06-24 13:41:48 +02:00
// When releasing a new version of the server, we should set xencenter_min and xencenter_max on the server
// as follows:
//
// xencenter_min should be the lowest version of XenCenter we want the new server to work with. In the
// (common) case that we want to force the user to upgrade XenCenter when they upgrade the server,
// xencenter_min should equal the current version of XenCenter. // if (server_min > current_version)
//
// xencenter_max should always equal the current version of XenCenter. This ensures that even if they are
// not required to upgrade, we at least warn them. // else if (server_max > current_version)
2023-05-10 16:22:46 +02:00
int serverMin = coordinator . XenCenterMin ( ) ;
int serverMax = coordinator . XenCenterMax ( ) ;
2013-06-24 13:41:48 +02:00
2023-05-10 16:22:46 +02:00
if ( serverMin > 0 & & serverMax > 0 )
2013-06-24 13:41:48 +02:00
{
2023-05-10 16:22:46 +02:00
int currentVersion = ( int ) API_Version . LATEST ;
2013-06-24 13:41:48 +02:00
2023-05-10 16:22:46 +02:00
if ( serverMin > currentVersion )
2013-06-24 13:41:48 +02:00
{
connection . EndConnect ( ) ;
2013-09-26 15:12:26 +02:00
2018-10-03 10:12:11 +02:00
Program . Invoke ( Program . MainWindow , delegate
2013-06-24 13:41:48 +02:00
{
2021-08-31 12:31:16 +02:00
var msg = string . Format ( Messages . GUI_OUT_OF_DATE , BrandManager . BrandConsole , Helpers . GetName ( coordinator ) ) ;
2019-04-01 15:56:29 +02:00
var url = InvisibleMessages . OUT_OF_DATE_WEBSITE ;
2021-08-31 12:31:16 +02:00
var title = string . Format ( Messages . CONNECTION_REFUSED_TITLE , Helpers . GetName ( coordinator ) . Ellipsise ( 80 ) ) ;
2019-02-01 14:25:44 +01:00
var error = $"{msg}\n{url}" ;
2013-09-26 15:12:26 +02:00
2022-04-11 22:44:27 +02:00
new DummyAction ( title , "" , error ) . Run ( ) ;
2018-10-03 10:12:11 +02:00
2020-07-30 12:29:01 +02:00
using ( var dlog = new ErrorDialog ( msg )
{
WindowTitle = title ,
ShowLinkLabel = ! HiddenFeatures . LinkLabelHidden ,
LinkText = url ,
LinkData = url
} )
2013-09-26 15:12:26 +02:00
dlog . ShowDialog ( this ) ;
2013-06-24 13:41:48 +02:00
} ) ;
return ;
}
2021-01-26 18:45:12 +01:00
2023-07-11 12:23:36 +02:00
// Allow connection only to Naples or greater versions
2023-05-10 16:22:46 +02:00
2023-07-11 12:23:36 +02:00
if ( ! Helpers . NaplesOrGreater ( coordinator ) )
2021-01-26 18:45:12 +01:00
{
connection . EndConnect ( ) ;
Program . Invoke ( Program . MainWindow , delegate
{
2023-05-10 16:22:46 +02:00
var msg = string . Format ( Messages . GUI_NOT_COMPATIBLE , BrandManager . BrandConsole , BrandManager . ProductVersion712 ,
BrandManager . ProductVersion80 , Helpers . GetName ( coordinator ) ) ;
2021-01-26 18:45:12 +01:00
var url = InvisibleMessages . OUT_OF_DATE_WEBSITE ;
2021-08-31 12:31:16 +02:00
var title = string . Format ( Messages . CONNECTION_REFUSED_TITLE , Helpers . GetName ( coordinator ) . Ellipsise ( 80 ) ) ;
2019-02-01 14:25:44 +01:00
var error = $"{msg}\n{url}" ;
2013-09-26 15:12:26 +02:00
2022-04-11 22:44:27 +02:00
new DummyAction ( title , "" , error ) . Run ( ) ;
2018-10-03 10:12:11 +02:00
2020-07-30 12:29:01 +02:00
using ( var dlog = new ErrorDialog ( msg )
{
WindowTitle = title ,
ShowLinkLabel = ! HiddenFeatures . LinkLabelHidden ,
LinkText = url ,
LinkData = url
} )
2013-09-26 15:12:26 +02:00
dlog . ShowDialog ( this ) ;
2013-06-24 13:41:48 +02:00
} ) ;
return ;
}
2018-10-03 10:12:11 +02:00
2023-05-10 16:22:46 +02:00
if ( serverMax > currentVersion )
2013-06-24 13:41:48 +02:00
Alert . AddAlert ( new GuiOldAlert ( ) ) ;
LoadTasksAsMeddlingActions ( connection ) ;
}
//
// Every time we connect, make sure any host with other_config[maintenance_mode] == true
// is disabled.
//
CheckMaintenanceMode ( connection ) ;
if ( HelpersGUI . iSCSIisUsed ( ) )
HelpersGUI . PerformIQNCheck ( ) ;
if ( licenseTimer ! = null )
2013-10-15 18:15:21 +02:00
licenseTimer . CheckActiveServerLicense ( connection , false ) ;
2013-11-21 16:56:24 +01:00
2023-02-21 01:04:14 +01:00
if ( BrandManager . BrandConsole = = "[XenCenter]" | | BrandManager . BrandConsole = = "XenCenter" )
2021-01-12 16:26:22 +01:00
{
2023-02-14 23:13:01 +01:00
Pool pool = Helpers . GetPoolOfOne ( connection ) ;
if ( pool ! = null & & pool . GetHealthCheckStatus ( ) = = Pool . HealthCheckStatus . Enabled )
{
Program . BeginInvoke ( Program . MainWindow , ( ) = >
{
2023-02-21 01:04:14 +01:00
using ( var dlg = new InformationDialog (
string . Format ( Messages . PROBLEM_HEALTH_CHECK_ON_CONNECTION , pool . Name ( ) , BrandManager . BrandConsole ) ,
ThreeButtonDialog . ButtonOK ) )
2023-02-14 23:13:01 +01:00
{
2023-02-21 01:04:14 +01:00
if ( dlg . ShowDialog ( ) = = DialogResult . OK )
2023-02-14 23:13:01 +01:00
new DisableHealthCheckAction ( pool ) . RunAsync ( ) ;
}
} ) ;
}
2021-01-12 16:26:22 +01:00
}
2020-07-26 15:54:52 +02:00
2023-07-22 16:52:32 +02:00
if ( ! Program . RunInAutomatedTestMode & & ! Helpers . CommonCriteriaCertificationRelease & &
! Helpers . CloudOrGreater ( coordinator ) )
{
Program . BeginInvoke ( Program . MainWindow , ( ) = >
{
if ( Properties . Settings . Default . SeenAllowCfuUpdatesDialog )
return ;
Properties . Settings . Default . SeenAllowCfuUpdatesDialog = true ;
Settings . TrySaveSettings ( ) ;
bool launch ;
using ( var dlg = new NoIconDialog ( string . Format ( Messages . ALLOWED_UPDATES_DIALOG_MESSAGE_CFU , BrandManager . BrandConsole , BrandManager . ProductVersion821 ) ,
ThreeButtonDialog . ButtonYes , ThreeButtonDialog . ButtonNo )
{
HelpButton = true ,
HelpNameSetter = "AllowUpdatesDialog" ,
ShowCheckbox = false
} )
{
launch = dlg . ShowDialog ( this ) = = DialogResult . Yes ;
}
if ( launch )
{
using ( var dialog = new ConfigUpdatesDialog ( ) )
{
dialog . SelectLcmTab ( ) ;
dialog . ShowDialog ( this ) ;
}
}
} ) ;
}
2023-07-22 17:16:46 +02:00
if ( Helpers . CloudOrGreater ( connection ) )
{
2023-07-22 17:42:50 +02:00
if ( YumRepoNotConfiguredAlert . TryCreate ( connection , out var alert ) | | OutOfSyncWithCdnAlert . TryCreate ( connection , out alert ) )
Alert . AddAlert ( alert ) ;
2023-07-22 17:16:46 +02:00
Updates . CheckForCdnUpdates ( coordinator . Connection ) ;
}
else
{
Updates . RefreshUpdateAlerts ( Updates . UpdateType . ServerPatches | Updates . UpdateType . ServerVersion ) ;
Updates . CheckHotfixEligibility ( connection ) ;
}
2021-04-13 14:36:30 +02:00
2023-07-22 17:16:46 +02:00
RequestRefreshTreeView ( ) ;
2021-04-13 14:36:30 +02:00
CheckTlsVerification ( connection ) ;
}
private void CheckTlsVerification ( IXenConnection connection )
{
//Use BeginInvoke so the UI is not blocked in a connection-in-progress state
Program . BeginInvoke ( Program . MainWindow , ( ) = >
{
var pool = Helpers . GetPoolOfOne ( connection ) ;
var cmd = new EnableTlsVerificationCommand ( Program . MainWindow , pool , false ) ;
2021-09-01 15:43:23 +02:00
if ( cmd . CanRun ( ) )
2021-04-13 14:36:30 +02:00
{
var msg = string . Format ( "{0}\n\n{1}" ,
string . Format ( Messages . MESSAGEBOX_ENABLE_TLS_VERIFICATION_BLURB , Helpers . GetName ( connection ) ) ,
Messages . MESSAGEBOX_ENABLE_TLS_VERIFICATION_WARNING ) ;
using ( var dlg = new WarningDialog ( msg ,
new ThreeButtonDialog . TBDButton ( Messages . MESSAGEBOX_ENABLE_TLS_VERIFICATION_BUTTON ,
DialogResult . Yes , ThreeButtonDialog . ButtonType . ACCEPT , true ) ,
ThreeButtonDialog . ButtonNo ) )
if ( dlg . ShowDialog ( this ) = = DialogResult . Yes )
2021-09-01 15:43:23 +02:00
cmd . Run ( ) ;
2021-04-13 14:36:30 +02:00
}
} ) ;
2013-06-24 13:41:48 +02:00
}
2018-10-03 10:12:11 +02:00
private static bool SameProductBrand ( Host host )
2015-11-18 17:52:43 +01:00
{
2017-09-03 04:33:29 +02:00
var brand = host . ProductBrand ( ) ;
2021-02-26 02:26:53 +01:00
return brand = = BrandManager . ProductBrand | | brand = = BrandManager . LegacyProduct | |
2023-01-13 14:25:21 +01:00
BrandManager . ProductBrand = = "[XenServerProduct]" ;
2015-11-18 17:52:43 +01:00
}
2013-06-24 13:41:48 +02:00
/// <summary>
/// Ensures all hosts on the connection are disabled if they are in maintenance mode.
/// </summary>
/// <param name="connection"></param>
private void CheckMaintenanceMode ( IXenConnection connection )
{
foreach ( Host host in connection . Cache . Hosts )
{
CheckMaintenanceMode ( host ) ;
}
}
/// <summary>
/// Ensures the host is disabled if it is in maintenance mode by spawning a new HostAction if necessary.
/// </summary>
/// <param name="host"></param>
private void CheckMaintenanceMode ( Host host )
{
2017-09-03 04:33:29 +02:00
if ( host . IsLive ( ) & & host . MaintenanceMode ( ) & & host . enabled )
2013-06-24 13:41:48 +02:00
{
2020-02-26 14:27:52 +01:00
Program . Invoke ( this , ( ) = > XenDialogBase . CloseAll ( host ) ) ;
2013-06-24 13:41:48 +02:00
var action = new DisableHostAction ( host ) ;
action . Completed + = action_Completed ;
action . RunAsync ( ) ;
}
}
2023-07-22 17:16:46 +02:00
private void MessageCollectionChanged ( object sender , CollectionChangeEventArgs e )
2013-06-24 13:41:48 +02:00
{
Program . AssertOnEventThread ( ) ;
XenAPI . Message m = ( XenAPI . Message ) e . Element ;
if ( e . Action = = CollectionChangeAction . Add )
{
2017-09-03 04:33:29 +02:00
if ( ! m . ShowOnGraphs ( ) & & ! m . IsSquelched ( ) )
2013-06-24 13:41:48 +02:00
Alert . AddAlert ( MessageAlert . ParseMessage ( m ) ) ;
}
else if ( e . Action = = CollectionChangeAction . Remove )
{
2017-09-03 04:33:29 +02:00
if ( ! m . ShowOnGraphs ( ) )
2013-06-24 13:41:48 +02:00
MessageAlert . RemoveAlert ( m ) ;
}
}
2023-07-22 17:16:46 +02:00
private void CollectionChanged < T > ( object sender , CollectionChangeEventArgs e ) where T : XenObject < T >
2013-06-24 13:41:48 +02:00
{
Program . AssertOnEventThread ( ) ;
T o = ( T ) e . Element ;
if ( e . Action = = CollectionChangeAction . Add )
{
if ( o is Pool )
( ( Pool ) e . Element ) . PropertyChanged + = Pool_PropertyChanged ;
else if ( o is Host )
( ( Host ) e . Element ) . PropertyChanged + = Host_PropertyChanged ;
else if ( o is VM )
( ( VM ) e . Element ) . PropertyChanged + = VM_PropertyChanged ;
else
o . PropertyChanged + = o_PropertyChanged ;
}
else if ( e . Action = = CollectionChangeAction . Remove )
{
if ( o is Pool )
( ( Pool ) e . Element ) . PropertyChanged - = Pool_PropertyChanged ;
else if ( o is Host )
( ( Host ) e . Element ) . PropertyChanged - = Host_PropertyChanged ;
else if ( o is VM )
( ( VM ) e . Element ) . PropertyChanged - = VM_PropertyChanged ;
else
o . PropertyChanged - = o_PropertyChanged ;
if ( o is VM )
{
VM vm = ( VM ) e . Element ;
2022-01-31 12:37:34 +01:00
ConsolePanel . CloseVncForSource ( vm ) ;
2020-02-26 14:27:52 +01:00
XenDialogBase . CloseAll ( vm ) ;
2013-06-24 13:41:48 +02:00
}
selectedTabs . Remove ( o ) ;
2021-11-29 16:18:38 +01:00
PluginManager . DisposeURLs ( o ) ;
2013-06-24 13:41:48 +02:00
}
}
private void Pool_PropertyChanged ( object obj , PropertyChangedEventArgs e )
{
Pool pool = ( Pool ) obj ;
switch ( e . PropertyName )
{
case "other_config" :
// other_config may contain HideFromXenCenter
UpdateToolbars ( ) ;
2013-12-05 13:46:39 +01:00
// other_config contains which patches to ignore
2020-07-26 15:54:52 +02:00
Updates . RefreshUpdateAlerts ( Updates . UpdateType . ServerPatches | Updates . UpdateType . ServerVersion ) ;
2013-06-24 13:41:48 +02:00
break ;
case "name_label" :
pool . Connection . FriendlyName = Helpers . GetName ( pool ) ;
break ;
}
}
private void Host_PropertyChanged ( object obj , PropertyChangedEventArgs e )
{
Host host = ( Host ) obj ;
switch ( e . PropertyName )
{
case "allowed_operations" :
case "enabled" :
// We want to ensure that a host is disabled if it is in maintenance mode, by starting a new DisableHostAction if necessary (CheckMaintenanceMode)
2017-09-03 04:33:29 +02:00
if ( host . enabled & & host . MaintenanceMode ( ) )
2013-06-24 13:41:48 +02:00
{
// This is an invalid state: the host is enabled but still "in maintenance mode";
// But maybe MaintenanceMode hasn't been updated yet, because host.enabled being processed before host.other_config (CA-75625);
// We'll check it again after the cache update operation is complete, in Connection_XenObjectsUpdated
hostsInInvalidState . Add ( host ) ;
}
UpdateToolbars ( ) ;
break ;
case "edition" :
case "license_server" :
case "license_params" :
2017-09-28 17:10:41 +02:00
UpdateHeader ( ) ;
UpdateToolbars ( ) ;
2019-08-21 12:43:11 +02:00
Updates . CheckHotfixEligibility ( host . Connection ) ;
2017-09-28 17:10:41 +02:00
break ;
2013-06-24 13:41:48 +02:00
case "other_config" :
// other_config may contain HideFromXenCenter
UpdateToolbars ( ) ;
break ;
case "name_label" :
//check whether it's a standalone host
if ( Helpers . GetPool ( host . Connection ) = = null )
host . Connection . FriendlyName = Helpers . GetName ( host ) ;
break ;
2020-01-03 11:04:00 +01:00
case "patches" :
if ( ! Helpers . ElyOrGreater ( host ) )
2020-07-26 15:54:52 +02:00
Updates . RefreshUpdateAlerts ( Updates . UpdateType . ServerPatches | Updates . UpdateType . ServerVersion ) ;
2020-01-03 11:04:00 +01:00
break ;
case "updates" :
if ( Helpers . ElyOrGreater ( host ) )
2020-07-26 15:54:52 +02:00
Updates . RefreshUpdateAlerts ( Updates . UpdateType . ServerPatches | Updates . UpdateType . ServerVersion ) ;
2020-01-03 11:04:00 +01:00
break ;
2013-06-24 13:41:48 +02:00
}
}
private void VM_PropertyChanged ( object obj , PropertyChangedEventArgs e )
{
2023-07-07 19:10:04 +02:00
if ( ! ( obj is VM vm ) )
return ;
2013-06-24 13:41:48 +02:00
switch ( e . PropertyName )
{
case "allowed_operations" :
case "is_a_template" :
case "resident_on" :
UpdateToolbars ( ) ;
break ;
case "power_state" :
UpdateToolbars ( ) ;
2023-07-07 19:10:04 +02:00
vm . SetBodgeStartupTime ( DateTime . UtcNow ) ;
break ;
case "other_config" :
UpdateToolbars ( ) ; //other_config may contain HideFromXenCenter
DateTime newTime = vm . LastShutdownTime ( ) ;
if ( newTime ! = DateTime . MinValue & & newTime . Ticks > vm . GetBodgeStartupTime ( ) . Ticks )
vm . SetBodgeStartupTime ( newTime ) ;
2013-06-24 13:41:48 +02:00
break ;
}
}
2023-07-22 17:16:46 +02:00
private void o_PropertyChanged ( object sender , PropertyChangedEventArgs e )
2013-06-24 13:41:48 +02:00
{
switch ( e . PropertyName )
{
case "allowed_operations" :
case "power_state" :
case "is_a_template" :
case "enabled" :
2023-07-07 19:10:04 +02:00
case "other_config" :
UpdateToolbars ( ) ; //other_config may contain HideFromXenCenter
break ;
2013-06-24 13:41:48 +02:00
}
}
2018-10-03 12:05:41 +02:00
private void Connection_ConnectionResult ( object sender , Network . ConnectionResultEventArgs e )
2013-06-24 13:41:48 +02:00
{
RequestRefreshTreeView ( ) ;
}
2019-10-27 16:52:15 +01:00
private void Connection_ConnectionClosed ( IXenConnection conn )
2013-06-24 13:41:48 +02:00
{
RequestRefreshTreeView ( ) ;
gc ( ) ;
}
// called whenever our connection with the Xen server fails (i.e., after we've successfully logged in)
2019-10-27 16:52:15 +01:00
private void Connection_ConnectionLost ( IXenConnection conn )
2013-06-24 13:41:48 +02:00
{
if ( Program . Exiting )
return ;
2019-10-27 16:52:15 +01:00
Program . Invoke ( this , ( ) = > CloseActiveWizards ( conn ) ) ;
2013-06-24 13:41:48 +02:00
RequestRefreshTreeView ( ) ;
gc ( ) ;
}
private static void gc ( )
{
GC . Collect ( ) ;
}
2023-07-22 17:16:46 +02:00
private void connection_ConnectionReconnecting ( IXenConnection conn )
2013-06-24 13:41:48 +02:00
{
if ( Program . Exiting )
return ;
RequestRefreshTreeView ( ) ;
gc ( ) ;
}
private List < Host > hostsInInvalidState = new List < Host > ( ) ;
// called whenever Xen objects on the server change state
2023-07-22 17:16:46 +02:00
private void Connection_XenObjectsUpdated ( object sender , EventArgs e )
2013-06-24 13:41:48 +02:00
{
if ( Program . Exiting )
return ;
IXenConnection connection = ( IXenConnection ) sender ;
if ( hostsInInvalidState . Count > 0 )
{
foreach ( var host in hostsInInvalidState . Where ( host = > host . Connection = = connection ) )
CheckMaintenanceMode ( host ) ;
hostsInInvalidState . RemoveAll ( host = > host . Connection = = connection ) ;
}
RequestRefreshTreeView ( ) ;
}
/// <summary>
/// Requests a refresh of the main tree view. The refresh will be managed such that we are not overloaded using an UpdateManager.
/// </summary>
public void RequestRefreshTreeView ( )
{
2013-11-20 14:09:17 +01:00
Program . Invoke ( this , navigationPane . RequestRefreshTreeView ) ;
2013-06-24 13:41:48 +02:00
}
2023-07-22 17:16:46 +02:00
private void exitToolStripMenuItem_Click ( object sender , EventArgs e )
2013-06-24 13:41:48 +02:00
{
this . Close ( ) ;
}
2018-10-01 18:01:59 +02:00
private bool _menuShortcutsEnabled = true ;
public bool MenuShortcutsEnabled
2013-06-24 13:41:48 +02:00
{
2018-10-01 18:01:59 +02:00
get { return _menuShortcutsEnabled ; }
2013-06-24 13:41:48 +02:00
set
{
2018-10-01 18:01:59 +02:00
if ( value ! = _menuShortcutsEnabled )
2013-06-24 13:41:48 +02:00
{
//if the VNC Console is active (the user is typing into it etc) all of the shortcuts for XenCenter are disabled
//IMPORTANT! add any shortcuts you want to pass to the VNC console into this if, else statement
2018-10-01 18:01:59 +02:00
_menuShortcutsEnabled = value ;
2013-06-24 13:41:48 +02:00
// update the selection so menu items can enable/disable keyboard shortcuts as appropriate.
2013-08-22 18:25:12 +02:00
SelectionManager . RefreshSelection ( ) ;
2013-06-24 13:41:48 +02:00
}
}
}
/// <summary>
/// Must be called on the event thread.
/// </summary>
public void UpdateToolbars ( )
{
Program . AssertOnEventThread ( ) ;
2018-08-06 17:48:39 +02:00
try
{
ToolStrip . SuspendLayout ( ) ;
UpdateToolbarsCore ( ) ;
MainMenuBar_MenuActivate ( null , null ) ;
}
finally
{
ToolStrip . ResumeLayout ( ) ;
}
2018-10-01 17:08:15 +02:00
// Save and restore focus on treeView, since selecting tabs in ChangeToNewTabs() has the
// unavoidable side-effect of giving them focus - this is irritating if trying to navigate
// the tree using the keyboard.
navigationPane . SaveAndRestoreTreeViewFocus ( ChangeToNewTabs ) ;
2013-06-24 13:41:48 +02:00
}
private static int TOOLBAR_HEIGHT = 31 ;
2018-09-28 18:58:49 +02:00
2013-06-24 13:41:48 +02:00
/// <summary>
2018-10-01 17:08:15 +02:00
/// Updates the toolbar buttons.
2013-06-24 13:41:48 +02:00
/// </summary>
2018-08-06 19:42:24 +02:00
private void UpdateToolbarsCore ( )
2013-06-24 13:41:48 +02:00
{
// refresh the selection-manager
2013-08-22 18:25:12 +02:00
SelectionManager . RefreshSelection ( ) ;
2013-06-24 13:41:48 +02:00
2022-05-04 15:16:29 +02:00
ToolStrip . Height = Properties . Settings . Default . ToolbarsEnabled ? TOOLBAR_HEIGHT : 0 ;
ToolStrip . Enabled = Properties . Settings . Default . ToolbarsEnabled ;
ShowToolbarMenuItem . Checked = toolbarToolStripMenuItem . Checked = Properties . Settings . Default . ToolbarsEnabled ;
2013-06-24 13:41:48 +02:00
2015-02-11 14:46:23 +01:00
bool containerButtonsAvailable = startContainerToolStripButton . Enabled | | stopContainerToolStripButton . Enabled | |
resumeContainerToolStripButton . Enabled | | pauseContainerToolStripButton . Enabled | | restartContainerToolStripButton . Enabled ;
startContainerToolStripButton . Available = containerButtonsAvailable & & startContainerToolStripButton . Enabled ;
stopContainerToolStripButton . Available = containerButtonsAvailable & & ( stopContainerToolStripButton . Enabled | | ! startContainerToolStripButton . Available ) ;
resumeContainerToolStripButton . Available = containerButtonsAvailable & & resumeContainerToolStripButton . Enabled ;
pauseContainerToolStripButton . Available = containerButtonsAvailable & & ( pauseContainerToolStripButton . Enabled | | ! resumeContainerToolStripButton . Available ) ;
restartContainerToolStripButton . Available = containerButtonsAvailable ;
2013-06-24 13:41:48 +02:00
powerOnHostToolStripButton . Available = powerOnHostToolStripButton . Enabled ;
startVMToolStripButton . Available = startVMToolStripButton . Enabled ;
2015-02-11 14:46:23 +01:00
shutDownToolStripButton . Available = shutDownToolStripButton . Enabled | | ( ! startVMToolStripButton . Available & & ! powerOnHostToolStripButton . Available & & ! containerButtonsAvailable ) ;
RebootToolbarButton . Available = RebootToolbarButton . Enabled | | ! containerButtonsAvailable ;
2013-06-24 13:41:48 +02:00
resumeToolStripButton . Available = resumeToolStripButton . Enabled ;
2015-02-11 14:46:23 +01:00
SuspendToolbarButton . Available = SuspendToolbarButton . Enabled | | ( ! resumeToolStripButton . Available & & ! containerButtonsAvailable ) ;
2013-06-24 13:41:48 +02:00
ForceRebootToolbarButton . Available = ( ( ForceVMRebootCommand ) ForceRebootToolbarButton . Command ) . ShowOnMainToolBar ;
ForceShutdownToolbarButton . Available = ( ( ForceVMShutDownCommand ) ForceShutdownToolbarButton . Command ) . ShowOnMainToolBar ;
2018-10-01 17:08:15 +02:00
}
2013-06-24 13:41:48 +02:00
2018-10-01 17:08:15 +02:00
private List < TabPage > GetNewTabPages ( )
{
2013-08-22 18:25:12 +02:00
IXenConnection selectionConnection = SelectionManager . Selection . GetConnectionOfFirstItem ( ) ;
2013-06-24 13:41:48 +02:00
Pool selectionPool = selectionConnection = = null ? null : Helpers . GetPool ( selectionConnection ) ;
// 'Home' tab is only visible if the 'Overview' tree node is selected, or if the tree is
// empty (i.e. at startup).
2013-08-22 18:25:12 +02:00
bool show_home = SelectionManager . Selection . Count = = 1 & & SelectionManager . Selection [ 0 ] . Value = = null ;
2013-06-24 13:41:48 +02:00
// The upsell pages use the first selected XenObject: but they're only shown if there is only one selected object (see calls to ShowTab() below).
2017-10-11 15:58:10 +02:00
bool ha_upsell = Helpers . FeatureForbidden ( SelectionManager . Selection . FirstAsXenObject , Host . RestrictHA ) & & ( selectionPool ! = null & & ! selectionPool . ha_enabled ) ;
2013-08-22 18:25:12 +02:00
bool wlb_upsell = Helpers . FeatureForbidden ( SelectionManager . Selection . FirstAsXenObject , Host . RestrictWLB ) ;
2016-05-20 14:01:51 +02:00
bool ad_upsell = Helpers . FeatureForbidden ( SelectionManager . Selection . FirstAsXenObject , Host . RestrictAD ) ;
2013-06-24 13:41:48 +02:00
bool is_connected = selectionConnection ! = null & & selectionConnection . IsConnected ;
bool multi = SelectionManager . Selection . Count > 1 ;
2016-10-14 13:21:59 +02:00
bool isPoolSelected = SelectionManager . Selection . FirstIs < Pool > ( ) ;
bool isVMSelected = SelectionManager . Selection . FirstIs < VM > ( ) ;
bool isHostSelected = SelectionManager . Selection . FirstIs < Host > ( ) ;
2021-02-24 16:44:38 +01:00
SR selectedSr = SelectionManager . Selection . First as SR ;
bool isSRSelected = selectedSr ! = null ;
2016-10-14 14:51:51 +02:00
bool isVdiSelected = SelectionManager . Selection . FirstIs < VDI > ( ) ;
2013-08-22 18:25:12 +02:00
bool isRealVMSelected = SelectionManager . Selection . FirstIsRealVM ;
bool isTemplateSelected = SelectionManager . Selection . FirstIsTemplate ;
bool isHostLive = SelectionManager . Selection . FirstIsLiveHost ;
2014-12-05 15:16:58 +01:00
bool isDockerContainerSelected = SelectionManager . Selection . First is DockerContainer ;
2013-06-24 13:41:48 +02:00
2017-09-03 04:33:29 +02:00
bool selectedTemplateHasProvisionXML = SelectionManager . Selection . FirstIsTemplate & & ( ( VM ) SelectionManager . Selection [ 0 ] . XenObject ) . HasProvisionXML ( ) ;
2013-06-24 13:41:48 +02:00
2018-10-01 17:08:15 +02:00
var newTabs = new List < TabPage > ( ) ;
if ( ! SearchMode & & show_home )
newTabs . Add ( TabPageHome ) ;
if ( ! multi & & ! SearchMode & & ( isVMSelected | | ( isHostSelected & & ( isHostLive | | ! is_connected ) ) | |
isPoolSelected | | isSRSelected | | isVdiSelected | | isDockerContainerSelected ) )
newTabs . Add ( TabPageGeneral ) ;
if ( ! multi & & ! SearchMode & & ( isVMSelected | | ( isHostSelected & & isHostLive ) | | isPoolSelected ) )
newTabs . Add ( TabPageBallooning ) ;
if ( ! multi & & ! SearchMode & & ( isRealVMSelected | | ( isTemplateSelected & & ! selectedTemplateHasProvisionXML ) ) )
newTabs . Add ( TabPageStorage ) ;
if ( ! multi & & ! SearchMode & & isSRSelected )
newTabs . Add ( TabPageSR ) ;
if ( ! multi & & ! SearchMode & & ( ( isHostSelected & & isHostLive ) | | isPoolSelected ) )
newTabs . Add ( TabPagePhysicalStorage ) ;
if ( ! multi & & ! SearchMode & & ( isVMSelected | | ( isHostSelected & & isHostLive ) | | isPoolSelected ) )
newTabs . Add ( TabPageNetwork ) ;
if ( ! multi & & ! SearchMode & & isHostSelected & & isHostLive )
newTabs . Add ( TabPageNICs ) ;
2021-08-06 01:30:16 +02:00
if ( ! multi & & ! SearchMode & & isDockerContainerSelected & &
! Helpers . StockholmOrGreater ( SelectionManager . Selection . GetConnectionOfFirstItem ( ) ) )
{
if ( ! ( SelectionManager . Selection . First as DockerContainer ) . Parent . IsWindows ( ) )
newTabs . Add ( TabPageDockerProcess ) ;
2018-10-01 17:08:15 +02:00
newTabs . Add ( TabPageDockerDetails ) ;
2021-08-06 01:30:16 +02:00
}
2013-06-24 13:41:48 +02:00
2013-11-14 12:23:35 +01:00
bool isPoolOrLiveStandaloneHost = isPoolSelected | | ( isHostSelected & & isHostLive & & selectionPool = = null ) ;
2018-10-01 17:08:15 +02:00
2019-01-31 00:00:56 +01:00
if ( ! multi & & ! SearchMode & & ( ( isHostSelected & & isHostLive ) | | isPoolOrLiveStandaloneHost ) & &
! Helpers . FeatureForbidden ( selectionConnection , Host . RestrictGpu ) )
2018-10-01 17:08:15 +02:00
newTabs . Add ( TabPageGPU ) ;
2019-01-31 00:00:56 +01:00
if ( ! multi & & ! SearchMode & & isHostSelected & & isHostLive & & ( ( Host ) SelectionManager . Selection . First ) . PUSBs . Count > 0 & & ! Helpers . FeatureForbidden ( selectionConnection , Host . RestrictUsbPassthrough ) )
2018-10-01 17:08:15 +02:00
newTabs . Add ( TabPageUSB ) ;
2013-11-14 12:23:35 +01:00
2018-08-06 12:16:05 +02:00
var consoleFeatures = new List < TabPageFeature > ( ) ;
var otherFeatures = new List < TabPageFeature > ( ) ;
2013-06-24 13:41:48 +02:00
2018-08-06 12:16:05 +02:00
if ( SelectionManager . Selection . Count = = 1 & & ! SearchMode )
2018-08-06 19:42:16 +02:00
GetFeatureTabPages ( SelectionManager . Selection . FirstAsXenObject , out consoleFeatures , out otherFeatures ) ;
2018-08-06 12:16:05 +02:00
foreach ( var f in consoleFeatures )
2018-10-01 17:08:15 +02:00
newTabs . Add ( f . TabPage ) ;
2013-06-24 13:41:48 +02:00
2018-10-01 17:08:15 +02:00
if ( consoleFeatures . Count = = 0 & & ! multi & & ! SearchMode & & ( isRealVMSelected | | ( isHostSelected & & isHostLive ) ) )
newTabs . Add ( TabPageConsole ) ;
2021-02-24 16:44:38 +01:00
if ( consoleFeatures . Count = = 0 & & ! multi & & ! SearchMode & & isSRSelected & & selectedSr . HasDriverDomain ( out _ ) )
2018-10-01 17:08:15 +02:00
newTabs . Add ( TabPageCvmConsole ) ;
2013-06-24 13:41:48 +02:00
2018-10-01 17:08:15 +02:00
if ( ! multi & & ! SearchMode & & ( isRealVMSelected | | ( isHostSelected & & isHostLive ) ) )
newTabs . Add ( TabPagePeformance ) ;
if ( ! multi & & ! SearchMode & & isPoolSelected )
newTabs . Add ( ha_upsell ? TabPageHAUpsell : TabPageHA ) ;
if ( ! multi & & ! SearchMode & & isRealVMSelected )
newTabs . Add ( TabPageSnapshots ) ;
2014-04-28 07:44:37 +02:00
2014-05-07 07:15:29 +02:00
//Any Clearwater XenServer, or WLB is not licensed on XenServer, the WLB tab and any WLB menu items disappear completely.
2019-01-31 00:00:56 +01:00
if ( ! wlb_upsell & & ! multi & & ! SearchMode & & isPoolSelected )
2018-10-01 17:08:15 +02:00
newTabs . Add ( TabPageWLB ) ;
2014-04-28 07:44:37 +02:00
2018-10-01 17:08:15 +02:00
if ( ! multi & & ! SearchMode & & ( isPoolSelected | | isHostSelected & & isHostLive ) )
newTabs . Add ( ad_upsell ? TabPageADUpsell : TabPageAD ) ;
2013-06-24 13:41:48 +02:00
2018-10-01 17:08:15 +02:00
if ( ! multi & & ! SearchMode & & isPoolOrLiveStandaloneHost & & ! Helpers . FeatureForbidden ( SelectionManager . Selection . FirstAsXenObject , Host . RestrictPvsCache )
& & Helpers . PvsCacheCapability ( selectionConnection ) )
newTabs . Add ( TabPagePvs ) ;
2013-06-24 13:41:48 +02:00
2018-08-06 12:16:05 +02:00
foreach ( var f in otherFeatures )
2018-10-01 17:08:15 +02:00
newTabs . Add ( f . TabPage ) ;
2013-10-01 16:35:57 +02:00
2018-10-01 17:08:15 +02:00
newTabs . Add ( TabPageSearch ) ;
2013-06-24 13:41:48 +02:00
// N.B. Change NewTabs definition if you add more tabs here.
2018-10-01 17:08:15 +02:00
return newTabs ;
2013-06-24 13:41:48 +02:00
}
2018-08-06 19:42:16 +02:00
private void GetFeatureTabPages ( IXenObject xenObject , out List < TabPageFeature > consoleFeatures , out List < TabPageFeature > otherFeatures )
{
consoleFeatures = new List < TabPageFeature > ( ) ;
otherFeatures = new List < TabPageFeature > ( ) ;
2021-11-29 16:18:38 +01:00
var plugins = PluginManager . Plugins ;
2018-08-06 19:42:16 +02:00
foreach ( var p in plugins )
{
var features = p . Features ;
foreach ( var feature in features )
{
var f = feature as TabPageFeature ;
if ( f = = null )
continue ;
f . SelectedXenObject = xenObject ;
if ( ! f . ShowTab )
continue ;
if ( f . IsConsoleReplacement )
{
f . SetUrl ( ) ;
if ( ! f . IsError )
consoleFeatures . Add ( f ) ;
}
else
{
var page = GetLastSelectedPage ( xenObject ) ;
if ( page ! = null & & page . Tag = = f )
f . SetUrl ( ) ;
otherFeatures . Add ( f ) ;
}
}
}
}
2013-06-24 13:41:48 +02:00
private void ChangeToNewTabs ( )
{
2018-10-01 17:08:15 +02:00
var newTabs = GetNewTabPages ( ) ;
var pageToSelect = GetLastSelectedPage ( SelectionManager . Selection . First ) ;
if ( pageToSelect ! = null & & ! newTabs . Contains ( pageToSelect ) )
pageToSelect = null ;
2013-06-24 13:41:48 +02:00
TheTabControl . SuspendLayout ( ) ;
IgnoreTabChanges = true ;
2018-10-01 17:08:15 +02:00
2013-06-24 13:41:48 +02:00
try
{
2018-10-01 17:08:15 +02:00
foreach ( TabPage page in TheTabControl . TabPages )
2013-06-24 13:41:48 +02:00
{
2018-10-01 17:08:15 +02:00
if ( ! newTabs . Contains ( page ) )
TheTabControl . TabPages . Remove ( page ) ;
2013-06-24 13:41:48 +02:00
}
2018-10-01 17:08:15 +02:00
int m = 0 ; // Index into TheTabControl.TabPages
foreach ( var newTab in newTabs )
2013-06-24 13:41:48 +02:00
{
2018-10-01 17:08:15 +02:00
var index = TheTabControl . TabPages . IndexOf ( newTab ) ;
if ( index < 0 )
TheTabControl . TabPages . Insert ( m , newTab ) ;
m + + ;
if ( newTab = = pageToSelect )
TheTabControl . SelectedTab = newTab ;
2013-06-24 13:41:48 +02:00
}
2018-10-01 17:08:15 +02:00
if ( pageToSelect = = null )
TheTabControl . SelectedTab = TheTabControl . TabPages [ 0 ] ;
2013-06-24 13:41:48 +02:00
}
finally
{
IgnoreTabChanges = false ;
TheTabControl . ResumeLayout ( ) ;
2013-08-22 18:25:12 +02:00
SetLastSelectedPage ( SelectionManager . Selection . First , TheTabControl . SelectedTab ) ;
2013-06-24 13:41:48 +02:00
}
}
2013-09-02 15:45:42 +02:00
private void SetLastSelectedPage ( object o , TabPage p )
2013-06-24 13:41:48 +02:00
{
2013-08-25 13:42:38 +02:00
if ( SearchMode )
2013-06-24 13:41:48 +02:00
return ;
2019-07-15 02:26:11 +02:00
if ( o = = null | | ! Properties . Settings . Default . RememberLastSelectedTab )
2013-06-24 13:41:48 +02:00
{
selectedOverviewTab = p ;
}
else
{
selectedTabs [ o ] = p ;
}
}
private TabPage GetLastSelectedPage ( object o )
{
2019-07-15 02:26:11 +02:00
return o = = null | | ! Properties . Settings . Default . RememberLastSelectedTab
2018-08-06 19:42:16 +02:00
? selectedOverviewTab
: selectedTabs . ContainsKey ( o ) ? selectedTabs [ o ] : null ;
2013-06-24 13:41:48 +02:00
}
2013-12-31 11:34:11 +01:00
private void pluginManager_PluginsChanged ( )
2013-06-24 13:41:48 +02:00
{
2018-10-01 17:08:15 +02:00
UpdateToolbars ( ) ;
2018-08-06 19:42:24 +02:00
2013-12-31 11:34:11 +01:00
foreach ( ToolStripMenuItem menu in MainMenuBar . Items )
2013-06-24 13:41:48 +02:00
{
2013-12-31 11:34:11 +01:00
//clear existing plugin items
for ( int i = menu . DropDownItems . Count - 1 ; i > = 0 ; i - - )
2013-06-24 13:41:48 +02:00
{
2013-12-31 11:34:11 +01:00
CommandToolStripMenuItem commandMenuItem = menu . DropDownItems [ i ] as CommandToolStripMenuItem ;
2013-06-24 13:41:48 +02:00
2013-12-31 11:34:11 +01:00
if ( commandMenuItem ! = null & & ( commandMenuItem . Command is MenuItemFeatureCommand
| | commandMenuItem . Command is ParentMenuItemFeatureCommand ) )
2013-06-24 13:41:48 +02:00
{
menu . DropDownItems . RemoveAt ( i ) ;
2013-12-31 11:34:11 +01:00
if ( menu . DropDownItems . Count > 0 & & menu . DropDownItems [ i ] is ToolStripSeparator )
menu . DropDownItems . RemoveAt ( i ) ;
2013-06-24 13:41:48 +02:00
}
}
2013-12-31 11:34:11 +01:00
// get insert index using the placeholder
2022-02-01 14:42:11 +01:00
if ( ! pluginMenuItemStartIndexes . ContainsKey ( menu ) )
continue ;
2013-12-31 11:34:11 +01:00
int insertIndex = pluginMenuItemStartIndexes [ menu ] ;
2013-06-24 13:41:48 +02:00
2013-12-31 11:34:11 +01:00
bool itemAdded = false ;
2013-06-24 13:41:48 +02:00
2013-12-31 11:34:11 +01:00
// add plugin items for this menu at insertIndex
2021-11-29 16:18:38 +01:00
foreach ( PluginDescriptor plugin in PluginManager . Plugins )
2013-06-24 13:41:48 +02:00
{
2013-12-31 11:34:11 +01:00
if ( ! plugin . Enabled )
continue ;
2013-06-24 13:41:48 +02:00
2017-03-21 10:06:04 +01:00
foreach ( Plugins . Feature feature in plugin . Features )
2013-06-24 13:41:48 +02:00
{
2013-12-31 11:34:11 +01:00
var menuItemFeature = feature as MenuItemFeature ;
2013-06-24 13:41:48 +02:00
2013-12-31 11:34:11 +01:00
if ( menuItemFeature ! = null & & menuItemFeature . ParentFeature = = null & & ( int ) menuItemFeature . Menu = = MainMenuBar . Items . IndexOf ( menu ) )
{
2014-01-22 13:39:32 +01:00
Command cmd = menuItemFeature . GetCommand ( this , SelectionManager . Selection ) ;
2013-06-24 13:41:48 +02:00
2013-12-31 11:34:11 +01:00
menu . DropDownItems . Insert ( insertIndex , new CommandToolStripMenuItem ( cmd ) ) ;
insertIndex + + ;
itemAdded = true ;
}
2013-06-24 13:41:48 +02:00
2013-12-31 11:34:11 +01:00
var parentMenuItemFeature = feature as ParentMenuItemFeature ;
2013-06-24 13:41:48 +02:00
2013-12-31 11:34:11 +01:00
if ( parentMenuItemFeature ! = null & & ( int ) parentMenuItemFeature . Menu = = MainMenuBar . Items . IndexOf ( menu ) )
2013-06-24 13:41:48 +02:00
{
2014-01-22 13:39:32 +01:00
Command cmd = parentMenuItemFeature . GetCommand ( this , SelectionManager . Selection ) ;
2013-12-31 11:34:11 +01:00
CommandToolStripMenuItem parentMenuItem = new CommandToolStripMenuItem ( cmd ) ;
menu . DropDownItems . Insert ( insertIndex , parentMenuItem ) ;
insertIndex + + ;
itemAdded = true ;
foreach ( MenuItemFeature childFeature in parentMenuItemFeature . Features )
{
2014-01-22 13:39:32 +01:00
Command childCommand = childFeature . GetCommand ( this , SelectionManager . Selection ) ;
2013-12-31 11:34:11 +01:00
parentMenuItem . DropDownItems . Add ( new CommandToolStripMenuItem ( childCommand ) ) ;
}
2013-06-24 13:41:48 +02:00
}
}
}
2013-12-31 11:34:11 +01:00
if ( itemAdded & & insertIndex ! = menu . DropDownItems . Count )
menu . DropDownItems . Insert ( insertIndex , new ToolStripSeparator ( ) ) ;
2013-06-24 13:41:48 +02:00
}
}
private void MainMenuBar_MenuActivate ( object sender , EventArgs e )
{
2013-08-22 18:25:12 +02:00
bool vm = SelectionManager . Selection . FirstIsRealVM & & ! ( ( VM ) SelectionManager . Selection . First ) . Locked ;
2013-06-24 13:41:48 +02:00
exportSettingsToolStripMenuItem . Enabled = ConnectionsManager . XenConnectionsCopy . Count > 0 ;
2018-10-01 18:01:59 +02:00
MenuShortcutsEnabled = true ;
2013-06-24 13:41:48 +02:00
startOnHostToolStripMenuItem . Available = startOnHostToolStripMenuItem . Enabled ;
resumeOnToolStripMenuItem . Available = resumeOnToolStripMenuItem . Enabled ;
relocateToolStripMenuItem . Available = relocateToolStripMenuItem . Enabled ;
2013-08-22 18:25:12 +02:00
sendCtrlAltDelToolStripMenuItem . Enabled = ( TheTabControl . SelectedTab = = TabPageConsole ) & & vm & & ( ( VM ) SelectionManager . Selection . First ) . power_state = = vm_power_state . Running ;
2013-06-24 13:41:48 +02:00
2018-09-28 18:58:49 +02:00
IXenConnection conn = SelectionManager . Selection . GetConnectionOfAllItems ( ) ;
2016-01-29 12:34:44 +01:00
2020-07-08 13:59:29 +02:00
bool vmssOn = conn ! = null & & Helpers . FalconOrGreater ( conn ) ;
assignSnapshotScheduleToolStripMenuItem . Available = vmssOn ;
VMSnapshotScheduleToolStripMenuItem . Available = vmssOn ;
2013-06-24 13:41:48 +02:00
templatesToolStripMenuItem1 . Checked = Properties . Settings . Default . DefaultTemplatesVisible ;
customTemplatesToolStripMenuItem . Checked = Properties . Settings . Default . UserTemplatesVisible ;
localStorageToolStripMenuItem . Checked = Properties . Settings . Default . LocalSRsVisible ;
ShowHiddenObjectsToolStripMenuItem . Checked = Properties . Settings . Default . ShowHiddenVMs ;
connectDisconnectToolStripMenuItem . Enabled = ConnectionsManager . XenConnectionsCopy . Count > 0 ;
2019-08-22 11:47:43 +02:00
conversionToolStripMenuItem . Available = conn ! = null & & conn . Cache . VMs . Any ( v = > v . IsConversionVM ( ) ) ;
2020-04-08 01:57:39 +02:00
installToolsToolStripMenuItem . Available = SelectionManager . Selection . Any ( v = > ! Helpers . StockholmOrGreater ( v . Connection ) ) ;
2020-03-25 00:28:44 +01:00
toolStripMenuItemInstallCertificate . Available = Helpers . StockholmOrGreater ( conn ) ;
2022-07-12 16:02:33 +02:00
2020-07-08 13:59:29 +02:00
toolStripMenuItemRotateSecret . Available = SelectionManager . Selection . Any ( s = >
s . Connection ! = null & & Helpers . StockholmOrGreater ( s . Connection ) & &
! s . Connection . Cache . Hosts . Any ( Host . RestrictPoolSecretRotation ) ) ;
2022-07-12 16:02:33 +02:00
2021-04-13 14:36:30 +02:00
toolStripMenuItemEnableTls . Available = SelectionManager . Selection . Any ( s = >
2023-04-11 13:59:33 +02:00
s . Connection ! = null & & Helpers . CloudOrGreater ( s . Connection ) & & Helpers . XapiEqualOrGreater_1_290_0 ( s . Connection ) & &
2021-04-13 14:36:30 +02:00
! s . Connection . Cache . Hosts . Any ( Host . RestrictCertificateVerification ) & &
s . Connection . Cache . Pools . Any ( p = > ! p . tls_verification_enabled ) ) ;
2022-07-12 16:02:33 +02:00
toolStripMenuItemVtpm . Available = SelectionManager . Selection . Any ( s = >
2023-04-11 13:59:33 +02:00
s . Connection ! = null & & Helpers . CloudOrGreater ( s . Connection ) & & Helpers . XapiEqualOrGreater_22_26_0 ( s . Connection ) & &
2022-07-12 16:02:33 +02:00
! s . Connection . Cache . Hosts . Any ( Host . RestrictVtpm ) ) ;
2013-06-24 13:41:48 +02:00
}
private void xenSourceOnTheWebToolStripMenuItem_Click ( object sender , EventArgs e )
{
Program . OpenURL ( InvisibleMessages . HOMEPAGE ) ;
}
private void xenCenterPluginsOnTheWebToolStripMenuItem_Click ( object sender , EventArgs e )
{
Program . OpenURL ( InvisibleMessages . PLUGINS_URL ) ;
}
private void aboutXenSourceAdminToolStripMenuItem_Click ( object sender , EventArgs e )
{
2013-08-21 18:13:23 +02:00
ShowForm ( typeof ( AboutDialog ) ) ;
2013-06-24 13:41:48 +02:00
}
/// <summary>
/// Apply license, if HostAncestorOfSelectedNode is null, show host picker, if filepath == "" show filepicker
/// </summary>
public void LaunchLicensePicker ( string filepath )
{
HelpersGUI . BringFormToFront ( this ) ;
OpenFileDialog dialog = null ;
DialogResult result = DialogResult . Cancel ;
if ( filepath = = "" )
{
if ( ! Program . RunInAutomatedTestMode )
{
dialog = new OpenFileDialog ( ) ;
dialog . Multiselect = false ;
2020-03-10 12:33:21 +01:00
dialog . Title = Messages . SELECT_LICENSE_KEY ;
2013-06-24 13:41:48 +02:00
dialog . CheckFileExists = true ;
dialog . CheckPathExists = true ;
2021-03-16 02:50:45 +01:00
dialog . Filter = string . Format ( "{0} (*.xslic)|*.xslic|{1} (*.*)|*.*" ,
string . Format ( Messages . XS_LICENSE_FILES , BrandManager . ProductBrand ) , Messages . ALL_FILES ) ;
2013-06-24 13:41:48 +02:00
dialog . ShowHelp = true ;
2020-03-10 12:33:21 +01:00
dialog . HelpRequest + = dialog_HelpRequest ;
2013-06-24 13:41:48 +02:00
result = dialog . ShowDialog ( this ) ;
}
}
else
{
result = DialogResult . OK ;
}
if ( result = = DialogResult . OK | | Program . RunInAutomatedTestMode )
{
2021-12-21 16:53:46 +01:00
if ( Program . RunInAutomatedTestMode )
{
filepath = string . Empty ;
}
else if ( filepath = = string . Empty & & dialog ! = null )
{
filepath = dialog . FileName ;
}
2013-06-24 13:41:48 +02:00
2013-08-22 18:25:12 +02:00
Host hostAncestor = SelectionManager . Selection . Count = = 1 ? SelectionManager . Selection [ 0 ] . HostAncestor : null ;
2013-06-24 13:41:48 +02:00
2013-08-22 18:25:12 +02:00
if ( SelectionManager . Selection . Count = = 1 & & hostAncestor = = null )
2013-06-24 13:41:48 +02:00
{
SelectHostDialog hostdialog = new SelectHostDialog ( ) ;
hostdialog . TheHost = null ;
hostdialog . Owner = this ;
hostdialog . ShowDialog ( this ) ;
if ( string . IsNullOrEmpty ( filepath ) | | hostdialog . DialogResult ! = DialogResult . OK )
{
return ;
}
hostAncestor = hostdialog . TheHost ;
}
DoLicenseAction ( hostAncestor , filepath ) ;
}
}
private void DoLicenseAction ( Host host , string filePath )
{
2019-10-03 14:40:13 +02:00
//null can happen if the application is started from, say,
//double clicking on a license file without any connections on the tree
if ( host = = null )
return ;
var action = new ApplyLicenseAction ( host , filePath ) ;
2016-06-20 14:17:42 +02:00
using ( var actionProgress = new ActionProgressDialog ( action , ProgressBarStyle . Marquee ) )
{
actionProgress . Text = Messages . INSTALL_LICENSE_KEY ;
actionProgress . ShowDialog ( this ) ;
}
2013-06-24 13:41:48 +02:00
}
private void dialog_HelpRequest ( object sender , EventArgs e )
{
Help . HelpManager . Launch ( "LicenseKeyDialog" ) ;
}
2017-01-25 13:38:33 +01:00
private void TheTabControl_Deselected ( object sender , TabControlEventArgs e )
{
TabPage t = e . TabPage ;
if ( t = = null )
return ;
BaseTabPage tabPage = t . Controls . OfType < BaseTabPage > ( ) . FirstOrDefault ( ) ;
if ( tabPage ! = null )
tabPage . PageHidden ( ) ;
}
2018-03-20 14:23:00 +01:00
/// <param name="sender"></param>
2022-01-31 13:00:19 +01:00
/// <param name="e">If null, then we deduce the method was called by navigation panel
/// events (e.g. navigating in the treeView). In this case do not focus the VNC console,
/// we only do it if the user explicitly clicked on the console tab.</param>
2013-06-24 13:41:48 +02:00
private void TheTabControl_SelectedIndexChanged ( object sender , EventArgs e )
{
if ( IgnoreTabChanges )
return ;
TabPage t = TheTabControl . SelectedTab ;
if ( ! SearchMode )
2013-08-22 18:25:12 +02:00
History . NewHistoryItem ( new XenModelObjectHistoryItem ( SelectionManager . Selection . FirstAsXenObject , t ) ) ;
2013-06-24 13:41:48 +02:00
if ( t = = TabPageConsole )
{
2022-02-02 18:24:20 +01:00
CvmConsolePanel . PauseAllDockedViews ( ) ;
2013-08-22 18:25:12 +02:00
if ( SelectionManager . Selection . FirstIsRealVM )
2013-06-24 13:41:48 +02:00
{
2022-01-31 12:37:34 +01:00
ConsolePanel . SetCurrentSource ( ( VM ) SelectionManager . Selection . First ) ;
2022-02-02 18:24:20 +01:00
ConsolePanel . UnpauseActiveView ( e ! = null & & sender = = TheTabControl ) ;
2013-06-24 13:41:48 +02:00
}
2016-10-14 13:21:59 +02:00
else if ( SelectionManager . Selection . FirstIs < Host > ( ) )
2013-06-24 13:41:48 +02:00
{
2022-01-31 12:37:34 +01:00
ConsolePanel . SetCurrentSource ( ( Host ) SelectionManager . Selection . First ) ;
2022-02-02 18:24:20 +01:00
ConsolePanel . UnpauseActiveView ( e ! = null & & sender = = TheTabControl ) ;
2013-06-24 13:41:48 +02:00
}
2017-03-03 18:29:19 +01:00
ConsolePanel . UpdateRDPResolution ( ) ;
2013-06-24 13:41:48 +02:00
}
2016-07-05 09:14:13 +02:00
else if ( t = = TabPageCvmConsole )
{
2022-02-02 18:24:20 +01:00
ConsolePanel . PauseAllDockedViews ( ) ;
2021-02-24 16:44:38 +01:00
if ( SelectionManager . Selection . First is SR sr & & sr . HasDriverDomain ( out var vm ) )
2016-07-05 09:14:13 +02:00
{
2022-01-31 12:37:34 +01:00
CvmConsolePanel . SetCurrentSource ( vm ) ;
2022-02-02 18:24:20 +01:00
CvmConsolePanel . UnpauseActiveView ( e ! = null & & sender = = TheTabControl ) ;
2016-07-05 09:14:13 +02:00
}
}
2013-06-24 13:41:48 +02:00
else
{
2022-02-02 12:13:14 +01:00
ConsolePanel . PauseAllDockedViews ( ) ;
CvmConsolePanel . PauseAllDockedViews ( ) ;
2013-06-24 13:41:48 +02:00
if ( t = = TabPageGeneral )
{
2013-08-22 18:25:12 +02:00
GeneralPage . XenObject = SelectionManager . Selection . FirstAsXenObject ;
2013-06-24 13:41:48 +02:00
}
else if ( t = = TabPageBallooning )
{
2013-08-22 18:25:12 +02:00
BallooningPage . XenObject = SelectionManager . Selection . FirstAsXenObject ;
2013-06-24 13:41:48 +02:00
}
else if ( t = = TabPageSR )
{
2015-10-27 19:11:53 +01:00
SrStoragePage . SR = SelectionManager . Selection . First as SR ;
2013-06-24 13:41:48 +02:00
}
else if ( t = = TabPageNetwork )
{
2013-08-22 18:25:12 +02:00
NetworkPage . XenObject = SelectionManager . Selection . FirstAsXenObject ;
2013-06-24 13:41:48 +02:00
}
2017-09-27 14:37:17 +02:00
else if ( t = = TabPageUSB )
{
UsbPage . XenObject = SelectionManager . Selection . FirstAsXenObject as Host ;
}
2013-06-24 13:41:48 +02:00
else if ( t = = TabPageNICs )
{
2013-08-22 18:25:12 +02:00
NICPage . Host = SelectionManager . Selection . First as Host ;
2013-06-24 13:41:48 +02:00
}
else if ( t = = TabPageStorage )
{
2013-08-22 18:25:12 +02:00
VMStoragePage . VM = SelectionManager . Selection . First as VM ;
2013-06-24 13:41:48 +02:00
}
else if ( t = = TabPagePeformance )
{
2013-08-22 18:25:12 +02:00
PerformancePage . XenObject = SelectionManager . Selection . FirstAsXenObject ;
2013-06-24 13:41:48 +02:00
}
else if ( t = = TabPageSearch & & ! SearchMode )
{
2013-10-08 11:17:57 +02:00
var rootNode = SelectionManager . Selection . RootNode ;
var rootNodeGrouping = rootNode = = null ? null : rootNode . Tag as GroupingTag ;
var search = rootNode = = null ? null : rootNode . Tag as Search ;
if ( search ! = null )
{
SearchPage . Search = search ;
}
else if ( rootNodeGrouping ! = null )
2013-06-24 13:41:48 +02:00
{
2013-10-08 11:17:57 +02:00
var objectsView = rootNodeGrouping . Grouping as OrganizationViewObjects ;
var vappsView = rootNodeGrouping . Grouping as OrganizationViewVapps ;
2013-12-02 16:26:46 +01:00
var foldersView = rootNodeGrouping . Grouping as OrganizationViewFolders ;
2013-10-08 11:17:57 +02:00
if ( vappsView ! = null )
{
SearchPage . Search = Search . SearchForVappGroup ( rootNodeGrouping . Grouping ,
rootNodeGrouping . Parent , rootNodeGrouping . Group ) ;
}
else if ( objectsView ! = null )
{
2014-09-22 16:55:20 +02:00
//We are in Objects View
2014-09-17 16:47:43 +02:00
GroupingTag gt = null ;
2013-10-08 11:17:57 +02:00
2014-09-17 16:47:43 +02:00
if ( SelectionManager . Selection . Count = = 1 )
{
gt = SelectionManager . Selection . First as GroupingTag
? ? SelectionManager . Selection [ 0 ] . GroupAncestor ;
}
else
{
2014-09-22 16:55:20 +02:00
//If multiple items have been selected we count the number of the grouping tags in the selection
2020-06-20 15:35:25 +02:00
var selectedGroups = SelectionManager . Selection . Where ( s = > s . GroupingTag ! = null ) . ToList ( ) ;
2014-09-19 13:45:42 +02:00
2014-09-22 16:55:20 +02:00
//if exactly one grouping tag has been selected we show the search view for that one tag, but only if all the other items in the selection belong to this group/tag
2020-06-20 15:35:25 +02:00
if ( selectedGroups . Count = = 1 )
2014-09-19 13:45:42 +02:00
{
2020-06-20 15:35:25 +02:00
var groupingTag = selectedGroups [ 0 ] . GroupingTag ;
2014-09-19 13:45:42 +02:00
if ( SelectionManager . Selection . Where ( s = > s . GroupingTag = = null ) . All ( s = > s . GroupAncestor = = groupingTag ) )
gt = groupingTag ;
else
gt = null ;
}
else
{
gt = SelectionManager . Selection . GroupAncestor ;
}
2014-09-17 16:47:43 +02:00
}
2014-09-22 16:55:20 +02:00
//if there has been a grouping tag determined above we use that
//if not we show the search view for the root node
2014-09-17 16:47:43 +02:00
if ( gt ! = null )
{
SearchPage . Search = Search . SearchForNonVappGroup ( gt . Grouping , gt . Parent , gt . Group ) ;
}
else
{
SearchPage . Search = Search . SearchForNonVappGroup ( rootNodeGrouping . Grouping , rootNodeGrouping . Parent , rootNodeGrouping . Group ) ;
}
2013-10-08 11:17:57 +02:00
}
2013-12-02 16:26:46 +01:00
else if ( foldersView ! = null )
{
SearchPage . Search = Search . SearchForFolderGroup ( rootNodeGrouping . Grouping ,
rootNodeGrouping . Parent , rootNodeGrouping . Group ) ;
}
2013-10-08 11:17:57 +02:00
else
{
SearchPage . Search = Search . SearchForNonVappGroup ( rootNodeGrouping . Grouping ,
rootNodeGrouping . Parent , rootNodeGrouping . Group ) ;
}
2013-06-24 13:41:48 +02:00
}
else
{
2014-09-19 14:47:04 +02:00
// Infrastructure View:
2019-07-15 02:26:11 +02:00
// - In case of single selection or multiple selection within the same pool,
// find the top-level parent (pool or standalone server) and show that search
// - In case of multiple selection across pools or standalone servers,
// or selection of the XenCenter node, or selection of a disconnected host,
// show the default search.
var connection = SelectionManager . Selection . GetConnectionOfAllItems ( ) ;
if ( connection = = null )
2014-09-19 14:47:04 +02:00
{
2019-07-15 02:26:11 +02:00
SearchPage . XenObject = null ;
2014-09-19 14:47:04 +02:00
}
else
2019-07-15 02:26:11 +02:00
{
var pool = Helpers . GetPool ( connection ) ;
2021-08-31 12:31:16 +02:00
SearchPage . XenObject = pool ? ? ( IXenObject ) Helpers . GetCoordinator ( connection ) ;
2019-07-15 02:26:11 +02:00
}
2013-06-24 13:41:48 +02:00
}
}
else if ( t = = TabPageHA )
{
2013-08-22 18:25:12 +02:00
HAPage . XenObject = SelectionManager . Selection . FirstAsXenObject ;
2013-06-24 13:41:48 +02:00
}
else if ( t = = TabPageWLB )
{
2013-08-22 18:25:12 +02:00
WlbPage . Pool = SelectionManager . Selection . First as Pool ;
2013-06-24 13:41:48 +02:00
}
else if ( t = = TabPageSnapshots )
{
2013-08-22 18:25:12 +02:00
snapshotPage . VM = SelectionManager . Selection . First as VM ;
2013-06-24 13:41:48 +02:00
}
else if ( t = = TabPagePhysicalStorage )
{
2014-01-22 13:39:32 +01:00
PhysicalStoragePage . SetSelectionBroadcaster ( SelectionManager , this ) ;
2013-08-22 18:25:12 +02:00
PhysicalStoragePage . Host = SelectionManager . Selection . First as Host ;
PhysicalStoragePage . Connection = SelectionManager . Selection . GetConnectionOfFirstItem ( ) ;
2013-06-24 13:41:48 +02:00
}
else if ( t = = TabPageAD )
{
2013-08-22 18:25:12 +02:00
AdPage . XenObject = SelectionManager . Selection . FirstAsXenObject ;
2013-06-24 13:41:48 +02:00
}
2013-11-14 12:06:50 +01:00
else if ( t = = TabPageGPU )
{
GpuPage . XenObject = SelectionManager . Selection . FirstAsXenObject ;
}
2015-02-06 11:03:42 +01:00
else if ( t = = TabPageDockerProcess )
{
2015-02-26 10:45:43 +01:00
DockerProcessPage . DockerContainer = SelectionManager . Selection . First as DockerContainer ;
2015-02-06 11:03:42 +01:00
}
2015-02-09 08:42:00 +01:00
else if ( t = = TabPageDockerDetails )
{
2015-02-26 10:45:43 +01:00
DockerDetailsPage . DockerContainer = SelectionManager . Selection . First as DockerContainer ;
2015-02-09 08:42:00 +01:00
}
2016-07-13 14:36:49 +02:00
else if ( t = = TabPagePvs )
{
PvsPage . Connection = SelectionManager . Selection . GetConnectionOfFirstItem ( ) ;
}
2013-06-24 13:41:48 +02:00
}
if ( t = = TabPageSearch )
SearchPage . PanelShown ( ) ;
else
SearchPage . PanelHidden ( ) ;
2015-02-09 08:42:00 +01:00
if ( t = = TabPageDockerDetails )
DockerDetailsPage . ResumeRefresh ( ) ;
else
DockerDetailsPage . PauseRefresh ( ) ;
2015-02-18 10:50:55 +01:00
if ( t = = TabPageDockerProcess )
DockerProcessPage . ResumeRefresh ( ) ;
else
DockerProcessPage . PauseRefresh ( ) ;
2013-06-24 13:41:48 +02:00
if ( t ! = null )
2013-08-22 18:25:12 +02:00
SetLastSelectedPage ( SelectionManager . Selection . First , t ) ;
2018-08-06 19:42:16 +02:00
UpdateTabePageFeatures ( ) ;
}
private void UpdateTabePageFeatures ( )
{
2021-11-29 16:18:38 +01:00
var plugins = PluginManager . Plugins ;
2018-08-06 19:42:16 +02:00
foreach ( var p in plugins )
{
var features = p . Features ;
foreach ( var feature in features )
{
var f = feature as TabPageFeature ;
if ( f = = null )
continue ;
if ( ! f . ShowTab )
continue ;
if ( f . IsConsoleReplacement )
{
f . SetUrl ( ) ;
continue ;
}
var page = GetLastSelectedPage ( f . SelectedXenObject ) ;
if ( page ! = null & & page . Tag = = f )
f . SetUrl ( ) ;
}
}
2013-06-24 13:41:48 +02:00
}
/// <summary>
/// The tabs that may be visible in the main GUI window. Used in SwitchToTab().
/// </summary>
public enum Tab
{
2018-10-01 17:08:15 +02:00
Home , General , Storage , Network , Console , CvmConsole , Performance , NICs , SR , DockerProcess , DockerDetails , USB , Search
2013-06-24 13:41:48 +02:00
}
public void SwitchToTab ( Tab tab )
{
switch ( tab )
{
case Tab . Home :
TheTabControl . SelectedTab = TabPageHome ;
break ;
2018-10-01 17:08:15 +02:00
case Tab . General :
2013-06-24 13:41:48 +02:00
TheTabControl . SelectedTab = TabPageGeneral ;
break ;
case Tab . Storage :
TheTabControl . SelectedTab = TabPageStorage ;
break ;
case Tab . Network :
TheTabControl . SelectedTab = TabPageNetwork ;
break ;
case Tab . Console :
TheTabControl . SelectedTab = TabPageConsole ;
break ;
2016-07-05 09:14:13 +02:00
case Tab . CvmConsole :
TheTabControl . SelectedTab = TabPageCvmConsole ;
break ;
2013-06-24 13:41:48 +02:00
case Tab . Performance :
TheTabControl . SelectedTab = TabPagePeformance ;
break ;
case Tab . NICs :
TheTabControl . SelectedTab = TabPageNICs ;
break ;
case Tab . SR :
TheTabControl . SelectedTab = TabPageSR ;
break ;
2015-02-06 11:03:42 +01:00
case Tab . DockerProcess :
TheTabControl . SelectedTab = TabPageDockerProcess ;
break ;
2015-02-09 08:42:00 +01:00
case Tab . DockerDetails :
TheTabControl . SelectedTab = TabPageDockerDetails ;
break ;
2017-09-27 14:37:17 +02:00
case Tab . USB :
TheTabControl . SelectedTab = TabPageUSB ;
break ;
2018-10-01 17:08:15 +02:00
case Tab . Search :
TheTabControl . SelectedTab = TabPageSearch ;
break ;
2013-06-24 13:41:48 +02:00
default :
throw new NotImplementedException ( ) ;
}
}
private void templatesToolStripMenuItem1_Click ( object sender , EventArgs e )
{
templatesToolStripMenuItem1 . Checked = ! templatesToolStripMenuItem1 . Checked ;
2013-09-12 00:12:08 +02:00
Properties . Settings . Default . DefaultTemplatesVisible = templatesToolStripMenuItem1 . Checked ;
ViewSettingsChanged ( ) ;
2013-06-24 13:41:48 +02:00
}
private void customTemplatesToolStripMenuItem_Click ( object sender , EventArgs e )
{
customTemplatesToolStripMenuItem . Checked = ! customTemplatesToolStripMenuItem . Checked ;
2013-09-12 00:12:08 +02:00
Properties . Settings . Default . UserTemplatesVisible = customTemplatesToolStripMenuItem . Checked ;
ViewSettingsChanged ( ) ;
2013-06-24 13:41:48 +02:00
}
private void localStorageToolStripMenuItem_Click ( object sender , EventArgs e )
{
localStorageToolStripMenuItem . Checked = ! localStorageToolStripMenuItem . Checked ;
2013-09-12 00:12:08 +02:00
Properties . Settings . Default . LocalSRsVisible = localStorageToolStripMenuItem . Checked ;
ViewSettingsChanged ( ) ;
}
private void ShowHiddenObjectsToolStripMenuItem_Click ( object sender , EventArgs e )
{
ShowHiddenObjectsToolStripMenuItem . Checked = ! ShowHiddenObjectsToolStripMenuItem . Checked ;
Properties . Settings . Default . ShowHiddenVMs = ShowHiddenObjectsToolStripMenuItem . Checked ;
ViewSettingsChanged ( ) ;
}
private void ViewSettingsChanged ( )
{
2013-06-24 13:41:48 +02:00
Settings . TrySaveSettings ( ) ;
2013-09-12 00:12:08 +02:00
navigationPane . UpdateSearch ( ) ;
RequestRefreshTreeView ( ) ;
2013-06-24 13:41:48 +02:00
}
2013-08-24 18:00:32 +02:00
private void EditSelectedNodeInTreeView ( )
2013-06-24 13:41:48 +02:00
{
2013-08-26 12:42:32 +02:00
navigationPane . EditSelectedNode ( ) ;
2013-06-24 13:41:48 +02:00
}
protected override void OnClosing ( CancelEventArgs e )
{
bool currentTasks = false ;
foreach ( ActionBase a in ConnectionsManager . History )
{
2014-03-11 15:30:01 +01:00
if ( a is MeddlingAction | | a . IsCompleted )
continue ;
currentTasks = true ;
break ;
2013-06-24 13:41:48 +02:00
}
2013-10-09 14:33:06 +02:00
2013-06-24 13:41:48 +02:00
if ( currentTasks )
{
e . Cancel = true ;
2014-03-11 15:30:01 +01:00
if ( Program . RunInAutomatedTestMode | |
new Dialogs . WarningDialogs . CloseXenCenterWarningDialog ( ) . ShowDialog ( this ) = = DialogResult . OK )
2013-06-24 13:41:48 +02:00
{
this . Hide ( ) ;
// Close all open forms
List < Form > forms = new List < Form > ( ) ;
foreach ( Form form in Application . OpenForms )
{
if ( form ! = this )
{
forms . Add ( form ) ;
}
}
foreach ( Form form in forms )
{
form . Close ( ) ;
}
foreach ( ActionBase a in ConnectionsManager . History )
{
if ( ! Program . RunInAutomatedTestMode )
{
2022-12-05 23:55:18 +01:00
if ( a is AsyncAction asyncAction )
asyncAction . PrepareForEventReloadAfterRestart ( ) ;
2013-06-24 13:41:48 +02:00
if ( ! a . IsCompleted & & a . CanCancel & & ! a . SafeToExit )
a . Cancel ( ) ;
}
else
{
if ( ! a . IsCompleted & & a . CanCancel )
a . Cancel ( ) ;
}
}
2014-03-11 15:30:01 +01:00
ThreadPool . QueueUserWorkItem ( CloseWhenActionsCanceled ) ;
2013-06-24 13:41:48 +02:00
}
return ;
}
Properties . Settings . Default . WindowSize = this . Size ;
Properties . Settings . Default . WindowLocation = this . Location ;
base . OnClosing ( e ) ;
}
private void sendCtrlAltDelToolStripMenuItem_Click ( object sender , EventArgs e )
{
ConsolePanel . SendCAD ( ) ;
}
2014-01-22 13:39:32 +01:00
#region IMainWindowCommandInterface Members
2013-06-24 13:41:48 +02:00
/// <summary>
2020-05-08 04:03:40 +02:00
/// Closes all per-Connection and per-VM forms for the given connection.
/// Per-Host forms are excluded on purpose.
2013-06-24 13:41:48 +02:00
/// </summary>
/// <param name="connection"></param>
2014-01-22 13:39:32 +01:00
public void CloseActiveWizards ( IXenConnection connection )
2013-06-24 13:41:48 +02:00
{
Program . Invoke ( Program . MainWindow , delegate
{
2020-05-08 04:03:40 +02:00
XenDialogBase . CloseAll ( connection . Cache . VMs . Cast < IXenObject > ( ) . ToArray ( ) ) ;
2013-06-24 13:41:48 +02:00
2019-10-11 02:49:18 +02:00
if ( activePoolWizards . TryGetValue ( connection , out IList < Form > wizards ) )
2013-06-24 13:41:48 +02:00
{
2019-10-11 02:49:18 +02:00
foreach ( var wizard in wizards )
2013-06-24 13:41:48 +02:00
{
2019-10-11 02:49:18 +02:00
if ( ! wizard . IsDisposed )
wizard . Close ( ) ;
2013-06-24 13:41:48 +02:00
}
2019-10-11 02:49:18 +02:00
activePoolWizards . Remove ( connection ) ;
}
} ) ;
2013-06-24 13:41:48 +02:00
}
/// <summary>
/// Show the given wizard, and impose a one-wizard-per-connection limit.
/// </summary>
/// <param name="connection">The connection. May be null, in which case the wizard
2019-08-22 11:47:43 +02:00
/// is not added to any dictionary. This should happen iff this is the New Pool Wizard.</param>
2013-06-24 13:41:48 +02:00
/// <param name="wizard">The new wizard to show. May not be null.</param>
2019-08-22 11:47:43 +02:00
/// <param name="parentForm">The form owning the wizard to be launched.</param>
public void ShowPerConnectionWizard ( IXenConnection connection , Form wizard , Form parentForm = null )
2013-06-24 13:41:48 +02:00
{
if ( connection ! = null )
{
if ( activePoolWizards . ContainsKey ( connection ) )
{
2019-08-22 11:47:43 +02:00
var w = activePoolWizards [ connection ] . FirstOrDefault ( x = > x . GetType ( ) = = wizard . GetType ( ) ) ;
2013-06-24 13:41:48 +02:00
if ( w ! = null & & ! w . IsDisposed )
{
if ( w . WindowState = = FormWindowState . Minimized )
{
w . WindowState = FormWindowState . Normal ;
}
w . Focus ( ) ;
return ;
}
if ( w ! = null & & w . IsDisposed )
activePoolWizards [ connection ] . Remove ( w ) ;
}
//closeActivePoolWizards(connection);
if ( activePoolWizards . ContainsKey ( connection ) )
activePoolWizards [ connection ] . Add ( wizard ) ;
else
activePoolWizards . Add ( connection , new List < Form > ( ) { wizard } ) ;
}
if ( ! wizard . Disposing & & ! wizard . IsDisposed & & ! Program . Exiting )
{
2019-08-22 11:47:43 +02:00
wizard . Show ( parentForm ? ? this ) ;
2013-06-24 13:41:48 +02:00
}
}
/// <summary>
/// Shows a form of the specified type if it has already been created. If the form doesn't exist yet
/// it is created first and then shown.
/// </summary>
/// <param name="type">The type of the form to be shown.</param>
2018-08-06 13:55:25 +02:00
public Form ShowForm ( Type type )
2013-06-24 13:41:48 +02:00
{
2018-08-06 13:55:25 +02:00
return ShowForm ( type , null ) ;
2013-08-21 18:13:23 +02:00
}
/// <summary>
/// Shows a form of the specified type if it has already been created. If the form doesn't exist yet
/// it is created first and then shown.
/// </summary>
/// <param name="type">The type of the form to be shown.</param>
/// <param name="args">The arguments to pass to the form's consructor</param>
2018-08-06 13:55:25 +02:00
public Form ShowForm ( Type type , object [ ] args )
2013-08-21 18:13:23 +02:00
{
2013-12-31 11:34:11 +01:00
foreach ( Form form in Application . OpenForms )
2013-06-24 13:41:48 +02:00
{
if ( form . GetType ( ) = = type )
{
HelpersGUI . BringFormToFront ( form ) ;
2018-08-06 13:55:25 +02:00
return form ;
2013-06-24 13:41:48 +02:00
}
}
2013-08-21 18:13:23 +02:00
Form newForm = ( Form ) Activator . CreateInstance ( type , args ) ;
2013-06-24 13:41:48 +02:00
newForm . Show ( this ) ;
2018-08-06 13:55:25 +02:00
return newForm ;
2013-06-24 13:41:48 +02:00
}
2014-01-22 13:39:32 +01:00
public Form Form
{
get { return this ; }
}
public void Invoke ( MethodInvoker method )
{
Program . Invoke ( this , method ) ;
}
2020-02-26 10:03:26 +01:00
/// <summary>
/// Selects the specified object in the treeview.
/// </summary>
/// <param name="xenObject">The object to be selected.</param>
/// <returns>A value indicating whether selection was successful.</returns>
2014-01-22 13:39:32 +01:00
public bool SelectObjectInTree ( IXenObject xenObject )
{
2020-02-26 10:03:26 +01:00
return navigationPane . SelectObject ( xenObject ) ;
2014-01-22 13:39:32 +01:00
}
public Collection < IXenConnection > GetXenConnectionsCopy ( )
{
return new Collection < IXenConnection > ( ConnectionsManager . XenConnectionsCopy ) ;
}
public void SaveServerList ( )
{
Settings . SaveServerList ( ) ;
}
public bool RunInAutomatedTestMode
{
get { return Program . RunInAutomatedTestMode ; }
}
public void RemoveConnection ( IXenConnection connection )
{
ConnectionsManager . ClearCacheAndRemoveConnection ( connection ) ;
}
public void PutSelectedNodeIntoEditMode ( )
{
EditSelectedNodeInTreeView ( ) ;
}
public void TrySelectNewObjectInTree ( Predicate < object > tagMatch , bool selectNode , bool expandNode , bool ensureNodeVisible )
{
TrySelectNewNode ( tagMatch , selectNode , expandNode , ensureNodeVisible ) ;
}
public void TrySelectNewObjectInTree ( IXenConnection c , bool selectNode , bool expandNode , bool ensureNodeVisible )
{
TrySelectNewNode ( c , selectNode , expandNode , ensureNodeVisible ) ;
}
#endregion
2013-06-24 13:41:48 +02:00
#region Help
private string getSelectedXenModelObjectType ( )
{
// for now, since there are few topics which depend on the selected object we shall just check the special cases
// when more topic are added we can just return the ModelObjectName
2013-08-22 18:25:12 +02:00
if ( TheTabControl . SelectedTab = = TabPageGeneral & & SelectionManager . Selection . First is VM )
2013-06-24 13:41:48 +02:00
{
return "VM" ;
}
if ( TheTabControl . SelectedTab = = TabPagePhysicalStorage | | TheTabControl . SelectedTab = = TabPageStorage | | TheTabControl . SelectedTab = = TabPageSR )
{
2016-10-14 13:21:59 +02:00
if ( SelectionManager . Selection . FirstIs < Pool > ( ) )
2013-06-24 13:41:48 +02:00
return "Pool" ;
2016-10-14 13:21:59 +02:00
if ( SelectionManager . Selection . FirstIs < Host > ( ) )
2013-06-24 13:41:48 +02:00
return "Server" ;
2016-10-14 13:21:59 +02:00
if ( SelectionManager . Selection . FirstIs < VM > ( ) )
2013-06-24 13:41:48 +02:00
return "VM" ;
2016-10-14 13:21:59 +02:00
if ( SelectionManager . Selection . FirstIs < SR > ( ) )
2013-06-24 13:41:48 +02:00
return "Storage" ;
}
if ( TheTabControl . SelectedTab = = TabPageNetwork )
{
2016-10-14 13:21:59 +02:00
if ( SelectionManager . Selection . FirstIs < Host > ( ) )
2013-06-24 13:41:48 +02:00
return "Server" ;
2016-10-14 13:21:59 +02:00
if ( SelectionManager . Selection . FirstIs < VM > ( ) )
2013-06-24 13:41:48 +02:00
return "VM" ;
}
return "" ;
}
public void MainWindow_HelpRequested ( object sender , HelpEventArgs hlpevent )
{
2021-08-31 12:31:16 +02:00
// CA-28064. MessageBox hack to stop the hlpevent it passes to MainWindows.
2018-10-01 18:01:59 +02:00
if ( Program . MainWindow . ContainsFocus & & MenuShortcutsEnabled )
2013-06-24 13:41:48 +02:00
LaunchHelp ( ) ;
}
private void helpTopicsToolStripMenuItem_Click ( object sender , EventArgs e )
{
2019-09-13 18:47:27 +02:00
HelpManager . Launch ( "TOC" ) ;
2013-06-24 13:41:48 +02:00
}
private void helpContextMenuItem_Click ( object sender , EventArgs e )
{
LaunchHelp ( ) ;
}
private void LaunchHelp ( )
{
2019-09-13 18:47:27 +02:00
if ( TheTabControl . SelectedTab . Tag is TabPageFeature tpf & & tpf . HasHelp )
2013-11-05 15:40:16 +01:00
{
2019-09-13 18:47:27 +02:00
tpf . LaunchHelp ( ) ;
return ;
2013-11-05 15:40:16 +01:00
}
2019-09-13 18:47:27 +02:00
HelpManager . Launch ( TabHelpID ( ) ) ;
}
private string TabHelpID ( )
{
2023-07-28 16:21:31 +02:00
foreach ( var page in _notificationPages )
{
if ( page . Visible )
return alertPage . HelpID ;
}
2019-09-13 18:47:27 +02:00
if ( TheTabControl . SelectedTab . Controls . Count > 0 & & TheTabControl . SelectedTab . Controls [ 0 ] is IControlWithHelp ctrl )
return ctrl . HelpID + getSelectedXenModelObjectType ( ) ;
return "TOC" ;
2013-06-24 13:41:48 +02:00
}
public bool HasHelp ( )
{
2019-09-13 18:47:27 +02:00
return HelpManager . TryGetTopicId ( TabHelpID ( ) , out _ ) ;
2013-06-24 13:41:48 +02:00
}
private void viewApplicationLogToolStripMenuItem_Click ( object sender , EventArgs e )
{
Program . ViewLogFiles ( ) ;
}
#endregion
/// <summary>
/// Used to select the pool or standalone host node for the specified connection which is about to appear in the tree.
/// </summary>
/// <param name="connection">The connection.</param>
/// <param name="selectNode">if set to <c>true</c> then the pool/standalone host node will be selected.</param>
/// <param name="expandNode">if set to <c>true</c> then the pool/standalone host node will be expanded.</param>
/// <param name="ensureNodeVisible">if set to <c>true</c> then the matched node will be made visible.</param>
public void TrySelectNewNode ( IXenConnection connection , bool selectNode , bool expandNode , bool ensureNodeVisible )
{
if ( connection ! = null )
{
TrySelectNewNode ( delegate ( object o )
{
if ( o = = null )
{
return false ;
}
else if ( o . Equals ( Helpers . GetPool ( connection ) ) )
{
return true ;
}
Host [ ] hosts = connection . Cache . Hosts ;
return hosts . Length > 0 & & o . Equals ( hosts [ 0 ] ) ;
} , selectNode , expandNode , ensureNodeVisible ) ;
}
}
/// <summary>
/// Used to select or expand a node which is about to appear in the tree. This is used so that new hosts, folders, pools
/// etc. can be picked and then selected/expanded.
///
/// It fires off a new thread and then repeatedly tries to select a node which matches the specified match
/// delegate. It stops if it times out or is successful.
/// </summary>
/// <param name="tagMatch">A match for the tag of the node.</param>
/// <param name="selectNode">if set to <c>true</c> then the matched node will be selected.</param>
/// <param name="expandNode">if set to <c>true</c> then the matched node will be expanded.</param>
/// <param name="ensureNodeVisible">if set to <c>true</c> then the matched node will be made visible.</param>
public void TrySelectNewNode ( Predicate < object > tagMatch , bool selectNode , bool expandNode , bool ensureNodeVisible )
{
ThreadPool . QueueUserWorkItem ( delegate
{
bool success = false ;
for ( int i = 0 ; i < 20 & & ! success ; i + + )
{
Program . Invoke ( Program . MainWindow , delegate
2013-08-24 18:00:32 +02:00
{
2013-08-26 12:42:32 +02:00
success = navigationPane . TryToSelectNewNode ( tagMatch , selectNode , expandNode , ensureNodeVisible ) ;
2013-08-24 18:00:32 +02:00
} ) ;
2013-06-24 13:41:48 +02:00
Thread . Sleep ( 500 ) ;
}
} ) ;
}
2023-05-11 17:34:21 +02:00
private void NotificationsPage_FiltersChanged ( )
{
SetFiltersLabel ( ) ;
}
private void SetFiltersLabel ( )
{
2023-07-28 16:21:31 +02:00
labelFiltersOnOff . Visible = _notificationPages . Any ( p = > p . Visible ) ;
labelFiltersOnOff . Text = _notificationPages . Any ( p = > p . Visible & & p . FilterIsOn )
? Messages . FILTERS_ON
: Messages . FILTERS_OFF ;
2023-05-11 17:34:21 +02:00
}
2013-11-18 15:31:00 +01:00
private void eventsPage_GoToXenObjectRequested ( IXenObject obj )
{
navigationPane . SwitchToInfrastructureMode ( ) ;
navigationPane . SelectObject ( obj ) ;
}
2023-07-03 21:50:12 +02:00
private void Cdn_UpdateInfoChanged ( IXenConnection obj )
{
2023-07-22 17:43:02 +02:00
Program . Invoke ( this , ( ) = >
{
int cdnUpdatesCount = Updates . CdnUpdateInfoPerConnection . Values . SelectMany ( info = > info . Updates ) . Distinct ( ) . Count ( ) ;
navigationPane . UpdateNotificationsButton ( NotificationsSubMode . UpdatesFromCdn , cdnUpdatesCount ) ;
statusButtonCdnUpdates . Text = cdnUpdatesCount . ToString ( ) ;
statusButtonCdnUpdates . Visible = cdnUpdatesCount > 0 ;
if ( cdnUpdatesPage . Visible )
{
TitleLabel . Text = NotificationsSubModeItem . GetText ( NotificationsSubMode . UpdatesFromCdn , cdnUpdatesCount ) ;
TitleIcon . Image = NotificationsSubModeItem . GetImage ( NotificationsSubMode . UpdatesFromCdn , cdnUpdatesCount ) ;
}
} ) ;
2023-07-03 21:50:12 +02:00
RequestRefreshTreeView ( ) ;
}
2020-07-26 15:54:52 +02:00
private void Updates_CollectionChanged ( CollectionChangeEventArgs e )
2013-11-19 16:42:47 +01:00
{
2023-05-11 17:34:21 +02:00
Program . Invoke ( this , ( ) = >
{
int updatesCount = Updates . UpdateAlerts . Count ;
navigationPane . UpdateNotificationsButton ( NotificationsSubMode . Updates , updatesCount ) ;
2023-07-22 17:43:02 +02:00
statusButtonUpdates . Text = updatesCount . ToString ( ) ;
statusButtonUpdates . Visible = updatesCount > 0 ;
2023-05-11 17:34:21 +02:00
2023-07-22 17:16:46 +02:00
SetClientUpdateAlert ( ) ;
2023-05-11 17:34:21 +02:00
if ( updatesPage . Visible )
{
TitleLabel . Text = NotificationsSubModeItem . GetText ( NotificationsSubMode . Updates , updatesCount ) ;
TitleIcon . Image = NotificationsSubModeItem . GetImage ( NotificationsSubMode . Updates , updatesCount ) ;
}
} ) ;
2023-07-03 21:50:12 +02:00
RequestRefreshTreeView ( ) ; //to update item icons
2013-11-19 16:42:47 +01:00
}
2023-05-11 22:17:57 +02:00
private void ClientUpdatesCheck_Completed ( )
2022-01-07 16:49:18 +01:00
{
2022-06-08 16:17:06 +02:00
Program . Invoke ( this , ( ) = >
{
toolStripMenuItemCfu . Enabled = true ;
2023-07-22 17:16:46 +02:00
SetClientUpdateAlert ( ) ;
2022-06-08 16:17:06 +02:00
} ) ;
2022-05-11 10:39:02 +02:00
}
2023-07-22 17:16:46 +02:00
private void SetClientUpdateAlert ( )
2022-05-11 10:39:02 +02:00
{
updateAlert = Updates . UpdateAlerts . FirstOrDefault ( update = > update is ClientUpdateAlert ) as ClientUpdateAlert ;
if ( updateAlert ! = null )
2022-10-06 17:02:37 +02:00
relNotesToolStripMenuItem . Text = string . Format ( Messages . MAINWINDOW_UPDATE_RELEASE , updateAlert . NewVersion . Version ) ;
2022-05-11 10:39:02 +02:00
updateClientToolStripMenuItem . Visible = updateAlert ! = null ;
2022-01-07 16:49:18 +01:00
}
2023-05-11 22:17:57 +02:00
private void ClientUpdatesCheck_Started ( )
2022-01-07 16:49:18 +01:00
{
2022-06-08 16:17:06 +02:00
Program . Invoke ( this , ( ) = >
{
updateClientToolStripMenuItem . Visible = false ;
toolStripMenuItemCfu . Enabled = false ;
} ) ;
2022-01-07 16:49:18 +01:00
}
2013-06-24 13:41:48 +02:00
private void CloseWhenActionsCanceled ( object o )
{
int i = 0 ;
while ( true )
{
if ( i > 20 )
Program . ForcedExiting = true ;
if ( i > 40 | | AllActionsCompleted ( ) )
{
Program . Invoke ( this , Application . Exit ) ;
break ;
}
i + + ;
2022-11-11 17:33:04 +01:00
Thread . Sleep ( 500 ) ;
2013-06-24 13:41:48 +02:00
}
}
private bool AllActionsCompleted ( )
{
foreach ( ActionBase a in ConnectionsManager . History )
{
if ( ! a . IsCompleted )
return false ;
}
return true ;
}
private void preferencesToolStripMenuItem_Click ( object sender , EventArgs e )
{
2021-11-29 16:18:38 +01:00
using ( var dialog = new OptionsDialog ( PluginManager ) )
2020-06-19 18:31:01 +02:00
dialog . ShowDialog ( this ) ;
2013-06-24 13:41:48 +02:00
}
2013-08-05 15:28:21 +02:00
internal void action_Completed ( ActionBase sender )
2013-06-24 13:41:48 +02:00
{
if ( Program . Exiting )
return ;
2021-06-11 18:36:30 +02:00
sender . Completed - = action_Completed ;
2013-06-24 13:41:48 +02:00
RequestRefreshTreeView ( ) ;
}
2018-10-16 17:24:54 +02:00
private void OpenGlobalImportWizard ( string param )
2013-06-24 13:41:48 +02:00
{
HelpersGUI . BringFormToFront ( this ) ;
2013-08-22 18:25:12 +02:00
Host hostAncestor = SelectionManager . Selection . Count = = 1 ? SelectionManager . Selection [ 0 ] . HostAncestor : null ;
2021-11-05 22:44:14 +01:00
new ImportWizard ( SelectionManager . Selection . GetConnectionOfFirstItem ( ) , hostAncestor , param ) . Show ( ) ;
2013-06-24 13:41:48 +02:00
}
#region XenSearch
2018-08-06 12:16:05 +02:00
private bool searchMode ;
/// <summary>
/// SearchMode doesn't just mean we are looking at the Search tab.
/// It's set when we import a search from a file; or when we double-click
/// on a folder or tag name to search for it.
/// </summary>
private bool SearchMode
2013-06-24 13:41:48 +02:00
{
get
{
return searchMode ;
}
set
{
if ( searchMode = = value )
return ;
searchMode = value ;
2013-08-26 12:42:32 +02:00
navigationPane . InSearchMode = value ;
2018-10-01 17:08:15 +02:00
UpdateToolbars ( ) ;
2013-06-24 13:41:48 +02:00
}
}
2014-01-22 13:39:32 +01:00
public bool DoSearch ( string filename )
2013-06-24 13:41:48 +02:00
{
List < Search > searches = Search . LoadFile ( filename ) ;
if ( searches ! = null & & searches . Count > 0 )
{
Program . Invoke ( Program . MainWindow , delegate ( )
{
DoSearch ( searches [ 0 ] ) ;
} ) ;
return true ;
}
return false ;
}
public void DoSearch ( Search search )
{
History . NewHistoryItem ( new SearchHistoryItem ( search ) ) ;
SearchMode = true ;
SearchPage . Search = search ;
UpdateHeader ( ) ;
}
public void SearchForTag ( string tag )
{
DoSearch ( Search . SearchForTag ( tag ) ) ;
}
public void SearchForFolder ( string path )
{
DoSearch ( Search . SearchForFolder ( path ) ) ;
}
2023-07-22 17:16:46 +02:00
private void SearchPanel_SearchChanged ( )
2013-06-24 13:41:48 +02:00
{
if ( SearchMode )
History . ReplaceHistoryItem ( new SearchHistoryItem ( SearchPage . Search ) ) ;
else
History . ReplaceHistoryItem ( new ModifiedSearchHistoryItem (
2013-08-22 18:25:12 +02:00
SelectionManager . Selection . FirstAsXenObject , SearchPage . Search ) ) ;
2013-06-24 13:41:48 +02:00
}
/// <summary>
/// Updates the shiny gradient bar with selected object name and icon.
/// Also updates 'Logged in as:'.
/// </summary>
private void UpdateHeader ( )
{
2014-10-01 18:43:03 +02:00
if ( navigationPane . currentMode = = NavigationPane . NavigationMode . Notifications )
2013-11-07 11:00:53 +01:00
return ;
2021-04-30 18:39:57 +02:00
var licenseColor = VerticalGradientPanel . TextColor ;
2018-10-05 12:57:16 +02:00
var licenseText = string . Empty ;
2013-06-24 13:41:48 +02:00
if ( SearchMode & & SearchPage . Search ! = null )
{
TitleLabel . Text = HelpersGUI . GetLocalizedSearchName ( SearchPage . Search ) ;
TitleIcon . Image = Images . GetImage16For ( SearchPage . Search ) ;
}
2013-08-22 18:25:12 +02:00
else if ( ! SearchMode & & SelectionManager . Selection . ContainsOneItemOfType < IXenObject > ( ) )
2013-06-24 13:41:48 +02:00
{
2013-08-22 18:25:12 +02:00
IXenObject xenObject = SelectionManager . Selection [ 0 ] . XenObject ;
2017-09-03 04:33:29 +02:00
TitleLabel . Text = xenObject . NameWithLocation ( ) ;
2013-06-24 13:41:48 +02:00
TitleIcon . Image = Images . GetImage16For ( xenObject ) ;
2018-10-05 12:57:16 +02:00
licenseText = GetLicenseStatusText ( xenObject , out licenseColor ) ;
2013-06-24 13:41:48 +02:00
// When in folder view only show the logged in label if it is clear to which connection the object belongs (most likely pools and hosts)
2013-08-22 18:25:12 +02:00
if ( SelectionManager . Selection [ 0 ] . PoolAncestor = = null & & SelectionManager . Selection [ 0 ] . HostAncestor = = null )
2013-06-24 13:41:48 +02:00
loggedInLabel1 . Connection = null ;
else
loggedInLabel1 . Connection = xenObject . Connection ;
}
else
{
2021-03-16 02:50:45 +01:00
TitleLabel . Text = BrandManager . BrandConsole ;
2020-06-18 02:20:29 +02:00
TitleIcon . Image = Images . StaticImages . Logo ;
2013-06-24 13:41:48 +02:00
loggedInLabel1 . Connection = null ;
}
2017-09-28 17:10:41 +02:00
2018-10-05 12:57:16 +02:00
LicenseStatusTitleLabel . Text = licenseText ;
LicenseStatusTitleLabel . ForeColor = licenseColor ;
2017-09-28 17:10:41 +02:00
SetTitleLabelMaxWidth ( ) ;
}
2018-10-05 12:57:16 +02:00
private string GetLicenseStatusText ( IXenObject xenObject , out Color foreColor )
2017-09-28 17:10:41 +02:00
{
2021-04-30 18:39:57 +02:00
foreColor = VerticalGradientPanel . TextColor ;
2017-09-28 17:10:41 +02:00
2018-10-05 12:57:16 +02:00
var pool = xenObject as Pool ;
if ( pool ! = null & & pool . Connection ! = null & & pool . Connection . IsConnected & & pool . Connection . CacheIsPopulated )
{
if ( pool . IsFreeLicenseOrExpired ( ) )
2017-09-28 17:10:41 +02:00
{
2018-10-05 12:57:16 +02:00
foreColor = Color . Red ;
return Messages . MAINWINDOW_HEADER_UNLICENSED ;
2017-09-28 17:10:41 +02:00
}
2018-10-05 12:57:16 +02:00
return string . Format ( Messages . MAINWINDOW_HEADER_LICENSED_WITH , Helpers . GetFriendlyLicenseName ( pool ) ) ;
2017-09-28 17:10:41 +02:00
}
2018-10-05 12:57:16 +02:00
var host = xenObject as Host ;
if ( host ! = null & & host . Connection ! = null & & host . Connection . IsConnected & & host . Connection . CacheIsPopulated )
{
if ( host . IsFreeLicenseOrExpired ( ) )
2017-09-28 17:10:41 +02:00
{
2018-10-05 12:57:16 +02:00
foreColor = Color . Red ;
return Messages . MAINWINDOW_HEADER_UNLICENSED ;
2017-09-28 17:10:41 +02:00
}
2018-10-05 12:57:16 +02:00
return string . Format ( Messages . MAINWINDOW_HEADER_LICENSED_WITH , Helpers . GetFriendlyLicenseName ( host ) ) ;
}
2017-10-27 15:34:45 +02:00
2018-10-05 12:57:16 +02:00
return string . Empty ;
2017-09-28 17:10:41 +02:00
}
private void SetTitleLabelMaxWidth ( )
{
TitleLabel . MaximumSize = new Size ( tableLayoutPanel1 . Width - loggedInLabel1 . Width - LicenseStatusTitleLabel . Width - 6 , TitleLabel . Height ) ;
2013-06-24 13:41:48 +02:00
}
2013-10-09 10:13:47 +02:00
private void UpdateViewMenu ( NavigationPane . NavigationMode mode )
{
//the order is the reverse from the order in which we want them to appear
var items = new ToolStripItem [ ]
{
toolStripSeparator24 ,
ShowHiddenObjectsToolStripMenuItem ,
localStorageToolStripMenuItem ,
templatesToolStripMenuItem1 ,
customTemplatesToolStripMenuItem
} ;
if ( mode = = NavigationPane . NavigationMode . Infrastructure )
{
foreach ( var item in items )
{
if ( ! viewToolStripMenuItem . DropDownItems . Contains ( item ) )
viewToolStripMenuItem . DropDownItems . Insert ( 0 , item ) ;
}
}
else if ( mode = = NavigationPane . NavigationMode . Notifications )
{
foreach ( var item in items )
viewToolStripMenuItem . DropDownItems . Remove ( item ) ;
}
else
{
for ( int i = 2 ; i < items . Length ; i + + )
viewToolStripMenuItem . DropDownItems . Remove ( items [ i ] ) ;
for ( int i = 0 ; i < 2 ; i + + )
if ( ! viewToolStripMenuItem . DropDownItems . Contains ( items [ i ] ) )
viewToolStripMenuItem . DropDownItems . Insert ( 0 , items [ i ] ) ;
}
pluginMenuItemStartIndexes [ viewToolStripMenuItem ] = viewToolStripMenuItem . DropDownItems . IndexOf ( toolStripSeparator24 ) + 1 ;
}
2023-07-22 17:16:46 +02:00
private void navigationPane_DragDropCommandActivated ( string cmdText )
2013-11-12 13:44:19 +01:00
{
SetStatusBar ( null , cmdText ) ;
}
2013-08-26 12:42:32 +02:00
private void navigationPane_TreeViewSelectionChanged ( )
2013-08-24 18:00:32 +02:00
{
UpdateToolbars ( ) ;
// NB do not trigger updates to the panels in this method
// instead, put them in TheTabControl_SelectedIndexChanged,
// so only the selected tab is updated
2022-01-31 13:00:19 +01:00
TheTabControl_SelectedIndexChanged ( null , null ) ;
2013-08-24 18:00:32 +02:00
if ( TheTabControl . SelectedTab ! = null )
TheTabControl . SelectedTab . Refresh ( ) ;
UpdateHeader ( ) ;
}
2013-11-07 11:00:53 +01:00
private void navigationPane_NotificationsSubModeChanged ( NotificationsSubModeItem submodeItem )
2013-08-30 16:19:59 +02:00
{
2023-07-22 17:43:02 +02:00
foreach ( var page in _notificationPages )
2013-09-02 15:45:42 +02:00
{
2023-07-22 17:43:02 +02:00
if ( page . NotificationsSubMode = = submodeItem . SubMode )
page . ShowPage ( ) ;
else if ( page . Visible )
page . HidePage ( ) ;
2023-05-11 17:34:21 +02:00
}
SetFiltersLabel ( ) ;
2018-08-10 10:38:55 +02:00
TheTabControl . Visible = false ;
2013-11-07 11:00:53 +01:00
loggedInLabel1 . Connection = null ;
TitleLabel . Text = submodeItem . Text ;
TitleIcon . Image = submodeItem . Image ;
2013-08-30 16:19:59 +02:00
}
2013-08-30 14:35:32 +02:00
private void navigationPane_NavigationModeChanged ( NavigationPane . NavigationMode mode )
{
if ( mode = = NavigationPane . NavigationMode . Notifications )
{
2018-10-05 12:57:16 +02:00
LicenseStatusTitleLabel . Text = string . Empty ;
2013-08-30 14:35:32 +02:00
TheTabControl . Visible = false ;
}
else
{
2014-06-30 17:38:48 +02:00
bool tabControlWasVisible = TheTabControl . Visible ;
2013-08-30 14:35:32 +02:00
TheTabControl . Visible = true ;
2023-07-28 16:21:31 +02:00
foreach ( var page in _notificationPages )
{
if ( page . Visible )
page . HidePage ( ) ;
}
2014-06-30 17:38:48 +02:00
// force an update of the selected tab when switching back from Notification view,
// as some tabs ignore the update events when not visible (e.g. Snapshots, HA)
if ( ! tabControlWasVisible )
TheTabControl_SelectedIndexChanged ( null , null ) ;
2013-08-30 14:35:32 +02:00
}
2013-10-09 10:13:47 +02:00
2023-05-11 17:34:21 +02:00
SetFiltersLabel ( ) ;
2013-10-09 10:13:47 +02:00
UpdateViewMenu ( mode ) ;
2013-08-30 14:35:32 +02:00
}
2013-08-26 12:42:32 +02:00
private void navigationPane_TreeNodeBeforeSelected ( )
2013-08-24 18:00:32 +02:00
{
SearchMode = false ;
}
2013-08-26 12:42:32 +02:00
private void navigationPane_TreeNodeClicked ( )
2013-08-24 18:00:32 +02:00
{
if ( SearchMode )
{
SearchMode = false ;
TheTabControl_SelectedIndexChanged ( null , null ) ;
UpdateHeader ( ) ;
}
}
2013-08-26 12:42:32 +02:00
private void navigationPane_TreeNodeRightClicked ( )
2013-08-24 18:00:32 +02:00
{
MainMenuBar_MenuActivate ( MainMenuBar , new EventArgs ( ) ) ;
}
2013-08-26 12:42:32 +02:00
private void navigationPane_TreeViewRefreshed ( )
2013-08-24 18:00:32 +02:00
{
2018-10-16 17:24:54 +02:00
// This is required to update search results when things change.
if ( TheTabControl . SelectedTab = = TabPageGeneral )
GeneralPage . BuildList ( ) ;
else if ( TheTabControl . SelectedTab = = TabPageSearch )
SearchPage . BuildList ( ) ;
2013-08-24 18:00:32 +02:00
2018-10-16 17:24:54 +02:00
UpdateHeader ( ) ;
UpdateToolbars ( ) ;
2013-08-24 18:00:32 +02:00
}
2013-06-24 13:41:48 +02:00
#endregion
2020-03-24 03:07:15 +01:00
private void XenCenterAlerts_CollectionChanged ( object sender , CollectionChangeEventArgs e )
2013-06-24 13:41:48 +02:00
{
2013-11-19 16:42:47 +01:00
Program . BeginInvoke ( Program . MainWindow , ( ) = >
2020-03-24 03:07:15 +01:00
{
var count = Alert . NonDismissingAlertCount ;
navigationPane . UpdateNotificationsButton ( NotificationsSubMode . Alerts , count ) ;
2013-11-19 16:42:47 +01:00
2023-07-22 17:43:02 +02:00
statusButtonAlerts . Text = count . ToString ( ) ;
statusButtonAlerts . Visible = count > 0 ;
2020-03-24 03:07:15 +01:00
if ( alertPage . Visible )
{
TitleLabel . Text = NotificationsSubModeItem . GetText ( NotificationsSubMode . Alerts , count ) ;
TitleIcon . Image = NotificationsSubModeItem . GetImage ( NotificationsSubMode . Alerts , count ) ;
}
} ) ;
2013-06-24 13:41:48 +02:00
}
private void backButton_Click ( object sender , EventArgs e )
{
History . Back ( 1 ) ;
}
private void forwardButton_Click ( object sender , EventArgs e )
{
History . Forward ( 1 ) ;
}
private void backButton_DropDownOpening ( object sender , EventArgs e )
{
ToolStripSplitButton button = sender as ToolStripSplitButton ;
if ( button = = null )
return ;
History . PopulateBackDropDown ( button ) ;
}
private void forwardButton_DropDownOpening ( object sender , EventArgs e )
{
ToolStripSplitButton button = sender as ToolStripSplitButton ;
if ( button = = null )
return ;
History . PopulateForwardDropDown ( button ) ;
}
private void LicenseManagerMenuItem_Click ( object sender , EventArgs e )
{
2013-08-22 18:25:12 +02:00
licenseManagerLauncher . LaunchIfRequired ( false , ConnectionsManager . XenConnections , SelectionManager . Selection ) ;
2013-06-24 13:41:48 +02:00
}
private void MainWindow_KeyDown ( object sender , KeyEventArgs e )
{
if ( e . KeyCode = = Keys . F5 )
{
RequestRefreshTreeView ( ) ;
if ( TheTabControl . SelectedTab = = TabPageSearch )
SearchPage . PanelProd ( ) ;
}
}
private void ShowToolbarMenuItem_Click ( object sender , EventArgs e )
{
2022-05-04 15:16:29 +02:00
Properties . Settings . Default . ToolbarsEnabled = ! Properties . Settings . Default . ToolbarsEnabled ;
2013-06-24 13:41:48 +02:00
UpdateToolbars ( ) ;
}
private void MainMenuBar_MouseClick ( object sender , MouseEventArgs e )
{
if ( e . Button = = MouseButtons . Right )
{
ToolBarContextMenu . Show ( Program . MainWindow , e . Location ) ;
}
}
/// <summary>
/// Show a message telling the user that the connection has disappeared. We check this after
/// we've shown a dialog, in case it's happened in the time it took them to click OK.
/// </summary>
public static void ShowDisconnectedMessage ( Control parent )
{
// We could have done some teardown by now, so we need to be paranoid about things going away
// beneath us.
if ( Program . Exiting )
return ;
if ( parent = = null | | parent . Disposing | | parent . IsDisposed )
{
parent = Program . MainWindow ;
if ( parent . Disposing | | parent . IsDisposed )
return ;
}
2020-04-22 15:47:03 +02:00
using ( var dlg = new WarningDialog ( Messages . DISCONNECTED_BEFORE_ACTION_STARTED ) )
2016-06-20 11:49:12 +02:00
dlg . ShowDialog ( parent ) ;
2013-06-24 13:41:48 +02:00
}
#region ISynchronizeInvoke Members
// this explicit implementation of ISynchronizeInvoke is used to allow the model to update
// its API on the main program thread while being decoupled from MainWindow.
IAsyncResult ISynchronizeInvoke . BeginInvoke ( Delegate method , object [ ] args )
{
return Program . BeginInvoke ( this , method , args ) ;
}
object ISynchronizeInvoke . EndInvoke ( IAsyncResult result )
{
return EndInvoke ( result ) ;
}
object ISynchronizeInvoke . Invoke ( Delegate method , object [ ] args )
{
return Program . Invoke ( this , method , args ) ;
}
bool ISynchronizeInvoke . InvokeRequired
{
get { return InvokeRequired ; }
}
#endregion
private void importSettingsToolStripMenuItem_Click ( object sender , EventArgs e )
{
using ( OpenFileDialog dialog = new OpenFileDialog ( ) )
{
2021-03-16 02:50:45 +01:00
dialog . Filter = string . Format ( Messages . XENCENTER_CONFIG_FILTER , BrandManager . BrandConsole ) ;
2013-06-24 13:41:48 +02:00
if ( dialog . ShowDialog ( this ) ! = DialogResult . Cancel )
{
try
{
log . InfoFormat ( "Importing server list from '{0}'" , dialog . FileName ) ;
XmlDocument xmlDocument = new XmlDocument ( ) ;
using ( var stream = dialog . OpenFile ( ) )
xmlDocument . Load ( stream ) ;
foreach ( XmlNode itemConnection in xmlDocument . GetElementsByTagName ( "XenConnection" ) )
{
var conn = new XenConnection ( ) ;
foreach ( XmlNode item in itemConnection . ChildNodes )
{
switch ( item . Name )
{
case "Hostname" :
conn . Hostname = item . InnerText ;
break ;
case "Port" :
conn . Port = int . Parse ( item . InnerText ) ;
break ;
case "FriendlyName" :
conn . FriendlyName = item . InnerText ;
break ;
}
}
if ( null = = ConnectionsManager . XenConnections . Find ( existing = > ( existing . Hostname = = conn . Hostname & & existing . Port = = conn . Port ) ) )
ConnectionsManager . XenConnections . Add ( conn ) ;
2013-08-25 15:06:03 +02:00
RequestRefreshTreeView ( ) ;
2013-06-24 13:41:48 +02:00
}
log . InfoFormat ( "Imported server list from '{0}' successfully." , dialog . FileName ) ;
}
catch ( XmlException )
{
log . ErrorFormat ( "Failed to import server list from '{0}'" , dialog . FileName ) ;
2020-09-01 04:21:41 +02:00
using ( var dlg = new ErrorDialog ( Messages . ERROR_IMPORTING_SERVER_LIST ) )
2016-06-20 11:49:12 +02:00
dlg . ShowDialog ( this ) ;
2013-06-24 13:41:48 +02:00
}
}
}
}
private void exportSettingsToolStripMenuItem_Click ( object sender , EventArgs e )
{
using ( SaveFileDialog dialog = new SaveFileDialog ( ) )
{
2021-03-16 02:50:45 +01:00
dialog . Filter = string . Format ( Messages . XENCENTER_CONFIG_FILTER , BrandManager . BrandConsole ) ;
2013-06-24 13:41:48 +02:00
dialog . Title = Messages . ACTION_SAVE_CHANGES_IN_PROGRESS ;
dialog . CheckPathExists = true ;
if ( dialog . ShowDialog ( this ) ! = DialogResult . Cancel )
{
log . InfoFormat ( "Exporting server list to '{0}'" , dialog . FileName ) ;
try
{
using ( var xmlWriter = new XmlTextWriter ( dialog . OpenFile ( ) , Encoding . Unicode ) )
{
xmlWriter . WriteStartDocument ( ) ;
xmlWriter . WriteStartElement ( "XenConnections" ) ;
xmlWriter . WriteWhitespace ( "\n" ) ;
foreach ( var connection in ConnectionsManager . XenConnections )
{
xmlWriter . WriteStartElement ( "XenConnection" ) ;
{
xmlWriter . WriteElementString ( "Hostname" , connection . Hostname ) ;
xmlWriter . WriteElementString ( "Port" , connection . Port . ToString ( ) ) ;
xmlWriter . WriteWhitespace ( "\n " ) ;
xmlWriter . WriteElementString ( "FriendlyName" , connection . FriendlyName ) ;
}
xmlWriter . WriteEndElement ( ) ;
xmlWriter . WriteWhitespace ( "\n" ) ;
}
xmlWriter . WriteEndElement ( ) ;
xmlWriter . WriteEndDocument ( ) ;
}
log . InfoFormat ( "Exported server list to '{0}' successfully." , dialog . FileName ) ;
}
catch
{
log . ErrorFormat ( "Failed to export server list to '{0}'." , dialog . FileName ) ;
throw ;
}
}
}
}
private void MainWindow_Load ( object sender , EventArgs e )
{
SetSplitterDistance ( ) ;
}
2017-02-27 19:00:46 +01:00
FormWindowState lastState = FormWindowState . Normal ;
2013-06-24 13:41:48 +02:00
private void MainWindow_Resize ( object sender , EventArgs e )
{
2017-03-03 18:29:19 +01:00
TabPage t = TheTabControl . SelectedTab ;
if ( t = = TabPageConsole )
2017-02-27 19:00:46 +01:00
{
2017-03-03 18:29:19 +01:00
if ( WindowState ! = lastState & & WindowState ! = FormWindowState . Minimized )
{
lastState = WindowState ;
ConsolePanel . UpdateRDPResolution ( ) ;
}
mainWindowResized = true ;
2017-02-27 19:00:46 +01:00
}
2017-03-03 18:29:19 +01:00
SetSplitterDistance ( ) ;
2017-09-28 17:10:41 +02:00
SetTitleLabelMaxWidth ( ) ;
2013-06-24 13:41:48 +02:00
}
private void SetSplitterDistance ( )
{
//CA-71697: chosen min size so the tab contents are visible
2016-09-17 02:23:55 +02:00
int chosenPanel2MinSize = MinimumSize . Width * 3 / 5 ;
2013-06-24 13:41:48 +02:00
int min = splitContainer1 . Panel1MinSize ;
int max = splitContainer1 . Width - chosenPanel2MinSize ;
if ( max < min )
return ;
splitContainer1 . Panel2MinSize = chosenPanel2MinSize ;
if ( splitContainer1 . SplitterDistance < min )
splitContainer1 . SplitterDistance = min ;
else if ( splitContainer1 . SplitterDistance > max )
splitContainer1 . SplitterDistance = max ;
}
2017-02-27 19:00:46 +01:00
private void MainWindow_ResizeEnd ( object sender , EventArgs e )
{
2017-03-03 18:29:19 +01:00
TabPage t = TheTabControl . SelectedTab ;
if ( t = = TabPageConsole )
{
if ( mainWindowResized )
ConsolePanel . UpdateRDPResolution ( ) ;
mainWindowResized = false ;
}
2017-02-27 19:00:46 +01:00
}
private void splitContainer1_SplitterMoved ( object sender , SplitterEventArgs e )
{
2017-03-03 18:29:19 +01:00
TabPage t = TheTabControl . SelectedTab ;
if ( t = = TabPageConsole )
ConsolePanel . UpdateRDPResolution ( ) ;
2017-09-28 17:10:41 +02:00
SetTitleLabelMaxWidth ( ) ;
2017-02-27 19:00:46 +01:00
}
2020-03-24 03:07:15 +01:00
2023-07-22 17:43:02 +02:00
private void statusButtonAlerts_Click ( object sender , EventArgs e )
2020-03-24 03:07:15 +01:00
{
navigationPane . SwitchToNotificationsView ( NotificationsSubMode . Alerts ) ;
}
2023-07-22 17:43:02 +02:00
private void statusButtonUpdates_Click ( object sender , EventArgs e )
2023-05-11 17:34:21 +02:00
{
navigationPane . SwitchToNotificationsView ( NotificationsSubMode . Updates ) ;
}
2023-07-22 17:43:02 +02:00
private void statusButtonCdnUpdates_Click ( object sender , EventArgs e )
{
navigationPane . SwitchToNotificationsView ( NotificationsSubMode . UpdatesFromCdn ) ;
}
private void statusButtonErrors_Click ( object sender , EventArgs e )
{
navigationPane . SwitchToNotificationsView ( NotificationsSubMode . Events ) ;
}
private void statusButtonProgress_ButtonClick ( object sender , EventArgs e )
2020-03-24 03:07:15 +01:00
{
navigationPane . SwitchToNotificationsView ( NotificationsSubMode . Events ) ;
}
2022-01-07 16:49:18 +01:00
2022-05-11 10:39:02 +02:00
private void relNotesToolStripMenuItem_Click ( object sender , EventArgs e )
2022-01-18 14:33:21 +01:00
{
2022-05-11 10:39:02 +02:00
if ( updateAlert ! = null )
Program . OpenURL ( updateAlert . WebPageLabel ) ;
2022-01-18 14:33:21 +01:00
}
private void downloadInstallToolStripMenuItem_Click ( object sender , EventArgs e )
{
2022-02-01 14:42:11 +01:00
ClientUpdateAlert . DownloadAndInstallNewClient ( updateAlert , this ) ;
2022-01-07 16:49:18 +01:00
}
2022-06-08 16:17:06 +02:00
private void toolStripMenuItemCfu_Click ( object sender , EventArgs e )
{
2023-05-11 22:17:57 +02:00
Updates . CheckForClientUpdates ( true ) ;
2022-06-08 16:17:06 +02:00
}
2023-07-22 16:52:32 +02:00
private void configureUpdatesToolStripMenuItem_Click ( object sender , EventArgs e )
{
using ( var dialog = new ConfigUpdatesDialog ( ) )
dialog . ShowDialog ( this ) ;
}
2013-06-24 13:41:48 +02:00
}
}