summaryrefslogtreecommitdiffstats
path: root/lib/configure-vm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/configure-vm')
-rwxr-xr-xlib/configure-vm171
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()