Bump release. Merge from HEAD.
authorFaiyaz Ahmed <faiyaza@cs.princeton.edu>
Mon, 26 Feb 2007 18:04:40 +0000 (18:04 +0000)
committerFaiyaz Ahmed <faiyaza@cs.princeton.edu>
Mon, 26 Feb 2007 18:04:40 +0000 (18:04 +0000)
NodeManager.spec
accounts.py
api.py
bwmon.py
delegate.py
net.py
nm.py
setup.py
sliver_vs.py
sm.py

index c5f2f40..1c1fb34 100644 (file)
@@ -1,6 +1,6 @@
 Summary: PlanetLab Node Manager
 Name: NodeManager
-Version: 1.1
+Version: 1.2
 Release: 1%{?pldistro:.%{pldistro}}%{?date:.%{date}}
 License: PlanetLab
 Group: System Environment/Daemons
index fe0af53..1b8c8a8 100644 (file)
@@ -67,7 +67,7 @@ class Account:
         self.configure(rec)
 
     @staticmethod
-    def create(name): abstract
+    def create(name, vref = None): abstract
     @staticmethod
     def destroy(name): abstract
 
diff --git a/api.py b/api.py
index 8e8794a..5c4ab4a 100644 (file)
--- a/api.py
+++ b/api.py
@@ -147,7 +147,7 @@ class APIRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
                 target_name = args[0]
                 target_rec = database.db.get(target_name)
                 if not (target_rec and target_rec['type'].startswith('sliver.')): raise xmlrpclib.Fault(102, 'Invalid argument: the first argument must be a sliver name.')
-                if not (caller_name in (args[0], 'root') or (caller_name, method_name) in target_rec['delegations']): raise xmlrpclib.Fault(108, 'Permission denied.')
+                if not (caller_name in (args[0], 'root') or (caller_name, method_name) in target_rec['delegations'] or (caller_name == 'utah_elab_delegate' and target_name.startswith('utah_elab_'))): raise xmlrpclib.Fault(108, 'Permission denied.')
                 result = method(target_rec, *args[1:])
             else: result = method(*args)
             if result == None: result = 1
index 28c7341..68a118c 100644 (file)
--- a/bwmon.py
+++ b/bwmon.py
@@ -15,7 +15,7 @@
 # Faiyaz Ahmed <faiyaza@cs.princeton.edu>
 # Copyright (C) 2004-2006 The Trustees of Princeton University
 #
-# $Id: bwmon.py,v 1.2 2007/02/07 18:12:02 faiyaza Exp $
+# $Id$
 #
 
 import os
@@ -24,11 +24,22 @@ import time
 import pickle
 import database
 
-#import socket
+import socket
 #import xmlrpclib
 import bwlimit
+import logger
 
 from sets import Set
+try:
+    sys.path.append("/etc/planetlab")
+    from plc_config import *
+except:
+    logger.log("bwmon:  Warning: Configuration file /etc/planetlab/plc_config.py not found")
+    PLC_NAME = "PlanetLab"
+    PLC_SLICE_PREFIX = "pl"
+    PLC_MAIL_SUPPORT_ADDRESS = "support@planet-lab.org"
+    PLC_MAIL_SLICE_ADDRESS = "SLICE@slices.planet-lab.org"
+
 
 # Utility functions
 #from pl_mom import *
@@ -43,11 +54,12 @@ verbose = 0
 datafile = "/var/lib/misc/bwmon.dat"
 #nm = None
 
-# Burst to line rate (or node cap).  Set by NM.
-default_MaxRate = bwlimit.get_bwcap()
-default_Maxi2Rate = bwlimit.bwmax
+# Burst to line rate (or node cap).  Set by NM. in KBit/s
+default_MaxRate = int(bwlimit.get_bwcap() / 1000)
+default_Maxi2Rate = int(bwlimit.bwmax / 1000)
 # Min rate 8 bits/s 
-default_MinRate = 8
+default_MinRate = 0
+default_Mini2Rate = 0
 # 5.4 Gbyte per day. 5.4 * 1024 k * 1024M * 1024G 
 # 5.4 Gbyte per day max allowed transfered per recording period
 default_MaxKByte = 5662310
