func/minion/modules/filetracker.py | 27 ++++++ func/minion/modules/yumcmd.py | 144 ++++++++++++++++++++++++++++++++----- 2 files changed, 151 insertions(+), 20 deletions(-) New commits: commit aed9f6ea5de1505167ca09d3503f17fc0644c7cf Author: Ralph Bean <ralph.bean@xxxxxxxxx> Date: Wed Aug 25 16:37:20 2010 -0400 added recursive parameter to filetracker.track diff --git a/func/minion/modules/filetracker.py b/func/minion/modules/filetracker.py index 156f051..bfa6208 100644 --- a/func/minion/modules/filetracker.py +++ b/func/minion/modules/filetracker.py @@ -71,12 +71,14 @@ class FileTracker(func_module.FuncModule): #========================================================== - def track(self, file_name_globs, full_scan=0): + def track(self, file_name_globs, full_scan=0, recursive=0, files_only=0): """ Adds files to keep track of. file_names can be a single filename, a list of filenames, a filename glob or a list of filename globs full_scan implies tracking the full contents of the file, defaults to off + recursive implies tracking the contents of every subdirectory + files_only implies tracking files that are files (not directories) """ filehash = self.__load() @@ -87,11 +89,22 @@ class FileTracker(func_module.FuncModule): if type(file_name_globs) == type([]): filenameglobs = file_name_globs + def _recursive(original_filenames): + for filename in original_filenames: + for (dir, subdirs, subfiles) in os.walk(filename): + for subdir in subdirs: + yield "%s/%s" % (dir, subdir) + for subfile in subfiles: + yield "%s/%s" % (dir, subfile) # expand everything that might be a glob to a list # of names to track for filenameglob in filenameglobs: filenames = glob.glob(filenameglob) + if recursive: + filenames += _recursive(filenames) + if files_only: + filenames = [f for f in filenames if os.path.isfile(f)] for filename in filenames: filehash[filename] = full_scan self.__save(filehash) @@ -266,6 +279,18 @@ class FileTracker(func_module.FuncModule): 'optional':True, 'default':0, 'description':"The 0 is for off and 1 is for on" + }, + 'recursive':{ + 'type':'int', + 'optional':True, + 'default':0, + 'description':"The 0 is for off and 1 is for on" + }, + 'files_only':{ + 'type':'int', + 'optional':True, + 'default':0, + 'description':"Track only files (not dirs or links)" } }, 'description':"Adds files to keep track of" commit 9189076498a084258e5d9b296bd46eb19ea280a0 Author: Seth Vidal <skvidal@xxxxxxxxxxxxxxxxx> Date: Mon Aug 23 17:31:17 2010 -0400 lots and lots of updates to the yumcmd module: - add install/remove method - add version-specific rpmdbVersion method - add get_package_lists method - handle many errors better - return more interesting results from install/remove/update commands - lay groundwork for other handling diff --git a/func/minion/modules/yumcmd.py b/func/minion/modules/yumcmd.py index b361d76..b44a39f 100644 --- a/func/minion/modules/yumcmd.py +++ b/func/minion/modules/yumcmd.py @@ -1,7 +1,8 @@ -# Copyright 2007, Red Hat, Inc +# Copyright 2010, Red Hat, Inc # James Bowes <jbowes@xxxxxxxxxx> # Alex Wood <awood@xxxxxxxxxx> -# +# Seth Vidal <skvidal@xxxxxxxxxxxxxxxxx> + # This software may be freely redistributed under the terms of the GNU # general public license. # @@ -9,41 +10,126 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -import func_module +# TODOS: +# - config_dict handling +# multiple commands in a single call - multiple() == yum shell +# - permanent config changes +# - better _makeresults() that doesn't make me kinda hurl and makes the output more sensible +import func_module +from codes import FuncException + # XXX Use internal yum callback or write a useful one. class DummyCallback(object): def event(self, state, data=None): pass +def _makeresults(tsInfo): + results = '' + for pkg in tsInfo: + # FIXME obviously much more should happen here :) + if pkg.ts_state: + results += '%s\n' % pkg + + return results + +def _singleAction(action, items=[], config_dict={}, **kwargs): + #FIXME - config_dict needs to do the equiv of --setopt in the yumcli + import yum + ayum = yum.YumBase() + ayum.doGenericSetup() + ayum.doRepoSetup() + if type(items) == type([]): + pkglist = [] + for p in items: + pkglist.extend(p.split(' ')) + else: + if items: + pkglist = items.split(' ') + else: + pkglist = [] + + if len(pkglist) == 0 and action not in ('update', 'upgrade'): + raise FuncException("%s requires at least one pkg" % action) + + results = 'command: %s %s\n' % (action, ' '.join(pkglist)) + try: + ayum.doLock() + if pkglist: + for p in pkglist: + tx_mbrs = [] + if action == 'install': + tx_mbrs = ayum.install(pattern=p) + elif action in ('remove', 'erase'): + tx_mbrs = ayum.remove(pattern=p) + + elif action in ('update', 'upgrade'): + tx_mbrs = ayum.update(pattern=p) + + if not tx_mbrs: + results += "No %s matched for %s\n" % (action, p) + + else: + ayum.update() + + ayum.buildTransaction() + ayum.processTransaction( + callback=DummyCallback()) + finally: + results += _makeresults(ayum.tsInfo) + ayum.closeRpmDB() + ayum.doUnlock() + return results + class Yum(func_module.FuncModule): version = "0.0.1" api_version = "0.1.0" description = "Package updates through yum." - def update(self, pkg=None): + from yum import __version__ as yumversion + yvertuple = yumversion.split('.') + if int(yvertuple[0]) == 3 and int(yvertuple[2]) >= 25: + def rpmdbVersion(self, **kwargs): + import yum + ayum = yum.YumBase() + versionlist = ayum.rpmdb.simpleVersion(main_only=True) + version = versionlist[0] + return versionlist + + def update(self, pkg=None, config_dict={}): + return _singleAction('update', items=pkg, config_dict=config_dict) + + def install(self, pkg=None, config_dict={}): + return _singleAction('install', items=pkg, config_dict=config_dict) + + def remove(self, pkg=None, config_dict={}): + return _singleAction('remove', items=pkg, config_dict=config_dict) + + #def multiple(self, cmdlist=[]): + # """take multiple commands as a single transaction - equiv of yum shell""" + # raise FuncException("Not Implemented Yet!" + + def get_package_lists(self, pkgspec='installed,available,obsoletes,updates,extras', config_dict={}): import yum ayum = yum.YumBase() ayum.doGenericSetup() ayum.doRepoSetup() - try: - ayum.doLock() - if pkg not in [None, '']: - tx_result = ayum.update(pattern=pkg) - else: - tx_result = ayum.update() - - ayum.buildTransaction() - ayum.processTransaction( - callback=DummyCallback()) - finally: - ayum.closeRpmDB() - ayum.doUnlock() - return map(str, tx_result) - + resultsdict = {} + pkgspec = pkgspec.replace(',',' ') + pkgtypes = pkgspec.split(' ') + for pkgtype in pkgtypes: + pkgtype = pkgtype.strip() + obj = ayum.doPackageLists(pkgnarrow=pkgtype) + if hasattr(obj, pkgtype): + thislist = getattr(obj, pkgtype) + output_list = sorted(map(str, thislist)) + resultsdict[pkgtype] = output_list + + return resultsdict + def check_update(self, filter=[], repo=None): """Returns a list of packages due to be updated You can specify a filter using the standard yum wildcards @@ -98,6 +184,26 @@ class Yum(func_module.FuncModule): }, 'description':"Updating system according to a specified pattern" }, + 'install':{ + 'args':{ + 'pkg':{ + 'type':'string', + 'optional':False, + 'description':"The yum pattern for installing package" + } + }, + 'description':"install package(s) according to a specified pattern" + }, + 'remove':{ + 'args':{ + 'pkg':{ + 'type':'string', + 'optional':False, + 'description':"The yum pattern for removing package" + } + }, + 'description':"remove package(s) according to a specified pattern" + }, 'check_update':{ 'args':{ 'filter':{ _______________________________________________ Func-list mailing list Func-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/func-list