Merge from branch.
authorFaiyaz Ahmed <faiyaza@cs.princeton.edu>
Mon, 16 Feb 2009 20:14:44 +0000 (20:14 +0000)
committerFaiyaz Ahmed <faiyaza@cs.princeton.edu>
Mon, 16 Feb 2009 20:14:44 +0000 (20:14 +0000)
*  Changes delegate class to controller
*  Adds ability to disable HTBs
*  fixes bug in nm.py when API is unavailable.
*  adds sysctl slice attribute

LICENSE
accounts.py
bwmon.py
net.py
nm.py
setup.py
sm.py

diff --git a/LICENSE b/LICENSE
index 4a80642..8443213 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright 2008 Princeton University
+Copyright 2009 Princeton University
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
index 6bffdbe..d540368 100644 (file)
@@ -1,8 +1,8 @@
 """Functionality common to all account classes.
 
-Each subclass of Account must provide five methods: create() and
-destroy(), which are static; configure(), start(), and stop(), which
-are not.  configure(), which takes a record as its only argument, does
+Each subclass of Account must provide 6 methods: create() and
+destroy(), which are static; configure(), is_running(), start(), and stop(),
+which are not.  configure() takes a record as its only argument, and does
 things like set up ssh keys.  In addition, an Account subclass must
 provide static member variables SHELL, which contains the unique shell
 that it uses; and TYPE, a string that is used by the account creation
@@ -41,7 +41,6 @@ def register_class(acct_class):
 
 # private account name -> worker object association and associated lock
 name_worker_lock = threading.Lock()
-# dict of account_name: <Worker Object>
 name_worker = {}
 
 def allpwents():
@@ -55,9 +54,7 @@ def get(name):
     """Return the worker object for a particular username.  If no such object exists, create it first."""
     name_worker_lock.acquire()
     try:
-        if name not in name_worker: 
-            logger.verbose("Accounts:get(%s) new Worker" % name)
-            name_worker[name] = Worker(name)
+        if name not in name_worker: name_worker[name] = Worker(name)
         return name_worker[name]
     finally: name_worker_lock.release()
 
@@ -127,7 +124,7 @@ class Worker:
     def stop(self): self._acct.stop()
 
     def is_running(self): 
-        if self._acct.is_running():
+        if (self._acct != None) and self._acct.is_running():
             status = True
         else:
             status = False
index 38a70cc..be146f6 100644 (file)
--- a/bwmon.py
+++ b/bwmon.py
@@ -662,7 +662,10 @@ def getDefaults(nmdbcopy):
 
 
 def allOff():
-   # Get/set special slice IDs
+    """
+    Turn off all slice HTBs
+    """
+    # Get/set special slice IDs
     root_xid = bwlimit.get_xid("root")
     default_xid = bwlimit.get_xid("default")
     kernelhtbs = gethtbs(root_xid, default_xid)
@@ -674,9 +677,9 @@ def allOff():
 lock = threading.Event()
 def run():
     """
-       When run as a thread, wait for event, lock db, deep copy it, release it, 
-       run bwmon.GetSlivers(), then go back to waiting.
-       """
+    When run as a thread, wait for event, lock db, deep copy it, release it, 
+    run bwmon.GetSlivers(), then go back to waiting.
+    """
     logger.log("bwmon:  Thread started", 2)
     while True:
         lock.wait()
@@ -685,8 +688,10 @@ def run():
         nmdbcopy = copy.deepcopy(database.db)
         database.db_lock.release()
         try:  
-                       if getDefaults(nmdbcopy): sync(nmdbcopy)
-                       else: logger.log("bwmon:  DISABLED.")
+            if getDefaults(nmdbcopy) and len(bwlimit.tc("class show dev eth0")) > 0:
+                # class show to check if net:InitNodeLimit:bwlimit.init has run.
+                sync(nmdbcopy)
+            else: logger.log("bwmon:  BW limits DISABLED.")
         except: logger.log_exc()
         lock.clear()
 
diff --git a/net.py b/net.py
index bb60f1f..810490c 100644 (file)
--- a/net.py
+++ b/net.py
@@ -3,20 +3,33 @@
 #
 """network configuration"""
 