@@ -81,6 +93,78 @@ footer = \
 %(date)s %(hostname)s bwcap %(slice)s
 """.lstrip()
 
+def format_bytes(bytes, si = True):
+    """
+    Formats bytes into a string
+    """
+    if si:
+        kilo = 1000.
+    else:
+        # Officially, a kibibyte
+        kilo = 1024.
+
+    if bytes >= (kilo * kilo * kilo):
+        return "%.1f GB" % (bytes / (kilo * kilo * kilo))
+    elif bytes >= 1000000:
+        return "%.1f MB" % (bytes / (kilo * kilo))
+    elif bytes >= 1000:
+        return "%.1f KB" % (bytes / kilo)
+    else:
+        return "%.0f bytes" % bytes
+
+def format_period(seconds):
+    """
+    Formats a period in seconds into a string
+    """
+
+    if seconds == (24 * 60 * 60):
+        return "day"
+    elif seconds == (60 * 60):
+        return "hour"
+    elif seconds > (24 * 60 * 60):
+        return "%.1f days" % (seconds / 24. / 60. / 60.)
+    elif seconds > (60 * 60):
+        return "%.1f hours" % (seconds / 60. / 60.)
+    elif seconds > (60):
+        return "%.1f minutes" % (seconds / 60.)
+    else:
+        return "%.0f seconds" % seconds
+
+def slicemail(slice, subject, body):
+    sendmail = os.popen("/usr/sbin/sendmail -N never -t -f%s" % PLC_MAIL_SUPPORT_ADDRESS, "w")
+
+    # PLC has a separate list for pl_mom messages
+    if PLC_MAIL_SUPPORT_ADDRESS == "support@planet-lab.org":
+        to = ["pl-mom@planet-lab.org"]
+    else:
+        to = [PLC_MAIL_SUPPORT_ADDRESS]
+
+    if slice is not None and slice != "root":
+        to.append(PLC_MAIL_SLICE_ADDRESS.replace("SLICE", slice))
+
+    header = {'from': "%s Support <%s>" % (PLC_NAME, PLC_MAIL_SUPPORT_ADDRESS),
+              'to': ", ".join(to),
+              'version': sys.version.split(" ")[0],
+              'subject': subject}
+
+    # Write headers
+    sendmail.write(
+"""
+Content-type: text/plain
+From: %(from)s
+Reply-To: %(from)s
+To: %(to)s
+X-Mailer: Python/%(version)s
+Subject: %(subject)s
+
+""".lstrip() % header)
+
+    # Write body
+    sendmail.write(body)
+    # Done
+    sendmail.close()
+
+
 class Slice:
     """
     Stores the last recorded bandwidth parameters of a slice.
