2017-01-16 20:59:50 +01:00
|
|
|
|
/* Copyright (c) Citrix Systems, Inc.
|
2013-06-24 13:41:48 +02:00
|
|
|
|
* 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<VDI>, IEquatable<VDI>
|
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public override string Name()
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
if (Connection != null)
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
SR sr = Connection.Resolve(this.SR);
|
|
|
|
|
if (sr != null)
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
Host host = sr.GetStorageHost();
|
|
|
|
|
if (sr.Physical() && host != null)
|
|
|
|
|
return string.Format(Messages.CD_DRIVE, host.Name());
|
2013-06-24 13:41:48 +02:00
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
}
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
2017-09-03 04:33:29 +02:00
|
|
|
|
return name_label;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public override string Description()
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
return name_description;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public string VMsOfVDI()
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
bool comma = false;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
foreach (VM vm in this.GetVMs().Where(vm => vm.Show(true)))
|
|
|
|
|
{
|
|
|
|
|
if (comma)
|
|
|
|
|
sb.Append(", ");
|
|
|
|
|
else
|
|
|
|
|
comma = true;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
sb.Append(vm.is_a_snapshot ? String.Format(Messages.SNAPSHOT_BRACKETS, vm.Name()) : vm.Name());
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
2017-09-03 04:33:29 +02:00
|
|
|
|
|
|
|
|
|
return sb.ToString();
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool Show(bool showHiddenVMs)
|
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
return !missing && managed && (showHiddenVMs || !IsHidden());
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public override bool IsHidden()
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
return BoolKey(other_config, HIDE_FROM_XENCENTER);
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IList<VM> GetVMs()
|
|
|
|
|
{
|
|
|
|
|
List<VM> vms = new List<VM>();
|
|
|
|
|
|
|
|
|
|
if (this.type == vdi_type.crashdump)
|
|
|
|
|
{
|
|
|
|
|
foreach (Crashdump crashdump in Connection.ResolveAll<Crashdump>(crash_dumps))
|
|
|
|
|
{
|
|
|
|
|
VM vm = Connection.Resolve<VM>(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<VDI>(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;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-05 03:15:38 +02:00
|
|
|
|
public string GetVmHint()
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2017-09-05 03:15:38 +02:00
|
|
|
|
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);
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
return Name();
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public virtual string SizeText()
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
if (is_a_snapshot)
|
|
|
|
|
return String.Empty;
|
|
|
|
|
else
|
|
|
|
|
return Util.DiskSizeString(virtual_size);
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
2015-01-14 17:20:36 +01:00
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public override string NameWithLocation()
|
2015-01-14 17:20:36 +01:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
if (Connection != null)
|
2015-01-14 17:20:36 +01:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
var srOfVdi = Connection.Resolve(SR);
|
|
|
|
|
if (srOfVdi == null)
|
|
|
|
|
return base.NameWithLocation();
|
2015-01-14 17:20:36 +01:00
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
return string.Format(Messages.VDI_ON_SR_TITLE, Name(), srOfVdi.Name(), srOfVdi.LocationString());
|
2015-01-14 17:20:36 +01:00
|
|
|
|
}
|
2017-09-03 04:33:29 +02:00
|
|
|
|
|
|
|
|
|
return base.NameWithLocation();
|
2015-01-14 17:20:36 +01:00
|
|
|
|
}
|
|
|
|
|
|
2013-06-24 13:41:48 +02:00
|
|
|
|
#region IEquatable<VDI> Members
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Indicates whether the current object is equal to the specified object. This calls the implementation from XenObject.
|
|
|
|
|
/// This implementation is required for ToStringWrapper.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool Equals(VDI other)
|
|
|
|
|
{
|
|
|
|
|
return base.Equals(other);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 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.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public enum FriendlyType { SNAPSHOT, ISO, SYSTEM_DISK, VIRTUAL_DISK, NONE };
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 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.
|
|
|
|
|
/// </summary>
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public FriendlyType VDIType()
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
SR sr = Connection.Resolve<SR>(SR);
|
|
|
|
|
if (sr == null)
|
|
|
|
|
return FriendlyType.NONE;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
if (is_a_snapshot && GetVMs().Count >= 1)
|
|
|
|
|
return FriendlyType.SNAPSHOT;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
if (sr.content_type == XenAPI.SR.Content_Type_ISO)
|
|
|
|
|
return FriendlyType.ISO;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
if (type == vdi_type.system)
|
|
|
|
|
return FriendlyType.SYSTEM_DISK;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
return FriendlyType.VIRTUAL_DISK;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Is the disk of a type used by HA?
|
|
|
|
|
/// </summary>
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public bool IsHaType()
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
return type == vdi_type.ha_statefile || type == vdi_type.redo_log;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Is the disk currently being used by HA?
|
|
|
|
|
/// </summary>
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public bool IsUsedByHA()
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
return IsHaType() && Helpers.GetPoolOfOne(Connection).ha_enabled;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Is the disk used by DR?
|
|
|
|
|
/// </summary>
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public bool IsMetadataForDR()
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
return type == vdi_type.metadata;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// VDIs associated with storage motion are specially marked. This
|
|
|
|
|
/// bool allows you to know if the current VDI is such.
|
|
|
|
|
/// </summary>
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public bool IsAnIntermediateStorageMotionSnapshot()
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
return sm_config.ContainsKey("base_mirror");
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Try to determine if this VDI belongs to a WSS VM - this is a best guess only
|
|
|
|
|
/// </summary>
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public bool CouldBeWss()
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
const string wssName = "Webss-disk";
|
|
|
|
|
return name_label.Contains(wssName);
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
2015-02-13 15:43:13 +01:00
|
|
|
|
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public bool IsCloudConfigDrive()
|
2015-02-13 15:43:13 +01:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
return other_config.ContainsKey("config-drive") && other_config["config-drive"].ToLower() == "true";
|
2015-02-23 18:57:18 +01:00
|
|
|
|
}
|
2016-02-25 18:18:48 +01:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
2016-08-17 23:35:01 +02:00
|
|
|
|
/// 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.
|
2016-02-25 18:18:48 +01:00
|
|
|
|
/// </summary>
|
2017-09-03 04:33:29 +02:00
|
|
|
|
public bool IsToolsIso()
|
2016-02-25 18:18:48 +01:00
|
|
|
|
{
|
2017-09-03 04:33:29 +02:00
|
|
|
|
string[] toolIsoNames = {"xswindrivers.iso", "xs-tools.iso", "guest-tools.iso"};
|
|
|
|
|
return is_tools_iso || toolIsoNames.Contains(name_label);
|
2016-02-25 18:18:48 +01:00
|
|
|
|
}
|
2017-09-03 04:33:29 +02:00
|
|
|
|
|
2015-02-19 15:09:08 +01:00
|
|
|
|
/// <summary>
|
2015-03-13 14:16:19 +01:00
|
|
|
|
/// Whether read caching is enabled on this disk on a specific host
|
2015-02-19 15:09:08 +01:00
|
|
|
|
/// </summary>
|
2015-03-13 14:16:19 +01:00
|
|
|
|
public bool ReadCachingEnabled(Host host)
|
2015-02-19 15:09:08 +01:00
|
|
|
|
{
|
2015-03-13 14:16:19 +01:00
|
|
|
|
return BoolKey(sm_config, "read-caching-enabled-on-" + host.uuid);
|
2015-02-19 15:09:08 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2015-03-16 20:54:55 +01:00
|
|
|
|
/// ... and if not, why not
|
2015-02-19 15:09:08 +01:00
|
|
|
|
/// </summary>
|
2015-03-16 20:54:55 +01:00
|
|
|
|
public ReadCachingDisabledReasonCode ReadCachingDisabledReason(Host host)
|
2015-02-19 15:09:08 +01:00
|
|
|
|
{
|
2015-03-16 20:54:55 +01:00
|
|
|
|
string reasonstr;
|
|
|
|
|
if (sm_config.TryGetValue("read-caching-reason-" + host.uuid, out reasonstr))
|
2015-02-19 15:09:08 +01:00
|
|
|
|
{
|
2015-03-16 20:54:55 +01:00
|
|
|
|
ReadCachingDisabledReasonCode reason;
|
|
|
|
|
if (Enum.TryParse(reasonstr, out reason))
|
|
|
|
|
return reason;
|
2015-02-19 15:09:08 +01:00
|
|
|
|
}
|
2015-03-16 20:54:55 +01:00
|
|
|
|
return ReadCachingDisabledReasonCode.UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Possible reasons for read caching being disabled
|
|
|
|
|
/// If there are multiple reasons, the topmost reason will be returned
|
|
|
|
|
/// </summary>
|
|
|
|
|
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
|
2015-02-13 15:43:13 +01:00
|
|
|
|
}
|
2015-10-06 15:04:36 +02:00
|
|
|
|
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
}
|