10 templatedir = os.getenv('LIB', '/var/opt/opnfv/lib') + '/installer/'
12 MAX_NUM_MACS = math.trunc(0xff/2)
15 def generate_baremetal_macs(count=1):
16 """Generate an Ethernet MAC address suitable for baremetal testing."""
17 # NOTE(dprince): We generate our own bare metal MAC address's here
18 # instead of relying on libvirt so that we can ensure the
19 # locally administered bit is set low. (The libvirt default is
20 # to set the 2nd MSB high.) This effectively allows our
21 # fake baremetal VMs to more accurately behave like real hardware
22 # and fixes issues with bridge/DHCP configurations which rely
23 # on the fact that bridges assume the MAC address of the lowest
25 # MACs generated for a given machine will also be in sequential
26 # order, which matches how most BM machines are laid out as well.
27 # Additionally we increment each MAC by two places.
30 if count > MAX_NUM_MACS:
31 raise ValueError("The MAX num of MACS supported is %i." % MAX_NUM_MACS)
34 random.randint(0x00, 0xff),
35 random.randint(0x00, 0xff),
36 random.randint(0x00, 0xff),
37 random.randint(0x00, 0xff)]
38 base_mac = ':'.join(map(lambda x: "%02x" % x, base_nums))
40 start = random.randint(0x00, 0xff)
41 if (start + (count * 2)) > 0xff:
42 # leave room to generate macs in sequence
43 start = 0xff - count * 2
44 for num in range(0, count*2, 2):
46 macs.append(base_mac + ":" + ("%02x" % mac))
50 parser = argparse.ArgumentParser(
51 description="Configure a kvm virtual machine for the seed image.")
52 parser.add_argument('--name', default='seed',
53 help='the name to give the machine in libvirt.')
54 parser.add_argument('--image',
55 help='Use a custom image file (must be qcow2).')
56 parser.add_argument('--diskbus', default='sata',
57 help='Choose an alternate bus type for the disk')
58 parser.add_argument('--baremetal-interface', nargs='+', default=['brbm'],
59 help='The interface which bare metal nodes will be connected to.')
60 parser.add_argument('--engine', default='kvm',
61 help='The virtualization engine to use')
62 parser.add_argument('--arch', default='i686',
63 help='The architecture to use')
64 parser.add_argument('--memory', default='2097152',
65 help="Maximum memory for the VM in KB.")
66 parser.add_argument('--cpus', default='1',
67 help="CPU count for the VM.")
68 parser.add_argument('--bootdev', default='hd',
69 help="What boot device to use (hd/network).")
70 parser.add_argument('--seed', default=False, action='store_true',
71 help='Create a seed vm with two interfaces.')
72 parser.add_argument('--ovsbridge', default="",
73 help='Place the seed public interface on this ovs bridge.')
74 parser.add_argument('--libvirt-nic-driver', default='virtio',
75 help='The libvirt network driver to use')
76 parser.add_argument('--enable-serial-console', action="store_true",
77 help='Enable a serial console')
78 parser.add_argument('--direct-boot',
79 help='Enable directboot to <value>.{vmlinux & initrd}')
80 parser.add_argument('--kernel-arg', action="append", dest='kernel_args',
81 help='Kernel arguments, use multiple time for multiple args.')
82 parser.add_argument('--uri', default='qemu:///system',
83 help='The server uri with which to connect.')
84 args = parser.parse_args()
85 with file(templatedir + '/domain.xml', 'rb') as f:
86 source_template = f.read()
87 imagefile = '/var/lib/libvirt/images/seed.qcow2'
89 imagefile = args.image
90 imagefile = os.path.realpath(imagefile)
93 'imagefile': imagefile,
94 'engine': args.engine,
96 'memory': args.memory,
98 'bootdev': args.bootdev,
100 'enable_serial_console': '',
103 'user_interface': '',
105 if args.image is not None:
106 params['imagefile'] = args.image
108 # Configure the bus type for the target disk device
109 params['diskbus'] = args.diskbus
111 'nicdriver': args.libvirt_nic_driver,
112 'ovsbridge': args.ovsbridge,
116 params['network'] = """
117 <interface type='bridge'>
118 <source bridge='%(ovsbridge)s'/>
119 <virtualport type='openvswitch'/>
120 <model type='%(nicdriver)s'/>
121 </interface>""" % nicparams
123 params['network'] = """
124 <!-- regular natted network, for access to the vm -->
125 <interface type='network'>
126 <source network='default'/>
127 <model type='%(nicdriver)s'/>
128 </interface>""" % nicparams
130 macs = generate_baremetal_macs(len(args.baremetal_interface))
132 params['bm_network'] = ""
133 for bm_interface, mac in zip(args.baremetal_interface, macs):
134 bm_interface_params = {
135 'bminterface': bm_interface,
137 'nicdriver': args.libvirt_nic_driver,
139 params['bm_network'] += """
140 <!-- bridged 'bare metal' network on %(bminterface)s -->
141 <interface type='network'>
142 <mac address='%(bmmacaddress)s'/>
143 <source network='%(bminterface)s'/>
144 <model type='%(nicdriver)s'/>
145 </interface>""" % bm_interface_params
147 if args.enable_serial_console:
148 params['enable_serial_console'] = """
153 <target type='serial' port='0'/>
157 params['direct_boot'] = """
158 <kernel>/var/lib/libvirt/images/%(direct_boot)s.vmlinuz</kernel>
159 <initrd>/var/lib/libvirt/images/%(direct_boot)s.initrd</initrd>
160 """ % { 'direct_boot': args.direct_boot }
162 params['kernel_args'] = """
163 <cmdline>%s</cmdline>
164 """ % ' '.join(args.kernel_args)
166 if args.arch == 'aarch64':
168 params['direct_boot'] += """
169 <loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader>
170 <nvram>/var/lib/libvirt/qemu/nvram/centos7.0_VARS.fd</nvram>
172 params['user_interface'] = """
173 <controller type='virtio-serial' index='0'>
174 <address type='virtio-mmio'/>
180 <target type='serial' port='0'/>
182 <channel type='unix'>
183 <target type='virtio' name='org.qemu.guest_agent.0'/>
184 <address type='virtio-serial' controller='0' bus='0' port='1'/>
188 params['user_interface'] = """
189 <input type='mouse' bus='ps2'/>
190 <graphics type='vnc' port='-1' autoport='yes'/>
192 <model type='cirrus' vram='9216' heads='1'/>
197 libvirt_template = source_template % params
198 conn=libvirt.open(args.uri)
199 a = conn.defineXML(libvirt_template)
200 print ("Created machine %s with UUID %s" % (args.name, a.UUIDString()))
202 if __name__ == '__main__':