From 872d25e96c50d8a5e4283609a7c2b4c4c76b490e Mon Sep 17 00:00:00 2001
From: Anders Blomdell <anders.blomdell@control.lth.se>
Date: Tue, 4 Dec 2018 18:48:32 +0100
Subject: [PATCH] Handle multiple interfaces with same info (intended for
 docking stations)

---
 src/hostinfo/dhcpd.py      | 50 ++++++++++++++--------------
 src/hostinfo/dhcpd_ipv6.py | 45 +++++++++++++------------
 src/hostinfo/ifconfig.py   | 68 ++++++++++++++++++++------------------
 src/hostinfo/pxelinux.py   |  9 +++--
 src/hostinfo/util.py       |  4 +++
 src/hostinfo/yp.py         | 12 +++++--
 6 files changed, 103 insertions(+), 85 deletions(-)

diff --git a/src/hostinfo/dhcpd.py b/src/hostinfo/dhcpd.py
index cb7be61..13f48e6 100755
--- a/src/hostinfo/dhcpd.py
+++ b/src/hostinfo/dhcpd.py
@@ -189,11 +189,14 @@ def emit_interface(tree, options, interface):
     subnet = dict(map(lambda d: (get_subnet(tree, d._parent), 
                                  map(None, d._parent._dhcpserver_)),
                       interface._ip_._dhcpserver_))
-    result += 'shared-network "MAC(%s)" {' % interface.ethernet[0]
-    for sn,dhcp in map(lambda n: (n, subnet[n]), sorted(subnet)): 
-        result += emit_network(tree, options, sn, dhcp).indent()
+    for ethernet in util.ethernets(interface.ethernet[0]):
+        result += 'shared-network "MAC(%s)" {' % ethernet
+        for sn,dhcp in map(lambda n: (n, subnet[n]),
+                           sorted(subnet, key=lambda s: s.network[0])): 
+            result += emit_network(tree, options, sn, dhcp).indent()
+            pass
+        result += "}"
         pass
-    result += "}"
     return result
 
 def emit_network(tree, options, subnet, dhcp):
@@ -261,27 +264,26 @@ def emit_hosts(tree, options, networks, pxeboot=False):
     never = {}
     for ip in tree._host_._interface_._ip_:
         # Find all hosts that associated with this network
-        ethernet = ip.ethernet[0:]
-        if not ethernet:
-            continue
-        if pxeboot == 'only' and not bool(ip._pxeboot_):
-            continue
-        if ethernet.lower() != ethernet:
-            raise util.HostinfoException('%s not lower-case' % ethernet)
-        if ip.never[0]:
-            if match(util.address(ip.never[0])):
-                if not ethernet in never:
-                    never[ethernet] = []
+        for ethernet in util.ethernets(ip.ethernet[0:]):
+            if pxeboot == 'only' and not bool(ip._pxeboot_):
+                continue
+            if ethernet.lower() != ethernet:
+                raise util.HostinfoException('%s not lower-case' % ethernet)
+            if ip.never[0]:
+                if match(util.address(ip.never[0])):
+                    if not ethernet in never:
+                        never[ethernet] = []
+                        pass
+                    never[ethernet].append(ip)
                     pass
-                never[ethernet].append(ip)
-                pass
-            continue
-        if match(util.address(ip)):
-            if not ethernet in static:
-                static[ethernet] = []
-                pass
-            static[ethernet].append(ip)
-            continue
+                continue
+            if match(util.address(ip)):
+                if not ethernet in static:
+                    static[ethernet] = []
+                    pass
+                static[ethernet].append(ip)
+                continue
+            pass
         pass
 
     def by_name(ether_ip_dict):
diff --git a/src/hostinfo/dhcpd_ipv6.py b/src/hostinfo/dhcpd_ipv6.py
index 9d589eb..98b7f35 100755
--- a/src/hostinfo/dhcpd_ipv6.py
+++ b/src/hostinfo/dhcpd_ipv6.py
@@ -105,11 +105,13 @@ def emit_interface(tree, options, interface):
     result = util.StringArray()
     subnet = dict(map(lambda d: (get_subnet(tree, d._parent), d),
                       interface._ipv6_._dhcpserver_))
