Setting tag nodemanager-2.0-27
[nodemanager.git] / accounts.py
index f07cb19..59ecedb 100644 (file)
@@ -3,10 +3,12 @@
 
 """Functionality common to all account classes.
 
 
 """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
-things like set up ssh keys.  In addition, an Account subclass must
+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
+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
 code.  For no particular reason, TYPE is divided hierarchically by
 provide static member variables SHELL, which contains the unique shell
 that it uses; and TYPE, a string that is used by the account creation
 code.  For no particular reason, TYPE is divided hierarchically by
@@ -23,18 +25,14 @@ numbers of accounts, this may cause the NM process to run out of
 maximum stack size.
 """
 
 maximum stack size.
 """
 
-import Queue
 import os
 import os
-import pwd
-import grp
+import pwd, grp
 import threading
 
 import logger
 import tools
 
 
 import threading
 
 import logger
 import tools
 
 
-# When this variable is true, start after any ensure_created
-Startingup = False
 # shell path -> account class association
 shell_acct_class = {}
 # account type -> account class association
 # shell path -> account class association
 shell_acct_class = {}
 # account type -> account class association
@@ -45,7 +43,9 @@ create_sem = threading.Semaphore(1)
 destroy_sem = threading.Semaphore(1)
 
 def register_class(acct_class):
 destroy_sem = threading.Semaphore(1)
 
 def register_class(acct_class):
-    """Call once for each account class.  This method adds the class to the dictionaries used to look up account classes by shell and type."""
+    """Call once for each account class. This method adds the class
+to the dictionaries used to look up account classes by shell and
+type."""
     shell_acct_class[acct_class.SHELL] = acct_class
     type_acct_class[acct_class.TYPE] = acct_class
 
     shell_acct_class[acct_class.SHELL] = acct_class
     type_acct_class[acct_class.TYPE] = acct_class
 
@@ -75,11 +75,11 @@ class Account:
         logger.verbose('accounts: Initing account %s'%rec['name'])
         self.name = rec['name']
         self.keys = ''
         logger.verbose('accounts: Initing account %s'%rec['name'])
         self.name = rec['name']
         self.keys = ''
-        self.initscriptchanged = False
         self.configure(rec)
 
     @staticmethod
     def create(name, vref = None): abstract
         self.configure(rec)
 
     @staticmethod
     def create(name, vref = None): abstract
+
     @staticmethod
     def destroy(name): abstract
 
     @staticmethod
     def destroy(name): abstract
 
@@ -123,13 +123,16 @@ class Account:
     def is_running(self): pass
 
 class Worker:
     def is_running(self): pass
 
 class Worker:
+
     def __init__(self, name):
         self.name = name  # username
         self._acct = None  # the account object currently associated with this worker
 
     def __init__(self, name):
         self.name = name  # username
         self._acct = None  # the account object currently associated with this worker
 
-    def ensure_created(self, rec, startingup = Startingup):
-        """Check account type is still valid.  If not, recreate sliver.  If still valid,
-        check if running and configure/start if not."""
+    def ensure_created(self, rec):
+        """Check account type is still valid.  If not, recreate sliver.
+If still valid, check if running and configure/start if not."""
+        logger.log_data_in_file(rec,"/var/lib/nodemanager/%s.rec.txt"%rec['name'],
+                                'raw rec captured in ensure_created',logger.LOG_VERBOSE)
         curr_class = self._get_class()
         next_class = type_acct_class[rec['type']]
         if next_class != curr_class:
         curr_class = self._get_class()
         next_class = type_acct_class[rec['type']]
         if next_class != curr_class:
@@ -138,22 +141,38 @@ class Worker:
             try: next_class.create(self.name, rec['vref'])
             finally: create_sem.release()
         if not isinstance(self._acct, next_class): self._acct = next_class(rec)
             try: next_class.create(self.name, rec['vref'])
             finally: create_sem.release()
         if not isinstance(self._acct, next_class): self._acct = next_class(rec)
-        if startingup or \
-          not self.is_running() or \
-          next_class != curr_class or \
-          self._acct.initscriptchanged:
-            self.start(rec)
-        else: self._acct.configure(rec)
+        logger.verbose("accounts.ensure_created: %s, running=%r"%(self.name,self.is_running()))
+
+        # reservation_alive is set on reervable nodes, and its value is a boolean
+        if 'reservation_alive' in rec:
+            # reservable nodes
+            if rec['reservation_alive']:
+                # this sliver has the lease, it is safe to start it
+                if not self.is_running(): self.start(rec)
+                else: self.configure(rec)
+            else:
+                # not having the lease, do not start it
+                self.configure(rec)
+        # usual nodes - preserve old code
+        # xxx it's not clear what to do when a sliver changes type/class
+        # in a reservable node
+        else:
+            if not self.is_running() or next_class != curr_class:
+                self.start(rec)
+            else: self.configure(rec)
 
     def ensure_destroyed(self): self._destroy(self._get_class())
 
 
     def ensure_destroyed(self): self._destroy(self._get_class())
 
-    def start(self, rec, d = 0): 
+    def start(self, rec, d = 0):
         self._acct.configure(rec)
         self._acct.start(delay=d)
 
         self._acct.configure(rec)
         self._acct.start(delay=d)
 
+    def configure(self, rec):
+        self._acct.configure(rec)
+
     def stop(self): self._acct.stop()
 
     def stop(self): self._acct.stop()
 
-    def is_running(self): 
+    def is_running(self):
         if (self._acct != None) and self._acct.is_running():
             status = True
         else:
         if (self._acct != None) and self._acct.is_running():
             status = True
         else: