/* 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 XenAdmin; using XenAdmin.Core; namespace XenAPI { public partial class VDI : IComparable, IEquatable { public override string Name() { if (Connection != null) { SR sr = Connection.Resolve(this.SR); if (sr != null) { Host host = sr.GetStorageHost(); if (sr.Physical() && host != null) return string.Format(Messages.CD_DRIVE, host.Name()); } } return name_label; } public override string Description() { return name_description; } public string VMsOfVDI() { StringBuilder sb = new StringBuilder(); bool comma = false; foreach (VM vm in this.GetVMs().Where(vm => vm.Show(true))) { if (comma) sb.Append(", "); else comma = true; sb.Append(vm.is_a_snapshot ? String.Format(Messages.SNAPSHOT_BRACKETS, vm.Name()) : vm.Name()); } return sb.ToString(); } public override bool Show(bool showHiddenVMs) { return !missing && managed && (showHiddenVMs || !IsHidden()); } public override bool IsHidden() { return BoolKey(other_config, HIDE_FROM_XENCENTER); } public IList GetVMs() { List vms = new List(); if (this.type == vdi_type.crashdump) { foreach (Crashdump crashdump in Connection.ResolveAll(crash_dumps)) { VM vm = Connection.Resolve(crashdump.VM); if (vm != null) vms.Add(vm); } } else if (this.type == vdi_type.suspend) { foreach (VM vm in Connection.Cache.VMs) { VDI vdi = Connection.Resolve(vm.suspend_VDI); if (vdi != null && vdi.uuid == this.uuid) vms.Add(vm); } } else { foreach (VBD vbd in Connection.ResolveAll(this.VBDs)) { VM vm = Connection.Resolve(vbd.VM); if (vm != null) vms.Add(vm); } } vms.Sort(); return vms; } public string GetVmHint() { if (sm_config != null && sm_config.ContainsKey("vmhint")) return sm_config["vmhint"]; else return ""; } public void SetVmHint(string value) { sm_config = SetDictionaryKey(sm_config, "vmhint", value); } public override string ToString() { return Name(); } public virtual string SizeText() { if (is_a_snapshot) return String.Empty; else return Util.DiskSizeString(virtual_size); } public override string NameWithLocation() { if (Connection != null) { var srOfVdi = Connection.Resolve(SR); if (srOfVdi == null) return base.NameWithLocation(); return string.Format(Messages.VDI_ON_SR_TITLE, Name(), srOfVdi.Name(), srOfVdi.LocationString()); } return base.NameWithLocation(); } #region IEquatable Members /// /// Indicates whether the current object is equal to the specified object. This calls the implementation from XenObject. /// This implementation is required for ToStringWrapper. /// public bool Equals(VDI other) { return base.Equals(other); } #endregion /// /// These are some types of VDI we care to distinguish between in the GUI. Determining what type a VDI is for XC depends on not /// just the vdi.type fields supplied by the server but some other logic. This is contained in VDI.VDIType, which returns one of /// these enums. /// public enum FriendlyType { SNAPSHOT, ISO, SYSTEM_DISK, VIRTUAL_DISK, NONE }; /// /// These are some types of VDI we care to distinguish between in the GUI. Determining what type a VDI is for XC depends on not /// just the vdi.type fields supplied by the server but some other logic. /// public FriendlyType VDIType() { SR sr = Connection.Resolve(SR); if (sr == null) return FriendlyType.NONE; if (is_a_snapshot && GetVMs().Count >= 1) return FriendlyType.SNAPSHOT; if (sr.content_type == XenAPI.SR.Content_Type_ISO) return FriendlyType.ISO; if (type == vdi_type.system) return FriendlyType.SYSTEM_DISK; return FriendlyType.VIRTUAL_DISK; } /// /// Is the disk of a type used by HA? /// public bool IsHaType() { return type == vdi_type.ha_statefile || type == vdi_type.redo_log; } /// /// Is the disk currently being used by HA? /// public bool IsUsedByHA() { return IsHaType() && Helpers.GetPoolOfOne(Connection).ha_enabled; } /// /// Is the disk used by DR? /// public bool IsMetadataForDR() { return type == vdi_type.metadata; } /// /// VDIs associated with storage motion are specially marked. This /// bool allows you to know if the current VDI is such. /// public bool IsAnIntermediateStorageMotionSnapshot() { return sm_config.ContainsKey("base_mirror"); } /// /// Try to determine if this VDI belongs to a WSS VM - this is a best guess only /// public bool CouldBeWss() { const string wssName = "Webss-disk"; return name_label.Contains(wssName); } public bool IsCloudConfigDrive() { return other_config.ContainsKey("config-drive") && other_config["config-drive"].ToLower() == "true"; } /// /// Whether this is a Tools ISO. /// The new method is to check the is_tools_iso flag, the old one to check the name_label. /// public bool IsToolsIso() { string[] toolIsoNames = {"xswindrivers.iso", "xs-tools.iso", "guest-tools.iso"}; return is_tools_iso || toolIsoNames.Contains(name_label); } /// /// Whether read caching is enabled on this disk on a specific host /// public bool ReadCachingEnabled(Host host) { return BoolKey(sm_config, "read-caching-enabled-on-" + host.uuid); } /// /// ... and if not, why not /// public ReadCachingDisabledReasonCode ReadCachingDisabledReason(Host host) { string reasonstr; if (sm_config.TryGetValue("read-caching-reason-" + host.uuid, out reasonstr)) { ReadCachingDisabledReasonCode reason; if (Enum.TryParse(reasonstr, out reason)) return reason; } return ReadCachingDisabledReasonCode.UNKNOWN; } /// /// Possible reasons for read caching being disabled /// If there are multiple reasons, the topmost reason will be returned /// public enum ReadCachingDisabledReasonCode { UNKNOWN, // catch-all, shouldn't occur if read caching is disabled LICENSE_RESTRICTION, // self-explanatory SR_NOT_SUPPORTED, // the SR is not NFS or EXT NO_RO_IMAGE, // no part of the VDI is read-only => nothing to cache SR_OVERRIDE, // the feature has been explicitly disabled for the VDI's SR } } }