-    result += 'shared-network "MAC(%s)" {' % interface.ethernet[0]
-    for sn,dhcp in map(lambda n: (n, subnet[n]), sorted(subnet)): 
-        result += emit_network(tree, options, sn, dhcp).indent()
+    for ethernet in util.ethernets(interface.ethernet[0]):
+        result += 'shared-network "MAC(%s)" {' % ethernet
+        for sn,dhcp in map(lambda n: (n, subnet[n]), sorted(subnet)): 
+            result += emit_network(tree, options, sn, dhcp).indent()
+            pass
+        result += "}"
         pass
-    result += "}"
     return result
 
 def emit_network(tree, options, subnet, dhcp):
@@ -171,25 +173,24 @@ def emit_hosts(tree, options, networks):
     never = {}
     for ip in tree._host_._interface_._ipv6_:
         # Find all hosts that associated with this network
-        ethernet = ip.ethernet[0:]
-        if not ethernet:
-            continue
-        if ethernet.lower() != ethernet:
-            raise util.HostinfoException('%s not lower-case' % ethernet)
-        if ip.never[0]:
-            if match(util.address(ip.never[0])):
-                if not ethernet in never:
-                    never[ethernet] = []
+        for ethernet in util.ethernets(ip.ethernet[0:]):
+            if ethernet.lower() != ethernet:
+                raise util.HostinfoException('%s not lower-case' % ethernet)
+            if ip.never[0]:
+                if match(util.address(ip.never[0])):
+                    if not ethernet in never:
+                        never[ethernet] = []
+                        pass
+                    never[ethernet].append(ip)
                     pass
-                never[ethernet].append(ip)
-                pass
-            continue
-        if match(util.address(ip)):
-            if not ethernet in static:
-                static[ethernet] = []
-                pass
-            static[ethernet].append(ip)
-            continue
+                continue
+            if match(util.address(ip)):
+                if not ethernet in static:
+                    static[ethernet] = []
+                    pass
+                static[ethernet].append(ip)
+                continue
+            pass
         pass
 
     def by_name(ether_ip_dict):
diff --git a/src/hostinfo/ifconfig.py b/src/hostinfo/ifconfig.py
index d713f1e..6362748 100755
--- a/src/hostinfo/ifconfig.py
+++ b/src/hostinfo/ifconfig.py
@@ -236,40 +236,42 @@ def generate_ifcfg(tree, interface):
 def generate(tree, host):
     result = []
     for i in tree._host_._interface_:
-        if i._parent.name[0] != host or not device(i.ethernet[0]):
-            continue
-        device_name = device(i.ethernet[0])
-        if i.bridge[0]:
-            config = '# Generated by %s\n' % (' '.join(sys.argv))
-            config += 'DEVICE=%s\n' % i.bridge[0]
-            config += 'NAME=%s\n' % i.bridge[0]
-            config += 'ONBOOT=yes\n'
-            config += 'TYPE=Bridge\n'
-            config += 'STP=off\n'
-            config += get_nm_extra(i.bridge[0])
-            config += generate_ifcfg(tree, i)
-            result.append(('ifcfg-%s' %  i.bridge[0], config))
+        for ethernet in util.ethernets(i.ethernet[0]):
+            if i._parent.name[0] != host or not device(ethernet):
+                continue
+            device_name = device(ethernet)
+            if i.bridge[0]:
+                config = '# Generated by %s\n' % (' '.join(sys.argv))
+                config += 'DEVICE=%s\n' % i.bridge[0]
+                config += 'NAME=%s\n' % i.bridge[0]
+                config += 'ONBOOT=yes\n'
+                config += 'TYPE=Bridge\n'
+                config += 'STP=off\n'
+                config += get_nm_extra(i.bridge[0])
+                config += generate_ifcfg(tree, i)
+                result.append(('ifcfg-%s' %  i.bridge[0], config))
 
