-#!/usr/bin/python
+#!/usr/bin/env python3
""" Private Bridge configurator. """
-import httplib
+import http.client
import os
import select
import shutil
priority = 9
+class OvsException (Exception) :
+ def __init__ (self, message="no message"):
+ self.message=message
+ def __repr__ (self): return message
+
def start():
logger.log('private bridge plugin starting up...')
-def log_call_read(command,timeout=logger.default_timeout_minutes*60,poll=1):
+def log_call_read(command, timeout=logger.default_timeout_minutes*60, poll=1):
message=" ".join(command)
logger.log("log_call: running command %s" % message)
logger.verbose("log_call: timeout=%r s" % timeout)
logger.verbose("log_call: poll=%r s" % poll)
trigger=time.time()+timeout
try:
- child = subprocess.Popen(command, bufsize=1,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
+ child = subprocess.Popen(
+ command, bufsize=1,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ close_fds=True,
+ universal_newlines=True)
stdout = ""
while True:
# see if anything can be read within the poll interval
- (r,w,x)=select.select([child.stdout],[],[],poll)
+ (r, w, x)=select.select([child.stdout], [], [], poll)
if r: stdout = stdout + child.stdout.read(1)
# is process over ?
returncode=child.poll()
return (returncode, stdout)
# child has failed
else:
- log("log_call:end command (%s) returned with code %d" %(message,returncode))
+ log("log_call:end command (%s) returned with code %d" %(message, returncode))
return (returncode, stdout)
# no : still within timeout ?
if time.time() >= trigger:
child.terminate()
- logger.log("log_call:end terminating command (%s) - exceeded timeout %d s"%(message,timeout))
+ logger.log("log_call:end terminating command (%s) - exceeded timeout %d s"%(message, timeout))
return (-2, None)
break
- except:
- logger.log_exc("failed to run command %s" % message)
+ except Exception as e:
+ logger.log_exc("failed to run command %s -> %s" % (message, e))
return (-1, None)
+### Thierry - 23 Sept 2014
+# regardless of this being shipped on lxc-only or on all nodes,
+# it is safer to check for the availability of the ovs-vsctl command and just print
+# out a warning when it's not there, instead of a nasty traceback
+def ovs_available ():
+ "return True if ovs-vsctl can be run"
+ try:
+ child = subprocess.Popen (['ovs-vsctl', '--help'])
+ child.communicate()
+ return True
+ except:
+ return False
+
def ovs_vsctl(args):
return log_call_read(["ovs-vsctl"] + args)
def ovs_listbridge():
(returncode, stdout) = ovs_vsctl(["list-br"])
- if (returncode != 0):
- raise OvsException()
+ if (returncode != 0): raise OvsException("list-br")
return stdout.split()
def ovs_addbridge(name):
- (returncode, stdout) = ovs_vsctl(["add-br",name])
- if (returncode != 0):
- raise OvsException()
+ (returncode, stdout) = ovs_vsctl(["add-br", name])
+ if (returncode != 0): raise OvsException("add-br")
def ovs_listports(name):
(returncode, stdout) = ovs_vsctl(["list-ports", name])
- if (returncode != 0):
- raise OvsException()
+ if (returncode != 0): raise OvsException("list-ports")
return stdout.split()
+def ovs_delbridge(name):
+ (returncode, stdout) = ovs_vsctl(["del-br", name])
+ if (returncode != 0): raise OvsException("del-br")
+
def ovs_addport(name, portname, type, remoteip, key):
args = ["add-port", name, portname, "--", "set", "interface", portname, "type="+type]
if remoteip:
args = args + ["options:key=" + str(key)]
(returncode, stdout) = ovs_vsctl(args)
- if (returncode != 0):
- raise OvsException()
+ if (returncode != 0): raise OvsException("add-port")
def ovs_delport(name, portname):
- (returncode, stdout) = ovs_vsctl(["del-port",name,portname])
- if (returncode != 0):
- raise OvsException()
+ (returncode, stdout) = ovs_vsctl(["del-port", name, portname])
+ if (returncode != 0): raise OvsException("del-port")
def ensure_slicebridge_created(name, addr):
bridges = ovs_listbridge()
ensure_slicebridge_neighbors(slice_bridge_name, sliver_id, slice_bridge_neighbors)
def GetSlivers(data, conf = None, plc = None):
+
+ if not ovs_available():
+ logger.log ("privatebridge: warning, ovs-vsctl not found - exiting")
+ return
+
node_id = tools.node_id()
if 'slivers' not in data:
- logger.log_missing_data("privatebridge.GetSlivers",'slivers')
+ logger.log_missing_data("privatebridge.GetSlivers", 'slivers')
return
+ valid_bridges = []
for sliver in data['slivers']:
sliver_name = sliver['name']
for attribute in sliver['attributes']:
attributes[attribute['tagname']] = attribute['value']
- if attributes.get('slice_bridge_name',None):
+ bridge_name = attributes.get('slice_bridge_name', None)
+ if bridge_name:
configure_slicebridge(sliver, attributes)
+ valid_bridges.append(bridge_name)
+
+ # now, delete the bridges that we don't want
+ bridges = ovs_listbridge()
+ for bridge_name in bridges:
+ if not bridge_name.startswith("br-slice-"):
+ # ignore ones we didn't create
+ continue
+
+ if bridge_name in valid_bridges:
+ # ignore ones we want to keep
+ continue
+ logger.log("privatebridge: deleting unused bridge %s" % bridge_name)
+ ovs_delbridge(bridge_name)