Example #1
0
 /// <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);
 }
Example #2
0
 /// <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;
 }
Example #4
0
        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);
        }
Example #5
0
        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;
        }
Example #6
0
 /// <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);
 }
Example #7
0
 /// <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();
 }
Example #8
0
 /// <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);
 }
Example #9
0
 /// <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();
                }
            }
        }
Example #11
0
 /// <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;
 }