-            config = '# Generated by %s\n' % (' '.join(sys.argv))
-            config += 'DEVICE=%s\n' % device_name
-            config += 'NAME=%s\n' % device_name
-            config += 'HWADDR=%s\n' % i.ethernet[0].upper()
-            config += 'ONBOOT=yes\n'
-            config += 'TYPE=Ethernet\n'
-            config += 'BRIDGE=%s\n' % i.bridge[0]
-            config += get_nm_extra(device_name)
-            result.append(('ifcfg-%s' %  device_name, config))
-            pass
-        elif i.ethernet[0]:
-            config = '# Generated by %s\n' % (' '.join(sys.argv))
-            config += 'DEVICE=%s\n' % device_name
-            config += 'NAME=%s\n' % device_name
-            config += 'HWADDR=%s\n' % i.ethernet[0].upper()
-            config += 'ONBOOT=yes\n'
-            config += 'TYPE=Ethernet\n'
-            config += get_nm_extra(device_name)
-            config += generate_ifcfg(tree, i)
-            result.append(('ifcfg-%s' %  device_name, config))
+                config = '# Generated by %s\n' % (' '.join(sys.argv))
+                config += 'DEVICE=%s\n' % device_name
+                config += 'NAME=%s\n' % device_name
+                config += 'HWADDR=%s\n' % ethernet.upper()
+                config += 'ONBOOT=yes\n'
+                config += 'TYPE=Ethernet\n'
+                config += 'BRIDGE=%s\n' % i.bridge[0]
+                config += get_nm_extra(device_name)
+                result.append(('ifcfg-%s' %  device_name, config))
+                pass
+            else:
+                config = '# Generated by %s\n' % (' '.join(sys.argv))
+                config += 'DEVICE=%s\n' % device_name
+                config += 'NAME=%s\n' % device_name
+                config += 'HWADDR=%s\n' % ethernet.upper()
+                config += 'ONBOOT=yes\n'
+                config += 'TYPE=Ethernet\n'
+                config += get_nm_extra(device_name)
+                config += generate_ifcfg(tree, i)
+                result.append(('ifcfg-%s' %  device_name, config))
+                pass
             pass
         pass
     return result
diff --git a/src/hostinfo/pxelinux.py b/src/hostinfo/pxelinux.py
index ce7de35..986771b 100755
--- a/src/hostinfo/pxelinux.py
+++ b/src/hostinfo/pxelinux.py
@@ -1,14 +1,17 @@
 import sys
 import os
 from hostinfo.util import ntoa, aton
+import hostinfo.util as util
 
 def generate(tree, dhcphost):
     result = []
     for i in tree._host_._interface_:
         if i.ethernet[0] and i._kickstart_:
-            result.append(("01-" + i.ethernet[0].replace(':', '-'),
-                           i.name[0:],
-                           i._kickstart_[0].file[0]))
+            for ethernet in util.ethernets( i.ethernet[0]):
+                result.append(("01-" + ethernet.replace(':', '-'),
+                               i.name[0:],
+                               i._kickstart_[0].file[0]))
+                pass
             pass
         pass
     result.sort()
diff --git a/src/hostinfo/util.py b/src/hostinfo/util.py
index 9dc39dd..4272c04 100755
--- a/src/hostinfo/util.py
+++ b/src/hostinfo/util.py
@@ -29,6 +29,10 @@ def subnet(tree, addr):
                                 where=result)
     return result and result[0] or None
 
+def ethernets(ether):
+    if ether == None:
+        return []
+    return ether.split(',')
 
 def aton(addr):
     result = long(0)
diff --git a/src/hostinfo/yp.py b/src/hostinfo/yp.py
index 08fa695..cac7724 100755
--- a/src/hostinfo/yp.py
+++ b/src/hostinfo/yp.py
@@ -32,17 +32,23 @@ def ethers(tree):
     result = ""
     host = {}
     for i in filter(lambda i: i.ethernet[0], tree._host_._interface_):
-        host[i.ethernet[0]] = set([ i.name[0:] ])
+        for ethernet in util.ethernets(i.ethernet[0]):
+            host[ethernet] = set([ i.name[0:] ])
+            pass
         for ip in filter(util.address, i._ip_):
             fqn = util.fqn(tree, ip)
             if fqn:
-                host[i.ethernet[0]].add(fqn[0:-1])
+                for ethernet in util.ethernets(i.ethernet[0]):
+                    host[ethernet].add(fqn[0:-1])
+                    pass
                 pass
             pass
         for ipv6 in filter(util.address, i._ipv6_):
             fqn = util.fqn(tree, ipv6)
             if fqn:
-                host[i.ethernet[0]].add(fqn[0:-1])
+                for ethernet in util.ethernets(i.ethernet[0]):
+                    host[ethernet].add(fqn[0:-1])
+                    pass
                 pass
             pass
         pass
-- 
GitLab