Much much changes
This commit is contained in:
@@ -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']):
|
||||
|
||||
Reference in New Issue
Block a user