Last active
June 11, 2018 22:40
-
-
Save sedouard/0468d1b2d0153ca9a652 to your computer and use it in GitHub Desktop.
Create Blank VHD for Microsoft Azure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import datetime | |
import uuid | |
from azure.storage import BlobService | |
def generate_vhd_footer(size): | |
# Fixed VHD Footer Format Specification | |
# spec: https://technet.microsoft.com/en-us/virtualization/bb676673.aspx#E3B | |
# Field Size (bytes) | |
# Cookie 8 | |
# Features 4 | |
# Version 4 | |
# Data Offset 4 | |
# TimeStamp 4 | |
# Creator App 4 | |
# Creator Ver 4 | |
# CreatorHostOS 4 | |
# Original Size 8 | |
# Current Size 8 | |
# Disk Geo 4 | |
# Disk Type 4 | |
# Checksum 4 | |
# Unique ID 16 | |
# Saved State 1 | |
# Reserved 427 | |
# # the ascii string 'conectix' | |
cookie = bytearray([0x63, 0x6f, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x78]) | |
# no features enabled | |
features = bytearray([0x00, 0x00, 0x00, 0x02]) | |
# current file version | |
version = bytearray([0x00, 0x01, 0x00, 0x00]) | |
# in the case of a fixed disk, this is set to -1 | |
data_offset = bytearray([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]) | |
# hex representation of seconds since january 1st 2000 | |
timestamp = bytearray.fromhex(hex(long(datetime.datetime.now().strftime("%s")) - 946684800).replace('L','').replace('0x','').zfill(8)) | |
# ascii code for 'wa' = windowsazure | |
creator_app = bytearray([0x77, 0x61, 0x00, 0x00]) | |
# ascii code for version of creator application | |
creator_version = bytearray([0x00, 0x07, 0x00, 0x00]) | |
# creator host os. windows or mac, ascii for 'wi2k' | |
creator_os = bytearray([0x57, 0x69, 0x32, 0x6b]) | |
original_size = bytearray.fromhex(hex(size).replace('0x','').zfill(16)) | |
current_size = bytearray.fromhex(hex(size).replace('0x','').zfill(16)) | |
# ox820=2080 cylenders, 0x10=16 heads, 0x3f=63 sectors/track or cylender, | |
disk_geometry = bytearray([0x08, 0x20, 0x10, 0x3f]) | |
# 0x2 = fixed hard disk | |
disk_type = bytearray([0x00, 0x00, 0x00, 0x02]) | |
# a uuid | |
unique_id = bytearray.fromhex(uuid.uuid4().hex) | |
# saved state and reserved | |
saved_reserved = bytearray(428) | |
# Compute Checksum | |
# Checksum = ones compliment of sum of all fields excluding checksum field | |
to_checksum_array = cookie + features + version + data_offset + timestamp + creator_app + creator_version + creator_os + original_size + current_size + disk_geometry + disk_type + unique_id + saved_reserved | |
total = 0; | |
for b in to_checksum_array: | |
total += b | |
total = ~total | |
# handle two's compliment | |
def tohex(val, nbits): | |
return hex((val + (1 << nbits)) % (1 << nbits)) | |
checksum = bytearray.fromhex(tohex(total, 32).replace('0x','')) | |
blob_data = cookie + features + version + data_offset + timestamp + creator_app + creator_version + creator_os + original_size + current_size + disk_geometry + disk_type + checksum + unique_id + saved_reserved | |
return bytes(blob_data) | |
# 10 GB, must be divisible by 512(bytes) | |
size = 10737418240 | |
blob_service = BlobService('storage_acount_name', 'storage_account_key') | |
# Create blank blob | |
blob_service.put_blob(container_name='containername', | |
blob_name='a-new-vhd', | |
blob=None, | |
x_ms_blob_type='PageBlob', | |
x_ms_blob_content_type='application/octet-stream', | |
x_ms_blob_content_length=size) | |
# Mark blob as blank VHD by adding vhd footer | |
vhd_footer = generate_vhd_footer(size) | |
blob_service.put_page(container_name='containername', | |
blob_name='a-new-vhd', | |
page=vhd_footer, | |
x_ms_page_write='update', | |
x_ms_range='bytes='+str((size - 512))+'-'+str(size-1)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment