Changes for robustness when deleting a sliver
[nodemanager-topo.git] / topo.py
diff --git a/topo.py b/topo.py
index 4d4e4a9..fb9e33c 100755 (executable)
--- a/topo.py
+++ b/topo.py
@@ -10,11 +10,14 @@ import logger
 import subprocess
 import sioc
 import re
 import subprocess
 import sioc
 import re
+import vserver
+import os
 
 dryrun=0
 setup_link_cmd="/usr/share/vini/setup-egre-link"
 teardown_link_cmd="/usr/share/vini/teardown-egre-link"
 ifaces = {}
 
 dryrun=0
 setup_link_cmd="/usr/share/vini/setup-egre-link"
 teardown_link_cmd="/usr/share/vini/teardown-egre-link"
 ifaces = {}
+old_ifaces = {}
 
 def run(cmd):
     if dryrun:
 
 def run(cmd):
     if dryrun:
@@ -29,7 +32,6 @@ Check for existence of interface d<key>x<nodeid>
 """
 def virtual_link(key, nodeid):
     name = "d%sx%s" % (key, nodeid)
 """
 def virtual_link(key, nodeid):
     name = "d%sx%s" % (key, nodeid)
-    # logger.log("Looking for iface %s" % name)
     if name in ifaces:
         return True
     else:
     if name in ifaces:
         return True
     else:
@@ -41,7 +43,7 @@ Create a "virtual link" for slice between here and nodeid.
 The key is used to create the EGRE tunnel.
 """
 def setup_virtual_link(slice, key, rate, myid, nodeid, ipaddr):
 The key is used to create the EGRE tunnel.
 """
 def setup_virtual_link(slice, key, rate, myid, nodeid, ipaddr):
-    logger.log("Set up virtual link to node %d" % nodeid)
+    logger.log("%s: Set up virtual link to node %d" % (slice, nodeid))
     if myid < nodeid:
         virtip = "10.%d.%d.2" % (myid, nodeid)
     else:
     if myid < nodeid:
         virtip = "10.%d.%d.2" % (myid, nodeid)
     else:
@@ -55,25 +57,35 @@ def setup_virtual_link(slice, key, rate, myid, nodeid, ipaddr):
 """
 Tear down the "virtual link" for slice between here and nodeid.
 """
 """
 Tear down the "virtual link" for slice between here and nodeid.
 """
-def teardown_virtual_link(slice, key, nodeid):
-    logger.log("Tear down virtual link to node %s" % nodeid)
-    run(teardown_link_cmd + " %s %s %s" % (slice, nodeid, key))
+def teardown_virtual_link(key, nodeid):
+    logger.log("topo: Tear down virtual link %sx%s" % (key, nodeid))
+    run(teardown_link_cmd + " %s %s" % (nodeid, key))
     return
 
 
     return
 
 
+"""
+Called for all active virtual link interfaces, so they won't be cleaned up.
+"""
+def refresh_virtual_link(nodeid, key):
+    try:
+        name = "d%sx%s" % (key, nodeid)
+        del old_ifaces[name]
+    except:
+        pass
+
+
 """
 Clean up old virtual links (e.g., to nodes that have been deleted 
 from the slice).
 """
 """
 Clean up old virtual links (e.g., to nodes that have been deleted 
 from the slice).
 """
-def clean_up_old_virtual_links(slice, key, nodelist):
-    pattern = "d%sx(.*)" % key
-    for iface in ifaces:
+def clean_up_old_virtual_links():
+    pattern = "d(.*)x(.*)"
+    for iface in old_ifaces:
         m = re.match(pattern, iface)
         if m:
         m = re.match(pattern, iface)
         if m:
-            node = int(m.group(1))
-            if not node in nodelist:
-                logger.log("%s" % nodelist)
-                teardown_virtual_link(slice, key, node)
+            key = int(m.group(1))
+            node = int(m.group(2))
+            teardown_virtual_link(key, node)
 
 
 """
 
 
 """
