From d308254eaeefd86c494cc322459af131aa5428a7 Mon Sep 17 00:00:00 2001 From: Michael DeHaan Date: Sat, 25 Feb 2012 20:27:11 -0500 Subject: [PATCH] A basic service module with 'ensure' idempotence semantics. Playbook updated to use service module vs command module for restarting. May be some bugs and requires the service to implement 'status' -- and probably some better error handling (i.e. return JSON with "failed" element if failed). Improvements welcome. --- examples/playbook.yml | 2 +- lib/ansible/playbook.py | 1 - library/service | 86 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) create mode 100755 library/service diff --git a/examples/playbook.yml b/examples/playbook.yml index 800108b0cd..9f102a9b5e 100644 --- a/examples/playbook.yml +++ b/examples/playbook.yml @@ -21,7 +21,7 @@ handlers: - do: - restart apache - - command /sbin/service httpd restart + - service name=httpd ensure=restarted - do: - quack like a duck - command /bin/true diff --git a/lib/ansible/playbook.py b/lib/ansible/playbook.py index 79f7351ad3..6c2df6ab62 100755 --- a/lib/ansible/playbook.py +++ b/lib/ansible/playbook.py @@ -21,7 +21,6 @@ import ansible.runner import ansible.constants as C -import json import yaml import shlex diff --git a/library/service b/library/service new file mode 100755 index 0000000000..682d3b76f5 --- /dev/null +++ b/library/service @@ -0,0 +1,86 @@ +#!/usr/bin/python + +try: + import json +except ImportError: + import simplejson as json +import os +import sys +import shlex +import subprocess + +# =========================================== +# convert arguments of form ensure=running name=foo +# to a dictionary +# FIXME: make more idiomatic + +args = " ".join(sys.argv[1:]) +items = shlex.split(args) +params = {} +for x in items: + (k, v) = x.split("=") + params[k] = v + +name = params['name'] +ensure = params.get('ensure','running') + +# =========================================== +# get service status + +status = os.popen("/sbin/service %s status" % name).read() + +# =========================================== +# determine if we are going to change anything + +running = False +if status.find("not running") != -1: + running = False +elif status.find("running") != -1: + running = True +elif name == 'iptables' and status.find("ACCEPT") != -1: + # iptables status command output is lame + # TODO: lookup if we can use a return code for this instead? + running = True + +changed = False +if not running and ensure == "started": + changed = True +elif running and ensure == "stopped": + changed = True +elif ensure == "restarted": + changed = True + +# =========================================== +# run change commands if we need to + +def _run(cmd): + return subprocess.call(cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, shell=True) + + +rc = 0 +if changed: + if ensure == 'started': + rc = _run("/sbin/service %s start" % name) + elif ensure == 'stopped': + rc = _run("/sbin/service %s stop" % name) + elif ensure == 'restarted': + rc1 = _run("/sbin/service %s stop" % name) + rc2 = _run("/sbin/service %s start" % name) + rc = rc1 and rc2 + +if rc != 0: + # yeah, should probably include output of failure... + print json.dumps({ + "failed" : 1 + }) + sys.exit(1) + +# =============================================== +# success + +print json.dumps({ + "changed" : changed +}) +