X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=accounts.py;h=180a7389e43743a0a8a9fd618db30a0a05ad8bdb;hb=06cc8f49edbf66652df3949c2f24ff698edd81cb;hp=6bffdbe8ae725061ee626f7cf08245b96910052f;hpb=abe5b6479e9964d43166d731a04beac83c9d34c5;p=nodemanager.git diff --git a/accounts.py b/accounts.py index 6bffdbe..180a738 100644 --- a/accounts.py +++ b/accounts.py @@ -10,12 +10,20 @@ code. For no particular reason, TYPE is divided hierarchically by periods; at the moment the only convention is that all sliver accounts have type that begins with sliver. +There are any number of race conditions that may result from the fact +that account names are not unique over time. Moreover, it's a bad +idea to perform lengthy operations while holding the database lock. +In order to deal with both of these problems, we use a worker thread +for each account name that ever exists. On 32-bit systems with large +numbers of accounts, this may cause the NM process to run out of +*virtual* memory! This problem may be remedied by decreasing the +maximum stack size. """ import Queue import os import pwd -from grp import getgrnam +import grp import threading import logger @@ -41,7 +49,6 @@ def register_class(acct_class): # private account name -> worker object association and associated lock name_worker_lock = threading.Lock() -# dict of account_name: name_worker = {} def allpwents(): @@ -55,9 +62,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() @@ -81,15 +86,24 @@ class Account: new_keys = rec['keys'] if new_keys != self.keys: self.keys = new_keys - dot_ssh = '/home/%s/.ssh' % self.name + gid = grp.getgrnam("slices")[2] + pw_info = pwd.getpwnam(self.name) + uid = pw_info[2] + pw_dir = pw_info[5] + + dot_ssh = pw_dir + '/.ssh' if not os.access(dot_ssh, os.F_OK): os.mkdir(dot_ssh) + + auth_keys = dot_ssh + '/authorized_keys' + tools.write_file(auth_keys, lambda f: f.write(new_keys)) + os.chmod(dot_ssh, 0700) - tools.write_file(dot_ssh + '/authorized_keys', lambda f: f.write(new_keys)) - logger.log('%s: installing ssh keys' % self.name) - user = pwd.getpwnam(self.name)[2] - group = getgrnam("slices")[2] - os.chown(dot_ssh, user, group) - os.chown(dot_ssh + '/authorized_keys', user, group) + os.chmod(auth_keys, 0600) + + os.chown(dot_ssh, uid, gid) + os.chown(auth_keys, uid, gid) + + logger.log('%s: installed ssh keys' % self.name) def start(self, delay=0): pass def stop(self): pass @@ -127,7 +141,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