import json import subprocess import os, errno class VMHelper: def __init__(self): self.config = json.load(open("/root/tmp/config.json")) def getPid(self,vmid): result = None try: with open(self.config['kvm']['pidfile'].replace("$VMID", vmid)) as pidfd: firstline = pidfd.readline().strip() result = int(firstline) if firstline.isdigit() else None except IOError: pass return result def process_running(self,vmid): 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 else: result = True return result def startVM(self, vmid): self.setupNetwork(vmid) cmd = [] cmd.append(self.config['kvm']['executable']) cmd.append(vmid) cmd.append("-pidfile") cmd.append(self.config['kvm']['pidfile'].replace("$VMID", vmid)) cmd.append("-qmp") cmd.append("unix:" + self.config['kvm']['qmpsocket'].replace("$VMID", vmid) + ",server,nowait") 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) def createArguments(self, vmid): if ('VMs' in self.config) and (vmid in self.config['VMs']): config = self.config['VMs'][vmid] else: raise Exception("No such VM configuration") args = "" if ('cpu' in config): args += " -cpu " + config['cpu'] if ('smp' in config): args += " -smp " + str(config['smp']) if ('memory' in config): args += " -m " + str(config['memory']) if ('disk' in config): disk = config['disk'] if ('file' in disk): args += " -drive file=" + disk['file'] if ('hw' in disk): args += ",if=" + disk['hw'] if ('cdrom' in config): args += " -cdrom " + config['cdrom'] if ('network' in config): net = config['network'] args += " -net nic,vlan=1" if ('mac' in net): args += ",macaddr=" + net['mac'] if ('hw' in net): args += ",model=" + net['hw'] args += " -net tap,vlan=1" if ('dev' in net): args += ",ifname=" + net['dev'] args += ",script=no,downscript=no" if ('vnc' in config): vnc = config['vnc'] if ('display' in vnc): args += " -vnc 127.0.0.1:" + str(vnc['display']) if ('keyboard' in config): args += " -k " + config['keyboard'] if ('kernel' in config): args += " -kernel " + config['kernel'] if ('append' in config): args += " -append \"" + config['append'] + "\"" return args def setupNetwork(self, vmid): if ('VMs' in self.config) and (vmid in self.config['VMs']): config = self.config['VMs'][vmid] else: raise Exception("No such VM configuration") commands = [] if ('network' in config): net = config['network'] if ('dev' in net): 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"]) chain = "VMNET-FWD-" + vmid.upper() commands.append(["iptables", "--new-chain", chain]) if ('ip' in net): for ip in net['ip']: commands.append(["ip", "route", "add", ip, "dev", net['dev']]) commands.append(["iptables", "-A", chain, "-i", net['dev'], "-s", ip, "-j", "ACCEPT"]) commands.append(["iptables", "-A", chain, "-i", net['dev'], "-j", "REJECT", "--reject-with", "icmp-admin-prohibited"]) commands.append(["iptables", "-A", "FORWARD", "-j", chain]) commands.append(["ip6tables", "--new-chain", chain]) if ('ipv6' in net): for ipv6 in net['ipv6']: commands.append( ["ip", "-6", "route", "add", ipv6, "dev", net['dev']]) commands.append(["ip6tables", "-A", chain, "-i", net['dev'], "-s", ipv6, "-j", "ACCEPT"]) commands.append(["ip6tables", "-A", chain, "-i", net['dev'], "-j", "REJECT", "--reject-with", "icmp6-adm-prohibited"]) commands.append(["ip6tables", "-A", "FORWARD", "-j", chain]) for cmd in commands: subprocess.call(cmd, stdout=open("/dev/null")) def teardownNetwork(self, vmid): if ('VMs' in self.config) and (vmid in self.config['VMs']): config = self.config['VMs'][vmid] else: raise Exception("No such VM configuration") commands = [] if ('network' in config): net = config['network'] if ('dev' in net): commands.append(["tunctl", "-d", net['dev']]) chain = "VMNET-FWD-" + vmid.upper() commands.append(["iptables", "-F", chain]) commands.append(["iptables", "-D", "FORWARD", "-j", chain]) commands.append(["iptables", "--delete-chain", chain]) commands.append(["ip6tables", "-F", chain]) commands.append(["ip6tables", "-D", "FORWARD", "-j", chain]) commands.append(["ip6tables", "--delete-chain", chain]) for cmd in commands: subprocess.call(cmd, stdout=open("/dev/null"))