From ead380c4d0d626a0e41c2b8e18762629dfbc1fa4 Mon Sep 17 00:00:00 2001
From: Mark Goddard <mark@stackhpc.com>
Date: Thu, 16 Feb 2017 10:44:29 +0000
Subject: [PATCH] Add support for allocation pools to IP allocation role

Only allocate IPs from within the allocation pool range.
---
 ansible/ip-allocation.yml                     | 20 ++++++++++++++++---
 ansible/roles/ip-allocation/defaults/main.yml | 13 ++++++++++++
 .../ip-allocation/library/ip_allocation.py    | 13 ++++++++++--
 ansible/roles/ip-allocation/tasks/main.yml    |  2 ++
 deploy-overcloud.sh                           |  1 +
 deploy-seed.sh                                |  1 +
 6 files changed, 45 insertions(+), 5 deletions(-)
 create mode 100644 ansible/roles/ip-allocation/defaults/main.yml

diff --git a/ansible/ip-allocation.yml b/ansible/ip-allocation.yml
index 57aa07f7d..98b9fd331 100644
--- a/ansible/ip-allocation.yml
+++ b/ansible/ip-allocation.yml
@@ -1,10 +1,24 @@
 ---
 - name: Ensure IP addresses are allocated
-  hosts: controllers
+  hosts: seed:controllers
   gather_facts: no
   pre_tasks:
-    - set_fact:
-        ip_allocations: "{{ ip_allocations|default([]) + [{'net_name': item, 'cidr': item|net_cidr}] }}"
+    - name: Initialise the IP allocations fact
+      set_fact:
+        ip_allocations: []
+
+    - name: Update the IP allocations fact with IP allocation requests
+      set_fact:
+        ip_allocations: >
+          {{
+            ip_allocations +
+            [{
+              'net_name': item,
+              'cidr': item|net_cidr,
+              'allocation_pool_start': item|net_allocation_pool_start,
+              'allocation_pool_end': item|net_allocation_pool_end
+            }]
+          }}
       with_items: "{{ network_interfaces }}"
   roles:
     - role: ip-allocation
diff --git a/ansible/roles/ip-allocation/defaults/main.yml b/ansible/roles/ip-allocation/defaults/main.yml
new file mode 100644
index 000000000..634ad78ba
--- /dev/null
+++ b/ansible/roles/ip-allocation/defaults/main.yml
@@ -0,0 +1,13 @@
+---
+# Path to file in which to store IP allocations.
+ip_allocation_filename:
+
+# Name of host to allocate IPs for.
+ip_allocation_hostname:
+
+# List of IP allocations. Each item should be a dict with the following items:
+# net_name: Name of the network
+# cidr: CIDR representation of the IP subnet
+# allocation_pool_start: First IP address in the allocation pool (optional)
+# allocation_pool_end: Last IP address in the allocation pool (optional)
+ip_allocations:
diff --git a/ansible/roles/ip-allocation/library/ip_allocation.py b/ansible/roles/ip-allocation/library/ip_allocation.py
index 5ddb9032f..80da68214 100644
--- a/ansible/roles/ip-allocation/library/ip_allocation.py
+++ b/ansible/roles/ip-allocation/library/ip_allocation.py
@@ -57,6 +57,8 @@ def update_allocation(module, allocations):
     net_name = module.params['net_name']
     hostname = module.params['hostname']
     cidr = module.params['cidr']
+    allocation_pool_start = module.params['allocation_pool_start']
+    allocation_pool_end = module.params['allocation_pool_end']
     network = netaddr.IPNetwork(cidr)
     result = {
         'changed': False,
@@ -70,8 +72,13 @@ def update_allocation(module, allocations):
             (network, ", ".join("%s: %s" % (hn, ip) for hn, ip in invalid_allocations.items())))
     if hostname not in net_allocations:
         result['changed'] = True
-        ips = netaddr.IPSet(net_allocations.values())
-        free_ips = netaddr.IPSet([network]) - ips
+        allocated_ips = netaddr.IPSet(net_allocations.values())
+        if allocation_pool_start and allocation_pool_end:
+            allocation_pool = netaddr.IPRange(allocation_pool_start, allocation_pool_end)
+            allocation_pool = netaddr.IPSet(allocation_pool)
+        else:
+            allocation_pool = netaddr.IPSet([network])
+        free_ips = allocation_pool - allocated_ips
         for free_cidr in free_ips.iter_cidrs():
             ip = free_cidr[0]
             break
@@ -98,6 +105,8 @@ def main():
             net_name=dict(required=True, type='str'),
             hostname=dict(required=True, type='str'),
             cidr=dict(required=True, type='str'),
+            allocation_pool_start=dict(required=False, type='str'),
+            allocation_pool_end=dict(required=False, type='str'),
             allocation_file=dict(required=True, type='str'),
         ),
         supports_check_mode=True,
diff --git a/ansible/roles/ip-allocation/tasks/main.yml b/ansible/roles/ip-allocation/tasks/main.yml
index cccf3c2bc..e1ffb041e 100644
--- a/ansible/roles/ip-allocation/tasks/main.yml
+++ b/ansible/roles/ip-allocation/tasks/main.yml
@@ -6,4 +6,6 @@
     hostname: "{{ ip_allocation_hostname }}"
     net_name: "{{ item.net_name }}"
     cidr: "{{ item.cidr }}"
+    allocation_pool_start: "{{ item.allocation_pool_start | default(omit) }}"
+    allocation_pool_end: "{{ item.allocation_pool_end | default(omit) }}"
   with_items: "{{ ip_allocations }}"
diff --git a/deploy-overcloud.sh b/deploy-overcloud.sh
index 92f62d333..1d15d7410 100755
--- a/deploy-overcloud.sh
+++ b/deploy-overcloud.sh
@@ -33,6 +33,7 @@ function run_kolla_ansible {
 }
 
 function configure_os {
+    run_playbook ansible/ip-allocation.yml -l controllers
     run_playbook ansible/ssh-known-host.yml -l controllers
     run_playbook ansible/disable-selinux.yml -l controllers
     run_playbook ansible/network.yml -l controllers
diff --git a/deploy-seed.sh b/deploy-seed.sh
index 321e503b7..f024c36b8 100755
--- a/deploy-seed.sh
+++ b/deploy-seed.sh
@@ -34,6 +34,7 @@ function run_kolla_ansible {
 }
 
 function configure_os {
+    run_playbook ansible/ip-allocation.yml -l seed
     run_playbook ansible/ssh-known-host.yml -l seed
     run_playbook ansible/disable-selinux.yml -l seed
     run_playbook ansible/network.yml -l seed