diff --git a/XenAdmin/Controls/ConsolePanel.cs b/XenAdmin/Controls/ConsolePanel.cs index 61740f259..5e72d95ee 100644 --- a/XenAdmin/Controls/ConsolePanel.cs +++ b/XenAdmin/Controls/ConsolePanel.cs @@ -47,7 +47,7 @@ namespace XenAdmin.Controls public VNCView activeVNCView; private Dictionary vncViews = new Dictionary(); - private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + protected static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public ConsolePanel() { @@ -153,7 +153,7 @@ namespace XenAdmin.Controls ClearErrorMessage(); } - internal void setCurrentSource(Host source) + internal virtual void setCurrentSource(Host source) { if (source == null) { @@ -264,7 +264,7 @@ namespace XenAdmin.Controls closeVNCForSource(source); } - private void SetErrorMessage(string message) + protected void SetErrorMessage(string message) { errorLabel.Text = message; tableLayoutPanelError.Visible = true; @@ -356,4 +356,26 @@ namespace XenAdmin.Controls #endregion } + + internal class CvmConsolePanel : ConsolePanel + { + internal override void setCurrentSource(Host source) + { + if (source == null) + { + log.Error("No local copy of host information when connecting to host VNC console."); + SetErrorMessage(Messages.VNC_COULD_NOT_CONNECT_CONSOLE); + return; + } + + VM cvm = source.OtherControlDomains.FirstOrDefault(); + if (cvm == null) + { + log.Error("Could not find CVM console on host."); + SetErrorMessage(Messages.VNC_COULD_NOT_FIND_CONSOLES); + } + else + setCurrentSource(cvm); + } + } } diff --git a/XenAdmin/Controls/MultipleDvdIsoList.cs b/XenAdmin/Controls/MultipleDvdIsoList.cs index 40b94bec6..1cee71e50 100644 --- a/XenAdmin/Controls/MultipleDvdIsoList.cs +++ b/XenAdmin/Controls/MultipleDvdIsoList.cs @@ -32,8 +32,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Drawing; -using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; @@ -113,7 +111,7 @@ namespace XenAdmin.Controls } comboBoxDrive.Items.Clear(); - if (VM != null) + if (VM != null && !VM.is_control_domain) { List vbds = VM.Connection.ResolveAll(VM.VBDs); if (vbds == null) diff --git a/XenAdmin/MainWindow.Designer.cs b/XenAdmin/MainWindow.Designer.cs index 321bf8050..593e6e97b 100644 --- a/XenAdmin/MainWindow.Designer.cs +++ b/XenAdmin/MainWindow.Designer.cs @@ -83,6 +83,7 @@ namespace XenAdmin this.TabPageWLB = new System.Windows.Forms.TabPage(); this.TabPageWLBUpsell = new System.Windows.Forms.TabPage(); this.TabPageAD = new System.Windows.Forms.TabPage(); + this.TabPageADUpsell = new System.Windows.Forms.TabPage(); this.TabPageGPU = new System.Windows.Forms.TabPage(); this.TabPageSearch = new System.Windows.Forms.TabPage(); this.TabPageDockerProcess = new System.Windows.Forms.TabPage(); @@ -280,7 +281,7 @@ namespace XenAdmin this.StatusStrip = new System.Windows.Forms.StatusStrip(); this.statusLabel = new System.Windows.Forms.ToolStripStatusLabel(); this.statusProgressBar = new System.Windows.Forms.ToolStripProgressBar(); - this.TabPageADUpsell = new System.Windows.Forms.TabPage(); + this.TabPageCvmConsole = new System.Windows.Forms.TabPage(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); @@ -342,6 +343,7 @@ namespace XenAdmin this.TheTabControl.Controls.Add(this.TabPageBallooning); this.TheTabControl.Controls.Add(this.TabPageBallooningUpsell); this.TheTabControl.Controls.Add(this.TabPageConsole); + this.TheTabControl.Controls.Add(this.TabPageCvmConsole); this.TheTabControl.Controls.Add(this.TabPageStorage); this.TheTabControl.Controls.Add(this.TabPagePhysicalStorage); this.TheTabControl.Controls.Add(this.TabPageSR); @@ -471,6 +473,12 @@ namespace XenAdmin this.TabPageAD.Name = "TabPageAD"; this.TabPageAD.UseVisualStyleBackColor = true; // + // TabPageADUpsell + // + resources.ApplyResources(this.TabPageADUpsell, "TabPageADUpsell"); + this.TabPageADUpsell.Name = "TabPageADUpsell"; + this.TabPageADUpsell.UseVisualStyleBackColor = true; + // // TabPageGPU // resources.ApplyResources(this.TabPageGPU, "TabPageGPU"); @@ -1839,11 +1847,11 @@ namespace XenAdmin this.statusProgressBar.Name = "statusProgressBar"; this.statusProgressBar.Overflow = System.Windows.Forms.ToolStripItemOverflow.Never; // - // TabPageADUpsell + // TabPageCvmConsole // - resources.ApplyResources(this.TabPageADUpsell, "TabPageADUpsell"); - this.TabPageADUpsell.Name = "TabPageADUpsell"; - this.TabPageADUpsell.UseVisualStyleBackColor = true; + resources.ApplyResources(this.TabPageCvmConsole, "TabPageCvmConsole"); + this.TabPageCvmConsole.Name = "TabPageCvmConsole"; + this.TabPageCvmConsole.UseVisualStyleBackColor = true; // // MainWindow // @@ -2107,6 +2115,7 @@ namespace XenAdmin private CommandToolStripButton restartContainerToolStripButton; private CommandToolStripMenuItem healthCheckToolStripMenuItem1; private TabPage TabPageADUpsell; + private TabPage TabPageCvmConsole; } } diff --git a/XenAdmin/MainWindow.cs b/XenAdmin/MainWindow.cs index fb500e8c6..f40317388 100644 --- a/XenAdmin/MainWindow.cs +++ b/XenAdmin/MainWindow.cs @@ -85,6 +85,7 @@ namespace XenAdmin internal readonly BallooningPage BallooningPage = new BallooningPage(); internal readonly BallooningUpsellPage BallooningUpsellPage = new BallooningUpsellPage(); internal readonly ConsolePanel ConsolePanel = new ConsolePanel(); + internal readonly CvmConsolePanel CvmConsolePanel = new CvmConsolePanel(); internal readonly HAPage HAPage = new HAPage(); internal readonly HAUpsellPage HAUpsellPage = new HAUpsellPage(); internal readonly HomePage HomePage = new HomePage(); @@ -153,6 +154,7 @@ namespace XenAdmin components.Add(GeneralPage); components.Add(BallooningPage); components.Add(ConsolePanel); + components.Add(CvmConsolePanel); components.Add(NetworkPage); components.Add(HAPage); components.Add(HomePage); @@ -171,6 +173,7 @@ namespace XenAdmin AddTabContents(BallooningPage, TabPageBallooning); AddTabContents(BallooningUpsellPage, TabPageBallooningUpsell); AddTabContents(ConsolePanel, TabPageConsole); + AddTabContents(CvmConsolePanel, TabPageCvmConsole); AddTabContents(NetworkPage, TabPageNetwork); AddTabContents(HAPage, TabPageHA); AddTabContents(HAUpsellPage, TabPageHAUpsell); @@ -246,8 +249,8 @@ namespace XenAdmin if (SelectionManager.Selection.FirstIsRealVM) ConsolePanel.setCurrentSource((VM)SelectionManager.Selection.First); - else if (SelectionManager.Selection.FirstIsHost) - ConsolePanel.setCurrentSource((Host)SelectionManager.Selection.First); + else if (SelectionManager.Selection.FirstIsHost) + ConsolePanel.setCurrentSource((Host)SelectionManager.Selection.First); UnpauseVNC(sender == TheTabControl); } @@ -765,12 +768,17 @@ namespace XenAdmin foreach (VM vm in connection.Cache.VMs) { - this.ConsolePanel.closeVNCForSource(vm); + ConsolePanel.closeVNCForSource(vm); } foreach (Host host in connection.Cache.Hosts) + { ConsolePanel.closeVNCForSource(host.ControlDomainZero); + foreach (VM vm in host.OtherControlDomains) + CvmConsolePanel.closeVNCForSource(vm); + } + connection.EndConnect(); RequestRefreshTreeView(); @@ -1372,6 +1380,7 @@ namespace XenAdmin bool isTemplateSelected = SelectionManager.Selection.FirstIsTemplate; bool isHostLive = SelectionManager.Selection.FirstIsLiveHost; bool isDockerContainerSelected = SelectionManager.Selection.First is DockerContainer; + bool hasManyControlDomains = isHostSelected && ((Host)SelectionManager.Selection.First).HasManyControlDomains; bool selectedTemplateHasProvisionXML = SelectionManager.Selection.FirstIsTemplate && ((VM)SelectionManager.Selection[0].XenObject).HasProvisionXML; @@ -1401,6 +1410,7 @@ namespace XenAdmin } ShowTab(TabPageConsole, !shownConsoleReplacement && !multi && !SearchMode && (isRealVMSelected || (isHostSelected && isHostLive))); + ShowTab(TabPageCvmConsole, !shownConsoleReplacement && !multi && !SearchMode && isHostLive && hasManyControlDomains); ShowTab(TabPagePeformance, !multi && !SearchMode && (isRealVMSelected || (isHostSelected && isHostLive))); ShowTab(ha_upsell ? TabPageHAUpsell : TabPageHA, !multi && !SearchMode && isPoolSelected); ShowTab(TabPageSnapshots, !multi && !SearchMode && isRealVMSelected); @@ -1766,13 +1776,23 @@ namespace XenAdmin UnpauseVNC(e != null && sender == TheTabControl); } } + else if (t == TabPageCvmConsole) + { + if (SelectionManager.Selection.FirstIsHost) + { + CvmConsolePanel.setCurrentSource((Host)SelectionManager.Selection.First); + UnpauseVNC(e != null && sender == TheTabControl); + } + } else { - ConsolePanel.PauseAllViews(); + ConsolePanel.PauseAllViews(); + CvmConsolePanel.PauseAllViews(); // Start timer for closing the VNC connection after an interval (20 seconds) // when the console tab is not selected ConsolePanel.StartCloseVNCTimer(ConsolePanel.activeVNCView); + CvmConsolePanel.StartCloseVNCTimer(CvmConsolePanel.activeVNCView); if (t == TabPageGeneral) { @@ -1965,10 +1985,14 @@ namespace XenAdmin private void UnpauseVNC(bool focus) { ConsolePanel.UnpauseActiveView(); + CvmConsolePanel.UnpauseActiveView(); + if (focus) { ConsolePanel.FocusActiveView(); + CvmConsolePanel.FocusActiveView(); ConsolePanel.SwitchIfRequired(); + CvmConsolePanel.SwitchIfRequired(); } } @@ -1977,7 +2001,7 @@ namespace XenAdmin /// public enum Tab { - Overview, Home, Settings, Storage, Network, Console, Performance, NICs, SR, DockerProcess, DockerDetails + Overview, Home, Settings, Storage, Network, Console, CvmConsole, Performance, NICs, SR, DockerProcess, DockerDetails } public void SwitchToTab(Tab tab) @@ -2002,6 +2026,9 @@ namespace XenAdmin case Tab.Console: TheTabControl.SelectedTab = TabPageConsole; break; + case Tab.CvmConsole: + TheTabControl.SelectedTab = TabPageCvmConsole; + break; case Tab.Performance: TheTabControl.SelectedTab = TabPagePeformance; break; @@ -2366,6 +2393,8 @@ namespace XenAdmin return "TabPageSearch" + modelObj; if (TheTabControl.SelectedTab == TabPageConsole) return "TabPageConsole" + modelObj; + if (TheTabControl.SelectedTab == TabPageCvmConsole) + return "TabPageCvmConsole" + modelObj; if (TheTabControl.SelectedTab == TabPageGeneral) return "TabPageSettings" + modelObj; if (TheTabControl.SelectedTab == TabPagePhysicalStorage || TheTabControl.SelectedTab == TabPageStorage || TheTabControl.SelectedTab == TabPageSR) diff --git a/XenAdmin/MainWindow.resx b/XenAdmin/MainWindow.resx index b981e1cf4..4bdedf499 100644 --- a/XenAdmin/MainWindow.resx +++ b/XenAdmin/MainWindow.resx @@ -318,6 +318,30 @@ 4 + + 4, 22 + + + 753, 592 + + + 22 + + + CVM Console + + + TabPageCvmConsole + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + TheTabControl + + + 5 + Fill @@ -349,7 +373,7 @@ TheTabControl - 5 + 6 4, 22 @@ -376,7 +400,7 @@ TheTabControl - 6 + 7 Top, Bottom, Left, Right @@ -406,7 +430,7 @@ TheTabControl - 7 + 8 Fill @@ -436,7 +460,7 @@ TheTabControl - 8 + 9 Fill @@ -469,7 +493,7 @@ TheTabControl - 9 + 10 Fill @@ -499,7 +523,7 @@ TheTabControl - 10 + 11 4, 22 @@ -526,7 +550,7 @@ TheTabControl - 11 + 12 4, 22 @@ -553,7 +577,7 @@ TheTabControl - 12 + 13 True @@ -610,7 +634,7 @@ TheTabControl - 13 + 14 4, 22 @@ -634,7 +658,7 @@ TheTabControl - 14 + 15 4, 22 @@ -658,7 +682,7 @@ TheTabControl - 15 + 16 4, 22 @@ -682,7 +706,7 @@ TheTabControl - 16 + 17 4, 22 @@ -709,7 +733,7 @@ TheTabControl - 17 + 18 4, 22 @@ -733,7 +757,7 @@ TheTabControl - 18 + 19 Fill @@ -763,7 +787,7 @@ TheTabControl - 19 + 20 4, 22 @@ -793,7 +817,7 @@ TheTabControl - 20 + 21 Fill @@ -823,7 +847,7 @@ TheTabControl - 21 + 22 Verdana, 8.25pt @@ -1985,23 +2009,22 @@ - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK8gAA - CvIBPVL3EQAAAzRJREFUOE9tk21Mk1cYht9/BeGPYguzfsTFTzrnKAjO+bmZzLC5kCnQAHZKRVZGhcpa - EKGroWNStg4N1q0aSIYISjMx1BXCyhSDCmPpn20uuswumfHHEteK8SuGy/O+iwld9uM+yck59/PkPPd1 - JCBOw8PD6sHBQUcgELja39//zO/3P+vp6bna1dXl6OjoUP/3ftxGmG3fDV3EN+Ll01EHNVfMfHTZxIFg - BY3+Ory+47S3t9tmemaavX2hs7jGDmEbs1D6fSFVo/swXzKSG9jMjuDb7Ox/h8YT9bjdbm9cAWF2nxk5 - Tf21aiou72HnYC7bL77Fg6dTTAlln1uB7sxC1vals86/GkubGafT6VYKCLM2MDRA/ZiVvSPFlP1Qwm/3 - fiFfFJl6el/RpvN6wn9PsubsSlZ2LuCNzgzsjTbsdrtWEgNzHQt5sIyaRNc3uXHvZ6XrlvNZ3PjjV0Xp - 3VpiT2L8ePc6aW1J5JxcRX5zHlar1SWJaYdrQ1W8L97YMFZDLBbj49EKlp1OFaYo0cdRNCcSMQ0UKWcf - 9BWyuEXDZvfrVFZWhiUR1ZPSkIGN32bgnTjK75FbLO3SML8zWTHLUrcloGlN4tbtmxwJNpHqSCbnyGuU - l5dHJZFztCSYR9a55bRPePjzToR5HclovkpEfSwB9RcJzP1MFGiaReSvCK3BZtS2JLKbXsVkMk1JApJw - yYUd6HuXiMh2Mz09TdnQLqXr3NYEUpqFnCpMvcXKWek3xSy0q1lfn43RaAxLgjDX/p4PlXhe+jqZn+5O - EH0UxTxQSkqTijkOFWW9RqIP/2EyMk6KJZFMh45tlVspKipySQJP7VFfGxu6M1nu06L3rWDyzoTSbaYm - b4+zumEZL1fPI6tuFYUlBRQUFGgVkASe7gPHq5R40r9chMY5i93dBjwhN57hFoynDMwxJ7LUOh99bTrb - Tbmy+V+Q5EWWjGd1i4VNnhyyPn+FxQ1pzK5SMbtCxaLqVPQHdaytyeC9Pe/K5niUX0jgaatrqCXfkccW - xzoyP9GReUjH+ppstpm3Yig2yOb//0wvJPBME4QdFpCMi5zlqORpj4uBHRbmtPj7SM8BGG2BcDWQi8oA - AAAASUVORK5CYII= + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 + JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAryAAAK8gE9UvcRAAADNElE + QVQ4T22TbUyTVxiG338F4Y9iC7N+xMVPOucoCM75uZnMsLmQKdAAdkpFVkaFyloQoauhY1K2Dg3WrRpI + hghKMzHUFcLKFIMKY+mfbS66zC6Z8ccS14rxK4bL876LCV324z7JyTn38+Q893UkIE7Dw8PqwcFBRyAQ + uNrf3//M7/c/6+npudrV1eXo6OhQ//d+3EaYbd8NXcQ34uXTUQc1V8x8dNnEgWAFjf46vL7jtLe322Z6 + Zpq9faGzuMYOYRuzUPp9IVWj+zBfMpIb2MyO4Nvs7H+HxhP1uN1ub1wBYXafGTlN/bVqKi7vYedgLtsv + vsWDp1NMCWWfW4HuzELW9qWzzr8aS5sZp9PpVgoIszYwNED9mJW9I8WU/VDCb/d+IV8UmXp6X9Gm83rC + f0+y5uxKVnYu4I3ODOyNNux2u1YSA3MdC3mwjJpE1ze5ce9npeuW81nc+ONXRendWmJPYvx49zppbUnk + nFxFfnMeVqvVJYlph2tDVbwv3tgwVkMsFuPj0QqWnU4VpijRx1E0JxIxDRQpZx/0FbK4RcNm9+tUVlaG + JRHVk9KQgY3fZuCdOMrvkVss7dIwvzNZMctStyWgaU3i1u2bHAk2kepIJufIa5SXl0clkXO0JJhH1rnl + tE94+PNOhHkdyWi+SkR9LAH1FwnM/UwUaJpF5K8IrcFm1LYksptexWQyTUkCknDJhR3oe5eIyHYzPT1N + 2dAupevc1gRSmoWcKky9xcpZ6TfFLLSrWV+fjdFoDEuCMNf+ng+VeF76Opmf7k4QfRTFPFBKSpOKOQ4V + Zb1Gog//YTIyToolkUyHjm2VWykqKnJJAk/tUV8bG7ozWe7TovetYPLOhNJtpiZvj7O6YRkvV88jq24V + hSUFFBQUaBWQBJ7uA8erlHjSv1yExjmL3d0GPCE3nuEWjKcMzDEnstQ6H31tOttNubL5X5DkRZaMZ3WL + hU2eHLI+f4XFDWnMrlIxu0LFoupU9Ad1rK3J4L0978rmeJRfSOBpq2uoJd+RxxbHOjI/0ZF5SMf6mmy2 + mbdiKDbI5v//TC8k8EwThB0WkIyLnOWo5GmPi4EdFua0+PtIzwEYbYFwNZCLygAAAABJRU5ErkJggg== @@ -2015,22 +2038,21 @@ - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK8gAA - CvIBPVL3EQAAAvVJREFUOE9tU1tIk2EY/kW9VcRTsgvTi6TEC01E0As1ETQUCZ06dCBTJjoJL6YiJAvF - cEwUnWJkUlqZMkg8lGkWUcxTOtM5T/N0Y1fhpiEdlk/P/4fgoovnP7zv83zv973v8wkA3DA1NRU4MTFR - PzY2Zh4eHnaZTCbXwMCAub+/v763tzfwX77bD8XayfFxLHR0wFZXhz2VCjtFRbCUluKNVouezk4YjUbt - Rc1FcdeH589hr6nBflkZ7NnZ2Csuxk5BAWzx8dhMSsJSWhoe1dZCr9d3uS1Asd7c14eDigrsFhZi48YN - rCcm4vfJCVzHx1i5fBnLQUFYCQ/HakQEetRq6HQ6vbQAxbKp0VHsVlbCnpMDu1yOU6sVm6mpktjldMIa - GYlv8/NYDgvDTGAg3l+7Bh2PVF1dLRPYsMYFgwF7POt6QgJOV1cloTUqCgc2Gw7W1rDs7w+XwwGn2YxJ - T09MX7mC7sxMVFVVNQrstmWtvBwbycnYvX0bTla0s2lLvr74dXQk4SNPasnNlXLmW7dgYq4/NhYajcYi - cFQ/thi0clvbLS042N7Gko8PPrGSKP5JvOYCo/zf39rCrE6Hx97eeEK+Wq12CJyzYz0jAyuhodjR6/Fl - fx8LJItVp4mXxAtiiLFD5mYaGtDt5YWHV69CpVKdCDSJZTErC59lMuwoFDg7O4MtLw+TFI0RJuIZ8Y4x - MfeK704eoTU6Gkql0iLQYY2TJSXSeMys4pidlba9yKYOUdgnirnwd8a+MGcgp5tNrGPPFApFo0B7ynrb - 2jDLUb0LCMBbjuoriWK1izhkrJu5FnJauX0lxy2Xy2WSkWhP/SONRhrPSEgInrLKW3piqakJC8QIv+8x - ZggORhs55enpovivkcSHCNGe7XTiYEwMBkl64OeHVg8PNBMGfrcz1kxvlN28KYrdrXwO2lN7h3fBwKYa - 4+JwnyIj0XT9OrQpKSjMzxfF/79M56A9L9Fhd2mSOc5ZHJXY7Tk27C7Fl9z5EP4AZymF8JGogOsAAAAA - SUVORK5CYII= + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 + JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAryAAAK8gE9UvcRAAAC9UlE + QVQ4T21TW0iTYRj+Rb1VxFOyC9OLpMQLTUTQCzURNBQJnTp0IFMmOgkvpiIkC8VwTBSdYmRSWpkySDyU + aRZRzFM60zlP83RjV+GmIR2WT8//h+Cii+c/vO/zfO/3ve/zCQDcMDU1FTgxMVE/NjZmHh4edplMJtfA + wIC5v7+/vre3N/BfvtsPxdrJ8XEsdHTAVleHPZUKO0VFsJSW4o1Wi57OThiNRu1FzUVx14fnz2GvqcF+ + WRns2dnYKy7GTkEBbPHx2ExKwlJaGh7V1kKv13e5LUCx3tzXh4OKCuwWFmLjxg2sJybi98kJXMfHWLl8 + GctBQVgJD8dqRAR61GrodDq9tADFsqnRUexWVsKekwO7XI5TqxWbqamS2OV0whoZiW/z81gOC8NMYCDe + X7sGHY9UXV0tE9iwxgWDAXs863pCAk5XVyWhNSoKBzYbDtbWsOzvD5fDAafZjElPT0xfuYLuzExUVVU1 + Cuy2Za28HBvJydi9fRtOVrSzaUu+vvh1dCThI09qyc2VcuZbt2Birj82FhqNxiJwVD+2GLRyW9stLTjY + 3saSjw8+sZIo/km85gKj/N/f2sKsTofH3t54Qr5arXYInLNjPSMDK6Gh2NHr8WV/Hwski1WniZfEC2KI + sUPmZhoa0O3lhYdXr0KlUp0INIllMSsLn2Uy7CgUODs7gy0vD5MUjREm4hnxjjEx94rvTh6hNToaSqXS + ItBhjZMlJdJ4zKzimJ2Vtr3Ipg5R2CeKufB3xr4wZyCnm02sY88UCkWjQHvKetvaMMtRvQsIwFuO6iuJ + YrWLOGSsm7kWclq5fSXHLZfLZZKRaE/9I41GGs9ISAiesspbemKpqQkLxAi/7zFmCA5GGznl6emi+K+R + xIcI0Z7tdOJgTAwGSXrg54dWDw80EwZ+tzPWTG+U3bwpit2tfA7aU3uHd8HAphrj4nCfIiPRdP06tCkp + KMzPF8X/v0znoD0v0WF3aZI5zlkcldjtOTbsLsWX3PkQ/gBnKYXwkaiA6wAAAABJRU5ErkJggg== diff --git a/XenModel/XenAPI-Extensions/Host.cs b/XenModel/XenAPI-Extensions/Host.cs index c365c8439..2b2e669b3 100644 --- a/XenModel/XenAPI-Extensions/Host.cs +++ b/XenModel/XenAPI-Extensions/Host.cs @@ -1053,6 +1053,34 @@ namespace XenAPI } } + public bool HasManyControlDomains + { + get + { + if (Connection == null) + return false; + + var vms = Connection.ResolveAll(resident_VMs); + return vms.FindAll(v => v.is_control_domain).Count > 1; + } + } + + public IEnumerable OtherControlDomains + { + get + { + if (Connection == null) + return null; + + var vms = Connection.ResolveAll(resident_VMs); + + if (Helpers.DundeePlusOrGreater(Connection)) + return vms.Where(v => v.is_control_domain && v.opaque_ref != control_domain); + + return vms.Where(v => v.is_control_domain && v.domid != 0); + } + } + /// /// Interpret a value from the software_version dictionary as a int, or 0 if we couldn't parse it. ///