#!/usr/bin/python import sys, os, time, re import optparse, commands import ConfigParser, StringIO class ShellConfigParser(ConfigParser.ConfigParser): def read(self, filename): try: text = open(filename).read() except IOError: pass else: file = StringIO.StringIO("[shell]\n" + text) self.readfp(file, filename) config = ShellConfigParser() config.read('config.mak') external_module = config.get('shell', 'want_module') arch = config.get('shell', 'arch') p = re.compile("^i\d86$") if len(p.findall(arch)): arch = 'x86_64' if arch != 'x86_64' and arch != 'ia64': raise Exception('unsupported architecture %s' % arch) privileged = os.getuid() == 0 optparser = optparse.OptionParser() optparser.add_option('--no-reload-module', help = 'do not reload kvm module', action = 'store_false', dest = 'reload', default = privileged, ) optparser.add_option('--install', help = 'start up guest in installer boot cd', action = 'store_true', default = False, ) optparser.add_option('-m', '--memory', help = 'guest memory in MB', type = 'int', default = 384, dest = 'memory', ) optparser.add_option('--debugger', help = 'wait for gdb', action = 'store_true', default = False, ) optparser.add_option('--no-tap', help = 'run the guest without tap netif', action = 'store_true', dest = 'notap', default = not privileged, ) optparser.add_option('--nictype', help = 'use this specific nic type (vendor)', dest = 'nictype', default = 'rtl8139', ) optparser.add_option('--mac', help = 'use this specific mac addr', dest = 'mac', default = None, ) optparser.add_option('--vnc', help = 'use VNC rather than SDL', dest = 'vnc', default = None, ) optparser.add_option('--no-kvm', help = 'use standard qemu, without kvm', action = 'store_false', dest = 'kvm', default = True, ) optparser.add_option('--image', help = 'select disk image', dest = 'image', default = '/tmp/disk', ) optparser.add_option('--cdrom', help = 'select cdrom image', dest = 'cdrom', default = None, ) optparser.add_option('--hdb', help = 'secondary hard disk image', dest = 'hdb', default = None, ) optparser.add_option('--loadvm', help = 'select saved vm-image', dest = 'saved_image', default = None, ) optparser.add_option('--monitor', help = 'redirect monitor (currently only stdio or tcp)', dest = 'monitor', default = None, ) optparser.add_option('--stopped', help = 'start image in stopped mode', action = 'store_true', default = False, ) optparser.add_option('-s', '--smp', type = 'int', default = 1, dest = 'vcpus', help = 'define number of vcpus', ) optparser.add_option('--no-kvm-irqchip', action = 'store_false', default = True, dest = 'irqchip', help = 'avoid using in-kernel irqchip', ) optparser.add_option('-n', '--dry-run', help = "just print the qemu command line; don't run it", action = 'store_true', dest = 'dry_run', default = False, ) (options, args) = optparser.parse_args() if len(args) > 0: options.image = args[0] if len(args) > 1: options.cdrom = args[1] def remove_module(module): module = module.replace('-', '_') lines = commands.getoutput('/sbin/lsmod').split('\n') for x in lines: if x.startswith(module + ' '): if os.spawnl(os.P_WAIT, '/sbin/rmmod', 'rmmod', module) != 0: raise Exception('failed to remove %s module' % (module,)) def insert_module(module): if arch == 'x86_64': archdir = 'x86' elif arch == 'ia64': archdir = 'ia64' if os.spawnl(os.P_WAIT, '/sbin/insmod', 'insmod', 'kernel/' + archdir + '/%s.ko' % (module,)) != 0: raise Exception('failed to load kvm module') def probe_module(module): if os.spawnl(os.P_WAIT, '/sbin/modprobe', 'modprobe', module) != 0: raise Exception('failed to load kvm module') def vendor(): for x in file('/proc/cpuinfo').readlines(): m = re.match(r'vendor_id[ \t]*: *([a-zA-Z]+),*', x) if m: return m.group(1) return unknown vendor_module = { 'GenuineIntel': 'kvm-intel', 'AuthenticAMD': 'kvm-amd', }[vendor()] if options.kvm and options.reload: for module in [vendor_module, 'kvm']: remove_module(module) if external_module: insmod = insert_module else: insmod = probe_module for module in ['kvm', vendor_module]: insmod(module) commands.getstatusoutput('/sbin/udevsettle') if not os.access('/dev/kvm', os.F_OK): print '/dev/kvm not present' disk = options.image if options.install: (status, output) = commands.getstatusoutput( 'qemu/qemu-img create -f qcow2 "%s" 30G' % disk) if status: raise Exception, output bootdisk = 'c' if options.install: bootdisk = 'd' if arch == 'x86_64': cmd = 'qemu-system-' + arch else: cmd = 'qemu' local_cmd = 'qemu/' + arch + '-softmmu/' + cmd if os.access(local_cmd, os.F_OK): cmd = local_cmd else: cmd = '/usr/bin/kvm' qemu_args = (cmd, '-boot', bootdisk, '-hda', disk, '-m', str(options.memory), '-serial', 'file:/tmp/serial.log', '-smp', str(options.vcpus), #'-usbdevice', 'tablet', ) if options.cdrom: qemu_args += ('-cdrom', options.cdrom,) if options.hdb: qemu_args += ('-hdb', options.hdb,) if not options.kvm: qemu_args += ('-no-kvm',) if options.debugger: qemu_args += ('-s',) if not options.irqchip: qemu_args += ('-no-kvm-irqchip',) if not options.notap: mac = options.mac if not mac: for line in commands.getoutput('/sbin/ip link show eth0').splitlines(): m = re.match(r'.*link/ether (..:..:..:..:..:..).*', line) if m: mac = m.group(1) if not mac: raise Exception, 'Unable to determine eth0 mac address' mac_components = mac.split(':') mac_components[0] = 'a0' mac = ':'.join(mac_components) qemu_args += ('-net', 'nic,macaddr=%s,model=%s' % (mac,options.nictype,), '-net', 'tap,script=/etc/kvm/qemu-ifup',) if options.vnc: qemu_args += ('-vnc', str(options.vnc)) if options.saved_image: qemu_args += ('-loadvm' , options.saved_image, ) if options.monitor: if options.monitor == 'stdio': qemu_args += ('-monitor' , 'stdio', ) elif options.monitor == 'tcp': qemu_args += ('-monitor' , 'tcp:0:5555,server,nowait', ) else: raise Exception('illegal monitor option %s' % option.monitor) if options.stopped: qemu_args += ('-S',) if options.dry_run: def concat_func(x,y): return x + ' ' + y print reduce(concat_func, qemu_args) sys.exit(0) os.execvp(cmd, qemu_args)