示例#1
0
 private void LoadDescriptor(Stream s)
 {
     s.Position = 0;
     byte[] header = Utilities.ReadFully(s, (int)Math.Min(Sizes.Sector, s.Length));
     if (header.Length < Sizes.Sector || Utilities.ToUInt32LittleEndian(header, 0) != HostedSparseExtentHeader.VmdkMagicNumber)
     {
         s.Position  = 0;
         _descriptor = new DescriptorFile(s);
         if (_access != FileAccess.Read)
         {
             _descriptor.ContentId = (uint)_rng.Next();
             s.Position            = 0;
             _descriptor.Write(s);
             s.SetLength(s.Position);
         }
     }
     else
     {
         // This is a sparse disk extent, hopefully with embedded descriptor...
         HostedSparseExtentHeader hdr = HostedSparseExtentHeader.Read(header, 0);
         if (hdr.DescriptorOffset != 0)
         {
             Stream descriptorStream = new SubStream(s, hdr.DescriptorOffset * Sizes.Sector, hdr.DescriptorSize * Sizes.Sector);
             _descriptor = new DescriptorFile(descriptorStream);
             if (_access != FileAccess.Read)
             {
                 _descriptor.ContentId     = (uint)_rng.Next();
                 descriptorStream.Position = 0;
                 _descriptor.Write(descriptorStream);
                 byte[] blank = new byte[descriptorStream.Length - descriptorStream.Position];
                 descriptorStream.Write(blank, 0, blank.Length);
             }
         }
     }
 }
示例#2
0
        /// <summary>
        /// Creates a new virtual disk at the specified path.
        /// </summary>
        /// <param name="fileLocator">The object used to locate / create the component files.</param>
        /// <param name="path">The name of the VMDK to create.</param>
        /// <param name="parameters">The desired parameters for the new disk.</param>
        /// <returns>The newly created disk image</returns>
        internal static DiskImageFile Initialize(FileLocator fileLocator, string path, DiskParameters parameters)
        {
            if (parameters.Capacity <= 0)
            {
                throw new ArgumentException("Capacity must be greater than zero", "parameters");
            }

            Geometry geometry = parameters.Geometry ?? DefaultGeometry(parameters.Capacity);

            Geometry biosGeometry;

            if (parameters.BiosGeometry != null)
            {
                biosGeometry = parameters.BiosGeometry;
            }
            else
            {
                biosGeometry = Geometry.MakeBiosSafe(geometry, parameters.Capacity);
            }

            DiskAdapterType adapterType = (parameters.AdapterType == DiskAdapterType.None) ? DiskAdapterType.LsiLogicScsi : parameters.AdapterType;
            DiskCreateType  createType  = (parameters.CreateType == DiskCreateType.None) ? DiskCreateType.MonolithicSparse : parameters.CreateType;

            DescriptorFile baseDescriptor = CreateSimpleDiskDescriptor(geometry, biosGeometry, createType, adapterType);

            return(DoInitialize(fileLocator, path, parameters.Capacity, createType, baseDescriptor));
        }
示例#3
0
        private static DescriptorFile CreateDifferencingDiskDescriptor(DiskCreateType type, DiskImageFile parent, string parentPath)
        {
            DescriptorFile baseDescriptor = new DescriptorFile();

            baseDescriptor.ContentId          = (uint)_rng.Next();
            baseDescriptor.ParentContentId    = parent.ContentId;
            baseDescriptor.ParentFileNameHint = parentPath;
            baseDescriptor.CreateType         = type;
            return(baseDescriptor);
        }
示例#4
0
        internal static DescriptorFile CreateSimpleDiskDescriptor(Geometry geometry, Geometry biosGeometery, DiskCreateType createType, DiskAdapterType adapterType)
        {
            DescriptorFile baseDescriptor = new DescriptorFile();

            baseDescriptor.DiskGeometry    = geometry;
            baseDescriptor.BiosGeometry    = biosGeometery;
            baseDescriptor.ContentId       = (uint)_rng.Next();
            baseDescriptor.CreateType      = createType;
            baseDescriptor.UniqueId        = Guid.NewGuid();
            baseDescriptor.HardwareVersion = "4";
            baseDescriptor.AdapterType     = adapterType;
            return(baseDescriptor);
        }
