/* Copyright (c) Citrix Systems Inc. * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using XenAPI; using XenAdmin.Commands.Controls; using XenAdmin.Actions; using XenAdmin.Dialogs; namespace XenAdmin.Commands { class DetachVirtualDiskCommand : Command { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private VM targetVM = null; /// /// Detaches a list of VDIs from all their attached VMs (VBD unplug + VBD destroy) /// /// /// public DetachVirtualDiskCommand(IMainWindow mainWindow, IEnumerable selection) : base(mainWindow, selection) { } /// /// Detaches the VDI from all VMs (VBD unplug + VBD destroy) /// /// /// public DetachVirtualDiskCommand(IMainWindow mainWindow, VDI vdi) : base(mainWindow, vdi) { } /// /// Detaches a list of VDIs from a specific VM (VBD unplug + VBD destroy) /// /// /// The VDIs to detach /// The VM to detach the VDIs from public DetachVirtualDiskCommand(IMainWindow mainWindow, IEnumerable selection, VM vm) : base(mainWindow, selection) { this.targetVM = vm; } /// /// Detaches a specific VDI from a specific VM (VBD unplug + VBD destroy) /// /// /// The VDI to detach /// The VM to detach it from public DetachVirtualDiskCommand(IMainWindow mainWindow, VDI vdi, VM vm) : base(mainWindow, vdi) { this.targetVM = vm; } public override string ContextMenuText { get { return Messages.MESSAGEBOX_DETACH_VD_TITLE; } } protected override bool CanExecuteCore(SelectedItemCollection selection) { return selection.AllItemsAre() && selection.AtLeastOneXenObjectCan(CanExecute); } protected bool CanExecute(VDI vdi) { if (vdi == null) return false; foreach (VBD vbd in vdi.Connection.ResolveAll(vdi.VBDs)) { if (targetVM == null || vbd.VM.opaque_ref == targetVM.opaque_ref) { if (!vbd.currently_attached) continue; DeactivateVBDCommand cmd = new DeactivateVBDCommand(Program.MainWindow, vbd); if (!cmd.CanExecute()) return false; } } return true; } protected override string GetCantExecuteReasonCore(SelectedItem item) { VDI vdi = item.XenObject as VDI; if (vdi == null) return base.GetCantExecuteReasonCore(item); foreach (VBD vbd in vdi.Connection.ResolveAll(vdi.VBDs)) { if (targetVM == null || vbd.VM.opaque_ref == targetVM.opaque_ref) { if (!vbd.currently_attached) continue; DeactivateVBDCommand cmd = new DeactivateVBDCommand(Program.MainWindow, vbd); if (!cmd.CanExecute()) { var reasons = cmd.GetCantExecuteReasons(); return reasons.Count > 0 ? reasons.ElementAt(0).Value : Messages.UNKNOWN; } } } return base.GetCantExecuteReasonCore(item); } protected override void ExecuteCore(SelectedItemCollection selection) { List actionsToComplete = new List(); foreach (VDI vdi in selection.AsXenObjects()) { if (vdi.Locked || !vdi.Show(XenAdmin.Properties.Settings.Default.ShowHiddenVMs)) continue; actionsToComplete.AddRange(getDetachVDIAction(vdi)); } if (actionsToComplete.Count < 1) return; if (actionsToComplete.Count == 1) actionsToComplete[0].RunAsync(); else RunMultipleActions(actionsToComplete, Messages.ACTION_DETACHING_MULTIPLE_VDIS_TITLE, Messages.ACTION_DETACHING_MULTIPLE_VDIS_STATUS, Messages.COMPLETED, true); } private List getDetachVDIAction(VDI vdi) { List actions = new List(); foreach (VBD vbd in vdi.Connection.ResolveAll(vdi.VBDs)) { if (targetVM == null || vbd.VM.opaque_ref == targetVM.opaque_ref) { VM vm = vdi.Connection.Resolve(vbd.VM); DetachVirtualDiskAction action = new DetachVirtualDiskAction(vdi, vm, true); actions.Add(action); } } return actions; } protected override bool Confirm() { if (Program.RunInAutomatedTestMode) return true; MultipleWarningDialog warningDialog = new MultipleWarningDialog( Messages.MESSAGEBOX_DETACH_VD_TITLE_MUTLIPLE, Messages.MULTI_VDI_DETACH_WARNING, Messages.DETACH_ALL_BUTTON_LABEL); SelectedItemCollection selectedItems = GetSelection(); List sysDisks = new List(); List regularDisks = new List(); foreach (VDI vdi in selectedItems.AsXenObjects()) { if (vdi.type == vdi_type.system) sysDisks.Add(vdi); else regularDisks.Add(vdi); } // Use the regular confirm dialog if we only have one warning type if (sysDisks.Count == 0 || regularDisks.Count == 0) return base.Confirm(); warningDialog.AddWarningMessage( Messages.MESSAGEBOX_DETACH_SYSTEMVD_TITLE, Messages.MESSAGEBOX_DETACH_SYSTEMVD, sysDisks.ConvertAll(delegate(VDI v) { return (IXenObject)v; })); warningDialog.AddWarningMessage( Messages.MESSAGEBOX_DETACH_VD_TITLE, Messages.MESSAGEBOX_DETACH_VD, regularDisks.ConvertAll(delegate(VDI v) { return (IXenObject)v; })); return warningDialog.ShowDialog(MainWindowCommandInterface.Form) == System.Windows.Forms.DialogResult.Yes; } protected override string ConfirmationDialogText { get { if (GetSelection().ContainsOneItemOfType(delegate(VDI vdi) { return vdi.type == vdi_type.system; })) { return Messages.MESSAGEBOX_DETACH_SYSTEMVD; } else { return Messages.MESSAGEBOX_DETACH_VD; } } } protected override string ConfirmationDialogTitle { get { if (GetSelection().ContainsOneItemOfType(delegate(VDI vdi) { return vdi.type == vdi_type.system; })) { return Messages.MESSAGEBOX_DETACH_SYSTEMVD_TITLE; } else { return Messages.MESSAGEBOX_DETACH_VD_TITLE; } } } protected override bool ConfirmationRequired { get { return true; } } protected override CommandErrorDialog GetErrorDialogCore(IDictionary cantExecuteReasons) { return new CommandErrorDialog(Messages.ERROR_ACTIVATING_VDIS_TITLE, Messages.ERROR_ACTIVATING_VDIS_MESSAGE, cantExecuteReasons); } } }