From 624a952c5cce3297ae2e2f6577a16a7aa89d2648 Mon Sep 17 00:00:00 2001
From: Michael DeHaan <michael.dehaan@gmail.com>
Date: Sat, 23 Feb 2013 20:31:29 -0500
Subject: [PATCH] The service module made some assumptions about how a service
 should be managed based on what was installed on the system in terms of
 service management tools, which meant upstart services on CentOS6 were not
 startable.  This tweak allows things like vmware-tools to be controlled via
 the service module.  More testing on other distributions (particularly with
 systemd) is presumably needed.

---
 library/service | 71 ++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 52 insertions(+), 19 deletions(-)

diff --git a/library/service b/library/service
index 963d8e6a68d..5fb3f1e9e1a 100644
--- a/library/service
+++ b/library/service
@@ -345,39 +345,45 @@ class LinuxService(Service):
     distribution = None
 
     def get_service_tools(self):
+
         paths = [ '/sbin', '/usr/sbin', '/bin', '/usr/bin' ]
-        binaries = [ 'service', 'chkconfig', 'update-rc.d', 'initctl', 'systemctl' ]
+        binaries = [ 'service', 'chkconfig', 'update-rc.d', 'initctl', 'systemctl', 'start', 'stop', 'restart' ]
         initpaths = [ '/etc/init.d' ]
         location = dict()
 
         for binary in binaries:
             location[binary] = None
-
         for binary in binaries:
             location[binary] = self.module.get_bin_path(binary)
 
         # Locate a tool for enable options
-        if location.get('systemctl', None):
-            self.enable_cmd = location['systemctl']
-        elif location.get('chkconfig', None):
+        if location.get('chkconfig', None) and os.path.exists("/etc/init.d/%s" % self.name):
+            # we are using a standard SysV service
             self.enable_cmd = location['chkconfig']
-        elif location.get('update-rc.d', None):
+        elif location.get('update-rc.d', None) and os.path.exists("/etc/init/%s.conf" % self.name):
+            # service is managed by upstart
             self.enable_cmd = location['update-rc.d']
-
-        if self.enable_cmd is None:
-            self.module.fail_json(msg='unable to find enable binary')
-
+        elif location.get('systemctl', None):
+            # service is managed by systemd
+            self.enable_cmd = location['systemctl']
+        
         # Locate a tool for runtime service management (start, stop etc.)
-        if location.get('service', None):
+        self.svc_cmd = ''
+        if location.get('service', None) and os.path.exists("/etc/init.d/%s" % self.name):
+            # SysV init script
             self.svc_cmd = location['service']
+        elif location.get('start', None) and os.path.exists("/etc/init/%s.conf" % self.name):
+            # upstart -- rather than being managed by one command, start/stop/restart are actual commands
+            self.svc_cmd = ''
         else:
+            # still a SysV init script, but /sbin/service isn't installed
             for initdir in initpaths:
                 initscript = "%s/%s" % (initdir,self.name)
                 if os.path.isfile(initscript):
                     self.svc_initscript = initscript
 
-        if not self.svc_cmd and not self.svc_initscript:
-            self.module.fail_json(msg='unable to find service binary nor initscript')
+        if self.svc_cmd is None and not self.svc_initscript:
+            self.module.fail_json(msg='cannot find \'service\' binary or init script for service, aborting')
 
         if location.get('initctl', None):
             self.svc_initctl = location['initctl']
@@ -386,7 +392,7 @@ class LinuxService(Service):
         self.action = "status"
         rc, status_stdout, status_stderr = self.service_control()
 
-        # Check if we have upstart on the system and then the job state
+        # if we have decided the service is managed by upstart, we check for some additional output...
         if self.svc_initctl and self.running is None:
             # check the job status by upstart response
             initctl_rc, initctl_status_stdout, initctl_status_stderr = self.execute_command("%s status %s" % (self.svc_initctl, self.name))
@@ -434,10 +440,14 @@ class LinuxService(Service):
 
 
     def service_enable(self):
+
+        if self.enable_cmd is None:
+            self.module.fail_json(msg='unable to find enable binary')
+
         # we change argument depending on real binary used
         # update-rc.d wants enable/disable while
         # chkconfig wants on/off
-        # also, systemctl needs the arguments reversed
+        # also, systemctl needs the argument order reversed
         if self.enable:
             on_off = "on"
             enable_disable = "enable"
@@ -463,19 +473,42 @@ class LinuxService(Service):
         if self.enable is not None and changed:
             return self.execute_command("%s %s %s" % args)
 
+
     def service_control(self):
 
         # Decide what command to run
+        svc_cmd = ''
         if self.svc_cmd:
+            # SysV or systemd
             svc_cmd = "%s %s" % (self.svc_cmd, self.name)
-        elif self.svc_initscript:
+        elif self.svc_initscript: 
+            # upstart
             svc_cmd = "%s" % self.svc_initscript
 
         if self.action is not "restart":
-            rc_state, stdout, stderr = self.execute_command("%s %s %s" % (svc_cmd, self.action, self.arguments), daemonize=True)
+            if svc_cmd != '':
+                # upstart
+                rc_state, stdout, stderr = self.execute_command("%s %s %s" % (svc_cmd, self.action, self.arguments), daemonize=True)
+            else:
+                # SysV or systemd
+                rc_state, stdout, stderr = self.execute_command("%s %s %s" % (self.action, self.name, self.arguments), daemonize=True)
         else:
-            rc1, stdout1, stderr1 = self.execute_command("%s %s %s" % (svc_cmd, 'stop', self.arguments), daemonize=True)
-            rc2, stdout2, stderr2 = self.execute_command("%s %s %s" % (svc_cmd, 'start', self.arguments), daemonize=True)
+            # not all services support restart. Do it the hard way.
+            if svc_cmd != '':
+                # upstart
+                rc1, stdout1, stderr1 = self.execute_command("%s %s %s" % (svc_cmd, 'stop', self.arguments), daemonize=True)
+            else:
+                # SysV or systemd
+                rc1, stdout1, stderr1 = self.execute_command("%s %s %s" % ('stop', self.name, self.arguments), daemonize=True)
+            
+            if svc_cmd != '':
+                # upstart
+                rc2, stdout2, stderr2 = self.execute_command("%s %s %s" % (svc_cmd, 'start', self.arguments), daemonize=True)
+            else:
+                # SysV or systemd
+                rc2, stdout2, stderr2 = self.execute_command("%s %s %s" % ('start', self.name, self.arguments), daemonize=True)
+
+            # merge return information
             if rc1 != 0 and rc2 == 0:
                 rc_state = rc2
                 stdout = stdout2