Esempio n. 1
0
        /// <summary>
        /// Initiates the build process.
        /// </summary>
        /// <param name="baseName">The base name for the VMDK, for example 'foo' to create 'foo.vhd'.</param>
        /// <returns>A set of one or more logical files that constitute the VHD.  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");
            }

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

            Geometry geometry = Geometry ?? Geometry.FromCapacity(Content.Length);

            Footer footer = new Footer(geometry, Content.Length, DiskType);

            if (_diskType == FileType.Fixed)
            {
                footer.UpdateChecksum();

                byte[] footerSector = new byte[Sizes.Sector];
                footer.ToBytes(footerSector, 0);

                SparseStream footerStream = SparseStream.FromStream(new MemoryStream(footerSector, false), Ownership.None);
                Stream imageStream = new ConcatStream(Ownership.None, Content, footerStream);
                fileSpecs.Add(new DiskImageFileSpecification(baseName + ".vhd", new PassthroughStreamBuilder(imageStream)));
            }
            else if (_diskType == FileType.Dynamic)
            {
                fileSpecs.Add(new DiskImageFileSpecification(baseName + ".vhd",  new DynamicDiskBuilder(Content, footer, (uint)Sizes.OneMiB * 2)));
            }
            else
            {
                throw new InvalidOperationException("Only Fixed and Dynamic disk types supported");
            }

            return fileSpecs.ToArray();
        }
Esempio n. 2
0
        /// <summary>
        /// Creates a new stream that contains the XVA image.
        /// </summary>
        /// <returns>The new stream.</returns>
        public override SparseStream Build()
        {
            TarFileBuilder tarBuilder = new TarFileBuilder();

            int[] diskIds;

            string ovaFileContent = GenerateOvaXml(out diskIds);
            tarBuilder.AddFile("ova.xml", Encoding.ASCII.GetBytes(ovaFileContent));

            int diskIdx = 0;
            foreach (var diskRec in _disks)
            {
                SparseStream diskStream = diskRec.Second;
                List<StreamExtent> extents = new List<StreamExtent>(diskStream.Extents);

                int lastChunkAdded = -1;
                foreach (StreamExtent extent in extents)
                {
                    int firstChunk = (int)(extent.Start / Sizes.OneMiB);
                    int lastChunk = (int)((extent.Start + extent.Length - 1) / Sizes.OneMiB);

                    for (int i = firstChunk; i <= lastChunk; ++i)
                    {
                        if (i != lastChunkAdded)
                        {
                            HashAlgorithm hashAlg = new SHA1Managed();
                            Stream chunkStream;

                            long diskBytesLeft = diskStream.Length - (i * Sizes.OneMiB);
                            if (diskBytesLeft < Sizes.OneMiB)
                            {
                                chunkStream = new ConcatStream(
                                    Ownership.Dispose,
                                    new SubStream(diskStream, i * Sizes.OneMiB, diskBytesLeft),
                                    new ZeroStream(Sizes.OneMiB - diskBytesLeft));
                            }
                            else
                            {
                                chunkStream = new SubStream(diskStream, i * Sizes.OneMiB, Sizes.OneMiB);
                            }

                            HashStream chunkHashStream = new HashStream(chunkStream, Ownership.Dispose, hashAlg);

                            tarBuilder.AddFile(string.Format(CultureInfo.InvariantCulture, "Ref:{0}/{1:D8}", diskIds[diskIdx], i), chunkHashStream);
                            tarBuilder.AddFile(string.Format(CultureInfo.InvariantCulture, "Ref:{0}/{1:D8}.checksum", diskIds[diskIdx], i), new ChecksumStream(hashAlg));

                            lastChunkAdded = i;
                        }
                    }
                }

                // Make sure the last chunk is present, filled with zero's if necessary
                int lastActualChunk = (int)((diskStream.Length - 1) / Sizes.OneMiB);
                if (lastChunkAdded < lastActualChunk)
                {
                    HashAlgorithm hashAlg = new SHA1Managed();
                    Stream chunkStream = new ZeroStream(Sizes.OneMiB);
                    HashStream chunkHashStream = new HashStream(chunkStream, Ownership.Dispose, hashAlg);
                    tarBuilder.AddFile(string.Format(CultureInfo.InvariantCulture, "Ref:{0}/{1:D8}", diskIds[diskIdx], lastActualChunk), chunkHashStream);
                    tarBuilder.AddFile(string.Format(CultureInfo.InvariantCulture, "Ref:{0}/{1:D8}.checksum", diskIds[diskIdx], lastActualChunk), new ChecksumStream(hashAlg));
                }

                ++diskIdx;
            }

            return tarBuilder.Build();
        }