Bumps OVS version to 2.8 for OVN
[apex.git] / lib / configure-vm
1 #!/usr/bin/env python
2
3 import argparse
4 import math
5 import os
6 import random
7
8 import libvirt
9
10 templatedir = os.getenv('LIB', '/var/opt/opnfv/lib') + '/installer/'
11
12 MAX_NUM_MACS = math.trunc(0xff/2)
13
14
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
24     # attached NIC.
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.
28     macs = []
29
30     if count > MAX_NUM_MACS:
31         raise ValueError("The MAX num of MACS supported is %i." % MAX_NUM_MACS)
32
33     base_nums = [0x00,
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))
39
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):
45         mac = start + num
46         macs.append(base_mac + ":" + ("%02x" % mac))
47     return macs
48
49 def main():
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'
88     if args.image:
89         imagefile = args.image
90     imagefile = os.path.realpath(imagefile)
91     params = {
92         'name': args.name,
93         'imagefile': imagefile,
94         'engine': args.engine,
95         'arch': args.arch,
96         'memory': args.memory,
97         'cpus': args.cpus,
98         'bootdev': args.bootdev,
99         'network': '',
100         'enable_serial_console': '',
101         'direct_boot': '',
102         'kernel_args': '',
103         'user_interface': '',
104         }
105     if args.image is not None:
106         params['imagefile'] = args.image
107
108     # Configure the bus type for the target disk device
109     params['diskbus'] = args.diskbus
110     nicparams = {
111         'nicdriver': args.libvirt_nic_driver,
112         'ovsbridge': args.ovsbridge,
113         }
114     if args.seed:
115         if 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
122         else:
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
129
130     macs = generate_baremetal_macs(len(args.baremetal_interface))
131
132     params['bm_network'] = ""
133     for bm_interface, mac in zip(args.baremetal_interface, macs):
134         bm_interface_params = {
135             'bminterface': bm_interface,
136             'bmmacaddress': mac,
137             'nicdriver': args.libvirt_nic_driver,
138             }
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
146
147     if args.enable_serial_console:
148         params['enable_serial_console'] = """
149         <serial type='pty'>
150           <target port='0'/>
151         </serial>
152         <console type='pty'>
153           <target type='serial' port='0'/>
154         </console>
155         """
156     if args.direct_boot:
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 }
161     if args.kernel_args:
162         params['kernel_args'] = """
163         <cmdline>%s</cmdline>
164         """ % ' '.join(args.kernel_args)
165
166     if args.arch == 'aarch64':
167
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>
171         """
172         params['user_interface'] = """
173         <controller type='virtio-serial' index='0'>
174           <address type='virtio-mmio'/>
175         </controller>
176         <serial type='pty'>
177           <target port='0'/>
178         </serial>
179         <console type='pty'>
180           <target type='serial' port='0'/>
181         </console>
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'/>
185         </channel>
186         """
187     else:
188         params['user_interface'] = """
189         <input type='mouse' bus='ps2'/>
190         <graphics type='vnc' port='-1' autoport='yes'/>
191         <video>
192           <model type='cirrus' vram='9216' heads='1'/>
193         </video>
194         """
195
196
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()))
201
202 if __name__ == '__main__':
203     main()