@@ -100,7 +184,7 @@ class Slice:
 
     """
 
-    def __init__(self, xid, name, maxrate, maxi2rate, bytes, i2bytes, data):
+    def __init__(self, xid, name, data):
         self.xid = xid
         self.name = name
         self.time = 0
@@ -109,6 +193,7 @@ class Slice:
         self.MaxRate = default_MaxRate
         self.MinRate = default_MinRate
         self.Maxi2Rate = default_Maxi2Rate
+        self.Mini2Rate = default_Mini2Rate
         self.MaxKByte = default_MaxKByte
         self.ThreshKByte = default_ThreshKByte
         self.Maxi2KByte = default_Maxi2KByte
@@ -116,8 +201,14 @@ class Slice:
         self.Share = default_Share
         self.emailed = False
 
-        # Get real values where applicable
-        self.reset(maxrate, maxi2rate, bytes, i2bytes, data)
+        self.updateSliceAttributes(data)
+        bwlimit.set(xid = self.xid, 
+                minrate = self.MinRate, 
+                maxrate = self.MaxRate, 
+                maxexemptrate = self.Maxi2Rate,
+                minexemptrate = self.Mini2Rate,
+                share = self.Share)
+
 
     def __repr__(self):
         return self.name
@@ -125,28 +216,49 @@ class Slice:
     @database.synchronized
     def updateSliceAttributes(self, data):
         for sliver in data['slivers']:
-            if sliver['name'] == self.name:    
+            if sliver['name'] == self.name: 
                 for attribute in sliver['attributes']:
-                    if attribute['name'] == 'net_min_rate':        
-                        self.MinRate = attribute['value']
-                    elif attribute['name'] == 'net_max_rate':        
-                        self.MaxRate = attribute['value']
+                    if attribute['name'] == 'net_min_rate':     
+                        self.MinRate = int(attribute['value'])
+                        logger.log("bwmon:  Updating %s. Min Rate = %s" \
+                          %(self.name, self.MinRate))
+                    elif attribute['name'] == 'net_max_rate':       
+                        self.MaxRate = int(attribute['value'])
+                        logger.log("bwmon:  Updating %s. Max Rate = %s" \
+                          %(self.name, self.MaxRate))
                     elif attribute['name'] == 'net_i2_min_rate':
-                        self.Mini2Rate = attribute['value']
+                        self.Mini2Rate = int(attribute['value'])
+                        logger.log("bwmon:  Updating %s. Min i2 Rate = %s" \
+                          %(self.name, self.Mini2Rate))
                     elif attribute['name'] == 'net_i2_max_rate':        
-                        self.Maxi2Rate = attribute['value']
-                    elif attribute['name'] == 'net_max_kbyte':        
-                        self.MaxKbyte = attribute['value']
-                    elif attribute['name'] == 'net_i2_max_kbyte':    
-                        self.Maxi2KByte = attribute['value']
-                    elif attribute['name'] == 'net_thresh_kbyte':    
-                        self.ThreshKByte = attribute['value']
+                        self.Maxi2Rate = int(attribute['value'])
+                        logger.log("bwmon:  Updating %s. Max i2 Rate = %s" \
+                          %(self.name, self.Maxi2Rate))
+                    elif attribute['name'] == 'net_max_kbyte':      
+                        self.MaxKByte = int(attribute['value'])
+                        logger.log("bwmon:  Updating %s. Max KByte lim = %s" \
+                          %(self.name, self.MaxKByte))
+                    elif attribute['name'] == 'net_i2_max_kbyte':   
+                        self.Maxi2KByte = int(attribute['value'])
+                        logger.log("bwmon:  Updating %s. Max i2 KByte = %s" \
+                          %(self.name, self.Maxi2KByte))
+                    elif attribute['name'] == 'net_thresh_kbyte':   
+                        self.ThreshKByte = int(attribute['value'])
+                        logger.log("bwmon:  Updating %s. Thresh KByte = %s" \
+                          %(self.name, self.ThreshKByte))
                     elif attribute['name'] == 'net_i2_thresh_kbyte':    
-                        self.Threshi2KByte = attribute['value']
-                    elif attribute['name'] == 'net_share':    
-                        self.Share = attribute['value']
-                    elif attribute['name'] == 'net_i2_share':    
-                        self.Sharei2 = attribute['value']
+                        self.Threshi2KByte = int(attribute['value'])
+                        logger.log("bwmon:  Updating %s. i2 Thresh KByte = %s" \
+                          %(self.name, self.Threshi2KByte))
+                    elif attribute['name'] == 'net_share':  
+                        self.Share = int(attribute['value'])
+                        logger.log("bwmon:  Updating %s. Net Share = %s" \
+                          %(self.name, self.Share))
+                    elif attribute['name'] == 'net_i2_share':   
+                        self.Sharei2 = int(attribute['value'])
+                        logger.log("bwmon:  Updating %s. Net i2 Share = %s" \
+                          %(self.name, self.i2Share))
+
 
     def reset(self, runningmaxrate, runningmaxi2rate, usedbytes, usedi2bytes, data):
         """
@@ -166,18 +278,19 @@ class Slice:
 
         # Reset email 
         self.emailed = False
-
+        maxrate = self.MaxRate * 1000 
+        maxi2rate = self.Maxi2Rate * 1000 
         # Reset rates.
         if (self.MaxRate != runningmaxrate) or (self.Maxi2Rate != runningmaxi2rate):
-            print "%s reset to %s/%s" % \
+            logger.log("bwmon:  %s reset to %s/%s" % \
                   (self.name,
-                   bwlimit.format_tc_rate(self.MaxRate),
-                   bwlimit.format_tc_rate(self.Maxi2Rate))
+                   bwlimit.format_tc_rate(maxrate),
+                   bwlimit.format_tc_rate(maxi2rate)))
             bwlimit.set(xid = self.xid, 
-                minrate = self.MinRate, 
-                maxrate = self.MaxRate, 
-                maxexemptrate = self.Maxi2Rate,
-                minexemptrate = self.Mini2Rate,
+                minrate = self.MinRate * 1000
+                maxrate = self.MaxRate * 1000
+                maxexemptrate = self.Maxi2Rate * 1000,
+                minexemptrate = self.Mini2Rate * 1000,
                 share = self.Share)
 
     def update(self, runningmaxrate, runningmaxi2rate, usedbytes, usedi2bytes, data):
