From: smbaker Date: Thu, 3 Jan 2013 08:00:13 +0000 (-0800) Subject: privatebridge plugin, initial check-in X-Git-Tag: nodemanager-2.1-18~4 X-Git-Url: http://git.onelab.eu/?p=nodemanager.git;a=commitdiff_plain;h=844f6a075205a46f96d816a2ee89677afc3f6318 privatebridge plugin, initial check-in --- diff --git a/plugins/privatebridge.py b/plugins/privatebridge.py new file mode 100644 index 0000000..f6d52f7 --- /dev/null +++ b/plugins/privatebridge.py @@ -0,0 +1,166 @@ +#!/usr/bin/python + +""" 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 + +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) + 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) + + 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) + # is process over ? + returncode=child.poll() + # yes + if returncode != None: + stdout = stdout + child.stdout.read() + # child is done and return 0 + if returncode == 0: + logger.log("log_call:end command (%s) completed" % message) + if stdout != "": + logger.log("log_call:stdout: %s" % stdout) + return (returncode, stdout) + # child has failed + else: + 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)) + return (-2, None) + break + except: + logger.log_exc("failed to run command %s" % message) + + return (-1, None) + +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() + return stdout.split() + +def ovs_addbridge(name): + (returncode, stdout) = ovs_vsctl(["add-br",name]) + if (returncode != 0): + raise OvsException() + +def ovs_listports(name): + (returncode, stdout) = ovs_vsctl(["list-ports", name]) + if (returncode != 0): + raise OvsException() + return stdout.split() + +def ovs_addport(name, portname, type, remoteip, key): + args = ["add-port", name, portname, "--", "set", "interface", portname, "type="+type] + if remoteip: + args = args + ["options:remote_ip=" + remoteip] + if key: + args = args + ["options:key=" + str(key)] + + (returncode, stdout) = ovs_vsctl(args) + if (returncode != 0): + raise OvsException() + +def ovs_delport(name, portname): + (returncode, stdout) = ovs_vsctl(["del-port",name,portname]) + if (returncode != 0): + raise OvsException() + +def ensure_slicebridge_created(name, addr): + bridges = ovs_listbridge() + logger.log("privatebridge: current bridges = " + ",".join(bridges)) + if name in bridges: + return + + ovs_addbridge(name) + + logger.log_call(["ifconfig", name, addr, "netmask", "255.0.0.0"]) + +def ensure_slicebridge_neighbors(name, sliver_id, neighbors): + ports = ovs_listports(name) + + want_ports = [] + for neighbor in neighbors: + (neighbor_node_id, neighbor_ip) = neighbor.split("/") + neighbor_node_id = int(neighbor_node_id) + portname = "gre%d-%d" % (sliver_id, neighbor_node_id) + + want_ports.append(portname) + + if not portname in ports: + ovs_addport(name, portname, "gre", neighbor_ip, sliver_id) + + for port in ports: + if port.startswith("gre") and (port not in want_ports): + ovs_delport(name, portname) + +def configure_slicebridge(sliver, attributes): + sliver_name = sliver['name'] + sliver_id = sliver['slice_id'] + + slice_bridge_name = attributes["slice_bridge_name"] + + slice_bridge_addr = attributes.get("slice_bridge_addr", None) + if not slice_bridge_addr: + logger.log("privatebridge: no slice_bridge_addr for %s" % sliver_name) + return + + slice_bridge_neighbors = attributes.get("slice_bridge_neighbors", None) + if not slice_bridge_neighbors: + logger.log("privatebridge: no slice_bridge_neighbors for %s" % sliver_name) + return + + slice_bridge_neighbors = [x.strip() for x in slice_bridge_neighbors.split(",")] + + ensure_slicebridge_created(slice_bridge_name, slice_bridge_addr) + ensure_slicebridge_neighbors(slice_bridge_name, sliver_id, slice_bridge_neighbors) + +def GetSlivers(data, conf = None, plc = None): + node_id = tools.node_id() + + if 'slivers' not in data: + logger.log_missing_data("privatebridge.GetSlivers",'slivers') + return + + for sliver in data['slivers']: + sliver_name = sliver['name'] + + # build a dict of attributes, because it's more convenient + attributes={} + for attribute in sliver['attributes']: + attributes[attribute['tagname']] = attribute['value'] + + if attributes.get('slice_bridge_name',None): + configure_slicebridge(sliver, attributes) + +