- Microsoft Windows Azure Development Cookbook
- Neil Mackenzie
- 1309字
- 2021-04-02 18:51:58
Uploading a VHD into a page blob
An instance of a Windows Azure role comprises several virtual disks (VHD) deployed into a virtual machine. One VHD contains the Guest OS; another contains the role package, while the third is a writable VHD containing the local resources of the instance.
Windows Azure provides the Azure Drive feature whereby an arbitrary VHD, contained in a page blob, can be attached to an instance and then accessed as an NTFS drive. This VHD must be an NTFS-formatted, fixed-size VHD. The VHD can be created directly as a page blob or uploaded like any other page blob.
The Disk Management snap-in for the Microsoft Management Console (MMC) can be used to create and format a VHD on a local system. Once attached to the local system, files can be copied to, or created on the file system of the VHD just as they can with any hard drive. The VHD can then be detached from the local system and uploaded as a page blob to the Windows Azure Blob Service.
A page blob, which may have a maximum size of 1 TB, comprises a sequence of 512-byte pages. All writes to a page blob must be aligned with a page boundary. There is no charge for an empty page in a page blob. There is no need to upload empty pages in the VHD, which means that bandwidth need not be wasted uploading empty pages. The Blob service identifies these empty pages when a download of one of them is requested and it merely injects a page full of 0x0 bytes into the response stream.
Uploads to block blobs comprise a two-step process: upload the blocks and commit the blocks to the blob. Uploading a page blob is a single step process: write one or more 512-byte pages to the blob. Once uploaded, these pages immediately form part of the blob. This can cause problems if multiple writers are writing to the page blob simultaneously. The Windows Azure Storage Service REST API provides support for a sequence number that can be used to control which writer wins a contest to write to a single page. This functionality is not exposed in the Windows Azure Storage Client library.
In the Storage Client library, the CloudPageBlob
class provides various methods supporting page blob uploads. CloudPageBlob
is derived from CloudBlob
. Note that the upload methods in CloudBlob
class are not supported for CloudPageBlob
. Instead, CloudPageBlob
provides synchronous and asynchronous WritePages()
methods specifically for uploading page blobs. Additionally, there are synchronous and asynchronous forms of the GetPageRanges()
method that returns an IEnumerable<PageRange>
of the non-empty page ranges in the blob.
In this recipe, we will learn how to upload a VHD into a page blob.
Getting ready
We use the disk management snap-in to create and format a VHD on the local system that we will upload with the recipe. There is more documentation on the disk management snap-in at http://technet.microsoft.com/en-us/library/dd979539(WS.10).aspx.
We launch disk management by clicking on Start, typing diskmgmt.msc
in the Search box, and then pressing Enter. The Create VHD and Attach VHD operations are on the Actions menu.
We use the disk management snap-in for the following tasks:
- Creating VHD—as "fixed size" with a specified size in the specified location
- Initializing disk with a master boot record
- Creating a "new simple volume" formatted with NTFS with a specified drive letter
- Copying files and directories to the specified drive
- Detaching VHD
If the VHD already exists, then we use the disk management snap-in for the following tasks:
- Attaching the VHD
- Copying files and directories to the specified drive
- Detaching VHD
How to do it...
We are going to create a page blob and upload a VHD into it. We do this as follows:
- Add a new class named
UploadVhdExample
to the project. - Set the Target Framework for the project to .NET Framework 4.
- Add the following assembly references to the project:
Microsoft.WindowsAzure.StorageClient System.Configuration
- Add the following
using
statements to the top of the class file:using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.StorageClient; using System.Configuration; using System.IO;
- Add the following members to the class:
private const Int32 pageSize = 0x200; // 512 bytes private const Int32 uploadSize = 0x100000; // 1MBytes private CloudBlobClient cloudBlobClient;
- Add the following constructor to the class:
public UploadVhdExample() { CloudStorageAccount cloudStorageAccount =CloudStorageAccount.Parse(ConfigurationManager.AppSettings["DataConnectionString"]); cloudBlobClient =cloudStorageAccount.CreateCloudBlobClient(); }
- Add the following method, uploading a VHD, to the class:
private void UploadCloudDrive(String containerName, String blobName, String vhdPath) { CloudBlobContainer cloudBlobContainer =cloudBlobClient.GetContainerReference(containerName); cloudBlobContainer.CreateIfNotExist(); CloudPageBlob cloudPageBlob =cloudBlobContainer.GetPageBlobReference(blobName); cloudPageBlob.Properties.ContentType ="binary/octet-stream"; using (FileStream fileStream =new FileStream(vhdPath, FileMode.Open)) { Int32 blobSize = (Int32)fileStream.Length; if ((blobSize % pageSize) != 0) { throw new ApplicationException("Page blob size must be a multiple of page size"); } cloudPageBlob.Create(blobSize); Int32 pageBlobOffset = 0; Int32 numberIterations = blobSize / uploadSize; for (Int32 i = 0; i < numberIterations; i++) { pageBlobOffset = UploadPages(fileStream, cloudPageBlob, pageBlobOffset); } pageBlobOffset = UploadFooter(fileStream, cloudPageBlob, pageBlobOffset); } }
- Add the following method, uploading pages to a page blob, to the class:
private Int32 UploadPages(FileStream fileStream,CloudPageBlob cloudPageBlob, Int32 pageBlobOffset) { Byte[] buffer = new Byte[uploadSize]; Int32 countBytesRead = fileStream.Read(buffer, 0, uploadSize); Int32 countBytesUploaded = 0; Int32 bufferOffset = 0; Int32 rangeStart = 0; Int32 rangeSize = 0; while (bufferOffset < uploadSize) { Boolean nextPageIsLast =bufferOffset + pageSize >= uploadSize; Boolean nextPageHasData =NextPageHasData(buffer, bufferOffset); if (nextPageHasData) { if (rangeSize == 0) { rangeStart = bufferOffset; } rangeSize += pageSize; } if ((rangeSize > 0) && (!nextPageHasData ||nextPageIsLast)) { using (MemoryStream memoryStream =new MemoryStream(buffer, rangeStart, rangeSize)) { cloudPageBlob.WritePages(memoryStream, pageBlobOffset + rangeStart); countBytesUploaded += rangeSize; rangeSize = 0; } } bufferOffset += pageSize; } pageBlobOffset += uploadSize; return pageBlobOffset; }
- Add the following method, uploading the VHD footer, to the class:
private Int32 UploadFooter(FileStream fileStream,CloudPageBlob cloudPageBlob, Int32 pageBlobOffset) { const Int32 numberFooterBytes = 512; Byte[] footerBytes = new Byte[numberFooterBytes]; Int32 countBytesRead = fileStream.Read(footerBytes, 0, numberFooterBytes); using (MemoryStream memoryStream =new MemoryStream(footerBytes)) { cloudPageBlob.WritePages(memoryStream, pageBlobOffset); pageBlobOffset += numberFooterBytes; } return pageBlobOffset; }
- Add the following method, verifying a page contains data, to the class:
private Boolean NextPageHasData(Byte[] buffer,Int32 bufferOffset) { for (Int32 i = bufferOffset; i < bufferOffset + pageSize; i++) { if (buffer[i] != 0x0) { return true; } } return false; }
- Add the following method, using the methods added earlier, to the class:
public static void UseUploadVhdExample() { String containerName = "{CONTAINER_NAME}"; String blobName = "{BLOB_NAME}"; String pathName = @"{PATH_TO_THE_VHD}"; UploadVhdExample example = new UploadVhdExample(); example.UploadCloudDrive(containerName, blobName, pathName); }
- Add the following to the
configuration
section ofapp.config
:
How it works...
In steps 1 through 4, we set up the class. In step 5, we define various constants and the CloudBlobClient
we use to access the Blob service. We initialize this in the constructor we add in step 6.
In step 7, we add the method that controls the upload process. We open a FileStream
on the VHD and create a page blob the same size as the VHD. We then iterate over the VHD file in increments of 1 MB, invoking UploadPages()
to upload the data in each 1 MB window. Finally, we invoke UploadFooter()
to upload the VHD footer.
In step 8, we add the UploadPages()
method to upload non-empty pages to the page blob. We read the VHD into a buffer in 1 MB chunks. We then look for ranges of 512-byte pages containing some data and upload only these ranges. Remember, we do not need to upload empty pages. The tricky part of this process is identifying the end of a range when we come across an empty page or reach the end of the buffer.
In step 9, we add the UploadFooter()
method to upload the 512-byte VHD footer. We simply load the footer into a Byte[]
buffer and create a MemoryStream
on it. We then invoke WritePages()
to upload this to the page blob.
In Step 10, we add a method that returns false
if every byte of a specified 512-byte page of a buffer is 0x0; otherwise, NextPageHasData()
returns true
.
In step 11, we add a method to use the methods added earlier. We must replace {CONTAINER_NAME}
and {BLOB_KEY}
with actual values for account name and access key. We must also replace {PATH_TO_THE_VHD}
with the actual path to a VHD.
In step 12, we add the connection string to the app.config
configuration file. We must replace {ACCOUNT_NAME}
and {ACCOUNT_KEY}
with actual values for the account name and access key.
There's more...
When uploading an arbitrary file that—unlike the VHD—is not an integral multiple of the upload buffer, we need to handle correctly the final chunk that is smaller than the size of the upload buffer.
See also
- See the Uploading blocks to a block blob recipe to see how to upload a block blob.
- Joomla! 1.5 Site Blueprints
- 做好PPT就靠這幾招:圖解力+吸引力+說(shuō)服力
- Photoshop 2022從入門(mén)到精通
- 3ds Max/VRay室內(nèi)設(shè)計(jì)材質(zhì)、燈光與建模速查超級(jí)手冊(cè)
- Authorware應(yīng)用案例教程
- GlassFish Administration
- Photoshop+Illustrator商業(yè)廣告設(shè)計(jì)從入門(mén)到精通(第2版)
- Photoshop CS6案例教程(第3版)
- 中文版Photoshop CS6經(jīng)典自學(xué)教程
- Oracle Fusion Middleware Patterns
- 零基礎(chǔ)攝影后期修圖 Photoshop照片處理輕松入門(mén)
- CAD/CAM應(yīng)用教程
- 剪映專(zhuān)業(yè)版:短視頻創(chuàng)作案例教程(全彩慕課版)
- Plone 3 Theming
- Troux Enterprise Architecture Solutions