private static void DownloadVHDFromCloud(Config config) { StorageCredentialsAccountAndKey creds = new StorageCredentialsAccountAndKey(config.Account, config.Key); CloudBlobClient blobStorage = new CloudBlobClient(config.AccountUrl, creds); blobStorage.ReadAheadInBytes = 0; CloudBlobContainer container = blobStorage.GetContainerReference(config.Container); CloudPageBlob pageBlob = container.GetPageBlobReference(config.Blob); // Get the length of the blob pageBlob.FetchAttributes(); long vhdLength = pageBlob.Properties.Length; long totalDownloaded = 0; Console.WriteLine("Vhd size: " + Megabytes(vhdLength)); // Create a new local file to write into FileStream fileStream = new FileStream(config.Vhd.FullName, FileMode.Create, FileAccess.Write); fileStream.SetLength(vhdLength); // Download the valid ranges of the blob, and write them to the file IEnumerable<PageRange> pageRanges = pageBlob.GetPageRanges(); BlobStream blobStream = pageBlob.OpenRead(); foreach (PageRange range in pageRanges) { // EndOffset is inclusive... so need to add 1 int rangeSize = (int)(range.EndOffset + 1 - range.StartOffset); // Chop range into 4MB chucks, if needed for (int subOffset = 0; subOffset < rangeSize; subOffset += FourMegabyteAsBytes) { int subRangeSize = Math.Min(rangeSize - subOffset, FourMegabyteAsBytes); blobStream.Seek(range.StartOffset + subOffset, SeekOrigin.Begin); fileStream.Seek(range.StartOffset + subOffset, SeekOrigin.Begin); Console.WriteLine("Range: ~" + Megabytes(range.StartOffset + subOffset) + " + " + PrintSize(subRangeSize)); byte[] buffer = new byte[subRangeSize]; blobStream.Read(buffer, 0, subRangeSize); fileStream.Write(buffer, 0, subRangeSize); totalDownloaded += subRangeSize; } } Console.WriteLine("Downloaded " + Megabytes(totalDownloaded) + " of " + Megabytes(vhdLength)); }
public static Config Parse(string[] args) { if (args.Length != 3) { WriteConsoleAndExit("Usage: vhddownload <url> <file> <keyfile>"); } Config config = new Config(); config.Url = new Uri(args[0]); config.Vhd = new FileInfo(args[1]); if (config.Vhd.Exists) { try { config.Vhd.Delete(); } catch (Exception e) { WriteConsoleAndExit("Failed to delete vhd file:\n" + e.ToString()); } } config.ReadKey(args[2]); return config; }
private static void UploadVHDToCloud(Config config) { StorageCredentialsAccountAndKey creds = new StorageCredentialsAccountAndKey(config.Account, config.Key); CloudBlobClient blobStorage = new CloudBlobClient(config.AccountUrl, creds); CloudBlobContainer container = blobStorage.GetContainerReference(config.Container); container.CreateIfNotExist(); CloudPageBlob pageBlob = container.GetPageBlobReference(config.Blob); Console.WriteLine("Vhd size: " + Megabytes(config.Vhd.Length)); long blobSize = RoundUpToPageBlobSize(config.Vhd.Length); pageBlob.Create(blobSize); FileStream stream = new FileStream(config.Vhd.FullName, FileMode.Open, FileAccess.Read); BinaryReader reader = new BinaryReader(stream); long totalUploaded = 0; long vhdOffset = 0; int offsetToTransfer = -1; while (vhdOffset < config.Vhd.Length) { byte[] range = reader.ReadBytes(FourMegabytesAsBytes); int offsetInRange = 0; // Make sure end is page size aligned if ((range.Length % PageBlobPageSize) > 0) { int grow = (int)(PageBlobPageSize - (range.Length % PageBlobPageSize)); Array.Resize(ref range, range.Length + grow); } // Upload groups of contiguous non-zero page blob pages. while (offsetInRange <= range.Length) { if ((offsetInRange == range.Length) || IsAllZero(range, offsetInRange, PageBlobPageSize)) { if (offsetToTransfer != -1) { // Transfer up to this point int sizeToTransfer = offsetInRange - offsetToTransfer; MemoryStream memoryStream = new MemoryStream(range, offsetToTransfer, sizeToTransfer, false, false); pageBlob.WritePages(memoryStream, vhdOffset + offsetToTransfer); Console.WriteLine("Range ~" + Megabytes(offsetToTransfer + vhdOffset) + " + " + PrintSize(sizeToTransfer)); totalUploaded += sizeToTransfer; offsetToTransfer = -1; } } else { if (offsetToTransfer == -1) { offsetToTransfer = offsetInRange; } } offsetInRange += PageBlobPageSize; } vhdOffset += range.Length; } Console.WriteLine("Uploaded " + Megabytes(totalUploaded) + " of " + Megabytes(blobSize)); }