/// <summary> /// Adds a disk to the volume manager. /// </summary> /// <param name="disk">The disk to add</param> /// <returns>The GUID the volume manager will use to identify the disk</returns> public string AddDisk(VirtualDisk disk) { _needScan = true; int ordinal = _disks.Count; _disks.Add(disk); return GetDiskId(ordinal); }
/// <summary> /// Initializes a new instance of the PhysicalVolumeInfo class. /// </summary> /// <param name="diskId">The containing disk's identity.</param> /// <param name="disk">The disk containing the partition.</param> /// <param name="partitionInfo">Information about the partition.</param> /// <remarks>Use this constructor to represent a (BIOS or GPT) partition.</remarks> internal PhysicalVolumeInfo( string diskId, VirtualDisk disk, PartitionInfo partitionInfo) { _diskId = diskId; _disk = disk; _streamOpener = partitionInfo.Open; _type = partitionInfo.VolumeType; _partitionInfo = partitionInfo; }
/// <summary> /// Creates an instance representing a (BIOS or GPT) partition. /// </summary> /// <param name="diskId">The containing disk's identity</param> /// <param name="disk">The disk containing the partition</param> /// <param name="partitionInfo">Information about the partition</param> internal PhysicalVolumeInfo( string diskId, VirtualDisk disk, PartitionInfo partitionInfo ) { _diskId = diskId; _disk = disk; _streamOpener = partitionInfo.Open; _type = (partitionInfo is GuidPartitionInfo) ? PhysicalVolumeType.GptPartition : PhysicalVolumeType.BiosPartition; _partitionInfo = partitionInfo; }
private string GetDiskId(int ordinal) { VirtualDisk disk = _disks[ordinal]; if (disk.IsPartitioned) { Guid guid = disk.Partitions.DiskGuid; if (guid != Guid.Empty) { return("DG" + guid.ToString("B")); } } int sig = disk.Signature; if (sig != 0) { return("DS" + sig.ToString("X8", CultureInfo.InvariantCulture)); } return("DO" + ordinal); }
internal List<XenRef<VDI>> ImportFile(Session xenSession, string vmname, string pathToOvf, string filename, string compression, string version, string passcode, string sruuid, string description, string vdiuuid) { List<XenRef<VDI>> vdiRef = new List<XenRef<VDI>>(); // Get the disk transport method from the configuration in XenOvfTransport.Properties.Settings.TransferType. TransferType useTransport = (TransferType)Enum.Parse(typeof(TransferType), Properties.Settings.Default.TransferType, true); TransferMethod useTransferMethod = TransferMethod.Image; string sourcefile = filename; string encryptfilename = null; string uncompressedfilename = null; string destinationPath = Properties.Settings.Default.xenISOMount; string StartPath = Directory.GetCurrentDirectory(); Directory.SetCurrentDirectory(pathToOvf); Stream dataStream = null; long dataCapacity = 0; #region SET UP TRANSPORT if (filename != null) { if (IsKnownURIType(filename)) { Uri fileUri = new Uri(filename); filename = DownloadFileAsync(fileUri, 0); sourcefile = filename; } if (File.Exists(filename)) { string ext = Path.GetExtension(filename); try { encryptfilename = "enc_" + filename; uncompressedfilename = "unc_" + filename; // OK.. lets see is the file encrypted? #region ENCRYPTION if (passcode != null) { var statusMessage = string.Format(Messages.START_FILE_DECRYPTION, filename); OnUpdate(new XenOvfTranportEventArgs(XenOvfTranportEventType.MarqueeOn, "Security", statusMessage)); log.Debug(statusMessage); OVF.DecryptToTempFile(EncryptionClass, filename, version, passcode, encryptfilename); sourcefile = encryptfilename; statusMessage += Messages.COMPLETE; OnUpdate(new XenOvfTranportEventArgs(XenOvfTranportEventType.MarqueeOff, "Security", statusMessage)); } #endregion #region COMPRESSION // Identity == no compression, it is meant when a URL is used to identify the compression during transport. if (compression != null && !compression.ToLower().Equals("none") && !compression.ToLower().Equals("identity")) { // gz is the only understood 'compressed' format, strip it.. // the OVF is marked with "compressed=gzip" therefor it will get decompress // correctly and use with its disk extension (vmdk/vhd/vdi)... if (ext.ToLower().EndsWith(".gz")) { string newfilename = Path.GetFileNameWithoutExtension(uncompressedfilename); uncompressedfilename = newfilename; ext = Path.GetExtension(uncompressedfilename); } var statusMessage = string.Format(Messages.START_FILE_EXPANSION, filename); OnUpdate(new XenOvfTranportEventArgs(XenOvfTranportEventType.MarqueeOn, "Compression", statusMessage)); var ovfCompressor = new OvfCompressor(); ovfCompressor.UncompressFile(sourcefile, uncompressedfilename, compression); if (File.Exists(encryptfilename)) { File.Delete(encryptfilename); } sourcefile = uncompressedfilename; statusMessage += Messages.COMPLETE; OnUpdate(new XenOvfTranportEventArgs(XenOvfTranportEventType.MarqueeOff, "Compression", statusMessage)); } #endregion #region DISK SELECTION bool knownDisk = false; foreach (string diskext in VirtualDisk.SupportedDiskFormats) { if (ext.ToLower().Contains(diskext.ToLower())) { knownDisk = true; break; } } if (knownDisk) { log.DebugFormat("Found file {0} using {1} Stream", filename, ext); vhdDisk = VirtualDisk.OpenDisk(sourcefile, FileAccess.Read); dataStream = vhdDisk.Content; dataCapacity = vhdDisk.Capacity; } else if (ext.ToLower().Contains("wim")) { log.WarnFormat("EXPERIMENTAL CODE: Found file {0} using WIM file structure", filename); wimDisk = new DiscUtils.Wim.WimFile(new FileStream(sourcefile, FileMode.Open, FileAccess.Read)); //wimFS = wimDisk.GetImage(wimDisk.BootImage); dataStream = null; string manifest = wimDisk.Manifest; Wim_Manifest wimManifest = (Wim_Manifest)Tools.Deserialize(manifest, typeof(Wim_Manifest)); ulong imagesize = wimManifest.Image[wimDisk.BootImage].TotalBytes; // <----<<< Image data size wimFileCount = wimManifest.Image[wimDisk.BootImage].FileCount; dataCapacity = (long)(imagesize + AdditionalSpace); useTransferMethod = TransferMethod.Files; } else if (ext.ToLower().Contains("xva")) { log.WarnFormat("EXPERIMENTAL CODE: Found file {0} using XVA Stream (DISK {1} is being imported).", filename, xvadisk); DiscUtils.Xva.VirtualMachine vm = new DiscUtils.Xva.VirtualMachine(new FileStream(sourcefile, FileMode.Open, FileAccess.Read)); int i = 0; foreach (DiscUtils.Xva.Disk d in vm.Disks) { if (i == xvadisk) { vhdDisk = d; break; } } dataStream = vhdDisk.Content; dataCapacity = vhdDisk.Capacity; } else if (ext.ToLower().EndsWith("iso")) { if (string.IsNullOrEmpty(sruuid)) { useTransport = TransferType.Skip; } else { //DiscUtils.Iso9660.CDReader cdr = new DiscUtils.Iso9660.CDReader(File.OpenRead(filename), true); dataStream = File.OpenRead(filename); dataCapacity = dataStream.Length + (512 * KB); // Xen does 512KB rounding this is to ensure it doesn't round down below size. } } #endregion } catch (Exception ex) { log.Error(Messages.ISCSI_ERROR_CANNOT_OPEN_DISK); throw new Exception(Messages.ISCSI_ERROR_CANNOT_OPEN_DISK, ex); } } else { throw new FileNotFoundException(string.Format(Messages.FILE_MISSING, filename)); } } else { log.Error(Messages.ERROR_FILE_NAME_NULL); throw new InvalidDataException(Messages.ERROR_FILE_NAME_NULL); } #endregion try { #region SEE IF TARGET SR HAS ENOUGH SPACE if (useTransport == TransferType.UploadRawVDI || useTransport == TransferType.iSCSI) { long freespace; string contenttype = string.Empty; if(vdiuuid != null) { XenRef<VDI> vdiLookup = VDI.get_by_uuid(xenSession, vdiuuid); freespace = VDI.get_virtual_size(xenSession, vdiLookup); } else { XenRef<SR> srRef = SR.get_by_uuid(xenSession, sruuid); long size = SR.get_physical_size(xenSession, srRef); long usage = SR.get_physical_utilisation(xenSession, srRef); contenttype = SR.get_content_type(xenSession, srRef); freespace = size - usage; } if (freespace <= dataCapacity) { string message = string.Format(Messages.NOT_ENOUGH_SPACE_IN_SR, sruuid, Convert.ToString(vhdDisk.Capacity), filename); log.Error(message); throw new IOException(message); } } #endregion #region UPLOAD FILE switch (useTransport) { case TransferType.UploadRawVDI: { vdiRef.Add(UploadRawVDI(xenSession, sruuid, vmname, dataStream, dataCapacity, description)); break; } case TransferType.iSCSI: { if (useTransferMethod == TransferMethod.Image) { vdiRef.Add(UploadiSCSI(xenSession, sruuid, vmname, dataStream, dataCapacity, description, vdiuuid)); } else { for (int i = 0; i < wimDisk.ImageCount; i++) { Wim_Manifest wimManifest = (Wim_Manifest)Tools.Deserialize(wimDisk.Manifest, typeof(Wim_Manifest)); wimFileCount = wimManifest.Image[i].FileCount; int wimArch = wimManifest.Image[i].Windows.Architecture; vdiRef.Add(UploadiSCSIbyWimFile(xenSession, sruuid, vmname, wimDisk, i, dataCapacity, wimFileCount, wimArch, "")); } } break; } case TransferType.Skip: { log.Info("ImportFile: Upload Skipped"); break; } default: { log.Error(Messages.UNSUPPORTED_TRANSPORT); throw new InvalidDataException(Messages.UNSUPPORTED_TRANSPORT); } } #endregion } catch (Exception ex) { if (ex is OperationCanceledException) throw; throw new Exception(Messages.FILE_TRANSPORT_FAILED, ex); } finally { if (vhdDisk != null) { vhdDisk.Dispose(); vhdDisk = null; } if (wimDisk != null) { wimDisk = null; } if (File.Exists(encryptfilename)) { File.Delete(encryptfilename); } if (File.Exists(uncompressedfilename)) { File.Delete(uncompressedfilename); } } Directory.SetCurrentDirectory(StartPath); log.DebugFormat("OVF.Import.ImportFile leave: created {0} VDIs", vdiRef.Count); return vdiRef; }
/// <summary> /// Creates a new instance from the contents of an existing disk. /// </summary> /// <param name="initialDisk">The initial disk to add.</param> public VolumeManager(VirtualDisk initialDisk) : this() { AddDisk(initialDisk); }
/// <summary> /// Gets the physical volumes held on a disk. /// </summary> /// <param name="disk">The disk to inspect</param> /// <returns>An array of volumes</returns> /// <remarks>If the disk isn't partitioned, this method returns the entire disk contents /// as a single volume.</remarks> public static PhysicalVolumeInfo[] GetPhysicalVolumes(VirtualDisk disk) { return new VolumeManager(disk).GetPhysicalVolumes(); }
/// <summary> /// Initializes a new instance of the VolumeManager class. /// </summary> /// <param name="initialDisk">The initial disk to add.</param> public VolumeManager(VirtualDisk initialDisk) : this() { AddDisk(initialDisk); }
/// <summary> /// Gets the physical volumes held on a disk. /// </summary> /// <param name="disk">The disk to inspect.</param> /// <returns>An array of volumes.</returns> /// <remarks>If the disk isn't partitioned, this method returns the entire disk contents /// as a single volume.</remarks> public static PhysicalVolumeInfo[] GetPhysicalVolumes(VirtualDisk disk) { return(new VolumeManager(disk).GetPhysicalVolumes()); }
/// <summary> /// Opens an existing virtual disk. /// </summary> /// <param name="path">The path of the virtual disk to open, can be a URI.</param> /// <param name="forceType">Force the detected disk type (<c>null</c> to detect).</param> /// <param name="access">The desired access to the disk.</param> /// <param name="user">The user name to use for authentication (if necessary).</param> /// <param name="password">The password to use for authentication (if necessary).</param> /// <returns>The Virtual Disk, or <c>null</c> if an unknown disk format.</returns> /// <remarks> /// The detected disk type can be forced by specifying a known disk type: /// RAW, VHD, VMDK, etc. /// </remarks> public static VirtualDisk OpenDisk(string path, string forceType, FileAccess access, string user, string password) { Uri uri = PathToUri(path); VirtualDisk result = null; Type transportType; if (!VirtualDiskManager.DiskTransports.TryGetValue(uri.Scheme.ToUpperInvariant(), out transportType)) { throw new FileNotFoundException(string.Format(CultureInfo.InvariantCulture, "Unable to parse path '{0}'", path), path); } VirtualDiskTransport transport = (VirtualDiskTransport)Activator.CreateInstance(transportType); try { transport.Connect(uri, user, password); if (transport.IsRawDisk) { result = transport.OpenDisk(access); } else { bool foundFactory; VirtualDiskFactory factory; if (!string.IsNullOrEmpty(forceType)) { foundFactory = VirtualDiskManager.TypeMap.TryGetValue(forceType, out factory); } else { string extension = Path.GetExtension(uri.AbsolutePath).ToUpperInvariant(); if (extension.StartsWith(".", StringComparison.Ordinal)) { extension = extension.Substring(1); } foundFactory = VirtualDiskManager.ExtensionMap.TryGetValue(extension, out factory); } if (foundFactory) { result = factory.OpenDisk(transport.GetFileLocator(), transport.GetFileName(), access); } } if (result != null) { result._transport = transport; transport = null; } return(result); } finally { if (transport != null) { transport.Dispose(); } } }
/// <summary> /// Initializes a new instance of the PhysicalVolumeInfo class. /// </summary> /// <param name="diskId">The identity of the disk</param> /// <param name="disk">The disk itself</param> /// <remarks>Use this constructor to represent an entire disk as a single volume.</remarks> internal PhysicalVolumeInfo( string diskId, VirtualDisk disk) { _diskId = diskId; _disk = disk; _streamOpener = delegate { return new SubStream(disk.Content, Ownership.None, 0, disk.Capacity); }; _type = PhysicalVolumeType.EntireDisk; }