-import sioc
-import bwlimit
-import logger
-import string
-import iptables
-import os
-import plnet
-
-def GetSlivers(plc, data):
-    InitInterfaces(plc, data)
-    InitNodeLimit(data)
-    InitI2(plc, data)
+# system provided modules
+import os, string, time, socket
+
+# PlanetLab system modules
+import sioc, plnet
+
+# local modules
+import bwlimit, logger, iptables
+
+def GetSlivers(plc, data, config):
+    logger.verbose("net:GetSlivers called.")
+    InitInterfaces(plc, data) # writes sysconfig files.
+    if 'OVERRIDES' in dir(config):
+        if config.OVERRIDES.get('net_max_rate') == '-1':
+            logger.log("net: Slice and node BW Limits disabled.")
+            if len(bwlimit.tc("class show dev eth0")):
+                logger.verbose("*** DISABLING NODE BW LIMITS ***")
+                bwlimit.stop()
+        else:
+            InitNodeLimit(data)
+            InitI2(plc, data)
+    else:
+        InitNodeLimit(data)
+        InitI2(plc, data)
     InitNAT(plc, data)
 
+
 def InitNodeLimit(data):
     # query running network interfaces
     devs = sioc.gifconf()
diff --git a/nm.py b/nm.py
index 304db42..e9ca6d6 100755 (executable)
--- a/nm.py
+++ b/nm.py
@@ -50,18 +50,21 @@ if os.path.exists(options.path):
 
 modules = []
 
-def GetSlivers(plc):
+def GetSlivers(plc, config):
     '''Run call backs defined in modules'''
     try: 
         logger.log("Syncing w/ PLC")
         data = plc.GetSlivers()
+        getPLCDefaults(data, config)
+        if (options.verbose): logger.log_slivers(data)
     except: 
         logger.log_exc()
         #  XXX So some modules can at least boostrap.
+        logger.log("nm:  Can't contact PLC to GetSlivers().  Continuing.")
         data = {}
-    logger.log_slivers(data)
-    # Set i2 ip list for nodes in I2 nodegroup.
-    try: net.GetSlivers(plc, data)
+    # Set i2 ip list for nodes in I2 nodegroup
+    # and init network interfaces (unless overridden)
+    try: net.GetSlivers(plc, data, config) # TODO - num of args needs to be unified across mods.
     except: logger.log_exc()
     #  All other callback modules
     for module in modules:
@@ -70,6 +73,22 @@ def GetSlivers(plc):
             callback(data)
         except: logger.log_exc()
 
+
+def getPLCDefaults(data, config):
+    '''
+    Get PLC wide defaults from _default system slice.  Adds them to config class.
+    '''
+    for slice in data.get('slivers'): 
+        if slice['name'] == config.PLC_SLICE_PREFIX+"_default":
+            attr_dict = {}
+            for attr in slice.get('attributes'): attr_dict[attr['name']] = attr['value'] 
+            if len(attr_dict):
+                logger.verbose("Found default slice overrides.\n %s" % attr_dict)
+                config.OVERRIDES = attr_dict
+            return 
+    if 'OVERRIDES' in dir(config): del config.OVERRIDES
+
+
 def run():
     try:
         if options.daemon: tools.daemon()
@@ -118,7 +137,7 @@ def run():
         while True:
         # Main NM Loop
             logger.verbose('mainloop - nm:getSlivers - period=%d random=%d'%(iperiod,irandom))
-            GetSlivers(plc)
+            GetSlivers(plc, config)
             delay=iperiod + random.randrange(0,irandom)
             logger.verbose('mainloop - sleeping for %d s'%delay)
             time.sleep(delay)
index 8d00d1f..4e06e3e 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -18,8 +18,8 @@ setup(
         'bwmon',
         'conf_files',
         'config',
-        'curlwrapper',
         'controller',
+        'curlwrapper',
         'database',
         'iptables',
         'logger',
diff --git a/sm.py b/sm.py
index 881b05e..62e49d1 100644 (file)
--- a/sm.py
+++ b/sm.py
@@ -97,6 +97,9 @@ def GetSlivers(data, fullupdate=True):
         keys = rec.pop('keys')
         rec.setdefault('keys', '\n'.join([key_struct['key'] for key_struct in keys]))
 
+        ## 'Type' isn't returned by GetSlivers() for whatever reason.  We're overloading
+        ## instantiation here, but i suppose its the ssame thing when you think about it. -FA
+        # Handle nm controller here
         if rec['instantiation'].lower() == 'nm-controller': 
             rec.setdefault('type', attr_dict.get('type', 'controller.Controller'))
         else:
@@ -125,6 +128,11 @@ def GetSlivers(data, fullupdate=True):
             except (KeyError, ValueError): amt = default_amt
             rspec[resname] = amt
 
+        # add in sysctl attributes into the rspec
+        for key in attr_dict.keys():
+            if key.find("sysctl.") == 0:
+                rspec[key] = attr_dict[key]
+
         database.db.deliver_record(rec)
     if fullupdate: database.db.set_min_timestamp(data['timestamp'])
     # slivers are created here.