Much much changes

This commit is contained in:
2013-04-07 02:41:58 +02:00
parent 05b3f04c8c
commit 3917e799fb
4 changed files with 385 additions and 172 deletions

View File

@@ -1,12 +1,21 @@
import json
import subprocess
import os, errno
import threading
import time
from qmp import QEMUMonitorProtocol
class VMHelper:
def __init__(self):
self.config = json.load(open("/root/tmp/config.json"))
def __init__(self, filename):
self.config = json.load(open(filename))
def getPid(self,vmid):
def getVmIds(self):
if ('VMs' in self.config):
return [x for x , y in self.config['VMs'].items()]
else:
return []
def getPid(self,vmid) -> "int or None":
result = None
try:
with open(self.config['kvm']['pidfile'].replace("$VMID", vmid)) as pidfd:
@@ -17,23 +26,44 @@ class VMHelper:
return result
def process_running(self,vmid):
def process_running(self,vmid) -> bool:
pid = self.getPid(vmid)
if pid is None:
return False
result = None
try:
os.kill(pid,0)
except OSError as e:
result = e.errno != errno.ESRCH
return e.errno != errno.ESRCH
else:
result = True
return True
def getQMPStatus(self,vmid):
# cmd doku http://git.qemu.org/?p=qemu.git;a=blob;f=qmp-commands.hx;h=1e0e11ee32571209e2dfce41b5c18f01d6ad3880;hb=HEAD
proto = QEMUMonitorProtocol(self.config['kvm']['qmpsocket'].replace("$VMID", vmid))
proto.connect()
result = {}
queryKvm = proto.command("query-kvm")
result["kvm-enabled"] = queryKvm["enabled"]
result["kvm-present"] = queryKvm["present"]
result["status"] = proto.command("query-status")["status"]
proto.close()
return result
def autostartVMs(self):
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)
else:
raise Exception("Missing VMs config section!")
def startVM(self, vmid):
self.setupNetwork(vmid)
cmd = []
@@ -46,12 +76,77 @@ class VMHelper:
cmd.append("-qmp")
cmd.append("unix:" + self.config['kvm']['qmpsocket'].replace("$VMID", vmid) + ",server,nowait")
cmd += ["-name", vmid]
default_args = self.config['kvm']['default_args'].replace("$VMID", vmid)
cmd += default_args.split()
cmd += self.createArguments(vmid).split()
#print(" ".join(cmd))
subprocess.Popen(cmd, stdout=open("/dev/null"), stderr=open("/dev/null"))
#subprocess.call(cmd)
#subprocess.call(cmd
def shutdownVMs(self,timeout,parallel=True, statusCallback=lambda vmid, st : None):
threads = []
for vmid in self.getVmIds():
if self.process_running(vmid):
# i=vmid: strange workaround for strange problem the it uses the wrong vmid...
def stopCallback(st, i=vmid): statusCallback(i, st)
thread = threading.Thread(target=lambda : self.stopVM(vmid, timeout, stopCallback))
thread.start()
if parallel:
threads.append(thread)
else:
thread.join()
for thread in threads:
thread.join()
def stopVM(self, vmid, timeout=None, statusCallback=lambda st : None, wait=False):
proto = QEMUMonitorProtocol(self.config['kvm']['qmpsocket'].replace("$VMID", vmid))
proto.connect()
statusCallback("send_powerdown")
proto.cmd("system_powerdown")
if timeout is None and not wait:
proto.close()
return
timeoutEvent = threading.Event()
def waitForShutdown():
shutDown = False
while not timeoutEvent.is_set() and not shutDown :
event = proto.pull_event(wait=True)
shutDown = event is not None and event["event"] == 'SHUTDOWN'
eventWaitThread = threading.Thread(target=waitForShutdown)
eventWaitThread.start()
if(timeout is None and wait):
eventWaitThread.join()
proto.close()
return
eventWaitThread.join(timeout)
timeoutEvent.set()
if eventWaitThread.is_alive():
statusCallback("send_quit")
proto.cmd("quit")
time.sleep(1)
if(self.process_running(vmid)):
statusCallback("kill_vm")
self.killVm(vmid, 9) #kill it with fire!
proto.close()
def killVm(self, vmid, signal=15):
pid = self.getPid(vmid)
if pid is not None:
os.kill(pid,signal)
def createArguments(self, vmid):
if ('VMs' in self.config) and (vmid in self.config['VMs']):