mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-11-25 14:27:26 +01:00
7c0bc50b4a
Inc. Signed-off-by: Gabor Apati-Nagy<gabor.apati-nagy@citrix.com>
762 lines
34 KiB
C#
762 lines
34 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.
|
|
*/
|
|
|
|
// ============================================================================
|
|
// Description: Utilitiy functions built on top of libxen for use in all
|
|
// providers.
|
|
// ============================================================================
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Runtime.Serialization;
|
|
using System.Reflection;
|
|
using System.Reflection.Emit;
|
|
using System.Security;
|
|
using System.Security.Permissions;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Xml;
|
|
using System.Xml.Schema;
|
|
using System.Xml.Serialization;
|
|
|
|
using XenOvf.Definitions;
|
|
|
|
|
|
namespace XenOvf.Utilities
|
|
{
|
|
/// <summary>
|
|
/// Common TOOLS used within XenOvf.
|
|
/// </summary>
|
|
public sealed class Tools
|
|
{
|
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
|
|
private const long KB = 1024;
|
|
private const long MB = (KB * 1024);
|
|
private const long GB = (MB * 1024);
|
|
|
|
private Tools() { }
|
|
|
|
#region MISC TOOLS
|
|
/// <summary>
|
|
/// Load default namespaces required to define OVF.
|
|
/// Can be overriden in app.config: KnownNamespaces
|
|
/// </summary>
|
|
/// <returns>Collection: XmlSerializerNamespces</returns>
|
|
[SecurityPermission(SecurityAction.LinkDemand)]
|
|
public static XmlSerializerNamespaces LoadNamespaces()
|
|
{
|
|
string[] namespaces = Properties.Settings.Default.KnownNamespaces.Split(new char[] { ',' });
|
|
|
|
XmlSerializerNamespaces ns;
|
|
ns = new XmlSerializerNamespaces();
|
|
foreach (string name in namespaces)
|
|
{
|
|
string[] sep = name.Split(new char[] { '=' });
|
|
ns.Add(sep[0].Trim(), sep[1].Trim());
|
|
}
|
|
return ns;
|
|
}
|
|
/// <summary>
|
|
/// Load a file into a string
|
|
/// </summary>
|
|
/// <param name="filename">fullpath/filename</param>
|
|
/// <returns>string containing file contents</returns>
|
|
[SecurityPermission(SecurityAction.LinkDemand)]
|
|
public static string LoadFile(string filename)
|
|
{
|
|
FileStream fs = null;
|
|
StreamReader sr = null;
|
|
string xmldoc = null;
|
|
try
|
|
{
|
|
fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
sr = new StreamReader(fs);
|
|
xmldoc = sr.ReadToEnd();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.ErrorFormat("Utilities.LoadFile: failed: {0}", ex.Message);
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
if (sr != null) sr.Close();
|
|
if (fs != null) fs.Close();
|
|
}
|
|
return xmldoc;
|
|
}
|
|
#endregion
|
|
|
|
#region SERIALIZATION TOOLS
|
|
/// <summary>
|
|
/// Create an object from a string given the type to deserialize as.
|
|
/// </summary>
|
|
/// <param name="xmlString">xml string content</param>
|
|
/// <param name="objectType">Type object definition</param>
|
|
/// <returns>an object of Type objectType.</returns>
|
|
[SecurityPermission(SecurityAction.LinkDemand)]
|
|
public static object Deserialize(string xmlString, Type objectType)
|
|
{
|
|
object returnClass = null;
|
|
|
|
MemoryStream ms = new MemoryStream();
|
|
StreamWriter sw = new StreamWriter(ms);
|
|
sw.Write(xmlString);
|
|
sw.Flush();
|
|
ms.Position = 0;
|
|
StreamReader sr = new StreamReader(ms, true);
|
|
|
|
try
|
|
{
|
|
XmlSerializer xs = new XmlSerializer(objectType);
|
|
returnClass = xs.Deserialize(sr);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.DebugFormat("Tools.Deserialize failed attempt (may get retried) {0}", ex.Message);
|
|
if (ex.InnerException != null && ex.InnerException.Message.ToLower().Contains("hexadecimal value 0x00"))
|
|
{
|
|
throw new InvalidDataException(Messages.INVALID_DATA_IN_OVF, ex);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (sw != null) sw.Close();
|
|
if (ms != null) ms.Close();
|
|
}
|
|
return returnClass;
|
|
}
|
|
/// <summary>
|
|
/// Transform an object into a xml string.
|
|
/// </summary>
|
|
/// <param name="tbs">object To-Be-Serialized</param>
|
|
/// <param name="objectType">Object T value</param>
|
|
/// <returns>xml string</returns>
|
|
[SecurityPermission(SecurityAction.LinkDemand)]
|
|
public static string Serialize(object tbs, Type objectType)
|
|
{
|
|
return Tools.Serialize(tbs, objectType, null);
|
|
}
|
|
/// <summary>
|
|
/// Transform an object into a xml string, adding in known namespaces.
|
|
/// </summary>
|
|
/// <param name="tbs">object To-Be-Serialized</param>
|
|
/// <param name="objectType">Object T value</param>
|
|
/// <param name="ns">Namespace definitions.</param>
|
|
/// <returns>xml string</returns>
|
|
[SecurityPermission(SecurityAction.LinkDemand)]
|
|
public static string Serialize(object tbs, Type objectType, XmlSerializerNamespaces ns)
|
|
{
|
|
XmlSerializer xs = new XmlSerializer(objectType);
|
|
MemoryStream ms = new MemoryStream();
|
|
XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.Unicode);
|
|
StreamReader sr = null;
|
|
string returnXml = null;
|
|
try
|
|
{
|
|
if (ns != null)
|
|
{
|
|
xs.Serialize(xtw, tbs, ns);
|
|
}
|
|
else
|
|
{
|
|
xs.Serialize(xtw, tbs);
|
|
}
|
|
ms.Position = 0;
|
|
sr = new StreamReader(ms, true);
|
|
returnXml = sr.ReadToEnd();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.ErrorFormat("OVF.Tools.Serialize failed {0}", ex.Message);
|
|
throw new CtxUtilitiesException(ex.Message,ex);
|
|
}
|
|
finally
|
|
{
|
|
if (ms != null) ms.Close();
|
|
}
|
|
return returnXml;
|
|
}
|
|
#endregion
|
|
|
|
#region OVA.XML TOOLS
|
|
/// <summary>
|
|
/// This deserializes the OVA.XML File. The issue here is the form of the XML,
|
|
/// Though it is valid XML generic parsing tools cannot handle the same element name
|
|
/// in embedded elements (value in this case, it is the 'root' plus a member of member)
|
|
/// with out the use of name spaces, also the 'value' field can take on one of 3 different
|
|
/// formats:
|
|
/// 1. text (string)
|
|
/// 2. struct
|
|
/// 3. array
|
|
/// Therefore the deserializer will need some help in the processing. The first pass will
|
|
/// give the basic form up to the points of ambiquity, then we can take the xml nodes in their
|
|
/// current context and provide further deserialization.
|
|
/// </summary>
|
|
/// <param name="filename">pathto\\ova.xml</param>
|
|
/// <returns>XenXva Data Structure</returns>
|
|
[SecurityPermission(SecurityAction.LinkDemand)]
|
|
internal static XenXva LoadOvaXml(string filename)
|
|
{
|
|
return DeserializeOvaXml(LoadFile(filename));
|
|
}
|
|
/// <summary>
|
|
/// Load an old style OVA.XML file (version 0.1)
|
|
/// </summary>
|
|
/// <param name="filename">fullpath/filename</param>
|
|
/// <returns>object of type XcAppliance</returns>
|
|
[SecurityPermission(SecurityAction.LinkDemand)]
|
|
internal static XcAppliance LoadOldOvaXml(string filename)
|
|
{
|
|
return LoadFileXml<XcAppliance>(filename);
|
|
}
|
|
/// <summary>
|
|
/// Load an OVF xml File and convert to an EnvelopeType
|
|
/// </summary>
|
|
/// <param name="filename">fullpath/filename</param>
|
|
/// <returns>object EnvelopeType or NULL</returns>
|
|
[SecurityPermission(SecurityAction.LinkDemand)]
|
|
internal static EnvelopeType LoadOvfXml(string appliancePath)
|
|
{
|
|
string ovfFilePath = appliancePath;
|
|
|
|
string extension = Path.GetExtension(appliancePath);
|
|
|
|
if ((String.Compare(extension, ".gz", true) == 0) ||
|
|
(String.Compare(extension, ".bz2", true) == 0) ||
|
|
(String.Compare(extension, ".ova", true) == 0) ||
|
|
(String.Compare(extension, ".tar", true) == 0))
|
|
{
|
|
// Extract the contents of the archive.
|
|
OpenArchive(appliancePath);
|
|
|
|
// Get the OVF name from within the archive because it may not share the base name of the archive.
|
|
Package package = Package.Create(appliancePath);
|
|
|
|
string ovfFileName = package.DescriptorFileName;
|
|
|
|
if (string.IsNullOrEmpty(ovfFileName))
|
|
{
|
|
// An OVF file was not found.
|
|
// Default to the base file name of the archive.
|
|
// Remove the last extension that could be .gz, .bz2, .ova, or .tar.
|
|
ovfFileName = Path.GetFileNameWithoutExtension(appliancePath);
|
|
|
|
extension = Path.GetFileNameWithoutExtension(ovfFileName);
|
|
|
|
if ((String.Compare(extension, ".ova", true) == 0) ||
|
|
(String.Compare(extension, ".tar", true) == 0))
|
|
{
|
|
// Remove the second to last extension that could be ..ova, or .tar.
|
|
ovfFileName = Path.GetFileNameWithoutExtension(ovfFileName);
|
|
}
|
|
|
|
// Add the .ovf extension.
|
|
ovfFileName = ovfFileName + Properties.Settings.Default.ovfFileExtension;
|
|
}
|
|
|
|
string directory = Path.GetDirectoryName(appliancePath);
|
|
|
|
ovfFilePath = Path.Combine(directory, ovfFileName);
|
|
}
|
|
|
|
if (!File.Exists(ovfFilePath))
|
|
{
|
|
log.ErrorFormat("Utilities.LoadOvfXml: File not found: {0}", ovfFilePath);
|
|
throw new FileNotFoundException(string.Format(Messages.FILE_MISSING, ovfFilePath));
|
|
}
|
|
|
|
return DeserializeOvfXml(LoadFile(ovfFilePath));
|
|
}
|
|
/// <summary>
|
|
/// Give a fullpath/filename validate the OVF XML against DMTF v1.0 OVF Schema
|
|
/// </summary>
|
|
/// <param name="ovffilename">fullpath/filename</param>
|
|
/// <returns>true: validates false: failed validation</returns>
|
|
[SecurityPermission(SecurityAction.LinkDemand)]
|
|
public static EnvelopeType DeserializeOvfXml(string ovfxml)
|
|
{
|
|
bool isVmware = false;
|
|
EnvelopeType ovfEnv = null;
|
|
try
|
|
{
|
|
ovfEnv = (EnvelopeType)Deserialize(ovfxml, typeof(EnvelopeType));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.InfoFormat("Attempt reading xml failed. {0}", ex.Message);
|
|
}
|
|
|
|
if (ovfEnv != null && ovfEnv.AnyAttr != null)
|
|
{
|
|
foreach (XmlAttribute xa in ovfEnv.AnyAttr)
|
|
{
|
|
if (xa.Prefix.ToLower().Equals(Properties.Settings.Default.vmwNamespacePrefix) ||
|
|
xa.NamespaceURI.Equals(Properties.Settings.Default.vmwNameSpace) ||
|
|
xa.Prefix.ToLower() == Properties.Settings.Default.VMwareNamespacePrefix ||
|
|
xa.NamespaceURI == Properties.Settings.Default.VMwareNamespace)
|
|
{
|
|
isVmware = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//always call the vc4 conversion; even if the ovf is newer the
|
|
//replacements in the method (if they happen) are harmless
|
|
//and the only cost is the re-deserialization of the xml
|
|
if (isVmware)
|
|
ovfEnv = LoadVmw40OvfXml(ovfxml);
|
|
}
|
|
if (ovfEnv == null)
|
|
{
|
|
ovfEnv = LoadVmw35OvfXml(ovfxml);
|
|
log.Error("Last Change Convert died.");
|
|
}
|
|
|
|
return ovfEnv;
|
|
}
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="ovffilename"></param>
|
|
/// <returns></returns>
|
|
[SecurityPermission(SecurityAction.LinkDemand)]
|
|
public static bool ValidateXmlToSchema(string ovffilename)
|
|
{
|
|
bool isValid = false;
|
|
ValidationEventHandler eventHandler = new ValidationEventHandler(ShowSchemaValidationCompileErrors);
|
|
string currentPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
|
string xmlNamespaceSchemaFilename = Path.Combine(currentPath, Properties.Settings.Default.xmlNamespaceSchemaLocation);
|
|
string cimCommonSchemaFilename = Path.Combine(currentPath, Properties.Settings.Default.cimCommonSchemaLocation);
|
|
string cimRASDSchemaFilename = Path.Combine(currentPath, Properties.Settings.Default.cimRASDSchemaLocation);
|
|
string cimVSSDSchemaFilename = Path.Combine(currentPath, Properties.Settings.Default.cimVSSDSchemaLocation);
|
|
string ovfSchemaFilename = Path.Combine(currentPath, Properties.Settings.Default.ovfEnvelopeSchemaLocation);
|
|
string wsseSchemaFilename = Path.Combine(currentPath, Properties.Settings.Default.wsseSchemaLocation);
|
|
string xencSchemaFilename = Path.Combine(currentPath, Properties.Settings.Default.xencSchemaLocation);
|
|
string wsuSchemaFilename = Path.Combine(currentPath, Properties.Settings.Default.wsuSchemaLocation);
|
|
string xmldsigSchemaFilename = Path.Combine(currentPath, Properties.Settings.Default.xmldsigSchemaLocation);
|
|
|
|
// Allow use of xmlStream in finally block.
|
|
FileStream xmlStream = null;
|
|
|
|
try
|
|
{
|
|
string ovfname = ovffilename;
|
|
string ext = Path.GetExtension(ovffilename);
|
|
|
|
if (!string.IsNullOrEmpty(ext) && (ext.ToLower().EndsWith("gz") || ext.ToLower().EndsWith("bz2")))
|
|
{
|
|
ovfname = Path.GetFileNameWithoutExtension(ovffilename);
|
|
}
|
|
|
|
ext = Path.GetExtension(ovfname);
|
|
|
|
if (!string.IsNullOrEmpty(ext) && ext.ToLower().EndsWith("ova"))
|
|
{
|
|
ovfname = Path.GetFileNameWithoutExtension(ovfname) + ".ovf";
|
|
}
|
|
|
|
ext = Path.GetExtension(ovfname);
|
|
|
|
if (!ext.ToLower().EndsWith("ovf"))
|
|
{
|
|
throw new InvalidDataException("OVF.ValidateXmlToSchema: Incorrect filename: " + ovfname);
|
|
}
|
|
|
|
xmlStream = new FileStream(ovfname, FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
XmlReaderSettings settings = new XmlReaderSettings();
|
|
settings.DtdProcessing = DtdProcessing.Parse; //Upgrading to .Net 4.0: ProhibitDtd=false is obsolete, this line is the replacement according to: http://msdn.microsoft.com/en-us/library/system.xml.xmlreadersettings.prohibitdtd%28v=vs.100%29.aspx
|
|
XmlSchema schema = new XmlSchema();
|
|
bool useOnlineSchema = Convert.ToBoolean(Properties.Settings.Default.useOnlineSchema);
|
|
if (useOnlineSchema)
|
|
{
|
|
settings.Schemas.Add(null, Properties.Settings.Default.dsp8023OnlineSchema);
|
|
}
|
|
else
|
|
{
|
|
settings.Schemas.Add("http://www.w3.org/XML/1998/namespace", xmlNamespaceSchemaFilename);
|
|
settings.Schemas.Add("http://schemas.dmtf.org/wbem/wscim/1/common", cimCommonSchemaFilename);
|
|
settings.Schemas.Add("http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData", cimVSSDSchemaFilename);
|
|
settings.Schemas.Add("http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData", cimRASDSchemaFilename);
|
|
settings.Schemas.Add("http://schemas.dmtf.org/ovf/envelope/1", ovfSchemaFilename);
|
|
settings.Schemas.Add("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", wsseSchemaFilename);
|
|
settings.Schemas.Add("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", wsuSchemaFilename);
|
|
//settings.Schemas.Add("http://www.w3.org/2001/04/xmlenc#", xencSchemaFilename);
|
|
//settings.Schemas.Add("http://www.w3.org/2000/09/xmldsig#", xmldsigSchemaFilename);
|
|
}
|
|
settings.ValidationType = ValidationType.Schema;
|
|
XmlReader reader = XmlReader.Create(xmlStream,settings);
|
|
while (reader.Read()){}
|
|
isValid = true;
|
|
|
|
}
|
|
catch (XmlException xmlex)
|
|
{
|
|
log.ErrorFormat("ValidateXmlToSchema XML Exception: {0}", xmlex.Message);
|
|
throw new Exception(xmlex.Message, xmlex);
|
|
}
|
|
catch (XmlSchemaException schemaex)
|
|
{
|
|
log.ErrorFormat("ValidateXmlToSchema Schema Exception: {0}", schemaex.Message);
|
|
throw new Exception(schemaex.Message, schemaex);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.ErrorFormat("ValidateXmlToSchema Exception: {0}", ex.Message);
|
|
throw new Exception(ex.Message, ex);
|
|
}
|
|
finally
|
|
{
|
|
xmlStream.Close();
|
|
}
|
|
return isValid;
|
|
}
|
|
/// <summary>
|
|
/// Attempt to validate an object's property to ensure it is not null and contains a value
|
|
/// uses reflection into the provided object to find the named property.
|
|
/// </summary>
|
|
/// <param name="name">Name of property to test</param>
|
|
/// <param name="target">object containing property</param>
|
|
/// <returns>true: appears valid, false: something failed</returns>
|
|
[SecurityPermission(SecurityAction.LinkDemand)]
|
|
public static bool ValidateProperty(string name, object target)
|
|
{
|
|
bool isValid = true;
|
|
PropertyInfo[] properties = target.GetType().GetProperties();
|
|
foreach (PropertyInfo property in properties)
|
|
{
|
|
if (property.Name.Equals(name))
|
|
{
|
|
object outervalue = property.GetValue(target, null);
|
|
if (outervalue != null)
|
|
{
|
|
if (outervalue is cimString[])
|
|
{
|
|
cimString[] strvalue = (cimString[])property.GetValue(target, null);
|
|
if (!(strvalue != null &&
|
|
strvalue.Length > 0 &&
|
|
strvalue[0] != null &&
|
|
!string.IsNullOrEmpty(strvalue[0].Value)))
|
|
{
|
|
isValid = false;
|
|
}
|
|
}
|
|
else if (outervalue is Msg_Type[])
|
|
{
|
|
Msg_Type[] msgtype = (Msg_Type[])property.GetValue(target, null);
|
|
if (!(msgtype != null &&
|
|
msgtype.Length > 0 &&
|
|
msgtype[0] != null &&
|
|
!string.IsNullOrEmpty(msgtype[0].Value)))
|
|
{
|
|
isValid = false;
|
|
}
|
|
}
|
|
else if (!outervalue.GetType().IsPrimitive)
|
|
{
|
|
// The purpose of this code is still unclear.
|
|
// It seems meant to handle complex types like XenOvf.Definitions.CimString.
|
|
object innervalue = property.GetValue(target, null);
|
|
Type innertype = innervalue.GetType();
|
|
PropertyInfo innerproperty = innertype.GetProperty("Value");
|
|
object targetvalue = null;
|
|
if (innerproperty == null)
|
|
{
|
|
// There is no property.
|
|
// The outertype is likely a standard .Net type like String and not an alias for a type like XenOvf.Definitions.CimString.
|
|
// A case that causes a failure is when the target type is XenOvfEnvelope and the property name is "Name".
|
|
targetvalue = innervalue;
|
|
}
|
|
else
|
|
{
|
|
// The outertype is alias for a type like XenOvf.Definitions.CimString.
|
|
targetvalue = innerproperty.GetValue(outervalue, null);
|
|
}
|
|
|
|
if (targetvalue != null)
|
|
{
|
|
if (targetvalue is string)
|
|
{
|
|
if (((string)targetvalue).Length <= 0)
|
|
{
|
|
isValid = false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
isValid = false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
isValid = false;
|
|
}
|
|
}
|
|
}
|
|
return isValid;
|
|
}
|
|
/// <summary>
|
|
/// create an XenXva object give the OVA.XML version 2 string.
|
|
/// </summary>
|
|
/// <param name="ovaxml">xml string</param>
|
|
/// <returns>XenXva object</returns>
|
|
[SecurityPermission(SecurityAction.LinkDemand)]
|
|
public static XenXva DeserializeOvaXml(string ovaxml)
|
|
{
|
|
XenXva xenobj = (XenXva)Tools.Deserialize(ovaxml, typeof(XenXva));
|
|
xenobj.xenstruct.xenmember = DeserializeXenMembers(xenobj.xenstruct.xenmember);
|
|
return xenobj;
|
|
}
|
|
/// <summary>
|
|
/// Generic Method Attempt: Load and XML file and create
|
|
/// an object of type T
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of object to create</typeparam>
|
|
/// <param name="filename">fullpath/filename</param>
|
|
/// <returns>object of type T</returns>
|
|
[SecurityPermission(SecurityAction.LinkDemand)]
|
|
public static T LoadFileXml<T>(string filename)
|
|
{
|
|
return (T)Deserialize(LoadFile(filename), typeof(T));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region STREAM
|
|
public static bool CancelStreamCopy = false;
|
|
public static void StreamCopy(Stream Input, Stream Output)
|
|
{
|
|
long bufsize = 2 * MB;
|
|
byte[] block = new byte[bufsize];
|
|
ulong p = 0;
|
|
int n = 0;
|
|
while (true)
|
|
{
|
|
n = Input.Read(block, 0, block.Length);
|
|
if (n <= 0) break;
|
|
Output.Write(block, 0, n);
|
|
p += (ulong)n;
|
|
if (CancelStreamCopy) break;
|
|
ClearBuffer(block);
|
|
}
|
|
Output.Flush();
|
|
CancelStreamCopy = false; // Reset so next call will start.
|
|
}
|
|
private static void ClearBuffer(byte[] block)
|
|
{
|
|
for (int i = 0; i < block.Length; i++) block[i] = 0;
|
|
}
|
|
#endregion
|
|
|
|
|
|
private static void ShowSchemaValidationCompileErrors(object sender, ValidationEventArgs args)
|
|
{
|
|
log.ErrorFormat("ShowSchemaValidationCompileErrors: {0}", args.Message);
|
|
}
|
|
private static bool ValidateField(string name, object target)
|
|
{
|
|
bool isValid = true;
|
|
|
|
return isValid;
|
|
}
|
|
private static EnvelopeType LoadVmw40OvfXml(string ovfxml)
|
|
{
|
|
if (string.IsNullOrEmpty(ovfxml))
|
|
return null;
|
|
|
|
// With what VMWare currently publishes with VC4, we need to update the XML
|
|
|
|
ovfxml = ovfxml.Replace("<References", "<ovf:References").Replace("</References", "</ovf:References")
|
|
.Replace("<Section", "<ovf:Section").Replace("</Section", "</ovf:Section")
|
|
.Replace("<Content", "<ovf:Content").Replace("</Content", "</ovf:Content")
|
|
.Replace("<File", "<ovf:File").Replace("</File", "</ovf:File")
|
|
.Replace("<Disk", "<ovf:Disk").Replace("</Disk", "</ovf:Disk")
|
|
.Replace("<Info", "<ovf:Info").Replace("</Info", "</ovf:Info")
|
|
.Replace("<Network", "<ovf:Network").Replace("</Network", "</ovf:Network")
|
|
.Replace("<Description", "<ovf:Description").Replace("</Description", "</ovf:Description")
|
|
.Replace("<License", "<ovf:License").Replace("</License", "</ovf:License")
|
|
.Replace("<System", "<ovf:System").Replace("</System", "</ovf:System")
|
|
.Replace("<rasd:InstanceId", "<rasd:InstanceID").Replace("</rasd:InstanceId", "</rasd:InstanceID")
|
|
.Replace("<Item", "<ovf:Item").Replace("</Item", "</ovf:Item");
|
|
|
|
EnvelopeType ovfEnv = (EnvelopeType)Deserialize(ovfxml, typeof(EnvelopeType));
|
|
log.Debug("Finished LoadVmw40OvfXml");
|
|
return ovfEnv;
|
|
}
|
|
private static EnvelopeType LoadVmw35OvfXml(string ovfxml)
|
|
{
|
|
if (string.IsNullOrEmpty(ovfxml))
|
|
return null;
|
|
|
|
// With what VMWare currently publishes with VC35, we need to update the XML
|
|
|
|
ovfxml = ovfxml.Replace(Properties.Settings.Default.vmwEnvelopeNamespace, Properties.Settings.Default.cimEnvelopeURI)
|
|
.Replace("<References", "<ovf:References").Replace("</References", "</ovf:References")
|
|
.Replace("<Section", "<ovf:Section").Replace("</Section", "</ovf:Section")
|
|
.Replace("<Content", "<ovf:Content").Replace("</Content", "</ovf:Content")
|
|
.Replace("<File", "<ovf:File").Replace("</File", "</ovf:File")
|
|
.Replace("<Disk", "<ovf:Disk").Replace("</Disk", "</ovf:Disk")
|
|
.Replace("<Info", "<ovf:Info").Replace("</Info", "</ovf:Info")
|
|
.Replace("<Network", "<ovf:Network").Replace("</Network", "</ovf:Network")
|
|
.Replace("<Description", "<ovf:Description").Replace("</Description", "</ovf:Description")
|
|
.Replace("<License", "<ovf:License").Replace("</License", "</ovf:License")
|
|
.Replace("<System", "<ovf:System").Replace("</System", "</ovf:System")
|
|
.Replace("<rasd:InstanceId", "<rasd:InstanceID").Replace("</rasd:InstanceId", "</rasd:InstanceID")
|
|
.Replace("<Item", "<ovf:Item").Replace("</Item", "</ovf:Item");
|
|
|
|
EnvelopeType ovfEnv = (EnvelopeType)Deserialize(ovfxml, typeof(EnvelopeType));
|
|
log.Debug("Finished LoadVmw35OvfXml");
|
|
return ovfEnv;
|
|
}
|
|
private static XenMember[] DeserializeXenMembers(XenMember[] members)
|
|
{
|
|
foreach (XenMember xm in members)
|
|
{
|
|
if (xm.xenvalue is XmlNode[])
|
|
{
|
|
foreach (XmlNode xn in (XmlNode[])xm.xenvalue)
|
|
{
|
|
xm.xenvalue = DeserializeContent(xn);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xm.xenvalue = "";
|
|
}
|
|
}
|
|
return members;
|
|
}
|
|
private static object DeserializeContent(XmlNode node)
|
|
{
|
|
object xenobj = null;
|
|
if (node.NodeType == XmlNodeType.Element && node.Name.ToLower().Equals("struct"))
|
|
{
|
|
xenobj = Tools.Deserialize(node.OuterXml, typeof(XenStruct));
|
|
XenStruct xs = (XenStruct)xenobj;
|
|
if (xs.xenmember != null && xs.xenmember.Length > 0)
|
|
{
|
|
DeserializeXenMembers(xs.xenmember);
|
|
}
|
|
}
|
|
else if (node.NodeType == XmlNodeType.Element && node.Name.ToLower().Equals("data"))
|
|
{
|
|
xenobj = Tools.Deserialize(node.OuterXml, typeof(XenData));
|
|
}
|
|
else if (node.NodeType == XmlNodeType.Element && node.Name.ToLower().Equals("array"))
|
|
{
|
|
xenobj = Tools.Deserialize(node.OuterXml, typeof(XenArray));
|
|
XenArray xa = (XenArray)xenobj;
|
|
if (xa.xendata.xenvalue != null && xa.xendata.xenvalue[0] is XmlNode[])
|
|
{
|
|
List<object> values = new List<object>();
|
|
for (int i = 0; i < xa.xendata.xenvalue.Length; i++ )
|
|
{
|
|
values.Add(DeserializeContent((XmlNode)((XmlNode[])xa.xendata.xenvalue[i])[0]));
|
|
}
|
|
xa.xendata.xenvalue = values.ToArray();
|
|
}
|
|
else if (xa.xendata != null && xa.xendata.xenvalue != null && xa.xendata.xenvalue.Length > 0)
|
|
{
|
|
foreach (XenValue xv in xa.xendata.xenvalue)
|
|
{
|
|
if (xv.xenstruct != null)
|
|
{
|
|
DeserializeXenMembers(xv.xenstruct.xenmember);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xa.xendata.xenvalue = null;
|
|
}
|
|
}
|
|
else if (node.NodeType == XmlNodeType.Text )
|
|
{
|
|
xenobj = node.Value;
|
|
}
|
|
|
|
return xenobj;
|
|
}
|
|
private static T DeserializeNode<T>(XmlNode node)
|
|
{
|
|
XmlSerializer xs = new XmlSerializer(typeof(T));
|
|
try
|
|
{
|
|
return (T)xs.Deserialize(new XmlNodeReader(node));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.ErrorFormat("Tools.Deserialize FAILED {0}", ex.Message);
|
|
}
|
|
return (T) new object();
|
|
}
|
|
private static void OpenArchive(string filename)
|
|
{
|
|
log.InfoFormat("Utilities.OpenArchive: Opening OVF Archive: {0}", filename);
|
|
if (!File.Exists(filename))
|
|
{
|
|
log.ErrorFormat("Utilities.OpenArchive: Cannot find file: {0}", filename);
|
|
throw new FileNotFoundException(string.Format(Messages.FILE_MISSING, filename));
|
|
}
|
|
OVF.OpenOva(Path.GetDirectoryName(filename), Path.GetFileName(filename));
|
|
}
|
|
/// <summary>
|
|
/// Specific Exception starting from XenOvf.Utilities
|
|
/// </summary>
|
|
public class CtxUtilitiesException : Exception
|
|
{
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
public CtxUtilitiesException() : base() { }
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
public CtxUtilitiesException(string message) : base(message) { }
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
public CtxUtilitiesException(string message, Exception exception) : base(message, exception) { }
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
public CtxUtilitiesException(SerializationInfo serialinfo, StreamingContext context) : base(serialinfo, context) { }
|
|
}
|
|
}
|
|
}
|