Skip to content

Instantly share code, notes, and snippets.

@rgerganov
Last active September 17, 2015 08:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rgerganov/caeed4a28d8d621b7086 to your computer and use it in GitHub Desktop.
Save rgerganov/caeed4a28d8d621b7086 to your computer and use it in GitHub Desktop.
Import VM into vSphere
#!/usr/bin/env python
import argparse
import getpass
import os
import logging.config
import struct
import sys
import urlparse
logging.config.fileConfig('logging.conf')
logging.captureWarnings(True)
from oslo_vmware import api
from oslo_vmware import rw_handles
from oslo_vmware import vim_util
def err(msg):
sys.stderr.write(msg + '\n')
sys.exit(1)
def parse(url):
p = urlparse.urlparse(url)
if p.scheme != 'vi':
err('Invalid URL: only vi scheme is supported')
if not p.username:
err('Invalid URL: missing username')
if not p.hostname:
err('Invalid URL: missing hostname')
if not p.query:
err('Invalid URL: missing query')
if p.query.startswith('moref=vim.ClusterComputeResource'):
moref = vim_util.get_moref(p.query[33:], 'ClusterComputeResource')
elif p.query.startswith('moref=vim.ComputeResource'):
moref = vim_util.get_moref(p.query[26:], 'ComputeResource')
else:
err('Only references to compute resources are supported')
port = p.port if p.port else 443
pwd = p.password
if not pwd:
pwd = getpass.getpass()
return p.username, pwd, p.hostname, port, moref
def get_vm_config_spec(session, name, image_size, ds_name, num_cpu, mem_mb):
cf = session.vim.client.factory
controller_device = cf.create('ns0:VirtualLsiLogicController')
controller_device.key = -100
controller_device.busNumber = 0
controller_device.sharedBus = 'noSharing'
controller_spec = cf.create('ns0:VirtualDeviceConfigSpec')
controller_spec.operation = 'add'
controller_spec.device = controller_device
disk_device = cf.create('ns0:VirtualDisk')
disk_device.capacityInKB = int(image_size) / 1024
disk_device.key = -101
disk_device.unitNumber = 0
disk_device.controllerKey = -100
disk_device_bkng = cf.create('ns0:VirtualDiskFlatVer2BackingInfo')
disk_device_bkng.thinProvisioned = True
disk_device_bkng.fileName = '[%s]' % ds_name
disk_device_bkng.diskMode = 'persistent'
disk_device.backing = disk_device_bkng
disk_spec = cf.create('ns0:VirtualDeviceConfigSpec')
disk_spec.operation = 'add'
disk_spec.fileOperation = 'create'
disk_spec.device = disk_device
vm_file_info = cf.create('ns0:VirtualMachineFileInfo')
vm_file_info.vmPathName = '[%s]' % ds_name
create_spec = cf.create('ns0:VirtualMachineConfigSpec')
create_spec.name = name
create_spec.guestId = 'otherGuest'
create_spec.numCPUs = num_cpu
create_spec.memoryMB = mem_mb
create_spec.deviceChange = [controller_spec, disk_spec]
create_spec.files = vm_file_info
return create_spec
def get_image_size(image):
with open(image, 'rb') as f:
data = f.read(512)
header = struct.unpack('<IIIQQQQIQQQ?ccccH433s', data)
if header[0] != 0x564d444b:
err('This image is not VMDK')
if not (header[2] & (1 << 16)):
err('This image is not streamOptimized')
return header[3] * 512
def main():
parser = argparse.ArgumentParser()
parser.add_argument("-ds", help="Datastore name", required=True)
parser.add_argument("-name", help="VM name", required=True)
parser.add_argument("-mem", help="Memory (in MB)", type=int, default=512)
parser.add_argument("-cpu", help="Number of vCPUs", type=int, default=1)
parser.add_argument("-image", help="VMDK image", required=True)
parser.add_argument("url", help="URL to ComputeCluster (e.g. "
"'vi://user:pass@vchost?moref=vim.ClusterComputeResource:domain-c7')")
args = parser.parse_args()
user, pwd, host, port, moref = parse(args.url)
image_size = get_image_size(args.image)
session = api.VMwareAPISession(host, user, pwd, 10, 0.5, insecure=True)
rp_ref = vim_util.get_object_property(session.vim, moref, 'resourcePool')
folder_ref = vim_util.get_object_property(session.vim, moref, 'parent')
dc_ref = vim_util.get_object_property(session.vim, folder_ref, 'parent')
datastores = vim_util.get_object_property(session.vim, dc_ref, 'datastore').ManagedObjectReference
ds_ref = None
for ref in datastores:
ds_name = vim_util.get_object_property(session.vim, ref, 'name')
if ds_name == args.ds:
ds_ref = ref
break
if not ds_ref:
err("Datastore '{0}' is not accessible from this compute resource".format(args.ds))
vm_folder_ref = vim_util.get_object_property(session.vim, dc_ref, 'vmFolder')
file_size = os.path.getsize(args.image)
vm_config_spec = get_vm_config_spec(session, args.name, image_size, args.ds, args.cpu, args.mem)
client_factory = session.vim.client.factory
vm_import_spec = client_factory.create('ns0:VirtualMachineImportSpec')
vm_import_spec.configSpec = vm_config_spec
write_handle = rw_handles.VmdkWriteHandle(session,
session._host,
session._port,
rp_ref,
vm_folder_ref,
vm_import_spec,
file_size,
http_method='POST')
f = open(args.image, 'rb')
last_progress = 0
bytes_written = 0
try:
while True:
data = f.read(64 * 1024)
if not data:
break
write_handle.write(data)
write_handle.update_progress()
bytes_written += len(data)
progress = (bytes_written * 100 // file_size)
if progress != last_progress:
sys.stdout.write('\rProgress: {0}% '.format(progress))
sys.stdout.flush()
last_progress = progress
finally:
f.close()
write_handle.close()
sys.stdout.write('\rDone \n')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment