From: Thierry Parmentelat Date: Tue, 9 Mar 2010 11:48:45 +0000 (+0000) Subject: new omf-oriented plugins X-Git-Tag: NodeManager-2.0-3~8 X-Git-Url: http://git.onelab.eu/?p=nodemanager.git;a=commitdiff_plain;h=342c63a2acd2acfb5876b872cea47f152ca5f12e new omf-oriented plugins new tool for changing files only when needed --- diff --git a/nm.py b/nm.py index 2884df9..f421769 100755 --- a/nm.py +++ b/nm.py @@ -86,7 +86,7 @@ def GetSlivers(config, plc): data = {} # Invoke GetSlivers() functions from the callback modules for module in modules: -# logger.log('trigerring GetSlivers callback for module %s'%module.__name__) + logger.verbose('trigerring GetSlivers callback for module %s'%module.__name__) try: callback = getattr(module, 'GetSlivers') callback(data, config, plc) @@ -170,8 +170,8 @@ def run(): return getattr(m1,'priority',default_priority) - getattr(m2,'priority',default_priority) modules.sort(sort_module_priority) - logger.verbose('modules priorities and order:') - for module in modules: logger.verbose ('%s: %s'%(getattr(module,'priority',default_priority),module.__name__)) + logger.log('ordered modules:') + for module in modules: logger.log ('%s: %s'%(getattr(module,'priority',default_priority),module.__name__)) # Load /etc/planetlab/session if os.path.exists(options.session): diff --git a/plugins/omf_resctl.py b/plugins/omf_resctl.py new file mode 100644 index 0000000..1401bc8 --- /dev/null +++ b/plugins/omf_resctl.py @@ -0,0 +1,57 @@ +# +# $Id$ +# $URL$ +# +# NodeManager plugin - first step of handling omf_controlled slices + +""" +Overwrites the 'resctl' tag of slivers controlled by OMF so sm.py does the right thing +""" + +import subprocess + +import tools +import logger + +priority = 11 + +### xxx this should not be version-dependent +service_name='omf-resctl-5.3' + +def start(options, conf): + logger.log("omf_resctl: plugin starting up...") + +def GetSlivers(data, conf = None, plc = None): + if 'accounts' not in data: + logger.log_missing_data("omf_resctl.GetSlivers",'accounts') + return + + try: + xmpp_server=data['xmpp']['server'] + except: + # disabled feature - bailing out + # xxx might need to clean up more deeply.. + return + + for sliver in data['slivers']: + name=sliver['name'] + for chunk in sliver['attributes']: + if chunk['tagname']=='omf_control': + # filenames + yaml="/vservers/%s/etc/omf-resctl/omf-resctl.yaml"%name + template="%s.in"%yaml + # read template and replace + template=file(template).read() + yaml_contents=template\ + .replace('@XMPP_SERVER@',xmpp_server)\ + .replace('@NODE_HRN@','default')\ + .replace('@SLICE_NAME@',name) + changes=tools.replace_file_with_string(yaml,yaml_contents) + if changes: + sp=subprocess.Popen(['vserver',name,'exec','service',service_name,'restart'], + stdout=subprocess.PIPE,stderr=subprocess.STDOUT) + (output,retcod)=sp.communicate() + logger.log("omf_resctl: %s: restarted resource controller (retcod=%r)"%(name,retcod)) + logger.log("omf_resctl: got output\n%s"%output) + else: + logger.log("omf_resctl: %s: omf_control'ed sliver has no change" % name) diff --git a/plugins/omf_vref.py b/plugins/omf_vref.py new file mode 100644 index 0000000..2b41b52 --- /dev/null +++ b/plugins/omf_vref.py @@ -0,0 +1,30 @@ +# +# $Id$ +# $URL$ +# +# NodeManager plugin - first step of handling omf_controlled slices + +""" +Overwrites the 'vref' tag of slivers controlled by OMF so sm.py does the right thing +Needs to be done the 'sm' module kicks in +""" + +import logger + +# do this early, before step 10 +priority = 4 + +def start(options, conf): + logger.log("omf_vref: plugin starting up...") + +def GetSlivers(data, conf = None, plc = None): + if 'accounts' not in data: + logger.log_missing_data("omf_vref.GetSlivers",'accounts') + return + + for sliver in data['slivers']: + name=sliver['name'] + for chunk in sliver['attributes']: + if chunk['tagname']=='omf_control': + sliver['vref']='omf' + logger.log('omf_vref: %s now has vref==omf' % name) diff --git a/plugins/specialaccounts.py b/plugins/specialaccounts.py index fb33688..359ff21 100644 --- a/plugins/specialaccounts.py +++ b/plugins/specialaccounts.py @@ -26,7 +26,7 @@ import tools priority = 3 def start(options, conf): - logger.log("personkeys: plugin starting up...") + logger.log("specialaccounts: plugin starting up...") def GetSlivers(data, conf = None, plc = None): if 'accounts' not in data: @@ -50,21 +50,17 @@ def GetSlivers(data, conf = None, plc = None): if not os.access(dot_ssh, os.F_OK): os.mkdir(dot_ssh) auth_keys = os.path.join(dot_ssh,'authorized_keys') - logger.log("specialaccounts: new keys = %s" % auth_keys) - fd, fname = tempfile.mkstemp('','authorized_keys',dot_ssh) + # catenate all keys in string, add newlines just in case (looks like keys already have this, but) + auth_keys_contents = '\n'.join(new_keys)+'\n' - for key in new_keys: - os.write(fd,key) - os.write(fd,'\n') - - os.close(fd) - if os.path.exists(auth_keys): os.unlink(auth_keys) - os.rename(fname, auth_keys) - - # set permissions properly + changes = tools.replace_file_with_string(auth_keys,auth_keys_contents) + if changes: + logger.log("specialaccounts: keys file changed: %s" % auth_keys) + + # always set permissions properly os.chmod(dot_ssh, 0700) os.chown(dot_ssh, uid,gid) os.chmod(auth_keys, 0600) os.chown(auth_keys, uid,gid) - logger.log('specialacounts: installed ssh keys for %s' % name) + logger.log('specialaccounts: installed ssh keys for %s' % name) diff --git a/tools.py b/tools.py index 267ec31..80685de 100644 --- a/tools.py +++ b/tools.py @@ -3,18 +3,19 @@ """A few things that didn't seem to fit anywhere else.""" -import cPickle -import errno import os import pwd import tempfile -import threading import fcntl -import commands +import errno +import threading +import subprocess + import logger PID_FILE = '/var/run/nm.pid' +#################### def get_default_if(): interface = get_if_from_hwaddr(get_hwaddr_from_plnode()) if not interface: interface = "eth0" @@ -37,6 +38,8 @@ def get_if_from_hwaddr(hwaddr): if dev_hwaddr == hwaddr: return dev return None +#################### +# daemonizing def as_daemon_thread(run): """Call function with no arguments in its own thread.""" thr = threading.Thread(target=run) @@ -85,6 +88,8 @@ def fork_as(su, function, *args): os._exit(0) else: os.waitpid(child_pid, 0) +#################### +# manage files def pid_file(): """We use a pid file to ensure that only one copy of NM is running at a given time. If successful, this function will write a pid file containing the pid of the current process. The return value is the pid of the other running process, or None otherwise.""" other_pid = None @@ -115,6 +120,28 @@ def write_temp_file(do_write, mode=None, uidgid=None): finally: f.close() return temporary_filename +# replace a target file with a new contents - checks for changes +# return True if a change occurred, in which case +# chown/chmod settings should be taken care of +def replace_file_with_string (target, new_contents): + try: + current=file(target).read() + except: + current="" + # xxx if verbose, report diffs... + if current==new_contents: + return False + # overwrite target file + f=file(target,'w') + f.write(new_contents) + f.close() + return True + +# not needed yet - should that unlink the new file ? +#def replace_file_with_file (target, new): +# return replace_file_with_string (target, file(new).read()) + +#################### # utilities functions to get (cached) information from the node # get node_id from /etc/planetlab/node_id and cache it @@ -132,10 +159,13 @@ _root_context_arch=None def root_context_arch(): global _root_context_arch if not _root_context_arch: - _root_context_arch=commands.getoutput("uname -i") + sp=subprocess.Popen(["uname","-i"],stdout=subprocess.PIPE) + (_root_context_arch,_)=sp.communicate() + _root_context_arch=_root_context_arch.strip() return _root_context_arch +#################### class NMLock: def __init__(self, file): logger.log("tools: Lock %s initialized." % file, 2)