oops, too much messing about
[nodemanager.git] / database.py
index eaf78d4..2c4dc49 100644 (file)
@@ -1,6 +1,4 @@
-# $Id$
-# $URL$
-
+#
 """The database houses information on slivers.  This information
 reaches the sliver manager in two different ways: one, through the
 GetSlivers() call made periodically; two, by users delivering tickets.
@@ -15,28 +13,35 @@ In order to maintain service when the node reboots during a network
 partition, the database is constantly being dumped to disk.
 """
 
+import sys
+
 import cPickle
 import threading
 import time
 
-import accounts
+import account
 import logger
 import tools
 import bwmon
 
+# hopefully temporary
+# is there a good reason to have this done here and not in a plugin ?
+try:    from coresched_lxc import CoreSched
+except: from coresched_vs  import CoreSched
+
 # We enforce minimum allocations to keep the clueless from hosing their slivers.
 # Disallow disk loans because there's currently no way to punish slivers over quota.
-MINIMUM_ALLOCATION = {'cpu_pct': 0, 
-                      'cpu_share': 1, 
-                      'net_min_rate': 0, 
-                      'net_max_rate': 8, 
-                      'net_i2_min_rate': 0, 
-                      'net_i2_max_rate': 8, 
+MINIMUM_ALLOCATION = {'cpu_pct': 0,
+                      'cpu_share': 1,
+                      'net_min_rate': 0,
+                      'net_max_rate': 8,
+                      'net_i2_min_rate': 0,
+                      'net_i2_max_rate': 8,
                       'net_share': 1,
                       }
 LOANABLE_RESOURCES = MINIMUM_ALLOCATION.keys()
 
-DB_FILE = '/var/lib/nodemanager/nodemanager.pickle'
+DB_FILE = '/var/lib/nodemanager/database.pickle'
 
 
 # database object and associated lock
@@ -64,12 +69,12 @@ class Database(dict):
         self._min_timestamp = 0
 
     def _compute_effective_rspecs(self):
-        """Calculate the effects of loans and store the result in field _rspec. 
+        """Calculate the effects of loans and store the result in field _rspec.
 At the moment, we allow slivers to loan only those resources that they have received directly from PLC.
-In order to do the accounting, we store three different rspecs: 
- * field 'rspec', which is the resources given by PLC; 
- * field '_rspec', which is the actual amount of resources the sliver has after all loans; 
- * and variable resid_rspec, which is the amount of resources the sliver 
+In order to do the accounting, we store three different rspecs:
+ * field 'rspec', which is the resources given by PLC;
+ * field '_rspec', which is the actual amount of resources the sliver has after all loans;
+ * and variable resid_rspec, which is the amount of resources the sliver
    has after giving out loans but not receiving any."""
         slivers = {}
         for name, rec in self.iteritems():
@@ -100,8 +105,8 @@ keys."""
             old_rec.update(rec)
 
     def set_min_timestamp(self, ts):
-        """The ._min_timestamp member is the timestamp on the last comprehensive update.  
-We use it to determine if a record is stale.  
+        """The ._min_timestamp member is the timestamp on the last comprehensive update.
+We use it to determine if a record is stale.
 This method should be called whenever new GetSlivers() data comes in."""
         self._min_timestamp = ts
         for name, rec in self.items():
@@ -120,33 +125,41 @@ It may be necessary in the future to do something smarter."""
 
         self._compute_effective_rspecs()
 
+        try:
+            coresched = CoreSched()
+            coresched.adjustCores(self)
+        except:
+            logger.log_exc("database: exception while doing core sched")
+
         # create and destroy accounts as needed
         logger.verbose("database: sync : fetching accounts")
-        existing_acct_names = accounts.all()
+        existing_acct_names = account.all()
         for name in existing_acct_names:
-            if name not in self: 
+            if name not in self:
                 logger.verbose("database: sync : ensure_destroy'ing %s"%name)
-                accounts.get(name).ensure_destroyed()
+                account.get(name).ensure_destroyed()
         for name, rec in self.iteritems():
-            # protect this; if anything fails for a given sliver 
+            # protect this; if anything fails for a given sliver
             # we still need the other ones to be handled
             try:
-                sliver = accounts.get(name)
+                sliver = account.get(name)
                 logger.verbose("database: sync : looping on %s (shell account class from pwd %s)" %(name,sliver._get_class()))
                 # Make sure we refresh accounts that are running
-                if rec['instantiation'] == 'plc-instantiated': 
+                if rec['instantiation'] == 'plc-instantiated':
                     logger.verbose ("database: sync : ensure_create'ing 'instantiation' sliver %s"%name)
                     sliver.ensure_created(rec)
-                elif rec['instantiation'] == 'nm-controller': 
+                elif rec['instantiation'] == 'nm-controller':
                     logger.verbose ("database: sync : ensure_create'ing 'nm-controller' sliver %s"%name)
                     sliver.ensure_created(rec)
                 # Back door to ensure PLC overrides Ticket in delegation.
                 elif rec['instantiation'] == 'delegated' and sliver._get_class() != None:
                     # if the ticket has been delivered and the nm-controller started the slice
                     # update rspecs and keep them up to date.
-                    if sliver.is_running(): 
+                    if sliver.is_running():
                         logger.verbose ("database: sync : ensure_create'ing 'delegated' sliver %s"%name)
                         sliver.ensure_created(rec)
+            except SystemExit as e:
+                sys.exit(e)
             except:
                 logger.log_exc("database: sync failed to handle sliver",name=name)
 
@@ -169,8 +182,11 @@ It proceeds to handle dump requests forever."""
             db_pickle = cPickle.dumps(db, cPickle.HIGHEST_PROTOCOL)
             dump_requested = False
             db_lock.release()
-            try: tools.write_file(DB_FILE, lambda f: f.write(db_pickle))
-            except: logger.log_exc("database: failed in database.start.run")
+            try:
+                tools.write_file(DB_FILE, lambda f: f.write(db_pickle))
+                logger.log_database(db)
+            except:
+                logger.log_exc("database.start: failed to pickle/dump")
     global db
     try:
         f = open(DB_FILE)
@@ -182,4 +198,5 @@ It proceeds to handle dump requests forever."""
     except:
         logger.log_exc("database: failed in start")
         db = Database()
+    logger.log('database.start')
     tools.as_daemon_thread(run)