3 """ Private Bridge configurator. """
13 from threading import Thread
20 logger.log('private bridge plugin starting up...')
22 def log_call_read(command,timeout=logger.default_timeout_minutes*60,poll=1):
23 message=" ".join(command)
24 logger.log("log_call: running command %s" % message)
25 logger.verbose("log_call: timeout=%r s" % timeout)
26 logger.verbose("log_call: poll=%r s" % poll)
27 trigger=time.time()+timeout
29 child = subprocess.Popen(command, bufsize=1,
30 stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
34 # see if anything can be read within the poll interval
35 (r,w,x)=select.select([child.stdout],[],[],poll)
36 if r: stdout = stdout + child.stdout.read(1)
38 returncode=child.poll()
40 if returncode != None:
41 stdout = stdout + child.stdout.read()
42 # child is done and return 0
44 logger.log("log_call:end command (%s) completed" % message)
46 logger.log("log_call:stdout: %s" % stdout)
47 return (returncode, stdout)
50 log("log_call:end command (%s) returned with code %d" %(message,returncode))
51 return (returncode, stdout)
52 # no : still within timeout ?
53 if time.time() >= trigger:
55 logger.log("log_call:end terminating command (%s) - exceeded timeout %d s"%(message,timeout))
59 logger.log_exc("failed to run command %s" % message)
64 return log_call_read(["ovs-vsctl"] + args)
67 (returncode, stdout) = ovs_vsctl(["list-br"])
72 def ovs_addbridge(name):
73 (returncode, stdout) = ovs_vsctl(["add-br",name])
77 def ovs_listports(name):
78 (returncode, stdout) = ovs_vsctl(["list-ports", name])
83 def ovs_delbridge(name):
84 (returncode, stdout) = ovs_vsctl(["del-br",name])
88 def ovs_addport(name, portname, type, remoteip, key):
89 args = ["add-port", name, portname, "--", "set", "interface", portname, "type="+type]
91 args = args + ["options:remote_ip=" + remoteip]
93 args = args + ["options:key=" + str(key)]
95 (returncode, stdout) = ovs_vsctl(args)
99 def ovs_delport(name, portname):
100 (returncode, stdout) = ovs_vsctl(["del-port",name,portname])
101 if (returncode != 0):
104 def ensure_slicebridge_created(name, addr):
105 bridges = ovs_listbridge()
106 logger.log("privatebridge: current bridges = " + ",".join(bridges))
112 logger.log_call(["ifconfig", name, addr, "netmask", "255.0.0.0"])
114 def ensure_slicebridge_neighbors(name, sliver_id, neighbors):
115 ports = ovs_listports(name)
118 for neighbor in neighbors:
119 (neighbor_node_id, neighbor_ip) = neighbor.split("/")
120 neighbor_node_id = int(neighbor_node_id)
121 portname = "gre%d-%d" % (sliver_id, neighbor_node_id)
123 want_ports.append(portname)
125 if not portname in ports:
126 ovs_addport(name, portname, "gre", neighbor_ip, sliver_id)
128 for portname in ports:
129 if portname.startswith("gre") and (portname not in want_ports):
130 ovs_delport(name, portname)
132 def configure_slicebridge(sliver, attributes):
133 sliver_name = sliver['name']
134 sliver_id = sliver['slice_id']
136 slice_bridge_name = attributes["slice_bridge_name"]
138 slice_bridge_addr = attributes.get("slice_bridge_addr", None)
139 if not slice_bridge_addr:
140 logger.log("privatebridge: no slice_bridge_addr for %s" % sliver_name)
143 slice_bridge_neighbors = attributes.get("slice_bridge_neighbors", None)
144 if not slice_bridge_neighbors:
145 logger.log("privatebridge: no slice_bridge_neighbors for %s" % sliver_name)
148 slice_bridge_neighbors = [x.strip() for x in slice_bridge_neighbors.split(",")]
150 ensure_slicebridge_created(slice_bridge_name, slice_bridge_addr)
151 ensure_slicebridge_neighbors(slice_bridge_name, sliver_id, slice_bridge_neighbors)
153 def GetSlivers(data, conf = None, plc = None):
154 node_id = tools.node_id()
156 if 'slivers' not in data:
157 logger.log_missing_data("privatebridge.GetSlivers",'slivers')
161 for sliver in data['slivers']:
162 sliver_name = sliver['name']
164 # build a dict of attributes, because it's more convenient
166 for attribute in sliver['attributes']:
167 attributes[attribute['tagname']] = attribute['value']
169 bridge_name = attributes.get('slice_bridge_name',None)
171 configure_slicebridge(sliver, attributes)
172 valid_bridges.append(bridge_name)
174 # now, delete the bridges that we don't want
175 bridges = ovs_listbridge()
176 for bridge_name in bridges:
177 if not bridge_name.startswith("br-slice-"):
178 # ignore ones we didn't create
181 if bridge_name in valid_bridges:
182 # ignore ones we want to keep
185 logger.log("privatebridge: deleting unused bridge %s" % bridge_name)
187 ovs_delbridge(bridge_name)