From 8220d57690886dfffa252e99381bbdfd577db413 Mon Sep 17 00:00:00 2001 From: Michael DeHaan Date: Sat, 7 Jul 2012 08:45:06 -0400 Subject: [PATCH] Clean up md5 functions + make the fetch module stay happy if the remote file does not exist. --- lib/ansible/runner/__init__.py | 30 ++++++++++++++++++++++++------ lib/ansible/utils.py | 16 ++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/lib/ansible/runner/__init__.py b/lib/ansible/runner/__init__.py index aba6397bb70..1088f7c2f5e 100644 --- a/lib/ansible/runner/__init__.py +++ b/lib/ansible/runner/__init__.py @@ -481,19 +481,20 @@ class Runner(object): dest = dest.replace("//","/") # compare old and new md5 for support of change hooks - local_md5 = None - if os.path.exists(dest): - local_md5 = os.popen("/usr/bin/md5sum %(file)s 2> /dev/null || /sbin/md5 -q %(file)s" % {"file": dest}).read().split()[0] - remote_md5 = self._low_level_exec_command(conn, "/usr/bin/md5sum %(file)s 2> /dev/null || /sbin/md5 -q %(file)s" % {"file": source}, tmp, True).split()[0] + local_md5 = utils.local_md5(dest) + remote_md5 = self._remote_md5(conn, tmp, source) - if remote_md5 != local_md5: + if remote_md5 == '0': + result = dict(msg="missing remote file", changed=False) + return ReturnData(host=conn.host, result=result) + elif remote_md5 != local_md5: # create the containing directories, if needed if not os.path.isdir(os.path.dirname(dest)): os.makedirs(os.path.dirname(dest)) # fetch the file and check for changes conn.fetch_file(source, dest) - new_md5 = os.popen("/usr/bin/md5sum %(file)s 2> /dev/null || /sbin/md5 -q %(file)s" % {"file": dest}).read().split()[0] + new_md5 = utils.local_md5(dest) if new_md5 != remote_md5: result = dict(failed=True, msg="md5 mismatch", md5sum=new_md5) return ReturnData(host=conn.host, result=result) @@ -723,6 +724,23 @@ class Runner(object): # ***************************************************** + def _remote_md5(self, conn, tmp, path): + ''' + takes a remote md5sum without requiring python, and returns 0 if the + file does not exist + ''' + test = "[[ -r %s ]]" % path + md5s = [ + "(%s && /usr/bin/md5sum %s 2>/dev/null)" % (test,path), + "(%s && /sbin/md5sum -q %s 2>/dev/null)" % (test,path) + ] + cmd = " || ".join(md5s) + cmd = "%s || (echo \"0 %s\")" % (cmd, path) + remote_md5 = self._low_level_exec_command(conn, cmd, tmp, True).split()[0] + return remote_md5 + + # ***************************************************** + def _make_tmp_path(self, conn): ''' make and return a temporary path on a remote box ''' diff --git a/lib/ansible/utils.py b/lib/ansible/utils.py index 5dc8c8349ee..d54d00042bf 100644 --- a/lib/ansible/utils.py +++ b/lib/ansible/utils.py @@ -312,6 +312,22 @@ def parse_kv(args): options[k]=v return options +def local_md5(file): + ''' compute local md5sum, return None if file is not present ''' + cmd = "/usr/bin/md5sum %s 2> /dev/null || /sbin/md5 -q %s" % (file,file) + if not os.path.exists(file): + return None + else: + c = os.popen(cmd) + return c.read().split()[0] + + +#################################################################### +# option handling code for /usr/bin/ansible and ansible-playbook +# below this line + +# FIXME: move to seperate file + class SortedOptParser(optparse.OptionParser): '''Optparser which sorts the options by opt before outputting --help''' def format_help(self, formatter=None):