X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=account.py;h=293fc3f4687b90a2b4f1fc1144015d21f5bc2ae9;hb=e57432c1dfdfeaa52cc32799e2abbc34b7704ce9;hp=b15bb6701e8019519b169b0819be5096ec0ea2ac;hpb=cabdd946793b35b2fcaff5ee2ffec4a1644d8391;p=nodemanager.git diff --git a/account.py b/account.py index b15bb67..293fc3f 100644 --- a/account.py +++ b/account.py @@ -1,6 +1,7 @@ ### -"""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; @@ -43,9 +44,11 @@ create_sem = threading.Semaphore(1) 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 @@ -62,7 +65,10 @@ def all(): return [pw_ent[0] for pw_ent in allpwents()] def get(name): - """Return the worker object for a particular username. If no such object exists, create it first.""" + """ + 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: name_worker[name] = Worker(name) @@ -70,23 +76,29 @@ def get(name): finally: name_worker_lock.release() -# xxx strictly speaking this class should not use self.name that in fact -# is accidentally inited by the subclasses constructor... class Account: + """ + Base class for all types of account + """ + def __init__(self, name): self.name = name self.keys = '' logger.verbose('account: Initing account %s'%name) @staticmethod - def create(name, vref = None): abstract + def create(name, vref = None): + abstract @staticmethod - def destroy(name): abstract + def destroy(name): + abstract def configure(self, rec): - """Write to my authorized_keys file.""" - logger.verbose('account: configuring %s'%self.name) + """ + Write to my authorized_keys file. + """ + logger.verbose('account: configuring %s' % self.name) new_keys = rec['keys'] if new_keys != self.keys: # get the unix account info @@ -119,29 +131,52 @@ class Account: logger.log('account: %s: installed ssh keys' % self.name) - def start(self, delay=0): pass - def stop(self): pass - def is_running(self): pass + def start(self, delay=0): + pass + def stop(self): + pass + def is_running(self): + pass + + ### this used to be a plain method but because it needs to be invoked by destroy + # which is a static method, they need to become static as well + # needs to be done before sliver starts (checked with vs and lxc) + @staticmethod + def mount_ssh_dir (slicename): return Account._manage_ssh_dir (slicename, do_mount=True) + @staticmethod + def umount_ssh_dir (slicename): return Account._manage_ssh_dir (slicename, do_mount=False) - # bind mount root side dir to sliver side - # needs to be done before sliver starts, in the vserver case at least - def expose_ssh_dir (self): + # bind mount / umount root side dir to sliver side + @staticmethod + def _manage_ssh_dir (slicename, do_mount): + logger.log ("_manage_ssh_dir, requested to "+("mount" if do_mount else "umount")+" ssh dir for "+ slicename) try: - root_ssh="/home/%s/.ssh"%self.name - sliver_ssh="/vservers/%s/home/%s/.ssh"%(self.name,self.name) - # any of both might not exist yet - for path in [root_ssh,sliver_ssh]: - if not os.path.exists (path): - os.mkdir(path) - if not os.path.isdir (path): - raise Exception - mounts=file('/proc/mounts').read() - if mounts.find(sliver_ssh)<0: - # xxx perform mount - subprocess.call("mount --bind -o ro %s %s"%(root_ssh,sliver_ssh),shell=True) - logger.log("expose_ssh_dir: %s mounted into slice %s"%(root_ssh,self.name)) + root_ssh="/home/%s/.ssh"%slicename + sliver_ssh="/vservers/%s/home/%s/.ssh"%(slicename,slicename) + def is_mounted (root_ssh): + for mount_line in file('/proc/mounts').readlines(): + if mount_line.find (root_ssh)>=0: return True + return False + if do_mount: + # any of both might not exist yet + for path in [root_ssh,sliver_ssh]: + if not os.path.exists (path): + os.mkdir(path) + if not os.path.isdir (path): + raise Exception + if not is_mounted(root_ssh): + command=['mount','--bind','-o','ro',root_ssh,sliver_ssh] + mounted=logger.log_call (command) + msg="OK" if mounted else "WARNING: FAILED" + logger.log("_manage_ssh_dir: mounted %s into slice %s - %s"%(root_ssh,slicename,msg)) + else: + if is_mounted (sliver_ssh): + command=['umount',sliver_ssh] + umounted=logger.log_call(command) + msg="OK" if umounted else "WARNING: FAILED" + logger.log("_manage_ssh_dir: umounted %s - %s"%(sliver_ssh,msg)) except: - logger.log_exc("expose_ssh_dir with slice %s failed"%self.name) + logger.log_exc("_manage_ssh_dir failed",name=slicename) class Worker: @@ -150,8 +185,10 @@ class Worker: self._acct = None # the account object currently associated with this worker 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.""" + """ + 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() @@ -164,12 +201,13 @@ If still valid, check if running and configure/start if not.""" if not isinstance(self._acct, next_class): self._acct = next_class(rec) logger.verbose("account.Worker.ensure_created: %s, running=%r"%(self.name,self.is_running())) - # reservation_alive is set on reervable nodes, and its value is a boolean + # reservation_alive is set on reservable 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) + if not self.is_running(): + self.start(rec) else: self.configure(rec) else: # not having the lease, do not start it @@ -180,10 +218,13 @@ If still valid, check if running and configure/start if not.""" else: if not self.is_running() or next_class != curr_class: self.start(rec) - else: self.configure(rec) + else: + self.configure(rec) - def ensure_destroyed(self): self._destroy(self._get_class()) + def ensure_destroyed(self): + self._destroy(self._get_class()) + # take rec as an arg here for api_calls def start(self, rec, d = 0): self._acct.configure(rec) self._acct.start(delay=d) @@ -191,7 +232,8 @@ If still valid, check if running and configure/start if not.""" def configure(self, rec): self._acct.configure(rec) - def stop(self): self._acct.stop() + def stop(self): + self._acct.stop() def is_running(self): if (self._acct != None) and self._acct.is_running():