/* Copyright (c) Citrix Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ using System; using System.Collections.Generic; using XenAPI; using System.Windows.Forms; using XenAdmin.Model; using XenAdmin.Core; using System.Reflection; using System.Diagnostics; using System.Collections.ObjectModel; using System.Drawing; using System.Linq; using XenAdmin.Dialogs; using XenAdmin.Plugins; namespace XenAdmin.Commands { /// /// A class for building up the context menu for XenObjects. /// internal class ContextMenuBuilder { private readonly PluginManager _pluginManager; private readonly IMainWindow _mainWindow; private static readonly ReadOnlyCollection Builders; static ContextMenuBuilder() { List list = new List(); foreach (Type type in Assembly.GetCallingAssembly().GetTypes()) { if (typeof(Builder).IsAssignableFrom(type) && !type.IsAbstract) { try { list.Add((Builder)Activator.CreateInstance(type)); } catch (MissingMethodException) { } } } Builders = new ReadOnlyCollection(list); } /// /// Initializes a new instance of the class. /// /// The plugin manager. This can be found on MainWindow. /// The main window command interface. This can be found on mainwindow. public ContextMenuBuilder(PluginManager pluginManager, IMainWindow mainWindow) { Util.ThrowIfParameterNull(pluginManager, "pluginManager"); Util.ThrowIfParameterNull(pluginManager, "mainWindow"); _pluginManager = pluginManager; _mainWindow = mainWindow; } /// /// Shows the context menu for the specified xen object at the current mouse location. /// /// The xen object for which the context menu is required. public void Show(IXenObject xenObject) { Show(xenObject, Form.MousePosition); } /// /// Shows the context menu for the specified xen object at the specified location. /// /// The xen object for which the context menu is required. /// The location of the context menu. public void Show(IXenObject xenObject, Point point) { ContextMenuStrip menu = new ContextMenuStrip(); menu.Items.AddRange(Build(xenObject)); menu.Show(point); } /// /// Builds the context menu for the specified XenObject. /// /// The xen object for which the context menu items are required. /// The context menu items. public ToolStripItem[] Build(IXenObject xenObject) { return Build(new SelectedItem(xenObject)); } /// /// Builds the context menu for the specified selection. /// /// The selection for which the context menu items are required. /// The context menu items. public ToolStripItem[] Build(SelectedItem selection) { return Build(new SelectedItem[] { selection }); } /// /// Builds the context menu for the specified selection. /// /// The selection for which the context menu items are required. /// The context menu items. public ToolStripItem[] Build(IEnumerable selection) { Util.ThrowIfParameterNull(selection, "selection"); foreach (Builder builder in Builders) { SelectedItemCollection selectionList = new SelectedItemCollection(selection); if (builder.IsValid(selectionList)) { ContextMenuItemCollection items = new ContextMenuItemCollection(_mainWindow, _pluginManager); builder.Build(_mainWindow, selectionList, items); CheckAccessKeys(items); items.RemoveInvalidSeparators(); return items.ToArray(); } } return new ToolStripItem[0]; } [Conditional("DEBUG")] private void CheckAccessKeys(ContextMenuItemCollection items) { var usedKeys = new Dictionary>(); foreach (ToolStripItem item in items) { string text = item.Text.Replace("&&", ""); int index = text.IndexOf("&"); if (index >= 0) { string c = text[index + 1].ToString().ToLower(); if (usedKeys.ContainsKey(c)) usedKeys[c].Add(text); else usedKeys[c] = new List { text }; } } if (usedKeys.Any(kvp => kvp.Value.Count > 1)) Debug.Fail("Found duplicate access key. Here are the used ones:\n" + string.Join("\n", usedKeys.Select(kvp => $"{kvp.Key} => {string.Join(", ", kvp.Value)}"))); } private abstract class Builder { public abstract void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items); public abstract bool IsValid(SelectedItemCollection selection); } #region MixedPoolsAndStandaloneHosts class private class MixedPoolsAndStandaloneHosts : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new DisconnectHostsAndPoolsCommand(mainWindow, selection), true); items.AddIfEnabled(new ReconnectHostCommand(mainWindow, selection), true); items.AddIfEnabled(new EditTagsCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { bool containsPool = false; bool containsHost = false; if (selection.Count > 1) { foreach (SelectedItem item in selection) { Pool pool = item.XenObject as Pool; Host host = item.XenObject as Host; if (pool != null) { containsPool = true; } else if (host != null && item.PoolAncestor == null) { containsHost = true; } else { return false; } } } return containsPool && containsHost; } } #endregion #region MultiplePools class private class MultiplePools : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new DisconnectPoolCommand(mainWindow, selection), true); items.AddIfEnabled(new EditTagsCommand(mainWindow, selection)); items.AddPluginItems(PluginContextMenu.pool, selection); } public override bool IsValid(SelectedItemCollection selection) { if (selection.Count > 1) { foreach (SelectedItem item in selection) { Pool pool = item.XenObject as Pool; if (pool == null) { return false; } } return true; } return false; } } #endregion #region MultipleDifferentTypes private class MultipleDifferentXenObjectTypes : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new EditTagsCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { List types = new List(); if (selection.AllItemsAre()) { foreach (SelectedItem item in selection) { string name = item.XenObject.GetType().Name; VM vm = item.XenObject as VM; if (vm != null && vm.is_a_template) { name = vm.is_a_snapshot ? "snapshot" : "template"; } if (!types.Contains(name)) { types.Add(name); } } } if (types.Count > 1) { // if types only contains a mix of vms and templates then don't use this Builder. MixedVMsAndTemplates should be used instead. types.Remove("VM"); types.Remove("template"); return types.Count > 0; } return false; } } #endregion #region MultipleSRs private class MultipleSRs : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new RepairSRCommand(mainWindow, selection)); items.AddIfEnabled(new DetachSRCommand(mainWindow, selection)); items.AddIfEnabled(new ForgetSRCommand(mainWindow, selection)); items.AddIfEnabled(new DestroySRCommand(mainWindow, selection)); items.AddIfEnabled(new EditTagsCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { return selection.Count > 1 && selection.AllItemsAre(); } } #endregion #region SingleVDI private class SingleVDI : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.Add(MoveVirtualDiskDialog.MoveMigrateCommand(mainWindow, selection)); // Default behaviour of this command is very conservative, they wont be able to delete if there are multi vbds, // or if any of the vbds are plugged on top of the other constraints. items.Add(new DeleteVirtualDiskCommand(mainWindow, selection)); items.AddSeparator(); items.Add(new PropertiesCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { return selection.Count == 1 && selection[0].XenObject is VDI; } } #endregion #region MultipleVDI private class MultipleVDI : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.Add(MoveVirtualDiskDialog.MoveMigrateCommand(mainWindow, selection)); // Default behaviour of this command is very conservative, they wont be able to delete if there are multi vbds, // or if any of the vbds are plugged on top of the other constraints. items.Add(new DeleteVirtualDiskCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { return selection.AllItemsAre(); } } #endregion #region SingleNetwork private class SingleNetwork : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.Add(new PropertiesCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { return selection.ContainsOneItemOfType() && !(selection.FirstAsXenObject as XenAPI.Network).IsGuestInstallerNetwork(); // CA-218956 - Expose HIMN when showing hidden objects // HIMN should not be editable } } #endregion #region DisconnectedHosts private class DisconnectedHosts : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { List inProgressItems = new List(); foreach (SelectedItem item in selection) { if (item.Connection != null && !item.Connection.IsConnected && item.Connection.InProgress) { inProgressItems.Add(item); } } if (inProgressItems.Count > 0) { items.Add(new CancelHostConnectionCommand(mainWindow, inProgressItems)); } else { items.AddIfEnabled(new DisconnectHostsAndPoolsCommand(mainWindow, selection), true); items.Add(new ReconnectHostCommand(mainWindow, selection), true); items.Add(new ForgetSavedPasswordCommand(mainWindow, selection)); items.Add(new RemoveHostCommand(mainWindow, selection)); items.AddIfEnabled(new RestartToolstackCommand(mainWindow, selection)); } } public override bool IsValid(SelectedItemCollection selection) { foreach (SelectedItem item in selection) { if (item.Connection != null && !item.Connection.IsConnected) { return true; } } return false; } } #endregion #region MixedVMsSnapshotsTemplates class private class MixedVMsAndTemplates : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new DeleteVMsAndTemplatesCommand(mainWindow, selection)); items.AddIfEnabled(new EditTagsCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { if (selection.Count > 1) { bool vmFound = false, templateFound = false; foreach (SelectedItem item in selection) { VM vm = item.XenObject as VM; if (vm != null) { if (vm.is_a_template && !vm.is_a_snapshot) { templateFound = true; } else { vmFound = true; } } else { return false; } } return vmFound && templateFound; } return false; } } #endregion #region MultipleAliveHosts class private class MultipleAliveHosts : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new AddSelectedHostToPoolToolStripMenuItem(mainWindow, selection, true)); items.AddIfEnabled(new DisconnectHostCommand(mainWindow, selection)); items.AddIfEnabled(new RebootHostCommand(mainWindow, selection)); items.AddIfEnabled(new ShutDownHostCommand(mainWindow, selection)); items.AddIfEnabled(new RestartToolstackCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new EditTagsCommand(mainWindow, selection)); items.AddSeparator(); items.AddPluginItems(PluginContextMenu.server, selection); items.AddSeparator(); } public override bool IsValid(SelectedItemCollection selection) { if (selection.Count > 1) { foreach (SelectedItem item in selection) { Host host = item.XenObject as Host; if (host == null || !host.IsLive()) { return false; } } return true; } return false; } } #endregion #region SingleAliveHostInPool class private class SingleAliveHostInPool : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { Host host = (Host)selection[0].XenObject; items.AddIfEnabled(new NewVMCommand(mainWindow, selection)); items.AddIfEnabled(new NewSRCommand(mainWindow, selection)); items.AddIfEnabled(new ImportCommand(mainWindow, selection)); items.AddSeparator(); var certItem = new CommandToolStripMenuItem(new CertificateCommand(mainWindow, selection), true); if (certItem.Command.CanExecute()) { certItem.DropDownItems.Add(new CommandToolStripMenuItem(new InstallCertificateCommand(mainWindow, selection), true)); certItem.DropDownItems.Add(new CommandToolStripMenuItem(new ResetCertificateCommand(mainWindow, selection), true)); items.Add(certItem); } items.AddIfEnabled(new HostMaintenanceModeCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new RebootHostCommand(mainWindow, selection)); items.AddIfEnabled(new ShutDownHostCommand(mainWindow, selection)); items.AddIfEnabled(new RestartToolstackCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new RemoveHostCrashDumpsCommand(mainWindow, selection)); var cmd = new RemoveHostFromPoolCommand(mainWindow, selection); if (cmd.CanExecute()) { items.AddSeparator(); items.Add(cmd); } items.AddPluginItems(PluginContextMenu.server, selection); items.AddSeparator(); items.AddIfEnabled(new HostPropertiesCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { if (selection.Count == 1 && selection[0].PoolAncestor != null) { Host host = selection[0].XenObject as Host; return host != null && host.IsLive(); } return false; } } #endregion #region SingleAliveStandaloneHost class private class SingleAliveStandaloneHost : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { Host host = (Host)selection[0].XenObject; items.AddIfEnabled(new NewVMCommand(mainWindow, selection)); items.AddIfEnabled(new NewSRCommand(mainWindow, selection)); items.AddIfEnabled(new ImportCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new AddSelectedHostToPoolToolStripMenuItem(mainWindow, selection, true)); items.AddSeparator(); var certItem = new CommandToolStripMenuItem(new CertificateCommand(mainWindow, selection), true); if (certItem.Command.CanExecute()) { certItem.DropDownItems.Add(new CommandToolStripMenuItem(new InstallCertificateCommand(mainWindow, selection), true)); certItem.DropDownItems.Add(new CommandToolStripMenuItem(new ResetCertificateCommand(mainWindow, selection), true)); items.Add(certItem); } items.AddIfEnabled(new HostMaintenanceModeCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new RebootHostCommand(mainWindow, selection)); items.AddIfEnabled(new ShutDownHostCommand(mainWindow, selection)); items.AddIfEnabled(new PowerOnHostCommand(mainWindow, selection)); items.AddIfEnabled(new RestartToolstackCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new RemoveHostCrashDumpsCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new DisconnectHostCommand(mainWindow, selection)); items.AddIfEnabled(new HostReconnectAsCommand(mainWindow, selection)); items.AddPluginItems(PluginContextMenu.server, selection); items.AddSeparator(); items.AddIfEnabled(new HostPropertiesCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { if (selection.Count == 1 && selection[0].PoolAncestor == null) { Host host = selection[0].XenObject as Host; return host != null && host.IsLive(); } return false; } } #endregion #region MultipleHostsSomeDeadSomeAlive class private class MultipleHostsSomeDeadSomeAlive : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new ShutDownHostCommand(mainWindow, selection)); items.AddIfEnabled(new PowerOnHostCommand(mainWindow, selection)); items.AddIfEnabled(new RestartToolstackCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { bool foundAlive = false; bool foundDead = false; foreach (SelectedItem item in selection) { Host host = item.XenObject as Host; if (host == null) { return false; } bool isHostLive = host.IsLive(); foundAlive |= isHostLive; foundDead |= !isHostLive; } return foundAlive && foundDead; } } #endregion #region DeadHosts class private class DeadHosts : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new PowerOnHostCommand(mainWindow, selection)); items.AddIfEnabled(new DestroyHostCommand(mainWindow, selection)); if (selection.Count == 1) { items.AddSeparator(); items.AddIfEnabled(new HostPropertiesCommand(mainWindow, selection)); } } public override bool IsValid(SelectedItemCollection selection) { if (selection.Count > 0) { foreach (SelectedItem item in selection) { Host host = item.XenObject as Host; if (host == null || host.IsLive()) { return false; } } return true; } return false; } } #endregion #region SinglePool class private class SinglePool : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.Add(new NewVMCommand(mainWindow, selection)); items.Add(new NewSRCommand(mainWindow, selection)); items.Add(new ImportCommand(mainWindow, selection)); items.AddSeparator(); var haItem = new CommandToolStripMenuItem(new HACommand(mainWindow, selection), true); if (haItem.Command.CanExecute()) { haItem.DropDownItems.Add(new CommandToolStripMenuItem(new HAConfigureCommand(mainWindow, selection), true)); haItem.DropDownItems.Add(new CommandToolStripMenuItem(new HADisableCommand(mainWindow, selection), true)); items.Add(haItem); } items.AddIfEnabled(new VMGroupCommand(mainWindow, selection)); items.AddIfEnabled(new VMGroupCommand(mainWindow, selection)); var drItem = new CommandToolStripMenuItem(new DRCommand(mainWindow, selection), true); if (drItem.Command.CanExecute()) { drItem.DropDownItems.Add(new CommandToolStripMenuItem( new DRConfigureCommand(mainWindow, selection), true)); drItem.DropDownItems.Add(new CommandToolStripMenuItem(new DisasterRecoveryCommand(mainWindow, selection), true)); items.Add(drItem); } items.AddIfEnabled(new LaunchConversionManagerCommand(mainWindow, selection)); var pool = selection.FirstAsXenObject as Pool; if (pool != null && !pool.IsPoolFullyUpgraded()) items.Add(new RollingUpgradeCommand(mainWindow)); items.AddSeparator(); items.Add(new AddHostToSelectedPoolToolStripMenuItem(mainWindow, selection, true)); items.Add(new DisconnectPoolCommand(mainWindow, selection)); items.Add(new PoolReconnectAsCommand(mainWindow, selection)); items.AddSeparator(); items.AddPluginItems(PluginContextMenu.pool, selection); items.AddSeparator(); items.Add(new PoolPropertiesCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { return selection.ContainsOneItemOfType(); } } #endregion #region SingleSnapshot class private class SingleSnapshot : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new NewVMFromSnapshotCommand(mainWindow, selection)); items.AddIfEnabled(new NewTemplateFromSnapshotCommand(mainWindow, selection)); items.AddIfEnabled(new ExportSnapshotAsTemplateCommand(mainWindow, selection)); items.AddIfEnabled(new DeleteSnapshotCommand(mainWindow, selection)); items.AddPluginItems(PluginContextMenu.vm, selection); items.AddSeparator(); items.AddIfEnabled(new PropertiesCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { if (selection.Count == 1) { VM vm = selection[0].XenObject as VM; return vm != null && vm.is_a_snapshot; } return false; } } #endregion #region SingleTemplate class private class SingleTemplate : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new NewVMFromTemplateCommand(mainWindow, selection), true); items.AddIfEnabled(new InstantVMFromTemplateCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new ExportTemplateCommand(mainWindow, selection)); items.AddIfEnabled(new CopyTemplateCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new DeleteTemplateCommand(mainWindow, selection)); items.AddPluginItems(PluginContextMenu.template, selection); items.AddSeparator(); items.AddIfEnabled(new PropertiesCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { if (selection.Count == 1) { VM vm = selection[0].XenObject as VM; return vm != null && vm.is_a_template; } return false; } } #endregion #region SingleVmAppliance class private class SingleVmAppliance : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new VappStartCommand(mainWindow,selection)); items.AddIfEnabled(new VappShutDownCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new ExportCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new PropertiesCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { if (selection.Count == 1) { VM_appliance app = selection[0].XenObject as VM_appliance; return app != null; } return false; } } #endregion #region Multiple VMAppliance class private class MultipleVmAppliance : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new VappStartCommand(mainWindow, selection)); items.AddIfEnabled(new VappShutDownCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { return selection.AllItemsAre(); } } #endregion #region SingleVM class private class SingleVM : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { VM vm = (VM)selection[0].XenObject; items.AddIfEnabled(new ShutDownVMCommand(mainWindow, selection)); items.AddIfEnabled(new StartVMCommand(mainWindow, selection), vm.power_state == vm_power_state.Halted); items.AddIfEnabled(new ResumeVMCommand(mainWindow, selection)); items.AddIfEnabled(new SuspendVMCommand(mainWindow, selection)); items.AddIfEnabled(new RebootVMCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new ForceVMShutDownCommand(mainWindow, selection)); items.AddIfEnabled(new ForceVMRebootCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new VappStartCommand(mainWindow, selection)); items.AddIfEnabled(new VappShutDownCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new StartVMOnHostToolStripMenuItem(mainWindow, selection, true)); items.AddIfEnabled(new ResumeVMOnHostToolStripMenuItem(mainWindow, selection, true)); items.AddIfEnabled(new MigrateVMToolStripMenuItem(mainWindow, selection, true)); items.AddSeparator(); items.AddIfEnabled(new CopyVMCommand(mainWindow, selection)); items.AddIfEnabled(new MoveVMCommand(mainWindow, selection)); items.AddIfEnabled(new ExportCommand(mainWindow, selection)); items.AddIfEnabled(new TakeSnapshotCommand(mainWindow, selection)); items.AddIfEnabled(new ConvertVMToTemplateCommand(mainWindow, selection)); items.AddIfEnabled(new AssignGroupToolStripMenuItem(mainWindow, selection, true)); items.AddIfEnabled(new AssignGroupToolStripMenuItem(mainWindow, selection, true)); items.AddSeparator(); items.AddIfEnabled(new InstallToolsCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new DeleteVMCommand(mainWindow, selection)); items.AddPluginItems(PluginContextMenu.vm, selection); items.AddSeparator(); items.AddIfEnabled(new PropertiesCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { if (selection.Count == 1) { VM vm = selection[0].XenObject as VM; return vm != null && !vm.is_a_snapshot && !vm.is_a_template; } return false; } } #endregion #region SingleSR class private class SingleSR : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new RepairSRCommand(mainWindow, selection)); items.AddIfEnabled(new SetAsDefaultSRCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new DetachSRCommand(mainWindow, selection)); items.AddIfEnabled(new ReattachSRCommand(mainWindow, selection)); items.AddIfEnabled(new ForgetSRCommand(mainWindow, selection)); items.AddIfEnabled(new DestroySRCommand(mainWindow, selection)); items.AddPluginItems(PluginContextMenu.storage, selection); items.AddSeparator(); items.AddIfEnabled(new PropertiesCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { return selection.ContainsOneItemOfType(); } } #endregion #region SingleFolder class private class SingleFolder : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new NewFolderCommand(mainWindow, selection)); items.AddIfEnabled(new PutFolderIntoRenameModeCommand(mainWindow, selection)); items.AddIfEnabled(new DeleteFolderCommand(mainWindow, selection)); items.AddPluginItems(PluginContextMenu.folder, selection); } public override bool IsValid(SelectedItemCollection selection) { return selection.ContainsOneItemOfType(); } } #endregion #region MultipleVMs class private abstract class MultipleVMs : Builder { public override bool IsValid(SelectedItemCollection selection) { if (selection.Count > 1) { foreach (SelectedItem item in selection) { VM vm = item.XenObject as VM; if (vm == null || vm.is_a_template || vm.is_a_snapshot) { return false; } } return true; } return false; } } #endregion #region MultipleTemplates class private class MultipleTemplates : Builder { public override bool IsValid(SelectedItemCollection selection) { if (selection.Count > 1) { foreach (SelectedItem item in selection) { VM vm = item.XenObject as VM; if (vm == null || !vm.is_a_template || vm.is_a_snapshot) { return false; } } return true; } return false; } public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new DeleteTemplateCommand(mainWindow, selection)); items.AddIfEnabled(new EditTagsCommand(mainWindow, selection)); items.AddPluginItems(PluginContextMenu.template, selection); } } #endregion #region MultipleSnapshots class private class MultipleSnapshots : Builder { public override bool IsValid(SelectedItemCollection selection) { if (selection.Count > 1) { foreach (SelectedItem item in selection) { VM vm = item.XenObject as VM; if (vm == null || !vm.is_a_snapshot) { return false; } } return true; } return false; } public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new EditTagsCommand(mainWindow, selection)); items.AddIfEnabled(new DeleteSnapshotCommand(mainWindow, selection)); } } #endregion #region MultipleVMsInPool class private class MultipleVMsInPool : MultipleVMs { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new ShutDownVMCommand(mainWindow, selection)); items.AddIfEnabled(new StartVMCommand(mainWindow, selection)); items.AddIfEnabled(new ResumeVMCommand(mainWindow, selection)); items.AddIfEnabled(new SuspendVMCommand(mainWindow, selection)); items.AddIfEnabled(new RebootVMCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new ForceVMShutDownCommand(mainWindow, selection)); items.AddIfEnabled(new ForceVMRebootCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new VappStartCommand(mainWindow, selection)); items.AddIfEnabled(new VappShutDownCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new StartVMOnHostToolStripMenuItem(mainWindow, selection, true)); items.AddIfEnabled(new ResumeVMOnHostToolStripMenuItem(mainWindow, selection, true)); items.AddIfEnabled(new MoveVMCommand(mainWindow, selection)); items.AddIfEnabled(new MigrateVMToolStripMenuItem(mainWindow, selection, true)); items.AddIfEnabled(new ExportCommand(mainWindow, selection)); items.AddIfEnabled(new AssignGroupToolStripMenuItem(mainWindow, selection, true)); items.AddIfEnabled(new AssignGroupToolStripMenuItem(mainWindow, selection, true)); items.AddSeparator(); items.AddIfEnabled(new InstallToolsCommand(mainWindow, selection)); items.AddIfEnabled(new DeleteVMCommand(mainWindow, selection)); items.AddIfEnabled(new EditTagsCommand(mainWindow, selection)); items.AddPluginItems(PluginContextMenu.vm, selection); } public override bool IsValid(SelectedItemCollection selection) { if (base.IsValid(selection)) { Pool firstPool = Helpers.GetPoolOfOne(selection[0].Connection); if (firstPool != null) { foreach (SelectedItem item in selection) { Pool pool = Helpers.GetPoolOfOne(item.Connection); if (pool == null || !firstPool.Equals(pool)) { return false; } } return true; } } return false; } } #endregion #region MultipleVMsOverMultiplePools class private class MultipleVMsOverMultiplePools : MultipleVMs { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new ShutDownVMCommand(mainWindow, selection)); items.AddIfEnabled(new StartVMCommand(mainWindow, selection)); items.AddIfEnabled(new ResumeVMCommand(mainWindow, selection)); items.AddIfEnabled(new SuspendVMCommand(mainWindow, selection)); items.AddIfEnabled(new RebootVMCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new ForceVMShutDownCommand(mainWindow, selection)); items.AddIfEnabled(new ForceVMRebootCommand(mainWindow, selection)); items.AddSeparator(); items.AddIfEnabled(new InstallToolsCommand(mainWindow, selection)); items.AddIfEnabled(new DeleteVMCommand(mainWindow, selection)); items.AddIfEnabled(new EditTagsCommand(mainWindow, selection)); items.AddPluginItems(PluginContextMenu.vm, selection); } public override bool IsValid(SelectedItemCollection selection) { if (base.IsValid(selection)) { return !new MultipleVMsInPool().IsValid(selection); } return false; } } #endregion #region MultipleFolders class private class MultipleFolders : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new DeleteFolderCommand(mainWindow, selection)); items.AddPluginItems(PluginContextMenu.folder, selection); } public override bool IsValid(SelectedItemCollection selection) { return selection.AllItemsAre() && selection.Count > 1; } } #endregion #region SingleTag class private class SingleTag : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new DeleteTagCommand(mainWindow, selection)); items.AddIfEnabled(new PutTagIntoRenameModeCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { return selection.AllItemsAre(IsValid) && selection.Count == 1; } private static bool IsValid(GroupingTag groupingTag) { return groupingTag.Grouping.GroupingName == Messages.TAGS; } } #endregion #region MultipleTags class private class MultipleTags : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new DeleteTagCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { return selection.AllItemsAre(IsValid) && selection.Count > 1; } private static bool IsValid(GroupingTag groupingTag) { return groupingTag.Grouping.GroupingName == Messages.TAGS; } } #endregion #region SingleDockerContainer class private class SingleDockerContainer : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { DockerContainer vm = (DockerContainer)selection[0].XenObject; items.AddIfEnabled(new StartDockerContainerCommand(mainWindow, selection)); items.AddIfEnabled(new StopDockerContainerCommand(mainWindow, selection)); items.AddIfEnabled(new PauseDockerContainerCommand(mainWindow, selection)); items.AddIfEnabled(new ResumeDockerContainerCommand(mainWindow, selection)); items.AddIfEnabled(new RestartDockerContainerCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { if (selection.Count == 1) { DockerContainer dockerContainer = selection[0].XenObject as DockerContainer; return dockerContainer != null; } return false; } } #endregion #region MultipleDockerContainers class private abstract class MultipleDockerContainers : Builder { public override void Build(IMainWindow mainWindow, SelectedItemCollection selection, ContextMenuItemCollection items) { items.AddIfEnabled(new StartDockerContainerCommand(mainWindow, selection)); items.AddIfEnabled(new StopDockerContainerCommand(mainWindow, selection)); items.AddIfEnabled(new PauseDockerContainerCommand(mainWindow, selection)); items.AddIfEnabled(new ResumeDockerContainerCommand(mainWindow, selection)); items.AddIfEnabled(new RestartDockerContainerCommand(mainWindow, selection)); } public override bool IsValid(SelectedItemCollection selection) { return selection.AllItemsAre(); } } #endregion } }