示例#5
0
        /// <summary>
        /// Initiates the build process.
        /// </summary>
        /// <param name="baseName">The base name for the VMDK, for example 'foo' to create 'foo.vmdk'.</param>
        /// <returns>A set of one or more logical files that constitute the VMDK.  The first file is
        /// the 'primary' file that is normally attached to VMs.</returns>
        public override DiskImageFileSpecification[] Build(string baseName)
        {
            if (string.IsNullOrEmpty(baseName))
            {
                throw new ArgumentException("Invalid base file name", "baseName");
            }

            if (Content == null)
            {
                throw new InvalidOperationException("No content stream specified");
            }

            if (_diskType != DiskCreateType.Vmfs && _diskType != DiskCreateType.VmfsSparse)
            {
                throw new NotImplementedException("Only Vmfs and VmfsSparse disks implemented");
            }

            List <DiskImageFileSpecification> fileSpecs = new List <DiskImageFileSpecification>();

            Geometry geometry     = Geometry ?? DiskImageFile.DefaultGeometry(Content.Length);
            Geometry biosGeometry = BiosGeometry ?? Geometry.LbaAssistedBiosGeometry(Content.Length);

            DescriptorFile baseDescriptor = DiskImageFile.CreateSimpleDiskDescriptor(geometry, biosGeometry, _diskType, _adapterType);

            if (_diskType == DiskCreateType.Vmfs)
            {
                ExtentDescriptor extent = new ExtentDescriptor(ExtentAccess.ReadWrite, Content.Length / 512, ExtentType.Vmfs, baseName + "-flat.vmdk", 0);
                baseDescriptor.Extents.Add(extent);

                MemoryStream ms = new MemoryStream();
                baseDescriptor.Write(ms);

                fileSpecs.Add(new DiskImageFileSpecification(baseName + ".vmdk", new PassthroughStreamBuilder(ms)));
                fileSpecs.Add(new DiskImageFileSpecification(baseName + "-flat.vmdk", new PassthroughStreamBuilder(Content)));
            }
            else if (_diskType == DiskCreateType.VmfsSparse)
            {
                ExtentDescriptor extent = new ExtentDescriptor(ExtentAccess.ReadWrite, Content.Length / 512, ExtentType.VmfsSparse, baseName + "-sparse.vmdk", 0);
                baseDescriptor.Extents.Add(extent);

                MemoryStream ms = new MemoryStream();
                baseDescriptor.Write(ms);

                fileSpecs.Add(new DiskImageFileSpecification(baseName + ".vmdk", new PassthroughStreamBuilder(ms)));
                fileSpecs.Add(new DiskImageFileSpecification(baseName + "-sparse.vmdk", new VmfsSparseExtentBuilder(Content)));
            }

            return(fileSpecs.ToArray());
        }
示例#6
0
        /// <summary>
        /// Creates a new virtual disk that is a linked clone of an existing disk.
        /// </summary>
        /// <param name="path">The path to the new disk</param>
        /// <param name="type">The type of the new disk</param>
        /// <param name="parent">The disk to clone</param>
        /// <returns>The new virtual disk</returns>
        public static DiskImageFile InitializeDifferencing(string path, DiskCreateType type, string parent)
        {
            if (type != DiskCreateType.MonolithicSparse && type != DiskCreateType.TwoGbMaxExtentSparse && type != DiskCreateType.VmfsSparse)
            {
                throw new ArgumentException("Differencing disks must be sparse", "type");
            }

            using (DiskImageFile parentFile = new DiskImageFile(parent, FileAccess.Read))
            {
                DescriptorFile baseDescriptor = CreateDifferencingDiskDescriptor(type, parentFile, parent);

                FileLocator locator = new LocalFileLocator(Path.GetDirectoryName(path));
                return(DoInitialize(locator, Path.GetFileName(path), parentFile.Capacity, type, baseDescriptor));
            }
        }
