mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-11-29 02:18:07 +01:00
327 lines
10 KiB
C#
327 lines
10 KiB
C#
/* 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.Reflection;
|
|
using Newtonsoft.Json;
|
|
using XenAdmin.Core;
|
|
using XenAdmin.Network;
|
|
using XenAdmin;
|
|
using XenCenterLib;
|
|
|
|
namespace XenAPI
|
|
{
|
|
public abstract partial class XenObject<S> : IComparable<S> where S : XenObject<S>
|
|
{
|
|
protected const String HIDE_FROM_XENCENTER = "HideFromXenCenter";
|
|
|
|
private IXenConnection m_Connection = null;
|
|
|
|
private bool _locked;
|
|
|
|
[JsonIgnore]
|
|
public IXenConnection Connection
|
|
{
|
|
get { return m_Connection; }
|
|
set { m_Connection = value; }
|
|
}
|
|
|
|
|
|
public virtual string Description()
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
/// <summary>
|
|
/// True if the Xen server knows about this object; false otherwise, e.g., when the user has created an object
|
|
/// but not yet saved it to the server.
|
|
/// </summary>
|
|
public bool ExistsOnServer()
|
|
{
|
|
return this.opaque_ref != null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// True if a server request is in progress.
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public bool Locked
|
|
{
|
|
get { return _locked; }
|
|
set
|
|
{
|
|
if (_locked != value)
|
|
{
|
|
_locked = value;
|
|
this.NotifyPropertyChanged("Locked");
|
|
}
|
|
}
|
|
}
|
|
|
|
protected static T Get<T>(Dictionary<string, T> d, string k) where T : class
|
|
{
|
|
return d != null && d.ContainsKey(k) ? d[k] : null;
|
|
}
|
|
|
|
private String path = String.Empty;
|
|
|
|
[JsonIgnore]
|
|
public String Path
|
|
{
|
|
get { return path; }
|
|
set
|
|
{
|
|
if (!Helper.AreEqual(value, path))
|
|
{
|
|
path = value;
|
|
Changed = true;
|
|
NotifyPropertyChanged("Path");
|
|
}
|
|
}
|
|
}
|
|
|
|
public IXenObject Clone()
|
|
{
|
|
IXenObject result = (IXenObject)MemberwiseClone();
|
|
result.ClearEventListeners();
|
|
result.Locked = false;
|
|
return result;
|
|
}
|
|
|
|
public virtual bool Show(bool showHiddenVMs)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public virtual bool IsHidden()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public string SaveChanges(Session session)
|
|
{
|
|
return SaveChanges(session, null);
|
|
}
|
|
|
|
public string SaveChanges(Session session, IXenObject beforeObject)
|
|
{
|
|
S server =
|
|
opaque_ref == null ?
|
|
null :
|
|
session.Connection.Resolve(new XenRef<S>(opaque_ref));
|
|
|
|
if (server == null && opaque_ref != null)
|
|
return null;
|
|
|
|
if (opaque_ref != null && !server.Locked)
|
|
throw new InvalidOperationException("Instance must be locked before calling SaveChanges()");
|
|
|
|
if (beforeObject == null)
|
|
beforeObject = server;
|
|
return SaveChanges(session, opaque_ref, (S)beforeObject);
|
|
}
|
|
|
|
public virtual int CompareTo(S other)
|
|
{
|
|
if (other == null)
|
|
return -1;
|
|
|
|
int result = StringUtility.NaturalCompare(Name(), other.Name());
|
|
if (result != 0)
|
|
return result;
|
|
|
|
return this.opaque_ref.CompareTo(other.opaque_ref);
|
|
}
|
|
|
|
public int CompareTo(object obj)
|
|
{
|
|
S other = obj as S;
|
|
if (other != null)
|
|
return CompareTo(other);
|
|
|
|
IXenObject o = obj as IXenObject;
|
|
if (o == null)
|
|
return -1;
|
|
|
|
return StringUtility.NaturalCompare(Name(), o.Name());
|
|
}
|
|
|
|
/// <summary>
|
|
/// This method can be overridden by the derived classes. This is why the implementation is here and the typed
|
|
/// equals calls this one.
|
|
/// </summary>
|
|
/// <param name="other"></param>
|
|
/// <returns></returns>
|
|
public override bool Equals(object other)
|
|
{
|
|
IXenObject otherIXenObject = other as IXenObject;
|
|
if (otherIXenObject != null)
|
|
return opaque_ref == otherIXenObject.opaque_ref;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a hash code for this instance. This is required if you want to use this type as a key in a hashtable.
|
|
/// </summary>
|
|
public override int GetHashCode()
|
|
{
|
|
return opaque_ref.GetHashCode();
|
|
}
|
|
|
|
#region IEquatable<IXenObject> Members
|
|
|
|
/// <summary>
|
|
/// This is the implementation of IEquatable of IXenObject which is defined in IXenObject. This calls the virtual
|
|
/// Equals so that any derived classes can override Equals and it will used the derived class implementation in
|
|
/// all circumstances.
|
|
/// </summary>
|
|
public bool Equals(IXenObject other)
|
|
{
|
|
return Equals((object)other);
|
|
}
|
|
|
|
#endregion
|
|
|
|
public object Get(String property)
|
|
{
|
|
PropertyInfo pi = GetType().GetProperty(property);
|
|
if (pi == null)
|
|
return null;
|
|
|
|
return pi.GetValue(this, null);
|
|
}
|
|
|
|
public void Set(String property, object val)
|
|
{
|
|
PropertyInfo pi = GetType().GetProperty(property);
|
|
if (pi != null)
|
|
pi.SetValue(this, val, null);
|
|
}
|
|
|
|
public void Do(String method, params Object[] methodParams)
|
|
{
|
|
MethodInfo mi = GetType().GetMethod(method, BindingFlags.Public | BindingFlags.Static);
|
|
if (mi == null)
|
|
return;
|
|
|
|
try
|
|
{
|
|
mi.Invoke(this, methodParams);
|
|
}
|
|
catch (TargetInvocationException e)
|
|
{
|
|
throw e.InnerException;
|
|
}
|
|
}
|
|
|
|
public static Dictionary<string, string> SetDictionaryKey(Dictionary<string, string> dict, string key, string value)
|
|
{
|
|
return SetDictionaryKeys(dict, new KeyValuePair<string, string>(key, value));
|
|
}
|
|
|
|
public static Dictionary<string, string> SetDictionaryKeys(Dictionary<string, string> dict, params KeyValuePair<string, string>[] kvps)
|
|
{
|
|
var newDict = dict == null
|
|
? new Dictionary<string, string>()
|
|
: new Dictionary<string, string>(dict);
|
|
|
|
foreach (var kvp in kvps)
|
|
{
|
|
string key = kvp.Key;
|
|
string value = kvp.Value;
|
|
|
|
if (value == null)
|
|
newDict.Remove(key);
|
|
else
|
|
newDict[key] = value;
|
|
}
|
|
|
|
return newDict;
|
|
}
|
|
|
|
/// <summary>
|
|
/// If d[k] == "true", then return true. Anything else is false.
|
|
/// Handles all the cases with d being null or not containing k.
|
|
/// </summary>
|
|
protected static bool BoolKey(Dictionary<string, string> d, string k)
|
|
{
|
|
string v = Get(d, k);
|
|
return v != null && v == "true";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts dictionary pair to a bool.
|
|
/// Only return false if it's looked up otherwise return true
|
|
///
|
|
/// This is similar to BoolKey but BoolKey prefers to return false,
|
|
/// whereas BoolKeyPreferTrue prefers true;
|
|
/// </summary>
|
|
protected static bool BoolKeyPreferTrue(Dictionary<string, string> d, string k)
|
|
{
|
|
string v = Get(d, k);
|
|
return String.IsNullOrEmpty(v) || v != "false";
|
|
}
|
|
|
|
/// <summary>
|
|
/// If d[k] is parseable as an integer, then return it, otherwise return def.
|
|
/// Handles all the cases with d being null or not containing k.
|
|
/// </summary>
|
|
protected int IntKey(Dictionary<string, string> d, string k, int def)
|
|
{
|
|
int result;
|
|
string s = Get(d, k);
|
|
return s != null && int.TryParse(s, out result) ? result : def;
|
|
}
|
|
|
|
public virtual string Name()
|
|
{
|
|
return "";
|
|
}
|
|
|
|
public virtual string NameWithLocation()
|
|
{
|
|
return string.Format(Messages.NAME_WITH_LOCATION, Name(), LocationString());
|
|
}
|
|
|
|
internal virtual string LocationString()
|
|
{
|
|
if (Connection == null || string.IsNullOrEmpty(Connection.Name))
|
|
return string.Empty;
|
|
|
|
if (Helpers.IsPool(Connection))
|
|
return string.Format(Messages.IN_POOL, Connection.Name);
|
|
|
|
return string.Format(Messages.ON_SERVER, Connection.Name);
|
|
}
|
|
}
|
|
}
|