@@ -197,58 +310,58 @@ class Slice:
                   'date': time.asctime(time.gmtime()) + " GMT",
                   'period': format_period(period)} 
 
-        if usedi2bytes >= (self.usedbytes + self.ByteThresh):
+        if usedbytes >= (self.bytes + (self.ThreshKByte * 1024)):
             maxbyte = self.MaxKByte * 1024
-            bytesused = bytes - self.bytes
+            bytesused = usedbytes - self.bytes
             timeused = int(time.time() - self.time)
             new_maxrate = int(((maxbyte - bytesused) * 8)/(period - timeused))
             if new_maxrate < self.MinRate:
                 new_maxrate = self.MinRate
         else:
-            new_maxrate = self.MaxRate 
+            new_maxrate = self.MaxRate * 1000 
 
         # Format template parameters for low bandwidth message
         params['class'] = "low bandwidth"
         params['bytes'] = format_bytes(usedbytes - self.bytes)
         params['maxrate'] = bwlimit.format_tc_rate(runningmaxrate)
-        params['limit'] = format_bytes(self.MaxKByte)
+        params['limit'] = format_bytes(self.MaxKByte * 1024)
         params['new_maxrate'] = bwlimit.format_tc_rate(new_maxrate)
 
         if verbose:
-            print "%(slice)s %(class)s " \
+            logger.log("bwmon:  %(slice)s %(class)s " \
                   "%(bytes)s of %(limit)s (%(new_maxrate)s/s maxrate)" % \
-                  params
+                  params)
 
         # Cap low bandwidth burst rate
         if new_maxrate != runningmaxrate:
             message += template % params
-            print "%(slice)s %(class)s capped at %(new_maxrate)s/s " % params
+            logger.log("bwmon:      %(slice)s %(class)s capped at %(new_maxrate)s/s " % params)
     
-        if usedi2bytes >= (self.i2bytes + self.Threshi2KBytes):
+        if usedi2bytes >= (self.i2bytes + (self.Threshi2KByte * 1024)):
             maxi2byte = self.Maxi2KByte * 1024
-            i2bytesused = i2bytes - self.i2bytes
+            i2bytesused = usedi2bytes - self.i2bytes
             timeused = int(time.time() - self.time)
             new_maxi2rate = int(((maxi2byte - i2bytesused) * 8)/(period - timeused))
             if new_maxi2rate < self.Mini2Rate:
                 new_maxi2rate = self.Mini2Rate
         else:
-            new_maxi2rate = self.Maxi2Rate 
+            new_maxi2rate = self.Maxi2Rate * 1000
 
         # Format template parameters for high bandwidth message
         params['class'] = "high bandwidth"
         params['bytes'] = format_bytes(usedi2bytes - self.i2bytes)
         params['maxrate'] = bwlimit.format_tc_rate(runningmaxi2rate)
-        params['limit'] = format_bytes(self.Maxi2KByte)
+        params['limit'] = format_bytes(self.Maxi2KByte * 1024)
         params['new_maxexemptrate'] = bwlimit.format_tc_rate(new_maxi2rate)
 
         if verbose:
-            print "%(slice)s %(class)s " \
-                  "%(bytes)s of %(limit)s (%(new_maxrate)s/s maxrate)" % params
+            logger.log("bwmon:  %(slice)s %(class)s " \
+                  "%(bytes)s of %(limit)s (%(new_maxrate)s/s maxrate)" % params)
 
         # Cap high bandwidth burst rate
         if new_maxi2rate != runningmaxi2rate:
             message += template % params
-            print "%(slice)s %(class)s capped at %(new_maxexemptrate)s/s" % params
+            logger.log("bwmon:  %(slice)s %(class)s capped at %(new_maxexemptrate)s/s" % params)
 
         # Apply parameters
         if new_maxrate != runningmaxrate or new_maxi2rate != runningmaxi2rate:
@@ -258,8 +371,8 @@ class Slice:
         if message and self.emailed == False:
             subject = "pl_mom capped bandwidth of slice %(slice)s on %(hostname)s" % params
             if debug:
