summaryrefslogtreecommitdiff
path: root/lib/ansible/modules/cloud/vmware/vmware_host_service_manager.py
blob: d6e86a3b3b86753fdc17211692b988ffd74c7ab6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com>
# 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

ANSIBLE_METADATA = {
    'metadata_version': '1.1',
    'status': ['preview'],
    'supported_by': 'community'
}

DOCUMENTATION = r'''
---
module: vmware_host_service_manager
short_description: Manage services on a given ESXi host
description:
- This module can be used to manage (start, stop, restart) services on a given ESXi host.
- If cluster_name is provided, specified service will be managed on all ESXi host belonging to that cluster.
- If specific esxi_hostname is provided, then specified service will be managed on given ESXi host only.
version_added: '2.5'
author:
- Abhijeet Kasurde (@akasurde)
notes:
- Tested on vSphere 6.5
requirements:
- python >= 2.6
- PyVmomi
options:
  cluster_name:
    description:
    - Name of the cluster.
    - Service settings are applied to every ESXi host system/s in given cluster.
    - If C(esxi_hostname) is not given, this parameter is required.
  esxi_hostname:
    description:
    - ESXi hostname.
    - Service settings are applied to this ESXi host system.
    - If C(cluster_name) is not given, this parameter is required.
  state:
    description:
    - Desired state of service.
    - "State value 'start' and 'present' has same effect."
    - "State value 'stop' and 'absent' has same effect."
    choices: [ absent, present, restart, start, stop ]
    default: 'start'
  service_policy:
    description:
    - Set of valid service policy strings.
    - If set C(on), then service should be started when the host starts up.
    - If set C(automatic), then service should run if and only if it has open firewall ports.
    - If set C(off), then Service should not be started when the host starts up.
    choices: [ 'automatic', 'off', 'on' ]
  service_name:
    description:
    - Name of Service to be managed. This is brief identifier for the service, for example, ntpd, vxsyslogd etc.
    - This value should be a valid ESXi service name.
    required: True
extends_documentation_fragment: vmware.documentation
'''

EXAMPLES = r'''
- name: Start ntpd service setting for all ESXi Host in given Cluster
  vmware_host_service_manager:
    hostname: '{{ vcenter_hostname }}'
    username: '{{ vcenter_username }}'
    password: '{{ vcenter_password }}'
    cluster_name: cluster_name
    service_name: ntpd
    state: present

- name: Start ntpd setting for an ESXi Host
  vmware_host_service_manager:
    hostname: '{{ vcenter_hostname }}'
    username: '{{ vcenter_username }}'
    password: '{{ vcenter_password }}'
    esxi_hostname: '{{ esxi_hostname }}'
    service_name: ntpd
    state: present

- name: Start ntpd setting for an ESXi Host with Service policy
  vmware_host_service_manager:
    hostname: '{{ vcenter_hostname }}'
    username: '{{ vcenter_username }}'
    password: '{{ vcenter_password }}'
    esxi_hostname: '{{ esxi_hostname }}'
    service_name: ntpd
    service_policy: on
    state: present

- name: Stop ntpd setting for an ESXi Host
  vmware_host_service_manager:
    hostname: '{{ vcenter_hostname }}'
    username: '{{ vcenter_username }}'
    password: '{{ vcenter_password }}'
    esxi_hostname: '{{ esxi_hostname }}'
    service_name: ntpd
    state: absent
'''

RETURN = r'''#
'''

try:
    from pyVmomi import vim, vmodl
except ImportError:
    pass

from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi
from ansible.module_utils._text import to_native


class VmwareServiceManager(PyVmomi):
    def __init__(self, module):
        super(VmwareServiceManager, self).__init__(module)
        cluster_name = self.params.get('cluster_name', None)
        esxi_host_name = self.params.get('esxi_hostname', None)
        self.options = self.params.get('options', dict())
        self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name)
        self.desired_state = self.params.get('state')
        self.desired_policy = self.params.get('service_policy', None)
        self.service_name = self.params.get('service_name')
        self.results = {}

    def service_ctrl(self):
        changed = False
        host_service_state = []
        for host in self.hosts:
            actual_service_state, actual_service_policy = self.check_service_state(host=host, service_name=self.service_name)
            host_service_system = host.configManager.serviceSystem
            if host_service_system:
                changed_state = False
                self.results[host.name] = dict(service_name=self.service_name,
                                               actual_service_state='running' if actual_service_state else 'stopped',
                                               actual_service_policy=actual_service_policy,
                                               desired_service_policy=self.desired_policy,
                                               desired_service_state=self.desired_state,
                                               error='',
                                               )
                try:
                    if self.desired_state in ['start', 'present']:
                        if not actual_service_state:
                            host_service_system.StartService(id=self.service_name)
                            changed_state = True
                    elif self.desired_state in ['stop', 'absent']:
                        if actual_service_state:
                            host_service_system.StopService(id=self.service_name)
                            changed_state = True
                    elif self.desired_state == 'restart':
                        host_service_system.RestartService(id=self.service_name)
                        changed_state = True

                    if self.desired_policy:
                        if actual_service_policy != self.desired_policy:
                            host_service_system.UpdateServicePolicy(id=self.service_name,
                                                                    policy=self.desired_policy)
                            changed_state = True

                    host_service_state.append(changed_state)
                    self.results[host.name].update(changed=changed_state)
                except (vim.fault.InvalidState, vim.fault.NotFound,
                        vim.fault.HostConfigFault, vmodl.fault.InvalidArgument) as e:
                    self.results[host.name].update(changed=False,
                                                   error=to_native(e.msg))

        if any(host_service_state):
            changed = True
        self.module.exit_json(changed=changed, results=self.results)

    def check_service_state(self, host, service_name):
        host_service_system = host.configManager.serviceSystem
        if host_service_system:
            services = host_service_system.serviceInfo.service
            for service in services:
                if service.key == service_name:
                    return service.running, service.policy

        msg = "Failed to find '%s' service on host system '%s'" % (service_name, host.name)
        cluster_name = self.params.get('cluster_name', None)
        if cluster_name:
            msg += " located on cluster '%s'" % cluster_name
        msg += ", please check if you have specified a valid ESXi service name."
        self.module.fail_json(msg=msg)


def main():
    argument_spec = vmware_argument_spec()
    argument_spec.update(
        cluster_name=dict(type='str', required=False),
        esxi_hostname=dict(type='str', required=False),
        state=dict(type='str', default='start', choices=['absent', 'present', 'restart', 'start', 'stop']),
        service_name=dict(type='str', required=True),
        service_policy=dict(type='str', choices=['automatic', 'off', 'on']),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        required_one_of=[
            ['cluster_name', 'esxi_hostname'],
        ]
    )

    vmware_host_service = VmwareServiceManager(module)
    vmware_host_service.service_ctrl()


if __name__ == "__main__":
    main()