summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael DeHaan <mdehaan@redhat.com>2007-10-26 17:33:44 -0400
committerMichael DeHaan <mdehaan@redhat.com>2007-10-26 17:33:44 -0400
commit9060cccfbfa77fbc8592f07e4641514d7a740a1f (patch)
tree10b0420e6a8ab82087b2898fd96cf5764162bd75
parentd7f4a0ebebe416084ec726d38f485246aa88e886 (diff)
downloadfunc-9060cccfbfa77fbc8592f07e4641514d7a740a1f.tar.gz
func-9060cccfbfa77fbc8592f07e4641514d7a740a1f.tar.xz
func-9060cccfbfa77fbc8592f07e4641514d7a740a1f.zip
Adds the filetracker module, originally developed by fordship, with some tweaks. "func spec call filetracker track filename" can be
used to track a file, and "func spec call filetracker untrack filename" removes it. Then it shows up with lots of data using "func spec call filetracker inventory". Addition can also specify for the contents of data in the said files to be noted in inventory. Additionally, the inventory function can be told to return data structures instead of an easily-diffable list, and the checksums can be enabled/disabled.
-rw-r--r--AUTHORS3
-rw-r--r--func.spec1
-rw-r--r--func/minion/modules/filetracker.py197
-rwxr-xr-xfunc/minion/modules/virt.py11
-rw-r--r--setup.py2
5 files changed, 212 insertions, 2 deletions
diff --git a/AUTHORS b/AUTHORS
index b4539ca..ceef6cb 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -11,7 +11,8 @@ func is written by (alphabetically) ...
Additional patches and contributions by ...
+ Vito Laurenza <vitolaurenza@gmail.com>
...
- [ send in patches to get your name here ]
+ [ send in patches (or modules!) to get your name here ]
diff --git a/func.spec b/func.spec
index 386e2ae..579093c 100644
--- a/func.spec
+++ b/func.spec
@@ -50,6 +50,7 @@ rm -fr $RPM_BUILD_ROOT
%dir %{_sysconfdir}/%{name}
%dir %{_sysconfdir}/%{name}/minion-acl.d/
%dir %{_sysconfdir}/pki/%{name}
+%dir /etc/func/modules/
%config(noreplace) /etc/func/minion.conf
%config(noreplace) /etc/func/certmaster.conf
%config(noreplace) /etc/logrotate.d/func_rotate
diff --git a/func/minion/modules/filetracker.py b/func/minion/modules/filetracker.py
new file mode 100644
index 0000000..efcc31c
--- /dev/null
+++ b/func/minion/modules/filetracker.py
@@ -0,0 +1,197 @@
+#!/usr/bin/python
+
+## func
+##
+## filetracker
+## maintains a manifest of files of which to keep track
+## provides file meta-data (and optionally full data) to func-inventory
+##
+## (C) Vito Laurenza <vitolaurenza@gmail.com>
+##
+## This software may be freely redistributed under the terms of the GNU
+## general public license.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+##
+
+# func modules
+from modules import func_module
+
+# other modules
+# import ConfigParser
+from stat import *
+import os
+import sys
+import md5
+
+# defaults
+CONFIG_FILE='/etc/func/modules/filetracker.conf'
+
+class FileTracker(func_module.FuncModule):
+
+ def __init__(self):
+ self.methods = {
+ "track" : self.track,
+ "untrack" : self.untrack,
+ "info" : self.inventory,
+ "inventory" : self.inventory,
+ }
+ func_module.FuncModule.__init__(self)
+
+ #==========================================================
+
+ def __load(self):
+ """
+ Parse file and return data structure.
+ """
+
+ filehash = {}
+ if os.path.exists(CONFIG_FILE):
+ config = open(CONFIG_FILE, "r")
+ data = config.read()
+ lines = data.split("\n")
+ for line in lines:
+ tokens = line.split(None)
+ if len(tokens) < 2:
+ continue
+ scan_mode = tokens[0]
+ path = " ".join(tokens[1:])
+ if str(scan_mode).lower() == "0":
+ scan_mode = 0
+ else:
+ scan_mode = 1
+ filehash[path] = scan_mode
+ return filehash
+
+ #==========================================================
+
+ def __save(self, filehash):
+ """
+ Write data structure to file.
+ """
+
+ config = open(CONFIG_FILE, "w+")
+ for (path, scan_mode) in filehash.iteritems():
+ config.write("%s %s\n" % (scan_mode, path))
+ config.close()
+
+ #==========================================================
+
+ def track(self, file_name, full_scan=0):
+ """
+ Adds files to keep track of.
+ full_scan implies tracking the full contents of the file, defaults to off
+ """
+
+ filehash = self.__load()
+ filehash[file_name] = full_scan
+ self.__save(filehash)
+ return 1
+
+ #==========================================================
+
+ def untrack(self, file_name):
+ """
+ Stop keeping track of a file.
+ This routine is tolerant of most errors since we're forgetting about the file anyway.
+ """
+
+ filehash = self.__load()
+ print "DEBUG: deleting: %s" % file_name
+ print "DEBUG: keys: %s" % filehash
+ if file_name in filehash.keys():
+ del filehash[file_name]
+ self.__save(filehash)
+ return 1
+
+ #==========================================================
+
+ def inventory(self, flatten=1, checksum_enabled=1):
+ """
+ Returns information on all tracked files
+ By default, 'flatten' is passed in as True, which makes printouts very clean in diffs
+ for use by func-inventory. If you are writting another software application, using flatten=False will
+ prevent the need to parse the returns.
+ """
+
+ # XMLRPC feeds us strings from the CLI when it shouldn't
+ flatten = int(flatten)
+ checksum_enabled = int(checksum_enabled)
+
+ filehash = self.__load()
+
+ # we'll either return a very flat string (for clean diffs)
+ # or a data structure
+ if flatten:
+ results = ""
+ else:
+ results = []
+
+ for (file_name, scan_type) in filehash.iteritems():
+
+ if not os.path.exists(file_name):
+ if flatten:
+ results = results + "%s: does not exist\n" % file_name
+ else:
+ results.append("%s: does not exist\n" % file_name)
+ continue
+
+ this_result = []
+
+ # ----- always process metadata
+ filestat = os.stat(file_name)
+ mode = filestat[ST_MODE]
+ mtime = filestat[ST_MTIME]
+ uid = filestat[ST_UID]
+ gid = filestat[ST_GID]
+ if not os.path.isdir(file_name) and checksum_enabled:
+ sum_handle = open(file_name)
+ hash = self.sumfile(sum_handle)
+ sum_handle.close()
+ else:
+ hash = "N/A"
+
+ # ------ what we return depends on flatten
+ if flatten:
+ this_result = "%s: mode=%s mtime=%s uid=%s gid=%s md5sum=%s\n" % (file_name,mode,mtime,uid,gid,hash)
+ else:
+ this_result = [file_name,mode,mtime,uid,gid,hash]
+
+ # ------ add on file data only if requested
+ if scan_type != 0 and os.path.isfile(file_name):
+ tracked_file = open(file_name)
+ data = tracked_file.read()
+ if flatten:
+ this_result = this_result + "*** DATA *******\n" + data + "\n*** END DATA ***\n\n"
+ else:
+ this_result.append(data)
+ tracked_file.close()
+
+ if flatten:
+ results = results + "\n" + this_result
+ else:
+ results.append(this_result)
+
+
+ return results
+
+ #==========================================================
+
+ def sumfile(self, fobj):
+ """
+ Returns an md5 hash for an object with read() method.
+ credit: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/266486
+ """
+
+ m = md5.new()
+ while True:
+ d = fobj.read(8096)
+ if not d:
+ break
+ m.update(d)
+ return m.hexdigest()
+
+methods = FileTracker()
+register_rpc = methods.register_rpc
diff --git a/func/minion/modules/virt.py b/func/minion/modules/virt.py
index 7dc5697..3e7fc2d 100755
--- a/func/minion/modules/virt.py
+++ b/func/minion/modules/virt.py
@@ -22,7 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# other modules
import os
import sub_process
-import libvirt
+# import libvirt
# our modules
import codes
@@ -42,6 +42,13 @@ class FuncLibvirtConnection(object):
def __init__(self):
+ self.loaded = False
+
+ try:
+ import libvirt
+ self.loaded = True
+ except:
+ return
cmd = sub_process.Popen("uname -r", shell=True, stdout=sub_process.PIPE)
output = cmd.communicate()[0]
@@ -147,6 +154,8 @@ class Virt(func_module.FuncModule):
def get_conn(self):
self.conn = FuncLibvirtConnection()
+ if not self.conn.loaded:
+ return False
return self.conn
def info(self):
diff --git a/setup.py b/setup.py
index 7cb1bef..7675ed1 100644
--- a/setup.py
+++ b/setup.py
@@ -15,6 +15,7 @@ if __name__ == "__main__":
manpath = "share/man/man1/"
etcpath = "/etc/%s" % NAME
+ etcmodpath = "/etc/%s/modules" % NAME
initpath = "/etc/init.d/"
logpath = "/var/log/%s/" % NAME
pkipath = "/etc/pki/%s" % NAME
@@ -45,6 +46,7 @@ if __name__ == "__main__":
(initpath, ["init-scripts/certmaster"]),
(etcpath, ["etc/minion.conf"]),
(etcpath, ["etc/certmaster.conf"]),
+ (etcmodpath, []),
(manpath, ["docs/func.1.gz"]),
(manpath, ["docs/func-inventory.1.gz"]),
(manpath, ["docs/funcd.1.gz"]),