mention /usr/bin/python when invoking setup.py, because otherwise on
[pyplnet.git] / plnet.py
index f12c173..b46d720 100755 (executable)
--- a/plnet.py
+++ b/plnet.py
@@ -43,7 +43,7 @@ def InitInterfaces(logger, plc, data, root="", files_only=False, program="NodeMa
     failedToGetSettings = False
 
     # NOTE: GetInterfaces/NodeNetworks does not necessarily order the interfaces
-    # returned.  Because 'interface'is decremented as each interface is processed,
+    # returned.  Because 'interface' is decremented as each interface is processed,
     # by the time is_primary=True (primary) interface is reached, the device
     # "eth%s" % interface, is not eth0.  But, something like eth-4, or eth-12.
     # This code sorts the interfaces, placing is_primary=True interfaces first.  
@@ -59,6 +59,9 @@ def InitInterfaces(logger, plc, data, root="", files_only=False, program="NodeMa
     interfaces.sort( compare_by('is_primary') )
     interfaces.reverse()
 
+    # The names of the bridge devices
+    bridgeDevices = []
+
     for interface in interfaces:
         logger.verbose('net:InitInterfaces interface %d: %r'%(device_id,interface))
         logger.verbose('net:InitInterfaces macs = %r' % macs)
@@ -77,35 +80,10 @@ def InitInterfaces(logger, plc, data, root="", files_only=False, program="NodeMa
         if orig_ifname:
             logger.verbose('net:InitInterfaces orig_ifname = %s' % orig_ifname)
 
-        details = {}
-        details['ONBOOT']='yes'
-        details['USERCTL']='no'
-        if interface['mac']:
-            details['HWADDR'] = interface['mac']
+        details = prepDetails(interface, hostname)
+
         if interface['is_primary']:
-            details['PRIMARY']='yes'
-
-        if interface['method'] == "static":
-            details['BOOTPROTO'] = "static"
-            details['IPADDR'] = interface['ip']
-            details['NETMASK'] = interface['netmask']
-            details['GATEWAY'] = interface['gateway']
-            if interface['is_primary']:
-                gateway = interface['gateway']
-                if interface['dns1']:
-                    details['DNS1'] = interface['dns1']
-                if interface['dns2']:
-                    details['DNS2'] = interface['dns2']
-
-        elif interface['method'] == "dhcp":
-            details['BOOTPROTO'] = "dhcp"
-            details['PERSISTENT_DHCLIENT'] = "yes"
-            if interface['hostname']:
-                details['DHCP_HOSTNAME'] = interface['hostname']
-            else:
-                details['DHCP_HOSTNAME'] = hostname 
-            if not interface['is_primary']:
-                details['DHCLIENTARGS'] = "-R subnet-mask"
+            gateway = interface['gateway']
 
         if 'interface_tag_ids' in interface:
             version = 4.3
@@ -132,8 +110,12 @@ def InitInterfaces(logger, plc, data, root="", files_only=False, program="NodeMa
 
             for setting in settings:
                 settingname = setting[name_key].upper()
-                if settingname in ('IFNAME','ALIAS','CFGOPTIONS','DRIVER'):
+                if settingname in ('IFNAME','ALIAS','CFGOPTIONS','DRIVER','VLAN'):
                     details[settingname]=setting['value']
+                # IPv6 support on IPv4 interface
+                elif settingname in ('IPV6ADDR','IPV6_DEFAULTGW','IPV6ADDR_SECONDARIES'):
+                    details[settingname]=setting['value']
+                    details['IPV6INIT']='yes'
                 # wireless settings
                 elif settingname in \
                         [  "MODE", "ESSID", "NW", "FREQ", "CHANNEL", "SENS", "RATE",
@@ -141,6 +123,13 @@ def InitInterfaces(logger, plc, data, root="", files_only=False, program="NodeMa
                            "IWCONFIG", "IWPRIV" ] :
                     details [settingname] = setting['value']
                     details ['TYPE']='Wireless'
+                # Bridge setting
+                elif settingname in [ 'BRIDGE' ]:
+                    details['BRIDGE'] = setting['value']
+                elif settingname in [ 'OVS_BRIDGE' ]:
+                    details['OVS_BRIDGE'] = setting['value']
+                    details['TYPE'] = "OVSPort"
+                    details['DEVICETYPE'] = "ovs"
                 else:
                     logger.log("net:InitInterfaces WARNING: ignored setting named %s"%setting[name_key])
 
@@ -174,6 +163,31 @@ def InitInterfaces(logger, plc, data, root="", files_only=False, program="NodeMa
             else:
                 logger.log("net:InitInterfaces WARNING: interface alias (%s) not matched to an interface"% details['ALIAS'])
             device_id -= 1
+        elif ('BRIDGE' in details or 'OVS_BRIDGE' in details) and 'IFNAME' in details:
+            # The bridge inherits the mac of the first attached interface.
+            ifname = details['IFNAME']
+            device_id -= 1
+            if 'BRIDGE' in details:
+                bridgeName = details['BRIDGE']
+                bridgeType = 'Bridge'
+            else:
+                bridgeName = details['OVS_BRIDGE']
+                bridgeType = 'OVSBridge'
+
+            logger.log('net:InitInterfaces: %s detected. Adding %s to devices_map' % (bridgeType, ifname))
+            devices_map[ifname] = removeBridgedIfaceDetails(details)
+
+            logger.log('net:InitInterfaces: Adding %s %s' % (bridgeType, bridgeName))
+            bridgeDetails = prepDetails(interface)
+            bridgeDevices.append(bridgeName)
+            bridgeDetails['TYPE'] = bridgeType
+            if bridgeType == 'OVSBridge':
+                bridgeDetails['DEVICETYPE'] = 'ovs'
+                if bridgeDetails['BOOTPROTO'] == 'dhcp':
+                    del bridgeDetails['BOOTPROTO']
+                    bridgeDetails['OVSBOOTPROTO'] = 'dhcp'
+                    bridgeDetails['OVSDHCPINTERFACES'] = ifname
+            devices_map[bridgeName] = bridgeDetails
         else:
             if 'IFNAME' in details:
                 ifname = details['IFNAME']
@@ -191,6 +205,7 @@ def InitInterfaces(logger, plc, data, root="", files_only=False, program="NodeMa
                     logger.log("net:InitInterfaces WARNING: possibly blowing away %s configuration"%ifname)
             devices_map[ifname] = details
         device_id += 1 
+    logger.log('net:InitInterfaces: Device map: %r' % devices_map)
     m = modprobe.Modprobe()
     try:
         m.input("%s/etc/modprobe.conf" % root)
@@ -224,7 +239,7 @@ def InitInterfaces(logger, plc, data, root="", files_only=False, program="NodeMa
     lo = "ifcfg-lo"
     if lo in ifcfgs: ifcfgs.remove(lo)
 
-    # remove known devices from icfgs list
+    # remove known devices from ifcfgs list
     for (dev, details) in devices_map.iteritems():
         ifcfg = 'ifcfg-'+dev
         if ifcfg in ifcfgs: ifcfgs.remove(ifcfg)
@@ -255,6 +270,7 @@ def InitInterfaces(logger, plc, data, root="", files_only=False, program="NodeMa
 
     # Process ifcfg-$dev changes / additions
     newdevs = []
+    table = 10
     for (dev, details) in devices_map.iteritems():
         (fd, tmpnam) = tempfile.mkstemp(dir=sysconfig)
         f = os.fdopen(fd, "w")
@@ -301,10 +317,7 @@ def InitInterfaces(logger, plc, data, root="", files_only=False, program="NodeMa
         src_route_changed = False
         if ('PRIMARY' not in details and 'GATEWAY' in details and
             details['GATEWAY'] != ''):
-            i = len(dev) - 1
-            while dev[i - 1].isdigit():
-                i -= 1
-            table = 10 + int(dev[i:])
+            table += 1
             (fd, rule_tmpnam) = tempfile.mkstemp(dir=sysconfig)
             os.write(fd, "from %s lookup %d\n" % (details['IPADDR'], table))
             os.close(fd)
@@ -391,10 +404,64 @@ def InitInterfaces(logger, plc, data, root="", files_only=False, program="NodeMa
         # handle those correctly
         if getvar("SLAVE") == 'yes': continue
 
+        # Delay bringing up any bridge devices
+        if dev in bridgeDevices: continue
+
         if not files_only:
             logger.verbose('net:InitInterfaces bringing up %s' % dev)
             os.system("/sbin/ifup %s" % dev)
 
+    # Bring up the bridge devices
+    for bridge in bridgeDevices:
+        if not files_only and bridge in newdevs:
+            logger.verbose('net:InitInterfaces bringing up bridge %s' % bridge)
+            os.system("/sbin/ifup %s" % bridge)
+
+##
+# Prepare the interface details.
+#
+def prepDetails(interface, hostname=''):
+    details = {}
+    details['ONBOOT']  = 'yes'
+    details['USERCTL'] = 'no'
+    if interface['mac']:
+        details['HWADDR'] = interface['mac']
+    if interface['is_primary']:
+        details['PRIMARY'] = 'yes'
+
+    if interface['method'] == "static":
+        details['BOOTPROTO'] = "static"
+        details['IPADDR']    = interface['ip']
+        details['NETMASK']   = interface['netmask']
+        details['GATEWAY']   = interface['gateway']
+        if interface['is_primary']:
+            if interface['dns1']:
+                details['DNS1'] = interface['dns1']
+            if interface['dns2']:
+                details['DNS2'] = interface['dns2']
+
+    elif interface['method'] == "dhcp":
+        details['BOOTPROTO'] = "dhcp"
+        details['PERSISTENT_DHCLIENT'] = "yes"
+        if interface['hostname']:
+            details['DHCP_HOSTNAME'] = interface['hostname']
+        else:
+            details['DHCP_HOSTNAME'] = hostname
+        if not interface['is_primary']:
+            details['DHCLIENTARGS'] = "-R subnet-mask"
+
+    return details
+
+##
+# Remove duplicate entry from the bridged interface's configuration file.
+#
+def removeBridgedIfaceDetails(details):
+    for key in [ 'PRIMARY', 'PERSISTENT_DHCLIENT', 'DHCLIENTARGS', 'DHCP_HOSTNAME',
+                 'BOOTPROTO', 'IPADDR', 'NETMASK', 'GATEWAY', 'DNS1', 'DNS2' ]:
+        if key in details:
+            del details[key]
+    return details
+
 if __name__ == "__main__":
     import optparse
     import sys