-                print subject
-                print message + (footer % params)
+                logger.log("bwmon:  "+ subject)
+                logger.log("bwmon:  "+ message + (footer % params))
             else:
                 self.emailed = True
                 slicemail(self.name, subject, message + (footer % params))
@@ -268,45 +381,69 @@ def GetSlivers(data):
     # Defaults
     global datafile, \
         period, \
-           default_MaxRate, \
-           default_Maxi2Rate, \
-           default_MinRate, \
-           default_MaxKByte,\
-           default_ThreshKByte,\
+        default_MaxRate, \
+        default_Maxi2Rate, \
+        default_MinRate, \
+        default_MaxKByte,\
+        default_ThreshKByte,\
         default_Maxi2KByte,\
         default_Threshi2KByte,\
-        default_Share
+        default_Share,\
+        verbose
 
+    verbose = True
     # All slices
     names = []
 
     try:
         f = open(datafile, "r+")
         if verbose:
-            print "Loading %s" % datafile
+            logger.log("bwmon:  Loading %s" % datafile)
         (version, slices) = pickle.load(f)
         f.close()
         # Check version of data file
-        if version != "$Id: bwmon.py,v 1.2 2007/02/07 18:12:02 faiyaza Exp $":
-            print "Not using old version '%s' data file %s" % (version, datafile)
+        if version != "$Id$":
+            logger.log("bwmon:  Not using old version '%s' data file %s" % (version, datafile))
             raise Exception
     except Exception:
-        version = "$Id: bwmon.py,v 1.2 2007/02/07 18:12:02 faiyaza Exp $"
+        version = "$Id$"
         slices = {}
 
-    # Get special slice IDs
+    # Get/set special slice IDs
     root_xid = bwlimit.get_xid("root")
     default_xid = bwlimit.get_xid("default")
 
-    live = []
-    # Get actuall running values from tc.
+    if root_xid not in slices.keys():
+        slices[root_xid] = Slice(root_xid, "root", data)
+        slices[root_xid].reset(0, 0, 0, 0, data)
+
+    if default_xid not in slices.keys():
+        slices[default_xid] = Slice(default_xid, "default", data)
+        slices[default_xid].reset(0, 0, 0, 0, data)
+
+    live = {}
+    # Get running slivers. {xid: name}
+    for sliver in data['slivers']:
+        live[bwlimit.get_xid(sliver['name'])] = sliver['name']
+
+    # Setup new slices.
+    # live.xids - runing.xids = new.xids
+    newslicesxids = Set(live.keys()) - Set(slices.keys())
+    for newslicexid in newslicesxids:
+        if newslicexid != None:
+            logger.log("bwmon: New Slice %s" % live[newslicexid])
+            slices[newslicexid] = Slice(newslicexid, live[newslicexid], data)
+            slices[newslicexid].reset(0, 0, 0, 0, data)
+        else:
+            logger.log("bwmon  Slice %s doesn't have xid.  Must be delegated.  Skipping." % live[newslicexid])
+    # Get actual running values from tc.
+    # Update slice totals and bandwidth.
     for params in bwlimit.get():
         (xid, share,
          minrate, maxrate,
          minexemptrate, maxexemptrate,
-         bytes, i2bytes) = params
-        live.append(xid)
-
+         usedbytes, usedi2bytes) = params
+        
         # Ignore root and default buckets
         if xid == root_xid or xid == default_xid:
             continue
@@ -325,40 +462,44 @@ def GetSlivers(data):
         if slices.has_key(xid):
             slice = slices[xid]
             if time.time() >= (slice.time + period) or \
-               bytes < slice.bytes or i2bytes < slice.i2bytes:
+               usedbytes < slice.bytes or usedi2bytes < slice.i2bytes:
                 # Reset to defaults every 24 hours or if it appears
                 # that the byte counters have overflowed (or, more
                 # likely, the node was restarted or the HTB buckets
                 # were re-initialized).
-                slice.reset(maxrate, maxexemptrate, bytes, i2bytes, data)
+                slice.reset(maxrate, maxexemptrate, usedbytes, usedi2bytes, data)
             else:
                 # Update byte counts
-                slice.update(maxrate, maxexemptrate, bytes, i2bytes, data)
+                slice.update(maxrate, maxexemptrate, usedbytes, usedi2bytes, data)
         else:
