217 lines
7.1 KiB
Python
Executable File
217 lines
7.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
from pyVmomi import vim
|
|
import pyVim.connect
|
|
import atexit
|
|
import argparse
|
|
from pprint import pprint
|
|
import siteconf
|
|
|
|
site_conf = siteconf.read()
|
|
|
|
def get_args():
|
|
parser = argparse.ArgumentParser(
|
|
description='Clone VM from template')
|
|
|
|
parser.add_argument('-s', '--site',
|
|
required=True,
|
|
action='store',
|
|
help='Name of the site to create VM on')
|
|
|
|
parser.add_argument('-t', '--template',
|
|
required=False,
|
|
action='store',
|
|
help='Name of the template you wish to clone')
|
|
|
|
parser.add_argument('-v', '--vm-name',
|
|
required=True,
|
|
action='store',
|
|
help='Name of the VM you wish to make')
|
|
|
|
parser.add_argument('-c', '--cpu',
|
|
required=False,
|
|
type=int,
|
|
action='store',
|
|
default=1,
|
|
help='Set number of CPUs')
|
|
|
|
parser.add_argument('-m', '--memory',
|
|
required=False,
|
|
type=int,
|
|
action='store',
|
|
default=2048,
|
|
help='[MB] Set memory size')
|
|
|
|
parser.add_argument('-d', '--disk-size',
|
|
required=False,
|
|
type=int,
|
|
action='store',
|
|
default=0,
|
|
help='[GB] Resize LVM disk to this size')
|
|
|
|
parser.add_argument('--datastore',
|
|
required=False,
|
|
action='store',
|
|
default=None,
|
|
help='target datastore')
|
|
|
|
args = parser.parse_args()
|
|
args.disk_size = args.disk_size * 1024 * 1024
|
|
return args
|
|
|
|
|
|
def wait_for_task(task):
|
|
""" wait for a vCenter task to finish """
|
|
task_done = False
|
|
while not task_done:
|
|
if task.info.state == 'success':
|
|
return task.info.result
|
|
|
|
if task.info.state == 'error':
|
|
print("there was an error")
|
|
task_done = True
|
|
|
|
|
|
def get_obj(content, vimtype, name):
|
|
"""
|
|
Return an object by name, if name is None the
|
|
first found object is returned
|
|
"""
|
|
obj = None
|
|
container = content.viewManager.CreateContainerView(
|
|
content.rootFolder, vimtype, True)
|
|
for c in container.view:
|
|
if name:
|
|
if c.name == name:
|
|
obj = c
|
|
break
|
|
else:
|
|
obj = c
|
|
break
|
|
|
|
return obj
|
|
|
|
|
|
def clone_vm(content, template, vm_name, datacenter_name, datastore_name,
|
|
cluster_or_host):
|
|
datacenter = get_obj(content, [vim.Datacenter], datacenter_name)
|
|
destfolder = datacenter.vmFolder
|
|
datastore = get_obj(content, [vim.Datastore], datastore_name)
|
|
cluster = get_obj(content, [vim.ClusterComputeResource], cluster_or_host)
|
|
if cluster:
|
|
resource_pool = cluster.resourcePool
|
|
else:
|
|
host = get_obj(content, [vim.ComputeResource], cluster_or_host)
|
|
resource_pool = host.resourcePool
|
|
|
|
relospec = vim.vm.RelocateSpec()
|
|
relospec.datastore = datastore
|
|
relospec.pool = resource_pool
|
|
clonespec = vim.vm.CloneSpec()
|
|
clonespec.location = relospec
|
|
clonespec.powerOn = False
|
|
|
|
print(f"cloning to VM '{vm_name}'...")
|
|
task = template.Clone(folder=destfolder, name=vm_name, spec=clonespec)
|
|
wait_for_task(task)
|
|
|
|
def extend_disk(content, vm_name, extend_to_kb):
|
|
vm = get_obj(content, [vim.VirtualMachine], vm_name)
|
|
for dev in vm.config.hardware.device:
|
|
#print("dev "+ dev.deviceInfo.label)
|
|
if hasattr(dev.backing, 'fileName'):
|
|
size_kb = dev.capacityInKB
|
|
if size_kb > 5 * 1024 * 1024: # lvm disk
|
|
if extend_to_kb > size_kb:
|
|
disk_spec = vim.vm.device.VirtualDeviceSpec()
|
|
disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit
|
|
disk_spec.device = vim.vm.device.VirtualDisk()
|
|
disk_spec.device.key = dev.key
|
|
disk_spec.device.backing = vim.vm.device.VirtualDisk.FlatVer2BackingInfo()
|
|
disk_spec.device.backing.fileName = dev.backing.fileName
|
|
disk_spec.device.backing.diskMode = dev.backing.diskMode
|
|
disk_spec.device.controllerKey = dev.controllerKey
|
|
disk_spec.device.unitNumber = dev.unitNumber
|
|
disk_spec.device.capacityInKB = extend_to_kb
|
|
dev_changes = []
|
|
dev_changes.append(disk_spec)
|
|
spec = vim.vm.ConfigSpec()
|
|
spec.deviceChange = dev_changes
|
|
print(f"extending disk '{dev.deviceInfo.label}' to {str(extend_to_kb)} kB")
|
|
task = vm.ReconfigVM_Task(spec=spec)
|
|
wait_for_task(task)
|
|
|
|
def set_cpu_mem(content, vm_name, cpu, mem_mb):
|
|
vm = get_obj(content, [vim.VirtualMachine], vm_name)
|
|
spec = vim.vm.ConfigSpec()
|
|
spec.numCPUs = cpu
|
|
spec.memoryMB = mem_mb
|
|
print(f"set cpu={str(cpu)}, memory={str(mem_mb)} MB")
|
|
task = vm.ReconfigVM_Task(spec=spec)
|
|
wait_for_task(task)
|
|
|
|
def power_on(content, vm_name):
|
|
vm = get_obj(content, [vim.VirtualMachine], vm_name)
|
|
print(f"powering on '{vm_name}'")
|
|
task = vm.PowerOn()
|
|
wait_for_task(task)
|
|
|
|
def main():
|
|
args = get_args()
|
|
|
|
if not args.site in site_conf:
|
|
print(f"site not found: {args.site}")
|
|
exit(1)
|
|
site = site_conf[args.site];
|
|
|
|
si = pyVim.connect.SmartConnect(
|
|
host = site["vcenter"],
|
|
user = site["vcenter_user"],
|
|
pwd = site["vcenter_passwd"],
|
|
disableSslCertValidation = True
|
|
)
|
|
|
|
atexit.register(pyVim.connect.Disconnect, si)
|
|
|
|
content = si.RetrieveContent()
|
|
template_name = site["template"]
|
|
if args.template is None:
|
|
if len(site["template"]) == 1:
|
|
template_name, = site["template"].values()
|
|
else:
|
|
print("specify `-t TEMPLATE` with:")
|
|
for t in site["template"]:
|
|
print(f" - {t} ({site['template'][t]})")
|
|
print(f" - or any template in vsphere")
|
|
exit(1)
|
|
else:
|
|
if args.template in site["template"]:
|
|
template_name = site["template"][args.template]
|
|
else:
|
|
template_name = args.template
|
|
template = get_obj(content, [vim.VirtualMachine], template_name)
|
|
if not template:
|
|
print("template not found")
|
|
exit(1)
|
|
print(f"template: {template_name}")
|
|
|
|
vm = get_obj(content, [vim.VirtualMachine], args.vm_name)
|
|
if vm:
|
|
print(f"VM '{args.vm_name}' exists.")
|
|
exit(1)
|
|
|
|
datastore = site["datastore"]
|
|
if args.datastore is not None:
|
|
datastore = args.datastore
|
|
clone_vm(content, template, args.vm_name, site["datacenter"],
|
|
datastore, site["cluster_or_host"])
|
|
|
|
set_cpu_mem(content, args.vm_name, args.cpu, args.memory)
|
|
extend_disk(content, args.vm_name, args.disk_size)
|
|
power_on(content, args.vm_name)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|
|
# vim: set tabstop=4 shiftwidth=4 expandtab smarttab:
|