@@ -86,17 +98,36 @@ def convert_topospec_to_list(rspec):
 """
 Update virtual links for the slice
 """
 """
 Update virtual links for the slice
 """
-def update(slice, myid, topospec, key):
+def update(slice, myid, topospec, key, netns):
     topolist = convert_topospec_to_list(topospec)
     topolist = convert_topospec_to_list(topospec)
-    nodelist=[]
     for (nodeid,ipaddr,rate) in topolist:
     for (nodeid,ipaddr,rate) in topolist:
-        nodelist.append(nodeid)
         if not virtual_link(key, nodeid):
         if not virtual_link(key, nodeid):
-            setup_virtual_link(slice, key, rate, myid, nodeid, ipaddr)
+            if netns:
+                setup_virtual_link(slice, key, rate, myid, nodeid, ipaddr)
         else:
         else:
-            logger.log("Virtual link to node %s exists" % nodeid)
+            logger.log("%s: virtual link to node %s exists" % (slice, nodeid))
+            refresh_virtual_link(nodeid, key)
 
 
-    clean_up_old_virtual_links(slice, key, nodelist)
+"""
+Write /etc/vservers/<slicename>/spaces/net
+"""
+def writeConf(slicename, value):
+    SLICEDIR="/etc/vservers/%s/" % slicename
+    SPACESDIR="%s/spaces/" % SLICEDIR
+    if os.path.exists(SLICEDIR):
+        if not os.path.exists(SPACESDIR):
+            try:
+                os.mkdir(SPACESDIR)
+            except os.error:
+                logger.log("netns: could not create %s\n" % SPACESDIR)
+                return
+        f = open("%s/net" % SPACESDIR, "w")
+        f.write("%s\n" % value)
+        f.close()
+        STATUS="OFF"
+        if int(value) >= 1:
+            STATUS="ON"
+        logger.log("%s: network namespace %s\n" % (slicename, STATUS))
 
 
 def start(options, config):
 
 
 def start(options, config):
@@ -106,18 +137,35 @@ def start(options, config):
 """
 Update the virtual links for a sliver if it has a 'netns' attribute,
 an 'egre_key' attribute, and a 'topo_rspec' attribute.
 """
 Update the virtual links for a sliver if it has a 'netns' attribute,
 an 'egre_key' attribute, and a 'topo_rspec' attribute.
+
+Creating the virtual link depends on the contents of 
+/etc/vservers/<slice>/spaces/net.  Update this first.
 """
 def GetSlivers(data):
 """
 def GetSlivers(data):
-    global ifaces
-    ifaces = sioc.gifconf()
+    global ifaces, old_ifaces
+    ifaces = old_ifaces = sioc.gifconf()
 
     for sliver in data['slivers']:
         attrs = {}
         for attribute in sliver['attributes']:
             attrs[attribute['name']] = attribute['value']
 
     for sliver in data['slivers']:
         attrs = {}
         for attribute in sliver['attributes']:
             attrs[attribute['name']] = attribute['value']
-        if 'netns' in attrs and 'egre_key' in attrs and 'topo_rspec' in attrs:
-            if attrs['netns'] > 0:
-                logger.log("Update topology for slice %s" % sliver['name'])
-                update(sliver['name'], data['node_id'], 
-                       attrs['topo_rspec'], attrs['egre_key'])
+        if 'netns' in attrs:
+            writeConf(sliver['name'], attrs['netns'])
+            netns = attrs['netns']
+        else:
+            netns = 0
+
+        try:
+            if vserver.VServer(sliver['name']).is_running():
+                if 'egre_key' in attrs and 'topo_rspec' in attrs:
+                    logger.log("topo: Update topology for slice %s" % \
+                                   sliver['name'])
+                    update(sliver['name'], data['node_id'], 
+                           attrs['topo_rspec'], attrs['egre_key'], netns)
+        except:
+            logger.log("topo: sliver %s not running yet. Deferring." % \
+                           sliver['name'])
+
+    clean_up_old_virtual_links()
+