diff --git a/mc-vm-manager/VMHelper.py b/mc-vm-manager/VMHelper.py index c717604..888b9f1 100644 --- a/mc-vm-manager/VMHelper.py +++ b/mc-vm-manager/VMHelper.py @@ -3,6 +3,7 @@ import subprocess import os, errno import threading import time +import sys from qmp import QEMUMonitorProtocol class VMHelper: @@ -15,6 +16,15 @@ class VMHelper: else: return [] + def humanMonitorCommand(self, vmid: str, command: str, args: list) -> str: + proto = QEMUMonitorProtocol(self.config['kvm']['qmpsocket'].replace("$VMID", vmid)) + proto.connect() + commandline = command + " " + " ".join(args) + result = proto.cmd("human-monitor-command", { "command-line" : commandline }) + + proto.close() + return result["return"] + def getPid(self,vmid) -> "int or None": result = None try: @@ -56,17 +66,24 @@ class VMHelper: proto.close() return result - def autostartVMs(self): + def autostartVMs(self,managerpath): if ('VMs' in self.config): for vmid, vmcfg in self.config['VMs'].items(): if "autostart" in vmcfg and vmcfg["autostart"] and not self.process_running(vmid): - self.startVM(vmid) + self.startVM(vmid,managerpath) else: raise Exception("Missing VMs config section!") - def startVM(self, vmid): + def startVM(self, vmid, managerpath): self.setupNetwork(vmid) cmd = [] + + fullpath_helper = os.path.realpath(__file__) + pathname_helper = os.path.dirname(fullpath_helper) + + cmd.append(pathname_helper + "/qemu-wrapper.sh") + cmd.append(sys.executable) + cmd.append(managerpath) cmd.append(self.config['kvm']['executable']) cmd.append(vmid) @@ -205,6 +222,7 @@ class VMHelper: commands.append(["tunctl", "-t", net['dev']]) commands.append(["ip", "link", "set", "dev", net['dev'], "up"]) commands.append(["ip", "addr", "add", "dev", net['dev'], "0.0.0.0"]) + commands.append(["ip", "-6" , "addr", "add", "dev", net['dev'], "fe80::1/64"]) chain = "VMNET-FWD-" + vmid.upper() diff --git a/mc-vm-manager/config.json b/mc-vm-manager/config.json index 0a08122..bde5caf 100644 --- a/mc-vm-manager/config.json +++ b/mc-vm-manager/config.json @@ -1,6 +1,6 @@ { "kvm": { - "executable": "/root/tmp/qemu-wrapper.sh", + "executable": "/usr/bin/qemu-kvm", "default_args" : "", "pidfile": "/tmp/$VMID.pid", "qmpsocket" : "/tmp/$VMID.qmp" @@ -35,19 +35,24 @@ "cpu": "kvm64", "smp": 2, "memory": 2048, + "disk": { + "hw": "virtio", + "file": "/dev/mapper/vg3-bar" + }, "cdrom": "/root/tmp/install-amd64-minimal-20130207.iso", "network": { "hw": "virtio", - "dev": "tap-foo", - "mac": "54:52:00:00:01:01", - "ip": ["192.0.2.23", "192.0.2.24"] + "dev": "tap-bar", + "mac": "54:52:00:00:02:01", + "ip": ["185.15.245.166"] }, "vnc": { "display": 2 }, "keyboard" : "de", + "kernel": "/home/markus/linux-3.2.11-dkl", + "append": "root=/dev/vda", "owner": "markus", - "autostart" : true }, "baz": { @@ -58,8 +63,8 @@ "network": { "hw": "virtio", "dev": "tap-baz", - "mac": "54:52:00:00:01:03", - "ip": ["192.0.2.26", "192.0.2.27"] + "mac": "54:52:00:00:03:01", + "ip": ["178.63.173.238"] }, "vnc": { "display": 3 diff --git a/mc-vm-manager/manager.py b/mc-vm-manager/manager.py index 214f5fd..dc3a93a 100755 --- a/mc-vm-manager/manager.py +++ b/mc-vm-manager/manager.py @@ -3,6 +3,7 @@ import argparse import sys import time +import os from VMHelper import VMHelper @@ -39,10 +40,11 @@ def vmm_start(args): return print('Starting VM {0.vmid}.'.format(args)) - helper.startVM(args.vmid) + 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 not args.t.isdigit() else int(args.t) + 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) @@ -62,11 +64,11 @@ def vmm_stop(args): 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.isdigit(): - print ("timeout must be positve integer but is " + args.t + "!") + if args.t is not None and not args.t >= 0: + print ("timeout must be positve integer but is " + str(args.t) + "!") return - timeout = int(args.t) if args.t is not None else None + timeout = args.t if args.t is not None else None print('Stopping VM {0.vmid} with timeout {1}.'.format(args,timeout)) @@ -99,7 +101,18 @@ def vmm_version(args): print("MC VM Manager v0.1\nCopyright (c) M. Hauschild and P. Dahlberg 2013.\n") def vmm_autostart(args): - helper.autostartVMs() + 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 main(): #maybe we need to create a lockfile @@ -114,13 +127,13 @@ def main(): 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', help='forcefully quit after given timeout value (signed integer), implies -w') + 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', help='forcefully quit after given timeout value (signed integer, default: {0}'.format(SHUTDOWN_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) @@ -133,6 +146,12 @@ def main(): 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) diff --git a/mc-vm-manager/qemu-wrapper.sh b/mc-vm-manager/qemu-wrapper.sh index 2adf11d..2d93942 100755 --- a/mc-vm-manager/qemu-wrapper.sh +++ b/mc-vm-manager/qemu-wrapper.sh @@ -1,12 +1,14 @@ #!/bin/bash -vmid=$1 + +python=$1 +shift +manager=$1 +shift +QEMU=$1 +shift +vmid=$1 shift -date >> /tmp/cleanup -echo "Starting ${vmid}" >> /tmp/cleanup -/usr/bin/qemu-kvm $@ - -date >> /tmp/cleanup -echo "Cleaning up for ${vmid}" >> /tmp/cleanup -/root/tmp/manager.py cleanup $vmid +$QEMU $@ +$python $manager cleanup $vmid