2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # generate_baremetal_macs method ripped from
16 # openstack/tripleo-incubator/scripts/configure-vm
26 short_description: Generate a list of Ethernet MAC addresses
28 - Generate a list of Ethernet MAC addresses suitable for baremetal testing.
31 MAX_NUM_MACS = math.trunc(0xff / 2)
34 def generate_baremetal_macs(nodes, networks):
35 """Generate an Ethernet MAC address suitable for baremetal testing."""
36 # NOTE(dprince): We generate our own bare metal MAC address's here
37 # instead of relying on libvirt so that we can ensure the
38 # locally administered bit is set low. (The libvirt default is
39 # to set the 2nd MSB high.) This effectively allows our
40 # fake baremetal VMs to more accurately behave like real hardware
41 # and fixes issues with bridge/DHCP configurations which rely
42 # on the fact that bridges assume the MAC address of the lowest
44 # MACs generated for a given machine will also be in sequential
45 # order, which matches how most BM machines are laid out as well.
46 # Additionally we increment each MAC by two places.
48 count = len(nodes) * len(networks)
50 if count > MAX_NUM_MACS:
51 raise ValueError("The MAX num of MACS supported is %i "
52 "(you specified %i)." % (MAX_NUM_MACS, count))
54 # See the random number generator with the input so that MAC
55 # generation is idempotent.
56 random.seed(marshal.dumps(nodes + networks))
59 random.randint(0x00, 0xff),
60 random.randint(0x00, 0xff),
61 random.randint(0x00, 0xff),
62 random.randint(0x00, 0xff)]
63 base_mac = ':'.join(map(lambda x: "%02x" % x, base_nums))
65 start = random.randint(0x00, 0xff)
66 if (start + (count * 2)) > 0xff:
67 # leave room to generate macs in sequence
68 start = 0xff - count * 2
69 for num in range(0, count * 2, 2):
71 macs.append(base_mac + ":" + ("%02x" % mac))
75 result[node['name']] = {}
76 for network in networks:
77 result[node['name']][network['name']] = macs.pop(0)
83 module = AnsibleModule(
85 nodes=dict(required=True, type='list'),
86 networks=dict(required=True, type='list')
89 result = generate_baremetal_macs(module.params["nodes"],
90 module.params["networks"])
91 module.exit_json(**result)
93 # see http://docs.ansible.com/developing_modules.html#common-module-boilerplate
94 from ansible.module_utils.basic import AnsibleModule # noqa
97 if __name__ == '__main__':