From 4caa76cbd8217d6b13ae24f0df52597510ef36c7 Mon Sep 17 00:00:00 2001 From: Michael DeHaan Date: Mon, 20 Aug 2012 20:42:57 -0400 Subject: [PATCH] Add a callback that logs activity for each host in /var/log/ansible/hosts --- callbacks/log_plays.py | 106 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 callbacks/log_plays.py diff --git a/callbacks/log_plays.py b/callbacks/log_plays.py new file mode 100644 index 0000000000..f86c5e822e --- /dev/null +++ b/callbacks/log_plays.py @@ -0,0 +1,106 @@ +# (C) 2012, Michael DeHaan, + +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +import os +import time +import json + +TIME_FORMAT="%b %d %Y %H:%M:%S" +MSG_FORMAT="%(now)s - %(category)s - %(data)s\n\n" + +if not os.path.exists("/var/log/ansible/hosts"): + os.makedirs("/var/log/ansible/hosts") + +def log(host, category, data): + if type(data) == dict: + if 'verbose_override' in data: + # avoid logging extraneous data from facts + data = 'omitted' + else: + invocation = data.pop('invocation', None) + data = json.dumps(data) + if invocation is not None: + data = json.dumps(invocation) + " => %s " % data + + path = os.path.join("/var/log/ansible/hosts", host) + now = time.strftime(TIME_FORMAT, time.localtime()) + fd = open(path, "a") + fd.write(MSG_FORMAT % dict(now=now, category=category, data=data)) + fd.close() + +class CallbackModule(object): + """ + logs playbook results, per host, in /var/log/ansible/hosts + """ + + def on_any(self, *args, **kwargs): + pass + + def runner_on_failed(self, host, res, ignore_errors=False): + log(host, 'FAILED', res) + + def runner_on_ok(self, host, res): + log(host, 'OK', res) + + def runner_on_error(self, host, msg): + log(host, 'ERROR', msg) + + def runner_on_skipped(self, host, item=None): + log(host, 'SKIPPED') + + def runner_on_unreachable(self, host, res): + log(host, 'UNREACHABLE', res) + + def runner_on_no_hosts(self): + pass + + def runner_on_async_poll(self, host, res, jid, clock): + pass + + def runner_on_async_ok(self, host, res, jid): + pass + + def runner_on_async_failed(self, host, res, jid): + log(host, 'ASYNC_FAILED', res) + + def playbook_on_start(self): + pass + + def playbook_on_notify(self, host, handler): + pass + + def playbook_on_task_start(self, name, is_conditional): + pass + + def playbook_on_vars_prompt(self, varname, private=True, prompt=None, encrypt=None, confirm=False, salt_size=None, salt=None): + pass + + def playbook_on_setup(self): + pass + + def playbook_on_import_for_host(self, host, imported_file): + log(host, 'IMPORTED', imported_file) + + def playbook_on_not_import_for_host(self, host, missing_file): + log(host, 'NOTIMPORTED', missing_file) + + def playbook_on_play_start(self, pattern): + pass + + def playbook_on_stats(self, stats): + pass +