97 lines
3.4 KiB
Python
97 lines
3.4 KiB
Python
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
# implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
# generate_baremetal_macs method ripped from
|
|
# openstack/tripleo-incubator/scripts/configure-vm
|
|
|
|
import math
|
|
import random
|
|
import sys
|
|
import fnmatch
|
|
import os
|
|
import socket
|
|
import struct
|
|
from itertools import chain
|
|
import json
|
|
import netaddr
|
|
DOCUMENTATION = '''
|
|
---
|
|
module: ipam
|
|
version_added: "1.0"
|
|
short_description: Help with IPAM allocation
|
|
description:
|
|
- Generate IPs for instances, ensuring they're unique on every node
|
|
'''
|
|
# we don't support specifying subnet_bridge or instances yet
|
|
def allocate_ips(nodes, physical_primary_ip, physical_node_count=1, subnet_bridge='192.168.0.0/24', subnet_instances='192.168.4.0/22'):
|
|
"""Return IP assignments"""
|
|
# calculate some stuff
|
|
vm_instance_count = len(nodes)
|
|
last_octet = physical_primary_ip.split('.')[-1]
|
|
node_index = int(last_octet) % int(physical_node_count)
|
|
bridge_ip = netaddr.IPNetwork(subnet_bridge)[node_index+1]
|
|
# generate an ip for every vm in the entire environment
|
|
ip_buckets=[None] * physical_node_count
|
|
vm_ip_list = list(netaddr.IPNetwork(subnet_instances))
|
|
vm_ip_list.reverse()
|
|
|
|
# throw away 0, .1, .2, .3 - assumes we won't exceed .255
|
|
vm_ip_list.pop()
|
|
vm_ip_list.pop()
|
|
vm_ip_list.pop()
|
|
vm_ip_list.pop()
|
|
|
|
# now take IPs from this list - enough for all the VMs
|
|
# we need to create and place them into groups
|
|
# one for each physical node
|
|
for physnode in range(0, physical_node_count):
|
|
ip_buckets[physnode] = {}
|
|
ip_list = []
|
|
for vmidx in range(0, vm_instance_count):
|
|
ip_list.append(vm_ip_list.pop().__str__())
|
|
ip_buckets[physnode] = ip_list
|
|
|
|
bridge_subnet_netmask = cidr_to_netmask(subnet_bridge)
|
|
return {
|
|
'node_index': node_index,
|
|
'bridge_ip': bridge_ip.__str__(),
|
|
'instance_ips': ip_buckets[node_index],
|
|
'bridge_subnet_netmask': bridge_subnet_netmask,
|
|
}
|
|
|
|
def cidr_to_netmask(cidr):
|
|
_, net_bits = cidr.split('/')
|
|
host_bits = 32 - int(net_bits)
|
|
netmask = socket.inet_ntoa(struct.pack('!I', (1 << 32) - (1 << host_bits)))
|
|
return netmask
|
|
|
|
def main():
|
|
module = AnsibleModule(
|
|
argument_spec=dict(
|
|
nodes=dict(required=True, type='list'),
|
|
physical_node_count=dict(required=True, type='int'),
|
|
primary_ipaddress=dict(required=True, type='str'),
|
|
subnet_bridge=dict(required=True, type='str'),
|
|
subnet_instances=dict(required=True, type='str'),
|
|
)
|
|
)
|
|
result = allocate_ips(module.params["nodes"],
|
|
module.params["primary_ipaddress"],
|
|
module.params["physical_node_count"],
|
|
module.params["subnet_bridge"],
|
|
module.params["subnet_instances"])
|
|
module.exit_json(**result)
|
|
# see http://docs.ansible.com/developing_modules.html#common-module-boilerplate
|
|
from ansible.module_utils.basic import AnsibleModule # noqa
|
|
if __name__ == '__main__':
|
|
main()
|