+            # Just in case.  Probably (hopefully) this will never happen.
             # New slice, initialize state
-            slice = slices[xid] = Slice(xid, name, maxrate, maxexemptrate, bytes, i2bytes, data)
+            if verbose:
+                logger.log("bwmon: New Slice %s" % name)
+            slice = slices[xid] = Slice(xid, name, data)
+            slice.reset(maxrate, maxexemptrate, usedbytes, usedi2bytes, data)
 
     # Delete dead slices
-    dead = Set(slices.keys()) - Set(live)
+    dead = Set(slices.keys()) - Set(live.keys())
     for xid in dead:
+        if xid == root_xid or xid == default_xid:
+            continue
         del slices[xid]
         bwlimit.off(xid)
 
-    print "Saving %s" % datafile
+    logger.log("bwmon:  Saving %s" % datafile)
     f = open(datafile, "w")
     pickle.dump((version, slices), f)
     f.close()
 
 
 #def GetSlivers(data):
-#    for sliver in data['slivers']:
-#        if sliver.has_key('attributes'):
-#           print sliver
-#            for attribute in sliver['attributes']:
-#                if attribute['name'] == "KByteThresh": print attribute['value']
+#   for sliver in data['slivers']:
+#       if sliver.has_key('attributes'):
+#          print sliver
+#           for attribute in sliver['attributes']:
+#               if attribute['name'] == "KByteThresh": print attribute['value']
 
 def start(options, config):
     pass
 
-if __name__ == '__main__':
-    main()
index bb0942b..73a0743 100644 (file)
@@ -10,7 +10,7 @@ class Delegate(accounts.Account):
     TYPE = 'delegate'
 
     @staticmethod
-    def create(name):
+    def create(name, vref = None):
         add_shell(Delegate.SHELL)
         logger.log_call('/usr/sbin/useradd', '-p', '*', '-s', Delegate.SHELL, name)
 
diff --git a/net.py b/net.py
index cd71fe9..9db7f73 100644 (file)
--- a/net.py
+++ b/net.py
@@ -3,8 +3,13 @@
 import sioc
 import bwlimit
 import logger
+import string
 
-def GetSlivers(data):
+def GetSlivers(plc, data):
+    InitNodeLimit(data)
+    InitI2(plc, data)
+
+def InitNodeLimit(data):
     # query running network interfaces
     devs = sioc.gifconf()
     ips = dict(zip(devs.values(), devs.keys()))
@@ -14,16 +19,15 @@ def GetSlivers(data):
 
     # XXX Exempt Internet2 destinations from node bwlimits
     # bwlimit.exempt_init('Internet2', internet2_ips)
-
     for network in data['networks']:
         # Get interface name preferably from MAC address, falling
         # back on IP address.
-        if macs.has_key(network['mac'].lower()):
+        if macs.has_key(network['mac']):
             dev = macs[network['mac'].lower()]
         elif ips.has_key(network['ip']):
             dev = ips[network['ip']]
         else:
-            logger.log('%s: no such interface with address %s/%s' % (self.name, network['ip'], network['mac']))
+            logger.log('%s: no such interface with address %s/%s' % (network['hostname'], network['ip'], network['mac']))
             continue
 
         # Get current node cap
@@ -46,5 +50,14 @@ def GetSlivers(data):
             # some previously invalid sliver bwlimit is now valid
             # again, or vice-versa.
 
+def InitI2(plc, data):
+    if "Internet2" in data['groups']:
+        logger.log("This is an Internet2 node.  Setting rules.")
+        i2nodes = []
+        i2nodeids = plc.GetNodeGroups(["Internet2"])[0]['node_ids']
+        for node in plc.GetNodeNetworks({"node_id": i2nodeids}, ["ip"]):
+            i2nodes.append(node['ip'])
+        bwlimit.exempt_init('Internet2', i2nodes)
+
 def start(options, config):
     pass
diff --git a/nm.py b/nm.py
index 6e56501..c4760fc 100644 (file)
--- a/nm.py
+++ b/nm.py
@@ -14,7 +14,7 @@ import logger
 import tools
 
 from config import Config
-from plcapi import PLCAPI
+from plcapi import PLCAPI 
 
 
 savedargv = sys.argv[:]
