a little nicer
[nodemanager.git] / plugins / privatebridge.py
index 52c3932..9489f69 100644 (file)
@@ -1,39 +1,44 @@
-#!/usr/bin/python
+"""
+Private Bridge configurator.
+"""
 
-""" Private Bridge configurator.  """
-
-import httplib
-import os
 import select
-import shutil
 import subprocess
 import time
 import tools
 
-from threading import Thread
 import logger
-import tools
 
 priority = 9
 
+class OvsException (Exception) :
+    def __init__(self, message="no message"):
+        self.message = message
+    def __repr__(self):
+        return self.message
+
 def start():
     logger.log('private bridge plugin starting up...')
 
-def log_call_read(command,timeout=logger.default_timeout_minutes*60,poll=1):
-    message=" ".join(command)
+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
+    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)
-            if r: stdout = stdout + child.stdout.read(1)
+            (r, w, x) = select.select([child.stdout], [], [], poll)
+            if r:
+                stdout = stdout + child.stdout.read(1)
             # is process over ?
             returncode=child.poll()
             # yes
@@ -47,43 +52,54 @@ def log_call_read(command,timeout=logger.default_timeout_minutes*60,poll=1):
                     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()
+    (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]
@@ -92,14 +108,13 @@ def ovs_addport(name, portname, type, remoteip, key):
     if key:
         args = args + ["options:key=" + str(key)]
 
-    (returncode, stdout) = ovs_vsctl(args)
+    returncode, stdout = ovs_vsctl(args)
     if (returncode != 0):
-        raise OvsException()
+        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()
@@ -151,10 +166,15 @@ def configure_slicebridge(sliver, attributes):
     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 = []
@@ -162,11 +182,11 @@ def GetSlivers(data, conf = None, plc = None):
         sliver_name = sliver['name']
 
         # build a dict of attributes, because it's more convenient
-        attributes={}
+        attributes = {}
         for attribute in sliver['attributes']:
             attributes[attribute['tagname']] = attribute['value']
 
-        bridge_name = 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)
@@ -185,6 +205,3 @@ def GetSlivers(data, conf = None, plc = None):
         logger.log("privatebridge: deleting unused bridge %s" % bridge_name)
 
         ovs_delbridge(bridge_name)
-
-
-