示例#7
0
        /// <summary>
        /// Creates a new virtual disk that is a linked clone of an existing disk.
        /// </summary>
        /// <param name="fileSystem">The file system to create the VMDK on</param>
        /// <param name="path">The path to the new disk</param>
        /// <param name="type">The type of the new disk</param>
        /// <param name="parent">The disk to clone</param>
        /// <returns>The new virtual disk</returns>
        public static DiskImageFile InitializeDifferencing(DiscFileSystem fileSystem, string path, DiskCreateType type, string parent)
        {
            if (type != DiskCreateType.MonolithicSparse && type != DiskCreateType.TwoGbMaxExtentSparse && type != DiskCreateType.VmfsSparse)
            {
                throw new ArgumentException("Differencing disks must be sparse", "type");
            }

            string      basePath      = Utilities.GetDirectoryFromPath(path);
            FileLocator locator       = new DiscFileLocator(fileSystem, basePath);
            FileLocator parentLocator = locator.GetRelativeLocator(Utilities.GetDirectoryFromPath(parent));

            using (DiskImageFile parentFile = new DiskImageFile(parentLocator, Utilities.GetFileFromPath(parent), FileAccess.Read))
            {
                DescriptorFile baseDescriptor = CreateDifferencingDiskDescriptor(type, parentFile, parent);

                return(DoInitialize(locator, Utilities.GetFileFromPath(path), parentFile.Capacity, type, baseDescriptor));
            }
        }
示例#8
0
        private static DiskImageFile DoInitialize(FileLocator fileLocator, string file, long capacity, DiskCreateType type, DescriptorFile baseDescriptor)
        {
            if (type == DiskCreateType.MonolithicSparse)
            {
                // MonolithicSparse is a special case, the descriptor is embedded in the file itself...
                using (Stream fs = fileLocator.Open(file, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                {
                    long descriptorStart;
                    CreateExtent(fs, capacity, ExtentType.Sparse, 10 * Sizes.OneKiB, out descriptorStart);

                    ExtentDescriptor extent = new ExtentDescriptor(ExtentAccess.ReadWrite, capacity / Sizes.Sector, ExtentType.Sparse, file, 0);
                    fs.Position = descriptorStart * Sizes.Sector;
                    baseDescriptor.Extents.Add(extent);
                    baseDescriptor.Write(fs);
                }
            }
            else
            {
                ExtentType extentType           = CreateTypeToExtentType(type);
                long       totalSize            = 0;
                List <ExtentDescriptor> extents = new List <ExtentDescriptor>();
                if (type == DiskCreateType.MonolithicFlat || type == DiskCreateType.VmfsSparse || type == DiskCreateType.Vmfs)
                {
                    string adornment = "flat";
                    if (type == DiskCreateType.VmfsSparse)
                    {
                        adornment = string.IsNullOrEmpty(baseDescriptor.ParentFileNameHint) ? "sparse" : "delta";
                    }

                    string fileName = AdornFileName(file, adornment);

                    using (Stream fs = fileLocator.Open(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                    {
                        CreateExtent(fs, capacity, extentType);
                        extents.Add(new ExtentDescriptor(ExtentAccess.ReadWrite, capacity / Sizes.Sector, extentType, fileName, 0));
                        totalSize = capacity;
                    }
                }
                else if (type == DiskCreateType.TwoGbMaxExtentFlat || type == DiskCreateType.TwoGbMaxExtentSparse)
                {
                    int i = 1;
                    while (totalSize < capacity)
                    {
                        string adornment;
                        if (type == DiskCreateType.TwoGbMaxExtentSparse)
                        {
                            adornment = string.Format(CultureInfo.InvariantCulture, "s{0:x3}", i);
                        }
                        else
                        {
                            adornment = string.Format(CultureInfo.InvariantCulture, "{0:x6}", i);
                        }

                        string fileName = AdornFileName(file, adornment);

                        using (Stream fs = fileLocator.Open(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                        {
                            long extentSize = Math.Min((2 * Sizes.OneGiB) - Sizes.OneMiB, capacity - totalSize);
                            CreateExtent(fs, extentSize, extentType);
                            extents.Add(new ExtentDescriptor(ExtentAccess.ReadWrite, extentSize / Sizes.Sector, extentType, fileName, 0));
                            totalSize += extentSize;
                        }

                        ++i;
                    }
                }
                else
                {
                    throw new NotSupportedException("Creating disks of this type is not supported");
                }

                using (Stream fs = fileLocator.Open(file, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                {
                    baseDescriptor.Extents.AddRange(extents);
                    baseDescriptor.Write(fs);
                }
            }

            return(new DiskImageFile(fileLocator, file, FileAccess.ReadWrite));
        }