@@ -31,9 +31,13 @@ modules = []
 
 def GetSlivers(plc):
     data = plc.GetSlivers()
+    # net needs access to API for i2 nodes.
     for module in modules:
-        callback = getattr(module, 'GetSlivers')
-        callback(data)
+        if module.__name__ == 'net':
+            module.GetSlivers(plc, data)
+        else:
+            callback = getattr(module, 'GetSlivers')
+            callback(data)
 
 def run():
     try:
@@ -51,7 +55,7 @@ def run():
             print "Warning while writing PID file:", err
 
         # Load and start modules
-        for module in ['net', 'proper', 'conf_files', 'sm']:
+        for module in ['net', 'proper', 'conf_files', 'sm', 'bwmon']:
             try:
                 m = __import__(module)
                 m.start(options, config)
index 824a604..333bf63 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id: setup.py,v 1.3 2006/11/27 22:42:48 mlhuang Exp $
+# $Id$
 #
 
 from distutils.core import setup, Extension
@@ -32,6 +32,7 @@ setup(
     'sm',
     'ticket',
     'tools',
+       'bwmon'
     ],
     scripts = [
     'forward_api_calls',
index e4c438c..ce7a5cb 100644 (file)
@@ -118,14 +118,14 @@ class Sliver_VS(accounts.Account, vserver.VServer):
 
         # N.B. net_*_rate are in kbps because of XML-RPC maxint
         # limitations, convert to bps which is what bwlimit.py expects.
-        net_limits = (self.rspec['net_min_rate'] * 1000,
-                      self.rspec['net_max_rate'] * 1000,
-                      self.rspec['net_i2_min_rate'] * 1000,
-                      self.rspec['net_i2_max_rate'] * 1000,
-                      self.rspec['net_share'])
-        logger.log('%s: setting net limits to %s bps' % (self.name, net_limits[:-1]))
-        logger.log('%s: setting net share to %d' % (self.name, net_limits[-1]))
-        self.set_bwlimit(*net_limits)
+#        net_limits = (self.rspec['net_min_rate'] * 1000,
+#                      self.rspec['net_max_rate'] * 1000,
+#                      self.rspec['net_i2_min_rate'] * 1000,
+#                      self.rspec['net_i2_max_rate'] * 1000,
+#                      self.rspec['net_share'])
+#        logger.log('%s: setting net limits to %s bps' % (self.name, net_limits[:-1]))
+#        logger.log('%s: setting net share to %d' % (self.name, net_limits[-1]))
+#        self.set_bwlimit(*net_limits)
 
         cpu_min = self.rspec['cpu_min']
         cpu_share = self.rspec['cpu_share']
diff --git a/sm.py b/sm.py
index 956a11e..680120c 100644 (file)
--- a/sm.py
+++ b/sm.py
@@ -57,6 +57,17 @@ def GetSlivers(data, fullupdate=True):
             if network['is_primary'] and network['bwlimit'] is not None:
                 DEFAULT_ALLOCATION['net_max_rate'] = network['bwlimit'] / 1000
 
+### Emulab-specific hack begins here
+    emulabdelegate = {
+        'instantiation': 'plc-instantiated',
+        'keys': '''ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA5Rimz6osRvlAUcaxe0YNfGsLL4XYBN6H30V3l/0alZOSXbGOgWNdEEdohwbh9E8oYgnpdEs41215UFHpj7EiRudu8Nm9mBI51ARHA6qF6RN+hQxMCB/Pxy08jDDBOGPefINq3VI2DRzxL1QyiTX0jESovrJzHGLxFTB3Zs+Y6CgmXcnI9i9t/zVq6XUAeUWeeXA9ADrKJdav0SxcWSg+B6F1uUcfUd5AHg7RoaccTldy146iF8xvnZw0CfGRCq2+95AU9rbMYS6Vid8Sm+NS+VLaAyJaslzfW+CAVBcywCOlQNbLuvNmL82exzgtl6fVzutRFYLlFDwEM2D2yvg4BQ== root@boss.emulab.net''',
+        'name': 'utah_elab_delegate',
+        'timestamp': data['timestamp'],
+        'type': 'delegate',
+        'vref': None
+        }
+    database.db.deliver_record(emulabdelegate)
+### Emulab-specific hack ends here
     for sliver in data['slivers']:
         rec = sliver.copy()
         rec.setdefault('timestamp', data['timestamp'])