From 249e00780e3375c48b81c25cdd8f8110668f9200 Mon Sep 17 00:00:00 2001 From: Philipp Fruck Date: Wed, 5 Apr 2023 14:24:36 +0200 Subject: [PATCH 1/3] add vsan_health_silent_checks module This module adds functionality to silence or reactivate health checks that should not cause alarms in the vCenter UI. A common usecase could be to silence health checks that require internet connectivity in airgapped installations --- plugins/modules/vsan_health_silent_checks.py | 142 +++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 plugins/modules/vsan_health_silent_checks.py diff --git a/plugins/modules/vsan_health_silent_checks.py b/plugins/modules/vsan_health_silent_checks.py new file mode 100644 index 000000000..6c700f993 --- /dev/null +++ b/plugins/modules/vsan_health_silent_checks.py @@ -0,0 +1,142 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Hewlett Packard Enterprise Development LP +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = r''' +--- +module: vsan_health_silent_checks +short_description: Silence vSAN health checks +description: + - Take a list of vSAN health checks and silence them + - Re-enable alerts for previously silenced health checks +author: + - Philipp Fruck (@p-fruck) +requirements: + - vSAN Management SDK, which needs to be downloaded from VMware and installed manually. +options: + cluster_name: + description: + - Name of the vSAN cluster. + type: str + required: true + checks: + description: + - The checks to silence. + type: list + elements: str + required: false + state: + description: + - The state of the health checks. + - If set to C(present), all given health checks will be silenced. + - If set to C(absent), all given health checks will be removed from the list of silent checks. + default: 'present' + choices: [ 'present', 'absent' ] + type: str +extends_documentation_fragment: + - community.vmware.vmware.documentation +''' + +EXAMPLES = r''' +- name: Disable the vSAN Support Insight health check + community.vmware.vsan_health_silent_checks: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + checks: vsanenablesupportinsight + cluster_name: 'vSAN01' + delegate_to: localhost + +- name: Re-enable health check alerts for release catalog and HCL DB + community.vmware.vsan_health_silent_checks: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + checks: + - releasecataloguptodate + - autohclupdate + state: absent + cluster_name: 'vSAN01' + delegate_to: localhost +''' + +RETURN = r'''# +''' + + +import traceback + +VSANPYTHONSDK_IMP_ERR = None +try: + import vsanapiutils + HAS_VSANPYTHONSDK = True +except ImportError: + VSANPYTHONSDK_IMP_ERR = traceback.format_exc() + HAS_VSANPYTHONSDK = False + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.vmware.plugins.module_utils.vmware import PyVmomi, vmware_argument_spec + + +class VsanApi(PyVmomi): + def __init__(self, module): + super(VsanApi, self).__init__(module) + + client_stub = self.si._GetStub() + ssl_context = client_stub.schemeArgs.get('context') + apiVersion = vsanapiutils.GetLatestVmodlVersion(module.params['hostname']) + vcMos = vsanapiutils.GetVsanVcMos(client_stub, context=ssl_context, version=apiVersion) + self.vsanClusterHealthSystem = vcMos['vsan-cluster-health-system'] + + self.cluster = None + + def silence_checks(self): + cluster_name = self.params.get('cluster_name') + if cluster_name: + self.cluster = self.find_cluster_by_name(cluster_name=cluster_name) + if self.cluster is None: + self.module.fail_json(msg="Cluster %s does not exist." % cluster_name) + + kwargs = {'cluster': self.cluster} + checks = self.params.get('checks') + state = self.params.get('state') + if state == 'present': + kwargs['addSilentChecks'] = checks + else: + kwargs['removeSilentChecks'] = checks + + success = self.vsanClusterHealthSystem.VsanHealthSetVsanClusterSilentChecks(**kwargs) + self.module.exit_json(changed=success) + + +def main(): + argument_spec = vmware_argument_spec() + + argument_spec.update(dict( + checks=dict(type='list', elements='str', required=False), + cluster_name=dict(type='str', required=True), + state=dict(type='str', choices=['present', 'absent'], default='present'), + )) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + ) + + api = VsanApi(module) + try: + api.silence_checks() + except Exception as e: + module.fail_json(msg=str(e)) + + +if __name__ == '__main__': + main() From ed6c081415f8aeca6771fe5ab7764733b7f884f2 Mon Sep 17 00:00:00 2001 From: Philipp Fruck Date: Thu, 6 Apr 2023 13:16:36 +0000 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Mario Lenz --- plugins/modules/vsan_health_silent_checks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/vsan_health_silent_checks.py b/plugins/modules/vsan_health_silent_checks.py index 6c700f993..42d180b6d 100644 --- a/plugins/modules/vsan_health_silent_checks.py +++ b/plugins/modules/vsan_health_silent_checks.py @@ -13,6 +13,7 @@ DOCUMENTATION = r''' --- module: vsan_health_silent_checks +version_added: '3.6.0' short_description: Silence vSAN health checks description: - Take a list of vSAN health checks and silence them @@ -128,7 +129,6 @@ def main(): module = AnsibleModule( argument_spec=argument_spec, - supports_check_mode=True, ) api = VsanApi(module) From 8d2dcc32fc059cf04efd5ca7966265b420e4ab57 Mon Sep 17 00:00:00 2001 From: Philipp Fruck Date: Wed, 12 Apr 2023 17:40:13 +0200 Subject: [PATCH 3/3] vsan_health_silent_checks: make module idempotent --- plugins/modules/vsan_health_silent_checks.py | 29 +++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/plugins/modules/vsan_health_silent_checks.py b/plugins/modules/vsan_health_silent_checks.py index 42d180b6d..b62068220 100644 --- a/plugins/modules/vsan_health_silent_checks.py +++ b/plugins/modules/vsan_health_silent_checks.py @@ -96,26 +96,34 @@ def __init__(self, module): apiVersion = vsanapiutils.GetLatestVmodlVersion(module.params['hostname']) vcMos = vsanapiutils.GetVsanVcMos(client_stub, context=ssl_context, version=apiVersion) self.vsanClusterHealthSystem = vcMos['vsan-cluster-health-system'] + self.get_cluster() - self.cluster = None - - def silence_checks(self): + def get_cluster(self): cluster_name = self.params.get('cluster_name') - if cluster_name: - self.cluster = self.find_cluster_by_name(cluster_name=cluster_name) - if self.cluster is None: - self.module.fail_json(msg="Cluster %s does not exist." % cluster_name) + self.cluster = self.find_cluster_by_name(cluster_name=cluster_name) + if self.cluster is None: + self.module.fail_json(msg=f"Cluster {cluster_name} does not exist.") + def process_state(self): kwargs = {'cluster': self.cluster} - checks = self.params.get('checks') + silent_checks = self.vsanClusterHealthSystem.VsanHealthGetVsanClusterSilentChecks(**kwargs) + state = self.params.get('state') if state == 'present': + checks = [check for check in self.params.get('checks') if check not in silent_checks] kwargs['addSilentChecks'] = checks else: + checks = [check for check in self.params.get('checks') if check in silent_checks] kwargs['removeSilentChecks'] = checks + if not checks: + return False + success = self.vsanClusterHealthSystem.VsanHealthSetVsanClusterSilentChecks(**kwargs) - self.module.exit_json(changed=success) + if not success: + raise Exception(f"Unknown error modifying checks {checks}") + + return True def main(): @@ -133,7 +141,8 @@ def main(): api = VsanApi(module) try: - api.silence_checks() + changed = api.process_state() + module.exit_json(changed=changed) except Exception as e: module.fail_json(msg=str(e))