diff options
Diffstat (limited to 'lib/configure-vm')
-rwxr-xr-x | lib/configure-vm | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/lib/configure-vm b/lib/configure-vm new file mode 100755 index 00000000..340a7ab6 --- /dev/null +++ b/lib/configure-vm @@ -0,0 +1,171 @@ +#!/usr/bin/env python + +import argparse +import math +import os +import random + +import libvirt + +templatedir = os.getenv('LIB', '/var/opt/opnfv/lib') + '/installer/' + +MAX_NUM_MACS = math.trunc(0xff/2) + + +def generate_baremetal_macs(count=1): + """Generate an Ethernet MAC address suitable for baremetal testing.""" + # NOTE(dprince): We generate our own bare metal MAC address's here + # instead of relying on libvirt so that we can ensure the + # locally administered bit is set low. (The libvirt default is + # to set the 2nd MSB high.) This effectively allows our + # fake baremetal VMs to more accurately behave like real hardware + # and fixes issues with bridge/DHCP configurations which rely + # on the fact that bridges assume the MAC address of the lowest + # attached NIC. + # MACs generated for a given machine will also be in sequential + # order, which matches how most BM machines are laid out as well. + # Additionally we increment each MAC by two places. + macs = [] + + if count > MAX_NUM_MACS: + raise ValueError("The MAX num of MACS supported is %i." % MAX_NUM_MACS) + + base_nums = [0x00, + random.randint(0x00, 0xff), + random.randint(0x00, 0xff), + random.randint(0x00, 0xff), + random.randint(0x00, 0xff)] + base_mac = ':'.join(map(lambda x: "%02x" % x, base_nums)) + + start = random.randint(0x00, 0xff) + if (start + (count * 2)) > 0xff: + # leave room to generate macs in sequence + start = 0xff - count * 2 + for num in range(0, count*2, 2): + mac = start + num + macs.append(base_mac + ":" + ("%02x" % mac)) + return macs + +def main(): + parser = argparse.ArgumentParser( + description="Configure a kvm virtual machine for the seed image.") + parser.add_argument('--name', default='seed', + help='the name to give the machine in libvirt.') + parser.add_argument('--image', + help='Use a custom image file (must be qcow2).') + parser.add_argument('--diskbus', default='sata', + help='Choose an alternate bus type for the disk') + parser.add_argument('--baremetal-interface', nargs='+', default=['brbm'], + help='The interface which bare metal nodes will be connected to.') + parser.add_argument('--engine', default='kvm', + help='The virtualization engine to use') + parser.add_argument('--arch', default='i686', + help='The architecture to use') + parser.add_argument('--memory', default='2097152', + help="Maximum memory for the VM in KB.") + parser.add_argument('--cpus', default='1', + help="CPU count for the VM.") + parser.add_argument('--bootdev', default='hd', + help="What boot device to use (hd/network).") + parser.add_argument('--seed', default=False, action='store_true', + help='Create a seed vm with two interfaces.') + parser.add_argument('--ovsbridge', default="", + help='Place the seed public interface on this ovs bridge.') + parser.add_argument('--libvirt-nic-driver', default='virtio', + help='The libvirt network driver to use') + parser.add_argument('--enable-serial-console', action="store_true", + help='Enable a serial console') + parser.add_argument('--direct-boot', + help='Enable directboot to <value>.{vmlinux & initrd}') + parser.add_argument('--kernel-arg', action="append", dest='kernel_args', + help='Kernel arguments, use multiple time for multiple args.') + parser.add_argument('--uri', default='qemu:///system', + help='The server uri with which to connect.') + args = parser.parse_args() + with file(templatedir + '/domain.xml', 'rb') as f: + source_template = f.read() + imagefile = '/var/lib/libvirt/images/seed.qcow2' + if args.image: + imagefile = args.image + imagefile = os.path.realpath(imagefile) + params = { + 'name': args.name, + 'imagefile': imagefile, + 'engine': args.engine, + 'arch': args.arch, + 'memory': args.memory, + 'cpus': args.cpus, + 'bootdev': args.bootdev, + 'network': '', + 'enable_serial_console': '', + 'direct_boot': '', + 'kernel_args': '', + } + if args.image is not None: + params['imagefile'] = args.image + + # Configure the bus type for the target disk device + params['diskbus'] = args.diskbus + nicparams = { + 'nicdriver': args.libvirt_nic_driver, + 'ovsbridge': args.ovsbridge, + } + if args.seed: + if args.ovsbridge: + params['network'] = """ + <interface type='bridge'> + <source bridge='%(ovsbridge)s'/> + <virtualport type='openvswitch'/> + <model type='%(nicdriver)s'/> + </interface>""" % nicparams + else: + params['network'] = """ + <!-- regular natted network, for access to the vm --> + <interface type='network'> + <source network='default'/> + <model type='%(nicdriver)s'/> + </interface>""" % nicparams + + macs = generate_baremetal_macs(len(args.baremetal_interface)) + + params['bm_network'] = "" + for bm_interface, mac in zip(args.baremetal_interface, macs): + bm_interface_params = { + 'bminterface': bm_interface, + 'bmmacaddress': mac, + 'nicdriver': args.libvirt_nic_driver, + } + params['bm_network'] += """ + <!-- bridged 'bare metal' network on %(bminterface)s --> + <interface type='network'> + <mac address='%(bmmacaddress)s'/> + <source network='%(bminterface)s'/> + <model type='%(nicdriver)s'/> + </interface>""" % bm_interface_params + + if args.enable_serial_console: + params['enable_serial_console'] = """ + <serial type='pty'> + <target port='0'/> + </serial> + <console type='pty'> + <target type='serial' port='0'/> + </console> + """ + if args.direct_boot: + params['direct_boot'] = """ + <kernel>/var/lib/libvirt/images/%(direct_boot)s.vmlinuz</kernel> + <initrd>/var/lib/libvirt/images/%(direct_boot)s.initrd</initrd> + """ % { 'direct_boot': args.direct_boot } + if args.kernel_args: + params['kernel_args'] = """ + <cmdline>%s</cmdline> + """ % ' '.join(args.kernel_args) + + libvirt_template = source_template % params + conn=libvirt.open(args.uri) + a = conn.defineXML(libvirt_template) + print ("Created machine %s with UUID %s" % (args.name, a.UUIDString())) + +if __name__ == '__main__': + main() |