2020-01-28 13:38:07 +00:00
|
|
|
import argparse
|
|
|
|
import os
|
|
|
|
|
2020-01-28 16:44:53 +00:00
|
|
|
|
2020-01-28 13:38:07 +00:00
|
|
|
from pathlib import Path
|
|
|
|
from uncloud.vmm import VMM
|
2020-01-28 16:44:53 +00:00
|
|
|
from uncloud.host.virtualmachine import update_radvd_conf, create_vxlan_br_tap
|
2020-01-28 13:38:07 +00:00
|
|
|
|
|
|
|
from . import virtualmachine, logger
|
|
|
|
|
2020-01-28 16:44:53 +00:00
|
|
|
###
|
|
|
|
# Argument parser loaded by scripts/uncloud.
|
2020-01-28 13:38:07 +00:00
|
|
|
arg_parser = argparse.ArgumentParser('oneshot', add_help=False)
|
2020-01-28 16:44:53 +00:00
|
|
|
|
|
|
|
# Actions.
|
|
|
|
arg_parser.add_argument('--list', action='store_true',
|
|
|
|
help='list UUID and name of running VMs')
|
|
|
|
arg_parser.add_argument('--start', nargs=3,
|
2020-01-30 07:54:58 +00:00
|
|
|
metavar=('NAME', 'IMAGE', 'UPSTREAM_INTERFACE', 'NETWORK'),
|
2020-01-28 16:44:53 +00:00
|
|
|
help='start a VM using the OS IMAGE (full path), configuring networking on NETWORK IPv6 prefix')
|
|
|
|
arg_parser.add_argument('--stop', metavar='UUID',
|
|
|
|
help='stop a VM')
|
|
|
|
arg_parser.add_argument('--get-status', metavar='UUID',
|
|
|
|
help='return the status of the VM')
|
|
|
|
arg_parser.add_argument('--get-vnc', metavar='UUID',
|
|
|
|
help='return the path of the VNC socket of the VM')
|
|
|
|
arg_parser.add_argument('--reconfigure-radvd', metavar='NETWORK',
|
|
|
|
help='regenerate and reload RADVD configuration for NETWORK IPv6 prefix')
|
|
|
|
|
|
|
|
# Arguments.
|
|
|
|
arg_parser.add_argument('--workdir', default=Path.home(),
|
|
|
|
help='Working directory, defaulting to $HOME')
|
|
|
|
arg_parser.add_argument('--mac',
|
|
|
|
help='MAC address of the VM to create (--start)')
|
|
|
|
arg_parser.add_argument('--memory', type=int,
|
|
|
|
help='Memory (MB) to allocate (--start)')
|
|
|
|
arg_parser.add_argument('--cores', type=int,
|
|
|
|
help='Number of cores to allocate (--start)')
|
|
|
|
arg_parser.add_argument('--threads', type=int,
|
|
|
|
help='Number of threads to allocate (--start)')
|
|
|
|
arg_parser.add_argument('--image-format', choices=['raw', 'qcow2'],
|
|
|
|
help='Format of OS image (--start)')
|
2020-01-30 07:47:23 +00:00
|
|
|
arg_parser.add_argument('--accel', choices=['kvm', 'tcg'], default='kvm',
|
2020-01-28 16:44:53 +00:00
|
|
|
help='QEMU acceleration to use (--start)')
|
|
|
|
arg_parser.add_argument('--upstream-interface', default='eth0',
|
|
|
|
help='Name of upstream interface (--start)')
|
|
|
|
|
|
|
|
###
|
|
|
|
# Helpers.
|
|
|
|
|
|
|
|
# XXX: check if it is possible to use the type returned by ETCD queries.
|
|
|
|
class UncloudEntryWrapper:
|
|
|
|
def __init__(self, value):
|
|
|
|
self.value = value
|
|
|
|
|
|
|
|
def value(self):
|
|
|
|
return self.value
|
|
|
|
|
|
|
|
def status_line(vm):
|
|
|
|
return "VM: {} {} {}".format(vm.get_uuid(), vm.get_name(), vm.get_status())
|
|
|
|
|
|
|
|
###
|
|
|
|
# Entrypoint.
|
2020-01-28 13:38:07 +00:00
|
|
|
|
|
|
|
def main(arguments):
|
2020-01-28 16:44:53 +00:00
|
|
|
# Initialize VMM.
|
2020-01-28 13:38:07 +00:00
|
|
|
workdir = arguments['workdir']
|
|
|
|
vmm = VMM(vmm_backend=workdir)
|
|
|
|
|
2020-01-28 16:44:53 +00:00
|
|
|
# Harcoded debug values.
|
|
|
|
net_id = 0
|
2020-01-28 13:38:07 +00:00
|
|
|
|
|
|
|
# Build VM configuration.
|
|
|
|
vm_config = {}
|
2020-01-28 16:44:53 +00:00
|
|
|
vm_options = [
|
|
|
|
'mac', 'memory', 'cores', 'threads', 'image', 'image_format',
|
2020-01-30 07:47:23 +00:00
|
|
|
'--upstream_interface', 'upstream_interface', 'network', 'accel'
|
2020-01-28 16:44:53 +00:00
|
|
|
]
|
|
|
|
for option in vm_options:
|
|
|
|
if arguments.get(option):
|
|
|
|
vm_config[option] = arguments[option]
|
|
|
|
|
|
|
|
vm_config['net_id'] = net_id
|
2020-01-28 13:38:07 +00:00
|
|
|
|
|
|
|
# Execute requested VM action.
|
2020-01-28 16:44:53 +00:00
|
|
|
if arguments['reconfigure_radvd']:
|
|
|
|
# TODO: check that RADVD is available.
|
|
|
|
prefix = arguments['reconfigure_radvd']
|
|
|
|
network = UncloudEntryWrapper({
|
|
|
|
'id': net_id,
|
|
|
|
'ipv6': prefix
|
|
|
|
})
|
|
|
|
|
|
|
|
# Make use of uncloud.host.virtualmachine for network configuration.
|
|
|
|
update_radvd_conf([network])
|
|
|
|
elif arguments['start']:
|
|
|
|
# Extract from --start positional arguments. Quite fragile.
|
2020-01-30 07:54:58 +00:00
|
|
|
vm_config['name'] = arguments['start'][0]
|
|
|
|
vm_config['image'] = arguments['start'][1]
|
|
|
|
vm_config['network'] = arguments['start'][2]
|
|
|
|
vm_config['upstream_interface'] = arguments['start'][3]
|
2020-01-28 16:44:53 +00:00
|
|
|
|
|
|
|
vm_config['tap_interface'] = "uc{}".format(len(vmm.discover()))
|
|
|
|
vm = virtualmachine.VM(vmm, vm_config)
|
2020-01-28 13:38:07 +00:00
|
|
|
vm.start()
|
2020-01-28 16:44:53 +00:00
|
|
|
elif arguments['stop']:
|
|
|
|
vm = virtualmachine.VM(vmm, {'uuid': arguments['stop']})
|
2020-01-28 13:38:07 +00:00
|
|
|
vm.stop()
|
2020-01-28 16:44:53 +00:00
|
|
|
elif arguments['get_status']:
|
|
|
|
vm = virtualmachine.VM(vmm, {'uuid': arguments['get_status']})
|
|
|
|
print(status_line(vm))
|
|
|
|
elif arguments['get_vnc']:
|
|
|
|
vm = virtualmachine.VM(vmm, {'uuid': arguments['get_vnc']})
|
|
|
|
print(vm.get_vnc_addr())
|
|
|
|
elif arguments['list']:
|
|
|
|
vms = vmm.discover()
|
|
|
|
print("Found {} VMs.".format(len(vms)))
|
|
|
|
for uuid in vms:
|
|
|
|
vm = virtualmachine.VM(vmm, {'uuid': uuid})
|
|
|
|
print(status_line(vm))
|
2020-01-28 13:38:07 +00:00
|
|
|
else:
|
2020-01-28 16:44:53 +00:00
|
|
|
print('Please specify an action: --start, --stop, --list,\
|
|
|
|
--get-status, --get-vnc, --reconfigure-radvd')
|