
We don't need to pass the appropriate qemu binary into the vm template, as libvirt will inject the proper one for us. Similarly, we don't need to tell libvirt what specific model of PC hardware to emulate, because it will pick one that is appropriate to the devices we specify. Change-Id: Id3762cce9b2ba9f96c1e7e79fad9a4bf8770bf7a
135 lines
5.0 KiB
Python
Executable File
135 lines
5.0 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
import argparse
|
|
import os.path
|
|
import random
|
|
|
|
import libvirt
|
|
|
|
templatedir = os.path.join(
|
|
os.path.dirname(
|
|
os.path.dirname(
|
|
os.path.abspath(__file__))), 'templates')
|
|
|
|
def generate_bm_mac_address():
|
|
"""Generate an Ethernet MAC address suitable for baremetal testing."""
|
|
# NOTE(dprince): We generate our own bare metal MAC address 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.
|
|
mac = [0x00,
|
|
random.randint(0x00, 0xff),
|
|
random.randint(0x00, 0xff),
|
|
random.randint(0x00, 0xff),
|
|
random.randint(0x00, 0xff),
|
|
random.randint(0x00, 0xff)]
|
|
return ':'.join(map(lambda x: "%02x" % x, mac))
|
|
|
|
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', 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')
|
|
args = parser.parse_args()
|
|
with file(templatedir + '/vm.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,
|
|
'bmbridge': args.baremetal_interface,
|
|
'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,
|
|
'bminterface': args.baremetal_interface,
|
|
'bmmacaddress': generate_bm_mac_address(),
|
|
'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'/>
|
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
|
</interface>""" % nicparams
|
|
else:
|
|
params['network'] = """
|
|
<!-- regular natted network, for access to the vm -->
|
|
<interface type='network'>
|
|
<source network='default'/>
|
|
<model type='%(nicdriver)s'/>
|
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
|
</interface>""" % nicparams
|
|
|
|
params['bm_network'] = """
|
|
<!-- bridged 'bare metal' network -->
|
|
<interface type='network'>
|
|
<mac address='%(bmmacaddress)s'/>
|
|
<source network='%(bminterface)s'/>
|
|
<model type='%(nicdriver)s'/>
|
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
|
|
</interface>""" % nicparams
|
|
|
|
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("qemu:///system")
|
|
a = conn.defineXML(libvirt_template)
|
|
print ("Created machine %s with UUID %s" % (args.name, a.UUIDString()))
|
|
|
|
if __name__ == '__main__':
|
|
main()
|