Changes for robustness when deleting a sliver
authorAndy Bavier <acb@cs.princeton.edu>
Wed, 18 Feb 2009 20:52:31 +0000 (20:52 +0000)
committerAndy Bavier <acb@cs.princeton.edu>
Wed, 18 Feb 2009 20:52:31 +0000 (20:52 +0000)
NodeManager-topo.spec
setup-egre-link
teardown-egre-link
topo.py

index 4ba2ad8..45e5981 100644 (file)
@@ -1,7 +1,7 @@
 %define url $URL$
 
 Name:          NodeManager-topo
 %define url $URL$
 
 Name:          NodeManager-topo
-Version:       0.1
+Version:       0.2
 Release:       1
 Summary:       Plugin supporting creating a default virtual topology.
 
 Release:       1
 Summary:       Plugin supporting creating a default virtual topology.
 
index 829756d..cef4108 100755 (executable)
@@ -10,6 +10,7 @@ KEY=$4
 RATE=$5
 VIRTIP=$6
 
 RATE=$5
 VIRTIP=$6
 
+VIRTNET=`echo $VIRTIP|sed "s/\.[23]$/.0/"`
 LINK=${KEY}x${NODEID}
 
 modprobe ip_gre
 LINK=${KEY}x${NODEID}
 
 modprobe ip_gre
@@ -38,12 +39,12 @@ ifconfig $BRIDGE up
 iptables -t mangle -A FORWARD -o $BRIDGE -j MARK --set-mark $SLICEID
 
 ### Put a process in the vserver so we can move the interface there
 iptables -t mangle -A FORWARD -o $BRIDGE -j MARK --set-mark $SLICEID
 
 ### Put a process in the vserver so we can move the interface there
-su $SLICE -c "sleep 60" &
+su $SLICE -c "sleep 30" &
 sleep 1
 PID=`su $SLICE -c "pgrep sleep"`
 chcontext --ctx 1 -- echo $PID > /sys/class/net/$ETUN0/new_ns_pid 
 sleep 1
 sleep 1
 PID=`su $SLICE -c "pgrep sleep"`
 chcontext --ctx 1 -- echo $PID > /sys/class/net/$ETUN0/new_ns_pid 
 sleep 1
-su $SLICE -c "sudo /sbin/ifconfig $ETUN0 $VIRTIP/24 up"
+su $SLICE -c "sudo /sbin/ifconfig $ETUN0 $VIRTIP/24 up; sudo /sbin/route add -net $VIRTNET/24 dev $ETUN0"
 
 ### Set rate
 tc qdisc add dev $EGRE root handle 1: htb default 10
 
 ### Set rate
 tc qdisc add dev $EGRE root handle 1: htb default 10
index 77cc1d1..efa2aea 100755 (executable)
@@ -1,17 +1,19 @@
 #!/bin/sh +x
 
 #!/bin/sh +x
 
-SLICE=$1
-SLICEID=`id -u $SLICE`
-NODEID=$2
-KEY=$3
+NODEID=$1
+KEY=$2
 
 LINK=${KEY}x${NODEID}
 EGRE=d$LINK
 BRIDGE=c$LINK
 ETUN1=b$LINK
 
 
 LINK=${KEY}x${NODEID}
 EGRE=d$LINK
 BRIDGE=c$LINK
 ETUN1=b$LINK
 
-# Remove iptables rule
-iptables -t mangle -D FORWARD -o $BRIDGE -j MARK --set-mark $SLICEID
+MARK=`iptables -t mangle -L -v|grep -m 1 $BRIDGE|awk '{print $NF}'`
+
+# Remove iptables rules.  Sometimes there is more than one.
+while [ $? -eq 0 ]; do
+    iptables -t mangle -D FORWARD -o $BRIDGE -j MARK --set-mark $MARK
+done
 
 # Get rid of etun devices, only need name of one of them
 echo $ETUN1 > /sys/module/etun/parameters/delif
 
 # Get rid of etun devices, only need name of one of them
 echo $ETUN1 > /sys/module/etun/parameters/delif
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()
+