From 8cf23b75783fc09710093935c5282d931d7bbdec Mon Sep 17 00:00:00 2001
From: stack <stack@dev-director>
Date: Fri, 4 May 2018 19:03:54 +0100
Subject: [PATCH] Support DHCP for managed network interfaces

Adds support for setting the boot protocol of a network interface. Valid values
are 'static' and 'dhcp'.  The default is 'static'. When set to 'dhcp', an
external DHCP server must be provided.

Change-Id: Ie4cafdcd24c6706009ca9e8accac2017d7d6bba7
Story: 2001967
Task: 15717
---
 ansible/filter_plugins/networks.py                | 15 ++++++++++-----
 ansible/ip-allocation.yml                         |  4 +++-
 doc/source/configuration/network.rst              |  4 ++++
 .../notes/bootproto-52316b6dbc30e98c.yaml         |  5 +++++
 4 files changed, 22 insertions(+), 6 deletions(-)
 create mode 100644 releasenotes/notes/bootproto-52316b6dbc30e98c.yaml

diff --git a/ansible/filter_plugins/networks.py b/ansible/filter_plugins/networks.py
index 3c5d03f1..427fd2d5 100644
--- a/ansible/filter_plugins/networks.py
+++ b/ansible/filter_plugins/networks.py
@@ -127,6 +127,7 @@ net_mtu = _make_attr_filter('mtu')
 net_routes = _make_attr_filter('routes')
 net_rules = _make_attr_filter('rules')
 net_physical_network = _make_attr_filter('physical_network')
+net_bootproto = _make_attr_filter('bootproto')
 
 
 @jinja2.contextfilter
@@ -200,6 +201,7 @@ def net_interface_obj(context, name, inventory_hostname=None):
     if routes:
         routes = [_route_obj(route) for route in routes]
     rules = net_rules(context, name, inventory_hostname)
+    bootproto = net_bootproto(context, name, inventory_hostname)
     interface = {
         'device': device,
         'address': ip,
@@ -209,7 +211,7 @@ def net_interface_obj(context, name, inventory_hostname=None):
         'mtu': mtu,
         'route': routes,
         'rules': rules,
-        'bootproto': 'static',
+        'bootproto': bootproto or 'static',
         'onboot': 'yes',
     }
     interface = {k: v for k, v in interface.items() if v is not None}
@@ -241,6 +243,7 @@ def net_bridge_obj(context, name, inventory_hostname=None):
     if routes:
         routes = [_route_obj(route) for route in routes]
     rules = net_rules(context, name, inventory_hostname)
+    bootproto = net_bootproto(context, name, inventory_hostname)
     interface = {
         'device': device,
         'address': ip,
@@ -251,7 +254,7 @@ def net_bridge_obj(context, name, inventory_hostname=None):
         'ports': ports,
         'route': routes,
         'rules': rules,
-        'bootproto': 'static',
+        'bootproto': bootproto or 'static',
         'onboot': 'yes',
     }
     interface = {k: v for k, v in interface.items() if v is not None}
@@ -289,6 +292,7 @@ def net_bond_obj(context, name, inventory_hostname=None):
     if routes:
         routes = [_route_obj(route) for route in routes]
     rules = net_rules(context, name, inventory_hostname)
+    bootproto = net_bootproto(context, name, inventory_hostname)
     interface = {
         'device': device,
         'address': ip,
@@ -305,7 +309,7 @@ def net_bond_obj(context, name, inventory_hostname=None):
         'bond_lacp_rate': lacp_rate,
         'route': routes,
         'rules': rules,
-        'bootproto': 'static',
+        'bootproto': bootproto or 'static',
         'onboot': 'yes',
     }
     interface = {k: v for k, v in interface.items() if v is not None}
@@ -389,14 +393,14 @@ def net_configdrive_network_device(context, name, inventory_hostname=None):
     cidr = net_cidr(context, name, inventory_hostname)
     netmask = net_mask(context, name, inventory_hostname)
     gateway = net_gateway(context, name, inventory_hostname)
-    bootproto = 'static' if ip is not None else 'dhcp'
+    bootproto = net_bootproto(context, name, inventory_hostname)
     mtu = net_mtu(context, name, inventory_hostname)
     interface = {
         'device': device,
         'address': ip,
         'netmask': netmask,
         'gateway': gateway,
-        'bootproto': bootproto,
+        'bootproto': bootproto or 'static',
         'mtu': mtu,
     }
     interface = {k: v for k, v in interface.items() if v is not None}
@@ -459,6 +463,7 @@ class FilterModule(object):
             'net_routes': net_routes,
             'net_rules': net_rules,
             'net_physical_network': net_physical_network,
+            'net_bootproto': net_bootproto,
             'net_interface_obj': net_interface_obj,
             'net_bridge_obj': net_bridge_obj,
             'net_bond_obj': net_bond_obj,
diff --git a/ansible/ip-allocation.yml b/ansible/ip-allocation.yml
index 6d66e700..cb8520f9 100644
--- a/ansible/ip-allocation.yml
+++ b/ansible/ip-allocation.yml
@@ -24,7 +24,9 @@
             }]
           }}
       with_items: "{{ network_interfaces }}"
-      when: item|net_cidr != None
+      when:
+        - item | net_cidr != None
+        - item | net_bootproto != 'dhcp'
   roles:
     - role: ip-allocation
       ip_allocation_filename: "{{ kayobe_config_path }}/network-allocation.yml"
diff --git a/doc/source/configuration/network.rst b/doc/source/configuration/network.rst
index 27f6b9d8..c976c503 100644
--- a/doc/source/configuration/network.rst
+++ b/doc/source/configuration/network.rst
@@ -236,6 +236,10 @@ The following attributes are supported:
 
 ``interface``
     The name of the network interface attached to the network.
+``bootproto``
+    Boot protocol for the interface. Valid values are ``static`` and ``dhcp``.
+    The default is ``static``. When set to ``dhcp``, an external DHCP server
+    must be provided.
 ``bridge_ports``
     For bridge interfaces, a list of names of network interfaces to add to the
     bridge.
diff --git a/releasenotes/notes/bootproto-52316b6dbc30e98c.yaml b/releasenotes/notes/bootproto-52316b6dbc30e98c.yaml
new file mode 100644
index 00000000..73c896d7
--- /dev/null
+++ b/releasenotes/notes/bootproto-52316b6dbc30e98c.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - Adds support for setting the boot protocol of a network interface. Valid
+    values are ``static`` and ``dhcp``.  The default is ``static``. When set to
+    an external DHCP server must be provided.
-- 
GitLab