Repository: ansible/ansible

Issue:
Enable service doesn't work with chroot connection
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
systemd/service module

##### ANSIBLE VERSION
```
ansible 2.2.1.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides

```
##### OS / ENVIRONMENT
Arch Linux

##### SUMMARY
From http://0pointer.de/blog/projects/changing-roots
> First of all, systemctl detects when it is run in a chroot. If so, most of its operations will become NOPs, with the exception of systemctl enable and systemctl disable. If a package installation script hence calls these two commands, services will be enabled in the guest OS. However, should a package installation script include a command like systemctl restart as part of the package upgrade process this will have no effect at all when run in a chroot() environment.

In chroot environment, ansible fails to enable since this commit https://github.com/ansible/ansible-modules-core/commit/2f50979c34d998a5acf70652276e70dbeb70c74c
The variable "found" keep false value because "systemctl show" doesn't work
```
[root@archiso /]# systemctl show systemd-timesyncd.service
Running in chroot, ignoring request.
```
Therefore `fail_if_missing(module, found, unit, "cannot %s" % (action))` is triggered

##### STEPS TO REPRODUCE
Try to enable a service with chroot connection in systemd environment

```yaml
- hosts: /mnt
  user: root
  connection: chroot
  tasks:
    - name: Enable systemd-timesyncd.service
      systemd:
        name: systemd-timesyncd.service
        enabled: yes
```

##### EXPECTED RESULTS
Enable the service (symlink created)

##### ACTUAL RESULTS
```
fatal: [/mnt]: FAILED! => {"changed": false, "failed": true, "msg": "Could not find the requested service systemd-timesyncd.service: cannot enable"}

```



Discussion:
is there any way to verify the systemd service exists if systemd itself lies to us?
"found"  is set from the output of `(rc, out, err) = module.run_command("%s show '%s'" % (systemctl, unit))`. Replace `show` by `list-unit-files` should fix this problem since `list-unit-files` works in chroot environment :

```
[root@archiso /]# systemctl list-unit-files systemd-timesyncd.service 
UNIT FILE                 STATE   
systemd-timesyncd.service disabled

1 unit files listed.
```

Just noting that this prevents folks from using service/systemd modules in an installer environment like kickstart/anaconda -- which is counterintuitive because commands like `systemctl enable` and `systemctl disable` work.
sadly list-unit-files won't find init scripts systemd can also manage .... rock meet hard place

also it REQUIRES .service ... which is not required by the other commands 

Resolving patch:
diff --git a/lib/ansible/modules/system/systemd.py b/lib/ansible/modules/system/systemd.py
--- a/lib/ansible/modules/system/systemd.py
+++ b/lib/ansible/modules/system/systemd.py
@@ -33,7 +33,7 @@
     name:
         required: true
         description:
-            - Name of the service.
+            - Name of the service. When using in a chroot environment you always need to specify the full name i.e. (crond.service).
         aliases: ['unit', 'service']
     state:
         required: false
@@ -298,6 +298,7 @@ def main():
 
     # check service data, cannot error out on rc as it changes across versions, assume not found
     (rc, out, err) = module.run_command("%s show '%s'" % (systemctl, unit))
+
     if rc == 0:
         # load return of systemctl show into dictionary for easy access and return
         multival = []
@@ -328,6 +329,14 @@ def main():
             if is_systemd and 'LoadError' in result['status']:
                 module.fail_json(msg="Error loading unit file '%s': %s" % (unit, result['status']['LoadError']))
 
+    elif out.find('ignoring request') != -1:
+        # fallback list-unit-files as show does not work on some systems (chroot)
+        # not used as primary as it skips some services (like those using init.d) and requires .service/etc notation
+        (rc, out, err) = module.run_command("%s list-unit-files '%s'" % (systemctl, unit))
+        if rc == 0:
+            is_systemd = True
+
+
     # Does service exist?
     found = is_systemd or is_initd
     if is_initd and not is_systemd:


Test patch: