From cdf62edc65f564fff6b7e575e084026fa7faa409 Mon Sep 17 00:00:00 2001 From: dberg1 <48122102+dberg1@users.noreply.github.com> Date: Tue, 13 Oct 2020 17:28:59 +0200 Subject: [PATCH] service_facts: return service state information on AIX (#72073) * service_facts: return service state information on AIX AIX uses the System Resource Controller (SRC) to manage services. See https://www.ibm.com/support/knowledgecenter/ssw_aix_72/osmanagement/sysrescon.htm Use lssrc command on AIX to return service state information. Co-authored-by: dberg1 --- .../fragments/72073-service_facts-aix-src.yml | 2 + lib/ansible/modules/service_facts.py | 35 ++++- test/units/modules/test_service_facts.py | 126 ++++++++++++++++++ 3 files changed, 160 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/72073-service_facts-aix-src.yml create mode 100644 test/units/modules/test_service_facts.py diff --git a/changelogs/fragments/72073-service_facts-aix-src.yml b/changelogs/fragments/72073-service_facts-aix-src.yml new file mode 100644 index 00000000000..c50c5ac1366 --- /dev/null +++ b/changelogs/fragments/72073-service_facts-aix-src.yml @@ -0,0 +1,2 @@ +minor_changes: + - service_facts - return service state information on AIX. diff --git a/lib/ansible/modules/service_facts.py b/lib/ansible/modules/service_facts.py index 407be92128b..81b2496b955 100644 --- a/lib/ansible/modules/service_facts.py +++ b/lib/ansible/modules/service_facts.py @@ -16,7 +16,7 @@ short_description: Return service state information as fact data description: - Return service state information as fact data for various service management utilities version_added: "2.5" -requirements: ["Any of the following supported init systems: systemd, sysv, upstart"] +requirements: ["Any of the following supported init systems: systemd, sysv, upstart, AIX SRC"] notes: - When accessing the C(ansible_facts.services) facts collected by this module, @@ -25,6 +25,7 @@ notes: C(ansible_facts.services.zuul-gateway). It is instead recommended to using the string value of the service name as the key in order to obtain the fact data value like C(ansible_facts.services['zuul-gateway']) + - AIX SRC was added in version 2.11. author: - Adam Miller (@maxamillion) @@ -53,7 +54,7 @@ ansible_facts: source: description: - Init system of the service. - - One of C(systemd), C(sysv), C(upstart). + - One of C(systemd), C(sysv), C(upstart), C(src). returned: always type: str sample: sysv @@ -79,6 +80,7 @@ ansible_facts: ''' +import platform import re from ansible.module_utils.basic import AnsibleModule @@ -230,10 +232,37 @@ class SystemctlScanService(BaseService): return services +class AIXScanService(BaseService): + + def gather_services(self): + services = {} + if platform.system() != 'AIX': + return None + lssrc_path = self.module.get_bin_path("lssrc") + if lssrc_path is None: + return None + rc, stdout, stderr = self.module.run_command("%s -a" % lssrc_path) + for line in stdout.split('\n'): + line_data = line.split() + if len(line_data) < 2: + continue # Skipping because we expected more data + if line_data[0] == "Subsystem": + continue # Skip header + service_name = line_data[0] + if line_data[-1] == "active": + service_state = "running" + elif line_data[-1] == "inoperative": + service_state = "stopped" + else: + service_state = "unknown" + services[service_name] = {"name": service_name, "state": service_state, "source": "src"} + return services + + def main(): module = AnsibleModule(argument_spec=dict(), supports_check_mode=True) module.run_command_environ_update = dict(LANG="C", LC_ALL="C") - service_modules = (ServiceScanService, SystemctlScanService) + service_modules = (ServiceScanService, SystemctlScanService, AIXScanService) all_services = {} incomplete_warning = False for svc_module in service_modules: diff --git a/test/units/modules/test_service_facts.py b/test/units/modules/test_service_facts.py new file mode 100644 index 00000000000..07f6827e02f --- /dev/null +++ b/test/units/modules/test_service_facts.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2020 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +from units.compat import unittest +from units.compat.mock import patch + +from ansible.module_utils import basic +from ansible.modules.service_facts import AIXScanService + + +# AIX # lssrc -a +LSSRC_OUTPUT = """ +Subsystem Group PID Status + sendmail mail 5243302 active + syslogd ras 5636528 active + portmap portmap 5177768 active + snmpd tcpip 5308844 active + hostmibd tcpip 5374380 active + snmpmibd tcpip 5439918 active + aixmibd tcpip 5505456 active + nimsh nimclient 5571004 active + aso 6029758 active + biod nfs 6357464 active + nfsd nfs 5701906 active + rpc.mountd nfs 6488534 active + rpc.statd nfs 7209216 active + rpc.lockd nfs 7274988 active + qdaemon spooler 6816222 active + writesrv spooler 6685150 active + clcomd caa 7471600 active + sshd ssh 7602674 active + pfcdaemon 7012860 active + ctrmc rsct 6947312 active + IBM.HostRM rsct_rm 14418376 active + IBM.ConfigRM rsct_rm 6160674 active + IBM.DRM rsct_rm 14680550 active + IBM.MgmtDomainRM rsct_rm 14090676 active + IBM.ServiceRM rsct_rm 13828542 active + cthats cthats 13959668 active + cthags cthags 14025054 active + IBM.StorageRM rsct_rm 12255706 active + inetd tcpip 12517828 active + lpd spooler inoperative + keyserv keyserv inoperative + ypbind yp inoperative + gsclvmd inoperative + cdromd inoperative + ndpd-host tcpip inoperative + ndpd-router tcpip inoperative + netcd netcd inoperative + tftpd tcpip inoperative + routed tcpip inoperative + mrouted tcpip inoperative + rsvpd qos inoperative + policyd qos inoperative + timed tcpip inoperative + iptrace tcpip inoperative + dpid2 tcpip inoperative + rwhod tcpip inoperative + pxed tcpip inoperative + binld tcpip inoperative + xntpd tcpip inoperative + gated tcpip inoperative + dhcpcd tcpip inoperative + dhcpcd6 tcpip inoperative + dhcpsd tcpip inoperative + dhcpsdv6 tcpip inoperative + dhcprd tcpip inoperative + dfpd tcpip inoperative + named tcpip inoperative + automountd autofs inoperative + nfsrgyd nfs inoperative + gssd nfs inoperative + cpsd ike inoperative + tmd ike inoperative + isakmpd inoperative + ikev2d inoperative + iked ike inoperative + clconfd caa inoperative + ksys_vmmon inoperative + nimhttp inoperative + IBM.SRVPROXY ibmsrv inoperative + ctcas rsct inoperative + IBM.ERRM rsct_rm inoperative + IBM.AuditRM rsct_rm inoperative + isnstgtd isnstgtd inoperative + IBM.LPRM rsct_rm inoperative + cthagsglsm cthags inoperative +""" + + +class TestAIXScanService(unittest.TestCase): + + def setUp(self): + self.mock1 = patch.object(basic.AnsibleModule, 'get_bin_path', return_value='/usr/sbin/lssrc') + self.mock1.start() + self.addCleanup(self.mock1.stop) + self.mock2 = patch.object(basic.AnsibleModule, 'run_command', return_value=(0, LSSRC_OUTPUT, '')) + self.mock2.start() + self.addCleanup(self.mock2.stop) + self.mock3 = patch('platform.system', return_value='AIX') + self.mock3.start() + self.addCleanup(self.mock3.stop) + + def test_gather_services(self): + svcmod = AIXScanService(basic.AnsibleModule) + result = svcmod.gather_services() + + self.assertIsInstance(result, dict) + + self.assertIn('IBM.HostRM', result) + self.assertEqual(result['IBM.HostRM'], { + 'name': 'IBM.HostRM', + 'source': 'src', + 'state': 'running', + }) + self.assertIn('IBM.AuditRM', result) + self.assertEqual(result['IBM.AuditRM'], { + 'name': 'IBM.AuditRM', + 'source': 'src', + 'state': 'stopped', + })