Ein Zwischenstand einfach mal so
This commit is contained in:
@@ -1,6 +1,64 @@
|
|||||||
class VMHelper:
|
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")
|
||||||
|
|
||||||
def createArguments(self, config):
|
|
||||||
args = ""
|
args = ""
|
||||||
if ('cpu' in config):
|
if ('cpu' in config):
|
||||||
args += " -cpu " + config['cpu']
|
args += " -cpu " + config['cpu']
|
||||||
@@ -26,7 +84,7 @@ class VMHelper:
|
|||||||
args += " -net tap,vlan=1"
|
args += " -net tap,vlan=1"
|
||||||
if ('dev' in net):
|
if ('dev' in net):
|
||||||
args += ",ifname=" + net['dev']
|
args += ",ifname=" + net['dev']
|
||||||
args += ",script=no"
|
args += ",script=no,downscript=no"
|
||||||
if ('vnc' in config):
|
if ('vnc' in config):
|
||||||
vnc = config['vnc']
|
vnc = config['vnc']
|
||||||
if ('display' in vnc):
|
if ('display' in vnc):
|
||||||
@@ -39,23 +97,62 @@ class VMHelper:
|
|||||||
args += " -append \"" + config['append'] + "\""
|
args += " -append \"" + config['append'] + "\""
|
||||||
return args
|
return args
|
||||||
|
|
||||||
def setupNetwork(self, config):
|
def setupNetwork(self, vmid):
|
||||||
foo = ""
|
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):
|
if ('network' in config):
|
||||||
net = config['network']
|
net = config['network']
|
||||||
if ('dev' in net):
|
if ('dev' in net):
|
||||||
foo += "tunctl -d " + net['dev'] + "\n"
|
commands.append(["tunctl", "-t", net['dev']])
|
||||||
foo += "ip link set dev " + net['dev'] +" up\n"
|
commands.append(["ip", "link", "set", "dev", net['dev'], "up"])
|
||||||
foo += "ip addr add dev " + net['dev'] +" 0.0.0.0\n"
|
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):
|
if ('ip' in net):
|
||||||
for ip in net['ip']:
|
for ip in net['ip']:
|
||||||
foo += "ip route add " + ip + " dev " + net['dev'] + "\n"
|
commands.append(["ip", "route", "add", ip, "dev", net['dev']])
|
||||||
# TODO create extra chain
|
commands.append(["iptables", "-A", chain, "-i", net['dev'], "-s", ip, "-j", "ACCEPT"])
|
||||||
foo += "iptables -A FORWARD -i " + net['dev'] + " -s " + ip + " -j ACCEPT\n"
|
commands.append(["iptables", "-A", chain, "-i", net['dev'], "-j", "REJECT", "--reject-with", "icmp-admin-prohibited"])
|
||||||
foo += "iptables -A FORWARD -i " + net['dev'] + " -j REJECT --reject-with icmp-admin-prohibited\n"
|
commands.append(["iptables", "-A", "FORWARD", "-j", chain])
|
||||||
|
|
||||||
|
commands.append(["ip6tables", "--new-chain", chain])
|
||||||
if ('ipv6' in net):
|
if ('ipv6' in net):
|
||||||
for ipv6 in net['ipv6']:
|
for ipv6 in net['ipv6']:
|
||||||
foo += "ip -6 route add " + ipv6 + " dev " + net['dev'] + "\n"
|
commands.append( ["ip", "-6", "route", "add", ipv6, "dev", net['dev']])
|
||||||
foo += "ip6tables -A FORWARD -i " + net['dev'] + " -s " + ipv6 + " -j ACCEPT\n"
|
commands.append(["ip6tables", "-A", chain, "-i", net['dev'], "-s", ipv6, "-j", "ACCEPT"])
|
||||||
foo += "iptables -A FORWARD -i " + net['dev'] + " -j REJECT --reject-with icmp6-adm-prohibited\n"
|
commands.append(["ip6tables", "-A", chain, "-i", net['dev'], "-j", "REJECT", "--reject-with", "icmp6-adm-prohibited"])
|
||||||
return foo
|
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"))
|
||||||
|
|||||||
52
mc-vm-manager/config.json
Normal file
52
mc-vm-manager/config.json
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"kvm": {
|
||||||
|
"executable": "/root/tmp/qemu-wrapper.sh",
|
||||||
|
"default_args" : "",
|
||||||
|
"pidfile": "/tmp/$VMID.pid",
|
||||||
|
"qmpsocket" : "/tmp/$VMID.qmp"
|
||||||
|
},
|
||||||
|
"VMs": {
|
||||||
|
"foo": {
|
||||||
|
"cpu": "kvm64",
|
||||||
|
"smp": 2,
|
||||||
|
"memory": 2048,
|
||||||
|
"disk": {
|
||||||
|
"hw": "virtio",
|
||||||
|
"file": "/dev/mapper/vg3-foo"
|
||||||
|
},
|
||||||
|
"cdrom": "/pub/debian.iso",
|
||||||
|
"network": {
|
||||||
|
"hw": "virtio",
|
||||||
|
"dev": "tap-foo",
|
||||||
|
"mac": "54:52:00:00:01:01",
|
||||||
|
"ip": ["192.0.2.23", "192.0.2.24"],
|
||||||
|
"ipv6": ["2001:db8::/80"]
|
||||||
|
},
|
||||||
|
"vnc": {
|
||||||
|
"display": 1
|
||||||
|
},
|
||||||
|
"keyboard" : "de",
|
||||||
|
"kernel": "/home/markus/kernel-3.8.5",
|
||||||
|
"append": "root=/dev/vda",
|
||||||
|
"owner": "markus"
|
||||||
|
},
|
||||||
|
"bar": {
|
||||||
|
"cpu": "kvm64",
|
||||||
|
"smp": 2,
|
||||||
|
"memory": 2048,
|
||||||
|
"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"]
|
||||||
|
},
|
||||||
|
"vnc": {
|
||||||
|
"display": 2
|
||||||
|
},
|
||||||
|
"keyboard" : "de",
|
||||||
|
"owner": "markus"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -2,42 +2,60 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
|
from VMHelper import VMHelper
|
||||||
|
|
||||||
|
helper = None
|
||||||
|
|
||||||
def vmm_start(args):
|
def vmm_start(args):
|
||||||
if args.v >= 1:
|
|
||||||
print('Starting VM {0.vmid}.'.format(args))
|
print('Starting VM {0.vmid}.'.format(args))
|
||||||
|
helper.startVM(args.vmid)
|
||||||
|
|
||||||
def vmm_stop(args):
|
def vmm_stop(args):
|
||||||
if args.v >= 1:
|
|
||||||
print('Stopping VM {0.vmid}.'.format(args))
|
print('Stopping VM {0.vmid}.'.format(args))
|
||||||
|
helper.stopVM(args['vmid'])
|
||||||
|
|
||||||
def vmm_status(args):
|
def vmm_status(args):
|
||||||
if args.v >= 2:
|
if args.v >= 1:
|
||||||
print('Gathering status information for VM {0.vmid}.'.format(args))
|
print('Gathering status information for VM {0.vmid}.'.format(args))
|
||||||
|
|
||||||
def main():
|
print("VM ID: {0}".format(args.vmid))
|
||||||
print("MC VM Manager v0.1\nCopyright (c) M. Hauschild, 2013.\n")
|
print("Qemu process is running: " + ("yes (pid: {0})".format(helper.getPid(args.vmid)) if helper.process_running(args.vmid) else "no"))
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(prog='bkvmm', description='Manages VMs')
|
def vmm_cleanup(args):
|
||||||
|
print('Cleaning up for VM {0.vmid}.'.format(args))
|
||||||
|
helper.teardownNetwork(args.vmid)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global helper
|
||||||
|
|
||||||
|
print("MC VM Manager v0.1\nCopyright (c) M. Hauschild and P. Dahlberg 2013.\n")
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(prog='mcvmm', description='Manages VMs')
|
||||||
subparsers = parser.add_subparsers(title='subcommands')
|
subparsers = parser.add_subparsers(title='subcommands')
|
||||||
parser.add_argument('-v', action='count', default=0, help='increase verbosity')
|
parser.add_argument('-v', action='count', default=0, help='increase verbosity')
|
||||||
|
|
||||||
parser_start = subparsers.add_parser('start', help='starts a VM')
|
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('vmid', action='store', help='the ID of the VM')
|
||||||
parser_start.add_argument('-v', action='count', default=0, help='increase verbosity')
|
|
||||||
parser_start.set_defaults(func=vmm_start)
|
parser_start.set_defaults(func=vmm_start)
|
||||||
|
|
||||||
parser_stop = subparsers.add_parser('stop', help='stop a VM')
|
parser_stop = subparsers.add_parser('stop', help='stop a VM')
|
||||||
parser_stop.add_argument('vmid', action='store', help='the ID of the VM')
|
parser_stop.add_argument('vmid', action='store', help='the ID of the VM')
|
||||||
parser_stop.add_argument('-v', action='count', default=0, help='increase verbosity')
|
|
||||||
parser_stop.set_defaults(func=vmm_stop)
|
parser_stop.set_defaults(func=vmm_stop)
|
||||||
|
|
||||||
parser_status = subparsers.add_parser('status', help='statuss a VM')
|
parser_status = subparsers.add_parser('status', help='status a VM')
|
||||||
parser_status.add_argument('-v', action='count', help='increase verbosity')
|
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.add_argument('vmid', action='store', default=0, help='the ID of the VM')
|
||||||
parser_status.set_defaults(func=vmm_status)
|
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)
|
||||||
|
|
||||||
|
helper = VMHelper()
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
#TODO abfrage ob vmid existiert
|
||||||
args.func(args)
|
args.func(args)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
Reference in New Issue
Block a user