#!/usr/bin/python3 import argparse import sys import time import os from VMHelper import VMHelper #### Constants ### CONFIG_FILENAME_DEFAULT = "/etc/vm-manager.json" SHUTDOWN_TIMEOUT = 180 #### --------- ### helper = VMHelper(CONFIG_FILENAME_DEFAULT) stopStatusToMessage = { "send_powerdown" : "Sending ACPI poweroff Event.", "send_quit" : "Shoutdown has timed out! Quitting forcefully!", "kill_vm" : "Killing process!" } def vmm_list(args): print("Available VMs:") print() for vmid in helper.getVmIds(): s = "ID: {0} -- {1}" state = None if helper.process_running(vmid): state = helper.getQMPStatus(vmid)["status"] else : state = "stopped" print(s.format(vmid,state)) def vmm_start(args): if(helper.process_running(args.vmid)): print("VM {0} is already running!".format(args.vmid)) return #TODO: pass ignore hibernation file flag print('Starting VM {0.vmid}.'.format(args)) fullpath_manager = os.path.realpath(sys.argv[0]) helper.startVM(args.vmid,fullpath_manager) #print("Successfully started: " + ("yes" if helper.process_running(args.vmid) else "no")) def vmm_shutdown(args): timeout = SHUTDOWN_TIMEOUT if args.t is None or args.t < 0 else args.t stCallback = lambda vmid, st : print("VM {0}: {1}".format(vmid, stopStatusToMessage[st])) helper.shutdownVMs(timeout, args.s is None or args.s < 1, statusCallback=stCallback) def vmm_hibernate(args): #TODO: implement ;) def vmm_stop(args): if(not helper.process_running(args.vmid)): print("VM {0} is not running!".format(args.vmid)) return if args.k is not None and args.k >= 1: helper.killVm(args.vmid) time.sleep(0.3) if helper.process_running(args.vmid): time.sleep(2) if helper.process_running(args.vmid): helper.killVm(args.vmid , 9) print("VM killed successfully: " + ("yes" if not helper.process_running(args.vmid) else "no")) return if args.t is not None and not args.t >= 0: print ("timeout must be positve integer but is " + str(args.t) + "!") return timeout = args.t if args.t is not None else None print('Stopping VM {0.vmid} with timeout {1}.'.format(args,timeout)) helper.stopVM(args.vmid, timeout, lambda x: print(stopStatusToMessage[x]), wait=args.w is not None) def vmm_status(args): if args.v >= 1: print('Gathering status information for VM {0.vmid}.'.format(args)) proc_running = helper.process_running(args.vmid) print("VM ID: {0}".format(args.vmid)) print("Qemu process is running: " + ("yes (pid: {0})".format(helper.getPid(args.vmid)) if proc_running else "no")) #TODO write some decoder with status descriptions plaintext for key,val in helper.getQMPStatus(args.vmid).items(): print("{0}: {1}".format(key,val)) def vmm_cleanup(args): if(helper.process_running(args.vmid)): print("VM {0} is running, nothing to clean up!".format(args.vmid)) return print('Cleaning up for VM {0.vmid}.'.format(args)) helper.teardownNetwork(args.vmid) #TODO remove pidfile and qmpfile def vmm_version(args): print("MC VM Manager v0.1\nCopyright (c) M. Hauschild and P. Dahlberg 2013.\n") def vmm_autostart(args): fullpath_manager = os.path.realpath(sys.argv[0]) helper.autostartVMs(fullpath_manager) def vmm_monitor(args): if(not helper.process_running(args.vmid)): print("VM {0} is not running!".format(args.vmid)) return try: print(helper.humanMonitorCommand(args.vmid, args.monitorcmd, args.monitorargs)) except: print("unable to issue monitor command!") def vmm_authorized(args): helper.generateAuthorizedKeys() def main(): #maybe we need to create a lockfile parser = argparse.ArgumentParser(prog='mcvmm', description='Manages VMs') subparsers = parser.add_subparsers(title='subcommands') parser.add_argument('-v', action='count', default=0, help='increase verbosity') parser_start = subparsers.add_parser('start', help='starts a VM') parser_start.add_argument('vmid', action='store', help='the ID of the VM') parser_start.add_argument('-i', action='count', help='ignore saved VM state') parser_start.set_defaults(func=vmm_start) parser_authorized = subparsers.add_parser('gen-auth-keys', help='Regenerates authorized_keys file') parser_authorized.set_defaults(func=vmm_authorized) parser_stop = subparsers.add_parser('stop', help='Shutdown VM with ACPI poweroff') parser_stop.add_argument('vmid', action='store', help='the ID of the VM') parser_stop.add_argument('-t', action='store',type=int, help='forcefully quit after given timeout value (signed integer), implies -w') parser_stop.add_argument('-k', action='count', help='Kill the qemu process') parser_stop.add_argument('-w', action='count', help='wait until the VM has stopped') parser_stop.set_defaults(func=vmm_stop) parser_shutdown = subparsers.add_parser('shutdown', help='Shutdown all VMs ACPI poweroff and quit forcefully after timeout') parser_shutdown.add_argument('-t', action='store',type=int, default=SHUTDOWN_TIMEOUT, help='forcefully quit after given timeout value (signed integer)') parser_shutdown.add_argument('-s', action='count', help='sequencial mode, timeout for each vm') parser_shutdown.set_defaults(func=vmm_shutdown) parser_hibernate = subparsers.add_parser('hibernate', help='Suspend the execution of all VMs and save theire state to disk') parser_hibernate.set_defaults(func=vmm_hibernate) parser_status = subparsers.add_parser('status', help='query the status a VM') parser_status.add_argument('-v', action='count', help='increase verbosity') parser_status.add_argument('vmid', action='store', default=0, help='the ID of the VM') parser_status.set_defaults(func=vmm_status) parser_cleanup = subparsers.add_parser('cleanup', help='cleans up stuff for a VM') parser_cleanup.add_argument('vmid', action='store', default=0, help='the ID of the VM') parser_cleanup.set_defaults(func=vmm_cleanup) parser_monitor = subparsers.add_parser('monitor', help='sends a command to the monitor') parser_monitor.add_argument('vmid', action='store', default=0, help='the ID of the VM') parser_monitor.add_argument('monitorcmd', action="store", help="the command passed to the monitor") parser_monitor.add_argument('monitorargs', nargs=argparse.REMAINDER ,action="store", help="the arguments of the command") parser_monitor.set_defaults(func=vmm_monitor) parser_list = subparsers.add_parser('list', help='list available vms') parser_list.set_defaults(func=vmm_list) parser_version = subparsers.add_parser('version', help='Prints version and authors') parser_version.set_defaults(func=vmm_version) parser_autostart = subparsers.add_parser('autostart', help='Start VMs configured with autostart') parser_autostart.set_defaults(func=vmm_autostart) args = parser.parse_args() if "vmid" in args and args.vmid not in helper.getVmIds(): print("VM {0} does not exist!".format(args.vmid)) return args.func(args) if __name__ == '__main__': main()