// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft. All rights reserved. namespace Microsoft.Samples.HyperV.Storage { using System; using System.Diagnostics.CodeAnalysis; using System.Xml; using System.Globalization; using System.Management; using Microsoft.Samples.HyperV.Common; /// /// The different types of virtual hard disks. /// public enum VirtualHardDiskType { /// /// Unknown format. /// Unknown = 0, /// /// Fixed size virtual hard disk type. /// FixedSize = 2, /// /// Dynamically expanding virtual hard disk type. /// DynamicallyExpanding = 3, /// /// Differencing virtual hard disk type. /// Differencing = 4 } /// /// The different formats of virtual hard disks. /// public enum VirtualHardDiskFormat { /// /// Unknown format. /// Unknown = 0, /// /// VHD format. /// Vhd = 2, /// /// VHDX format. /// [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Vhdx")] Vhdx = 3 } /// /// Contains information about a virtual hard disk file. /// public class VirtualHardDiskSettingData { private VirtualHardDiskType m_DiskType; private VirtualHardDiskFormat m_DiskFormat; private string m_Path; private string m_ParentPath; private Int64 m_MaxInternalSize; private Int32 m_BlockSize; private Int32 m_LogicalSectorSize; private Int32 m_PhysicalSectorSize; /// /// Initializes a new class. /// /// The type of the disk. /// The format of the disk. /// The disk's path. /// The path of the disk's parent. This parameter should be null if /// the disk does not have a parent. /// The maximum disk size as viewable by the virtual machine. /// /// The block size of the virtual hard disk. /// The logical sector size of the virtual hard disk. /// The physical sector size of the virtual hard disk. /// public VirtualHardDiskSettingData( VirtualHardDiskType diskType, VirtualHardDiskFormat diskFormat, string path, string parentPath, Int64 maxInternalSize, Int32 blockSize, Int32 logicalSectorSize, Int32 physicalSectorSize) { m_DiskType = diskType; m_DiskFormat = diskFormat; m_Path = path; m_ParentPath = parentPath; m_MaxInternalSize = maxInternalSize; m_BlockSize = blockSize; m_LogicalSectorSize = logicalSectorSize; m_PhysicalSectorSize = physicalSectorSize; } /// /// Gets the type of this disk. /// public VirtualHardDiskType DiskType { get { return m_DiskType; } } /// /// Gets the format of this disk. /// public VirtualHardDiskFormat DiskFormat { get { return m_DiskFormat; } } /// /// Gets the path of the disk. /// public string Path { get { return m_Path; } } /// /// Gets the parent of the disk. If the disk does not have a parent this property is null. /// public string ParentPath { get { return m_ParentPath; } } /// /// Gets the disk's maximum size as viewable by the virtual machine. /// public long MaxInternalSize { get { return m_MaxInternalSize; } } /// /// Gets the block size of the virtual hard disk /// public long BlockSize { get { return m_BlockSize; } } /// /// Gets the logical sector size of the virtual hard disk /// public long LogicalSectorSize { get { return m_LogicalSectorSize; } } /// /// Gets the physical sector size of the virtual hard disk /// public long PhysicalSectorSize { get { return m_PhysicalSectorSize; } } /// /// Gets the embedded instance string usable by WMI /// /// Embedded instance string usable by WMI. public string GetVirtualHardDiskSettingDataEmbeddedInstance( string serverName, string namespacePath) { ManagementPath path = new ManagementPath() { Server = serverName, NamespacePath = namespacePath, ClassName = "Msvm_VirtualHardDiskSettingData" }; using (ManagementClass settingsClass = new ManagementClass(path)) { using (ManagementObject settingsInstance = settingsClass.CreateInstance()) { settingsInstance["Type"] = m_DiskType; settingsInstance["Format"] = m_DiskFormat; settingsInstance["Path"] = m_Path; settingsInstance["ParentPath"] = m_ParentPath; settingsInstance["MaxInternalSize"] = m_MaxInternalSize; settingsInstance["BlockSize"] = m_BlockSize; settingsInstance["LogicalSectorSize"] = m_LogicalSectorSize; settingsInstance["PhysicalSectorSize"] = m_PhysicalSectorSize; string settingsInstanceString = settingsInstance.GetText(TextFormat.WmiDtd20); return settingsInstanceString; } } } /// /// Parses the hard disk SettingData embedded instance returned from the server and /// creates a new VirtualHardDiskSettingData with that information. /// /// The disk SettingData embedded instance. /// A object with the data contained in /// the embedded instance. /// If either param is null. /// If there was a problem parsing the embedded instance. /// public static VirtualHardDiskSettingData Parse( string embeddedInstance) { VirtualHardDiskType type = VirtualHardDiskType.Unknown; VirtualHardDiskFormat format = VirtualHardDiskFormat.Unknown; string path = string.Empty; string parentPath = string.Empty; Int64 maxInternalSize = 0; Int32 blockSize = 0; Int32 logicalSectorSize = 0; Int32 physicalSectorSize = 0; XmlDocument doc = new XmlDocument(); doc.LoadXml(embeddedInstance); XmlNodeList nodelist = doc.SelectNodes(@"/INSTANCE/@CLASSNAME"); if (nodelist.Count != 1) { throw new FormatException(); } if (nodelist[0].Value != "Msvm_VirtualHardDiskSettingData") { throw new FormatException(); } // Disk type nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'Type']/VALUE/child::text()"); if (nodelist.Count != 1) { throw new FormatException(); } int itype = int.Parse(nodelist[0].Value, NumberStyles.None, CultureInfo.InvariantCulture); type = (VirtualHardDiskType)itype; if (type != VirtualHardDiskType.Differencing && type != VirtualHardDiskType.DynamicallyExpanding && type != VirtualHardDiskType.FixedSize) { // The type integer returned is of an unrecognized type. throw new FormatException(); } // Disk format nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'Format']/VALUE/child::text()"); if (nodelist.Count != 1) { throw new FormatException(); } int iformat = int.Parse(nodelist[0].Value, NumberStyles.None, CultureInfo.InvariantCulture); format = (VirtualHardDiskFormat)iformat; if (format != VirtualHardDiskFormat.Vhd && format != VirtualHardDiskFormat.Vhdx) { //The format integer returned is of an unrecognized type. throw new FormatException(); } // Path nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'Path']/VALUE/child::text()"); if (nodelist.Count != 1) { // There can not be multiple parents. throw new FormatException(); } path = nodelist[0].Value; // ParentPath nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'ParentPath']/VALUE/child::text()"); // A nodeList.Count == 0 is okay and indicates that there is no parent. if (nodelist.Count == 1) { parentPath = nodelist[0].Value; } else if (nodelist.Count != 0) { // There can not be multiple parents. throw new FormatException(); } if (type == VirtualHardDiskType.Differencing && string.IsNullOrEmpty(parentPath)) { // Parent path must be set if this is a differencing disk. throw new FormatException(); } // MaxInternalSize nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'MaxInternalSize']/VALUE/child::text()"); if (nodelist.Count != 1) { throw new FormatException(); } maxInternalSize = Int64.Parse(nodelist[0].Value, CultureInfo.InvariantCulture); // BlockSize nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'BlockSize']/VALUE/child::text()"); if (nodelist.Count != 1) { throw new FormatException(); } blockSize = Int32.Parse(nodelist[0].Value, CultureInfo.InvariantCulture); // LogicalSectorSize nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'LogicalSectorSize']/VALUE/child::text()"); if (nodelist.Count != 1) { throw new FormatException(); } logicalSectorSize = Int32.Parse(nodelist[0].Value, CultureInfo.InvariantCulture); // PhysicalSectorSize nodelist = doc.SelectNodes(@"//PROPERTY[@NAME = 'PhysicalSectorSize']/VALUE/child::text()"); if (nodelist.Count != 1) { throw new FormatException(); } physicalSectorSize = Int32.Parse(nodelist[0].Value, CultureInfo.InvariantCulture); return new VirtualHardDiskSettingData(type, format, path, parentPath, maxInternalSize, blockSize, logicalSectorSize, physicalSectorSize); } } }