* Merge with head. Incorporates fix for NM fork bombing, and bw min limits.
authorFaiyaz Ahmed <faiyaza@cs.princeton.edu>
Tue, 27 Feb 2007 23:13:09 +0000 (23:13 +0000)
committerFaiyaz Ahmed <faiyaza@cs.princeton.edu>
Tue, 27 Feb 2007 23:13:09 +0000 (23:13 +0000)
NodeManager.spec
api.py
bwmon.py
sliver_vs.py

index 1c1fb34..be0a0a7 100644 (file)
@@ -1,7 +1,7 @@
 Summary: PlanetLab Node Manager
 Name: NodeManager
-Version: 1.2
-Release: 1%{?pldistro:.%{pldistro}}%{?date:.%{date}}
+Version: 1.1
+Release: 2%{?pldistro:.%{pldistro}}%{?date:.%{date}}
 License: PlanetLab
 Group: System Environment/Daemons
 URL: http://cvs.planet-lab.org/cvs/NodeManager
diff --git a/api.py b/api.py
index 5c4ab4a..6baaf3e 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'] or (caller_name == 'utah_elab_delegate' and target_name.startswith('utah_elab_'))): 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_'))): raise xmlrpclib.Fault(108, 'Permission denied.')
                 result = method(target_rec, *args[1:])
             else: result = method(*args)
             if result == None: result = 1
index 68a118c..31eebd5 100644 (file)
--- a/bwmon.py
+++ b/bwmon.py
@@ -22,7 +22,6 @@ import os
 import sys
 import time
 import pickle
-import database
 
 import socket
 #import xmlrpclib
@@ -49,8 +48,8 @@ seconds_per_day = 24 * 60 * 60
 bits_per_byte = 8
 
 # Defaults
-debug = False
-verbose = 0
+debug = False 
+verbose = False
 datafile = "/var/lib/misc/bwmon.dat"
 #nm = None
 
@@ -213,15 +212,18 @@ class Slice:
     def __repr__(self):
         return self.name
 
-    @database.synchronized
     def updateSliceAttributes(self, data):
         for sliver in data['slivers']:
             if sliver['name'] == self.name: 
                 for attribute in sliver['attributes']:
                     if attribute['name'] == 'net_min_rate':     
-                        self.MinRate = int(attribute['value'])
                         logger.log("bwmon:  Updating %s. Min Rate = %s" \
                           %(self.name, self.MinRate))
+                        # To ensure min does not go above 25% of nodecap.
+                        if int(attribute['value']) > int(.25 * default_MaxRate):
+                            self.MinRate = int(.25 * default_MaxRate)
+                        else:    
+                            self.MinRate = int(attribute['value'])
                     elif attribute['name'] == 'net_max_rate':       
                         self.MaxRate = int(attribute['value'])
                         logger.log("bwmon:  Updating %s. Max Rate = %s" \
@@ -315,15 +317,14 @@ class Slice:
             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
+            if new_maxrate < (self.MinRate * 1000):
+                new_maxrate = self.MinRate * 1000
         else:
             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 * 1024)
         params['new_maxrate'] = bwlimit.format_tc_rate(new_maxrate)
 
@@ -335,22 +336,21 @@ class Slice:
         # Cap low bandwidth burst rate
         if new_maxrate != runningmaxrate:
             message += template % params
-            logger.log("bwmon:      %(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.Threshi2KByte * 1024)):
             maxi2byte = self.Maxi2KByte * 1024
             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
+            if new_maxi2rate < (self.Mini2Rate * 1000):
+                new_maxi2rate = self.Mini2Rate * 1000
         else:
             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 * 1024)
         params['new_maxexemptrate'] = bwlimit.format_tc_rate(new_maxi2rate)
 
@@ -391,14 +391,12 @@ def GetSlivers(data):
         default_Share,\
         verbose
 
-    verbose = True
     # All slices
     names = []
 
     try:
         f = open(datafile, "r+")
-        if verbose:
-            logger.log("bwmon:  Loading %s" % datafile)
+        logger.log("bwmon:  Loading %s" % datafile)
         (version, slices) = pickle.load(f)
         f.close()
         # Check version of data file
@@ -474,8 +472,7 @@ def GetSlivers(data):
         else:
             # Just in case.  Probably (hopefully) this will never happen.
             # New slice, initialize state
-            if verbose:
-                logger.log("bwmon: New Slice %s" % name)
+            logger.log("bwmon: New Slice %s" % name)
             slice = slices[xid] = Slice(xid, name, data)
             slice.reset(maxrate, maxexemptrate, usedbytes, usedi2bytes, data)
 
index ce7a5cb..e2e77f8 100644 (file)
@@ -85,11 +85,11 @@ class Sliver_VS(accounts.Account, vserver.VServer):
     def start(self, delay=0):
         if self.rspec['enabled']:
             logger.log('%s: starting in %d seconds' % (self.name, delay))
+            time.sleep(delay)
             child_pid = os.fork()
             if child_pid == 0:
                 # VServer.start calls fork() internally, so just close the nonstandard fds and fork once to avoid creating zombies
                 tools.close_nonstandard_fds()
-                time.sleep(delay)
                 vserver.VServer.start(self, True)
                 os._exit(0)
             else: os.waitpid(child_pid, 0)