X-Git-Url: http://git.onelab.eu/?p=nodemanager.git;a=blobdiff_plain;f=account.py;h=d45f5335f1c6f4a796aab9de5c175b04b554a9df;hp=9033aacbcfb6415962aad1f8535a493a5505d283;hb=HEAD;hpb=44e352eb6f5b0e1706234df9ade2f475fc75d9b7 diff --git a/account.py b/account.py index 9033aac..d45f533 100644 --- a/account.py +++ b/account.py @@ -71,9 +71,11 @@ def get(name): """ name_worker_lock.acquire() try: - if name not in name_worker: 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() + finally: + name_worker_lock.release() class Account: @@ -84,7 +86,7 @@ class Account: def __init__(self, name): self.name = name self.keys = '' - logger.verbose('account: Initing account %s'%name) + logger.verbose('account: Initing account {}'.format(name)) @staticmethod def create(name, vref = None): @@ -99,7 +101,8 @@ class Account: Write to my authorized_keys file. """ new_keys = rec['keys'] - logger.verbose('account: configuring {} with {} keys'.format(self.name, len(new_keys))) + nb_keys = len(new_keys) if isinstance(new_keys, list) else 1 + logger.verbose('account: configuring {} with {} keys'.format(self.name, nb_keys)) if new_keys != self.keys: # get the unix account info gid = grp.getgrnam("slices")[2] @@ -112,7 +115,8 @@ class Account: dot_ssh = os.path.join(pw_dir, '.ssh') if not os.path.isdir(dot_ssh): if not os.path.isdir(pw_dir): - logger.verbose('account: WARNING: homedir %s does not exist for %s!'%(pw_dir, self.name)) + logger.verbose('account: WARNING: homedir {} does not exist for {}!' + .format(pw_dir, self.name)) os.mkdir(pw_dir) os.chown(pw_dir, uid, gid) os.mkdir(dot_ssh) @@ -121,15 +125,15 @@ class Account: tools.write_file(auth_keys, lambda f: f.write(new_keys)) # set access permissions and ownership properly - os.chmod(dot_ssh, 0700) + os.chmod(dot_ssh, 0o700) os.chown(dot_ssh, uid, gid) - os.chmod(auth_keys, 0600) + os.chmod(auth_keys, 0o600) os.chown(auth_keys, uid, gid) # set self.keys to new_keys only when all of the above ops succeed self.keys = new_keys - logger.log('account: %s: installed ssh keys' % self.name) + logger.log('account: {}: installed ssh keys'.format(self.name)) def start(self, delay=0): pass @@ -137,26 +141,41 @@ class Account: pass def is_running(self): pass + def needs_reimage(self, target_slicefamily): + stampname = "/vservers/{}/etc/slicefamily".format(self.name) + try: + with open(stampname) as f: + current_slicefamily = f.read().strip() + return current_slicefamily != target_slicefamily + except IOError as e: + logger.verbose("Account.needs_reimage: missing slicefamily {} - left as-is" + .format(self.name)) + return False ### 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) + 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) + def umount_ssh_dir (slicename): + return Account._manage_ssh_dir (slicename, do_mount=False) # 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) + logger.log("_manage_ssh_dir, requested to " + + ( "mount" if do_mount else "umount" ) + + " ssh dir for "+ slicename) try: - root_ssh = "/home/%s/.ssh"%slicename - sliver_ssh = "/vservers/%s/home/%s/.ssh"%(slicename, slicename) + root_ssh = "/home/{}/.ssh".format(slicename) + sliver_ssh = "/vservers/{}/home/{}/.ssh".format(slicename, slicename) def is_mounted (root_ssh): - for mount_line in file('/proc/mounts').readlines(): - if mount_line.find (root_ssh) >= 0: - return True + with open('/proc/mounts') as mountsfile: + for mount_line in mountsfile.readlines(): + if mount_line.find (root_ssh) >= 0: + return True return False if do_mount: # any of both might not exist yet @@ -169,15 +188,17 @@ class Account: 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)) + logger.log("_manage_ssh_dir: mounted {} into slice {} - {}" + .format(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("_manage_ssh_dir failed", name=slicename) + logger.log("_manage_ssh_dir: umounted {} - {}" + .format(sliver_ssh, msg)) + except Exception as e: + logger.log_exc("_manage_ssh_dir failed : {}".format(e), name=slicename) class Worker: @@ -190,7 +211,7 @@ class Worker: 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'], + logger.log_data_in_file(rec, "/var/lib/nodemanager/{}.rec.txt".format(rec['name']), 'raw rec captured in ensure_created', logger.LOG_VERBOSE) curr_class = self._get_class() next_class = type_acct_class[rec['type']] @@ -199,8 +220,10 @@ class Worker: create_sem.acquire() try: next_class.create(self.name, rec) finally: create_sem.release() - 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())) + if not isinstance(self._acct, next_class): + self._acct = next_class(rec) + logger.verbose("account.Worker.ensure_created: {}, running={}" + .format(self.name, self.is_running())) # reservation_alive is set on reservable nodes, and its value is a boolean if 'reservation_alive' in rec: @@ -209,7 +232,8 @@ class Worker: # this sliver has the lease, it is safe to start it if not self.is_running(): self.start(rec) - else: self.configure(rec) + else: + self.configure(rec) else: # not having the lease, do not start it self.configure(rec) @@ -217,7 +241,7 @@ class Worker: # 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: + if not self.is_running() or self.needs_reimage(rec['vref']) or next_class != curr_class: self.start(rec) else: self.configure(rec) @@ -237,22 +261,41 @@ class Worker: self._acct.stop() def is_running(self): - if (self._acct != None) and self._acct.is_running(): - status = True + if self._acct and self._acct.is_running(): + return True else: - status = False - logger.verbose("account: Worker(%s): is not running" % self.name) - return status + logger.verbose("Worker.is_running ({}) - no account or not running".format(self.name)) + return False + def needs_reimage(self, target_slicefamily): + if not self._acct: + logger.verbose("Worker.needs_reimage ({}) - no account -> True".format(self.name)) + return True + else: + account_needs_reimage = self._acct.needs_reimage(target_slicefamily) + if account_needs_reimage: + logger.log("Worker.needs_reimage ({}) - account needs reimage (tmp: DRY RUN)" + .format(self.name)) + else: + logger.verbose("Worker.needs_reimage ({}) - everything fine" + .format(self.name)) + return account_needs_reimage + def _destroy(self, curr_class): self._acct = None if curr_class: destroy_sem.acquire() - try: curr_class.destroy(self.name) - finally: destroy_sem.release() + try: + logger.verbose("account._destroy is callling destroy from {}" + .format(curr_class.__name__)) + curr_class.destroy(self.name) + finally: + destroy_sem.release() def _get_class(self): - try: shell = pwd.getpwnam(self.name)[6] - except KeyError: return None + try: + shell = pwd.getpwnam(self.name)[6] + except KeyError: + return None return shell_acct_class[shell]