Skip to content

Instantly share code, notes, and snippets.

@sedouard
Last active June 11, 2018 22:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save sedouard/0468d1b2d0153ca9a652 to your computer and use it in GitHub Desktop.
Save sedouard/0468d1b2d0153ca9a652 to your computer and use it in GitHub Desktop.
Create Blank VHD for Microsoft Azure
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