###
-"""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;
import os
import pwd, grp
import threading
+import subprocess
import logger
import tools
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
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)
class Account:
- def __init__(self, rec):
- logger.verbose('account: Initing account %s'%rec['name'])
- self.name = rec['name']
+ """
+ Base class for all types of account
+ """
+
+ def __init__(self, name):
+ self.name = name
self.keys = ''
- self.configure(rec)
+ 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 <rec['keys']> to my authorized_keys file."""
- logger.verbose('account: configuring %s'%self.name)
+ """
+ Write <rec['keys']> 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
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 / 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"%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("_manage_ssh_dir failed",name=slicename)
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()
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.ensure_created: %s, running=%r"%(self.name,self.is_running()))
+ 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()
else: self.configure(rec)
else:
# not having the lease, do not start it
# in a reservable node
else:
if not self.is_running() or next_class != curr_class:
- self.start(rec)
- else: self.configure(rec)
+ self.start()
+ 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)
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():
except KeyError: return None
return shell_acct_class[shell]
- # 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):
- 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))
- except:
- logger.log_exc("expose_ssh_dir with slice %s failed"%self.name)
-