tripleo-incubator/scripts/configure-vm

160 lines
5.8 KiB
Python
Executable File

#!/usr/bin/env python
import argparse
import math
import os.path
import random
import libvirt
templatedir = os.path.join(
os.path.dirname(
os.path.dirname(
os.path.abspath(__file__))), 'templates')
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('--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': '',
}
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>
"""
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()