vino/vino-builder/assets/playbooks/roles/ipam/library/ipam.py

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()