summaryrefslogtreecommitdiffstats
path: root/func
diff options
context:
space:
mode:
authorJasper Capel <capel@stone-it.com>2008-10-06 10:25:18 +0200
committerJasper Capel <capel@stone-it.com>2008-10-06 10:25:18 +0200
commit00841af2928e7b0503428eecc236e5e4db9ffbd4 (patch)
treec4a2991ab35e24a5bdbe0246c3e7aec7df8e0b68 /func
parent2bbab70e9f83bd8f0cadec000c1aca258c791472 (diff)
downloadfunc-00841af2928e7b0503428eecc236e5e4db9ffbd4.tar.gz
func-00841af2928e7b0503428eecc236e5e4db9ffbd4.tar.xz
func-00841af2928e7b0503428eecc236e5e4db9ffbd4.zip
Added methods to permanently add/remove bridges or permanently add/remove interfaces from bridges.
Diffstat (limited to 'func')
-rw-r--r--func/minion/modules/bridge.py178
1 files changed, 175 insertions, 3 deletions
diff --git a/func/minion/modules/bridge.py b/func/minion/modules/bridge.py
index 1058425..67a5ed9 100644
--- a/func/minion/modules/bridge.py
+++ b/func/minion/modules/bridge.py
@@ -19,11 +19,11 @@
# 02110-1301 USA
import func_module
-import os
+import os, re
class Bridge(func_module.FuncModule):
- version = "0.0.1"
- api_version = "0.0.1"
+ version = "0.0.2"
+ api_version = "0.0.2"
description = "Func module for Bridge management"
# A list of bridge names that should be ignored. You can use this if you
@@ -34,6 +34,8 @@ class Bridge(func_module.FuncModule):
ignorebridges = [ "virbr0" ]
brctl = "/usr/sbin/brctl"
ip = "/sbin/ip"
+ ifup = "/sbin/ifup"
+ ifdown = "/sbin/ifdown"
def list(self):
# Returns a dictionary. Elements look like this:
@@ -79,6 +81,62 @@ class Bridge(func_module.FuncModule):
retlist[curbr].append(elements[0])
return retlist
+
+ def list_permanent(self):
+ # Returns a list of permanent bridges (bridges configured to be enabled
+ # at boot-time.
+ retlist = {}
+ ifpattern = re.compile('ifcfg-([a-z0-9]+)')
+ # RHEL treats this value as case-sensitive, so so will we.
+ brpattern = re.compile('TYPE=Bridge')
+ brifpattern = re.compile('BRIDGE=([a-zA-Z0-9]+)')
+ devpattern = re.compile('DEVICE=([a-zA-Z0-9\.]+)')
+ nwscriptdir = "/etc/sysconfig/network-scripts"
+
+ # Pass one: find bridges
+ for item in os.listdir(nwscriptdir):
+ match = ifpattern.match(item)
+ if match:
+ filename = "%s/%s" % (nwscriptdir, item)
+ fp = open(filename, "r")
+ lines = fp.readlines()
+ fp.close()
+ bridge = False
+ ifname = ""
+ for line in lines:
+ if brpattern.match(line):
+ bridge = True
+ devmatch = devpattern.match(line)
+ if devmatch:
+ ifname = devmatch.group(1)
+ if bridge == True:
+ # Create empty interface list for bridge
+ retlist[ifname] = []
+
+ # Pass two: match interface to bridge
+ for item in os.listdir(nwscriptdir):
+ match = ifpattern.match(item)
+ if match:
+ filename = "%s/%s" % (nwscriptdir, item)
+ fp = open(filename, "r")
+ lines = fp.readlines()
+ fp.close()
+ ifname = ""
+ brname = ""
+ for line in lines:
+ devmatch = devpattern.match(line)
+ if devmatch:
+ ifname = devmatch.group(1)
+ brmatch = brifpattern.match(line)
+ if brmatch:
+ brname = brmatch.group(1)
+ if brname != "":
+ # Interface belongs to bridge
+ if brname in retlist:
+ # Just to be sure... if it doesn't match this interface
+ # is orphaned.
+ retlist[brname].append(ifname)
+ return retlist
def add_bridge(self, brname):
# Creates a bridge
@@ -89,6 +147,27 @@ class Bridge(func_module.FuncModule):
return exitcode
+ def add_bridge_permanent(self, brname, ipaddr=None, netmask=None, gateway=None):
+ # Creates a permanent bridge (writes to
+ # /etc/sysconfig/network-scripts)
+ if brname not in self.ignorebridges:
+ filename = "/etc/sysconfig/network-scripts/ifcfg-%s" % brname
+ fp = open(filename, "w")
+ filelines = [ "DEVICE=%s\n" % brname, "TYPE=Bridge\n", "ONBOOT=yes\n" ]
+ if ipaddr != None:
+ filelines.append("IPADDR=%s\n" % ipaddr)
+ if netmask != None:
+ filelines.append("NETMASK=%s\n" % netmask)
+ if gateway != None:
+ filelines.append("GATEWAY=%s\n" % gateway)
+ fp.writelines(filelines)
+ fp.close()
+ exitcode = os.spawnv(os.P_WAIT, self.ifup, [ self.ifup, brname ] )
+ else:
+ exitcode = -1
+ return exitcode
+
+
def add_interface(self, brname, ifname):
# Adds an interface to a bridge
if brname not in self.ignorebridges:
@@ -98,15 +177,61 @@ class Bridge(func_module.FuncModule):
return exitcode
+ def add_interface_permanent(self, brname, ifname):
+ # Permanently adds an interface to a bridge.
+ # Both interface and bridge must have a ifcfg-file we can write to.
+ brfilename = "/etc/sysconfig/network-scripts/ifcfg-%s" % brname
+ iffilename = "/etc/sysconfig/network-scripts/ifcfg-%s" % ifname
+ if os.path.exists(brfilename) and os.path.exists(iffilename):
+ # Read all lines first, then we append a BRIDGE= line.
+ fp = open(iffilename, "r")
+ lines = fp.readlines()
+ fp.close()
+ pattern = re.compile("BRIDGE=(.*)")
+ exitcode = 0
+ for line in lines:
+ if pattern.match(line) != None:
+ # This interface is configured to bridge already, leave it
+ # alone.
+ exitcode = 1
+ break
+ if exitcode == 0:
+ # Try change on live interface
+ if self.add_interface(brname, ifname) == 0:
+ # Change succeeded, write to ifcfg-file
+ # Reopen file for writing
+ fp = open(iffilename, "w")
+ lines.append("BRIDGE=%s\n" % brname)
+ fp.writelines(lines)
+ fp.close()
+ else:
+ exitcode = 2
+ else:
+ exitcode = -1
+
+ return exitcode
+
def delete_bridge(self, brname):
# Deletes a bridge
if brname not in self.ignorebridges:
# This needs some more error checking. :)
+ self.down_bridge(brname)
exitcode = os.spawnv(os.P_WAIT, self.brctl, [ self.brctl, "delbr", brname ] )
else:
exitcode = -1
return exitcode
+
+ def delete_bridge_permanent(self, brname):
+ # Deletes a bridge permanently
+ filename = "/etc/sysconfig/network-scripts/ifcfg-%s" % brname
+ if brname not in self.ignorebridges:
+ returncode = self.delete_bridge(brname)
+ if os.path.exists(filename):
+ os.remove(filename)
+ else:
+ returncode = -1
+ return returncode
def delete_interface(self, brname, ifname):
# Deletes an interface from a bridge
@@ -117,6 +242,53 @@ class Bridge(func_module.FuncModule):
return exitcode
+ def delete_interface_permanent(self, brname, ifname):
+ # Permanently deletes interface from bridge
+ iffilename = "/etc/sysconfig/network-scripts/ifcfg-%s" % ifname
+
+ if brname in self.ignorebridges:
+ exitcode = -1
+ elif os.path.exists(iffilename):
+ # This only works if the interface itself is permanent
+ fp = open(iffilename, "r")
+ lines = fp.readlines()
+ fp.close()
+ pattern = re.compile("BRIDGE=(.*)")
+ exitcode = 1
+ for line in lines:
+ if pattern.match(line):
+ lines.remove(line)
+ exitcode = 0
+ if exitcode == 0:
+ # Try change live
+ trychange = self.delete_interface(brname, ifname)
+ if trychange == 0:
+ # Change succeeded, write new interface file.
+ fp = open(iffilename, "w")
+ fp.writelines(lines)
+ fp.close()
+ else:
+ exitcode = trychange
+ else:
+ exitcode = 2
+ return exitcode
+
+ def delete_all_interfaces(self, brname):
+ # Deletes all interfaces from a bridge
+ if brname not in self.ignorebridges:
+ bridgelist = self.list()
+ if brname in bridgelist:
+ # Does this bridge exist?
+ exitcode = 0
+ interfaces = bridgelist[brname]
+ for interface in interfaces:
+ childexitcode = self.delete_interface(brname, interface)
+ if exitcode == 0 and childexitcode != 0:
+ exitcode = childexitcode
+ else:
+ exitcode = -1
+ return exitcode
+
def add_promisc_bridge(self, brname, ifname):
# Creates a new bridge brname, attaches interface ifname to it and sets
# the MAC address of the connected interface to FE:FF:FF:FF:FF:FF so