bridgeconfig wip
smbaker [Wed, 2 Jan 2013 03:02:16 +0000 (19:02 -0800)]
apps/gacks/bridgeconfig.py [new file with mode: 0644]

diff --git a/apps/gacks/bridgeconfig.py b/apps/gacks/bridgeconfig.py
new file mode 100644 (file)
index 0000000..3f625ff
--- /dev/null
@@ -0,0 +1,112 @@
+class NetworkBuilder:
+    def __init__(self, plc):
+        self.plc = plc
+
+    def set_tag(self, tagname, slice_id, node_id, value):
+        tags = self.plc.GetSliceTags({"tagname": tagname, "slice_id": slice_id, "node_id": node_id})
+        if tags:
+            if tags[0]["value"] != value:
+                self.plc.UpdateSliceTag(tags[0]['slice_tag_id'], value)\r
+        else:\r
+            self.plc.AddSliceTag(slice_id, "interface", value, node_id)
+
+class NetworkBuilder_gre(NetworkBuilder):
+    """ This sets up nodes using private bridges and GRE tunnels.
+
+        There can be up to 65535 node_ids.
+
+        Each bridge gets the address 10.1.<node_id_hi>.<node_id_lo>
+        Each sliver gets the address 10.2.<node_id_hi>.<node_id_lo>
+
+        GRE tunnels are setup between nodes. Nodes can talk to each other across
+        sites. The current topology that is used is a star, with all nodes talking
+        to a head node. This represents a single point of failure, as well as a
+        bottleneck.
+    """
+
+    def __init__(self, plc):
+        NetworkBuilder.init(self, plc)
+
+    def configure_slice(self, slice_name_or_id):
+        slices = self.plc.GetSlices(slice_name_or_id, ["slice_id", "node_ids", "slice_tag_ids"])
+        if not slices:
+            # we couldn't find it
+            return
+
+        slice = slices[0]
+        slice_id = slice["slice_id"]
+
+        nodes = self.plc.GetNodes(slice["node_ids"], ["node_id", "hostname"])
+        interfaces = self.plc.GetInterfaces({"node_id": slice["node_ids"]}, ["node_id", "ip", "is_primary"])
+        topology = self.generate_star_topology(self, nodes)
+
+        node_ips = {}
+        for interface in interfaces:
+            if interface["is_primary"]:
+                node_ips[interface["node_id"]] = interface["ip"]
+
+        # filter out any nodes where we do not know the ip address
+        nodes = [x for x in nodes if node_ips.get(x["node_id"], None)]
+
+        bridge_name = "br-slice-" + str(slice_id)
+        self.set_tag("slice_bridge_name", slice_id, None, bridge_name)
+
+        for (node_id,neighbor_list) in topology.items():
+            neighbor_ip = [node_ips[x] for x in neighbor_list]
+            set_tag("slice_bridge_addr", slice_id, node_id, "10.1.%d.%d" % (node_id>>8, node_id&0xFF))
+            set_tag("slice_bridge_neighbors", slice_id, node_id, ",".join(neighbor_list))
+            set_tag("interface", "{'bridge':'%s', 'DEVICE':'eth0', 'BOOTPROTO':'static', 'ONBOOT':'yes', 'PRIMARY':'yes', 'IPADDR': '10.2.%d.%d', 'NETMASK': '255.0.0.0'}" % (bridge_name, node_id>>8, node_id&0xFF))
+
+    def generate_star_topology(self, nodes):
+        if not nodes:
+            # if there are no nodes, then there is no topology
+            return {}
+
+        headnode = nodes[0]
+        headnode_id = headnode["node_id"]
+        for node in nodes[1:]:
+            node_id = node["node_id"]
+            topology[headnode_id] = topology.get(headnode_id, []).apppend(node_id)
+            topology[node_id] = [headnode_id]
+        return topology
+
+class NetworkBuilder_10(NetworkBuilder):
+    """ This sets up each slice as a class A private network.
+
+        10.<slice_id_hi>.<slice_id_lo>.<node_id>
+
+        There can be at most 65535 slice_ids. There can be at most 255 nodes
+        per site.
+
+        Nodes in one site cannot talk to nodes in another site
+    """
+
+    def configure_slice(self, slice_name_or_id):
+        slices = self.plc.GetSlices(slice_name_or_id, ["slice_id", "node_ids", "slice_tag_ids"])
+        if not slices:
+            # we couldn't find it
+            return
+
+        slice = slices[0]
+        slice_id = slice["slice_id"]
+
+        nodes = self.plc.GetNodes(slice["node_ids"], ["node_id", "hostname", "site_id"])
+
+        site_ids = []
+        for node in nodes:
+           if not (node["site_id"] in site_ids):
+               site_ids.append(node["site_id"])
+
+        node_indices = {}
+        sites = self.plc.GetSites(site_ids)
+        for site in sites:
+            for (i, node_id) in enumerate(site["node_ids"]):
+                node_indices[node_id] = i
+
+        for node in nodes:
+            node_id = node["node_id"]
+            node_index = node_indices.get(node_id, 0)
+            ip_addr = "10.%d.%d.%d" % (slice_id>>8, slice_id&0xFF, node_index + 1)
+            self.set_tag("interface", slice_id, node_id, "{'bridge':'public0', 'DEVICE':'eth0', 'BOOTPROTO':'static', 'ONBOOT':'yes', 'PRIMARY':'yes', 'IPADDR': '%s', 'NETMASK': '255.255.255.0'}" % ip_addr)
+
+