From fec883dfffcd8685d5d57a07463e402c2cd36931 Mon Sep 17 00:00:00 2001 From: Mario Lenz Date: Sun, 8 Dec 2019 19:51:39 +0100 Subject: [PATCH] VMware: Add advanced settings to vmware_cluster_ha --- ...24-vmware_cluster_ha-advanced-settings.yml | 2 + lib/ansible/module_utils/vmware.py | 24 ++++++++ .../modules/cloud/vmware/vmware_cluster_ha.py | 21 ++++++- .../targets/vmware_cluster_ha/tasks/main.yml | 56 +++++++++++++++---- 4 files changed, 91 insertions(+), 12 deletions(-) create mode 100644 changelogs/fragments/58824-vmware_cluster_ha-advanced-settings.yml diff --git a/changelogs/fragments/58824-vmware_cluster_ha-advanced-settings.yml b/changelogs/fragments/58824-vmware_cluster_ha-advanced-settings.yml new file mode 100644 index 00000000000..b62eae6d686 --- /dev/null +++ b/changelogs/fragments/58824-vmware_cluster_ha-advanced-settings.yml @@ -0,0 +1,2 @@ +minor_changes: +- vmware_cluster_ha - Implemented HA advanced settings (https://github.com/ansible/ansible/issues/61421) diff --git a/lib/ansible/module_utils/vmware.py b/lib/ansible/module_utils/vmware.py index e9bcb1d0250..35b2c3d77bc 100644 --- a/lib/ansible/module_utils/vmware.py +++ b/lib/ansible/module_utils/vmware.py @@ -841,6 +841,30 @@ def is_truthy(value): return False +# options is the dict as defined in the module parameters, current_options is +# the list of the currently set options as returned by the vSphere API. +def option_diff(options, current_options): + current_options_dict = {} + for option in current_options: + current_options_dict[option.key] = option.value + + change_option_list = [] + for option_key, option_value in options.items(): + if is_boolean(option_value): + option_value = VmomiSupport.vmodlTypes['bool'](is_truthy(option_value)) + elif isinstance(option_value, int): + option_value = VmomiSupport.vmodlTypes['int'](option_value) + elif isinstance(option_value, float): + option_value = VmomiSupport.vmodlTypes['float'](option_value) + elif isinstance(option_value, str): + option_value = VmomiSupport.vmodlTypes['string'](option_value) + + if option_key not in current_options_dict or current_options_dict[option_key] != option_value: + change_option_list.append(vim.option.OptionValue(key=option_key, value=option_value)) + + return change_option_list + + def quote_obj_name(object_name=None): """ Replace special characters in object name diff --git a/lib/ansible/modules/cloud/vmware/vmware_cluster_ha.py b/lib/ansible/modules/cloud/vmware/vmware_cluster_ha.py index a7ac29ad489..2dd22f16211 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_cluster_ha.py +++ b/lib/ansible/modules/cloud/vmware/vmware_cluster_ha.py @@ -173,6 +173,12 @@ options: type: str default: 'medium' choices: [ 'disabled', 'high', 'low', 'medium' ] + advanced_settings: + version_added: "2.10" + description: + - A dictionary of advanced HA settings. + default: {} + type: dict extends_documentation_fragment: vmware.documentation ''' @@ -225,7 +231,7 @@ except ImportError: from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.vmware import (PyVmomi, TaskError, find_datacenter_by_name, - vmware_argument_spec, wait_for_task) + vmware_argument_spec, wait_for_task, option_diff) from ansible.module_utils._text import to_native @@ -255,6 +261,12 @@ class VMwareCluster(PyVmomi): if self.cluster is None: self.module.fail_json(msg="Cluster %s does not exist." % self.cluster_name) + self.advanced_settings = self.params.get('advanced_settings') + if self.advanced_settings: + self.changed_advanced_settings = option_diff(self.advanced_settings, self.cluster.configurationEx.dasConfig.option) + else: + self.changed_advanced_settings = None + def get_failover_hosts(self): """ Get failover hosts for failover_host_admission_control policy @@ -320,6 +332,9 @@ class VMwareCluster(PyVmomi): if das_config.admissionControlPolicy.failoverHosts != self.get_failover_hosts(): return True + if self.changed_advanced_settings: + return True + return False def configure_ha(self): @@ -376,6 +391,9 @@ class VMwareCluster(PyVmomi): cluster_config_spec.dasConfig.hostMonitoring = self.params.get('ha_host_monitoring') cluster_config_spec.dasConfig.vmMonitoring = self.params.get('ha_vm_monitoring') + if self.changed_advanced_settings: + cluster_config_spec.dasConfig.option = self.changed_advanced_settings + try: task = self.cluster.ReconfigureComputeResource_Task(cluster_config_spec, True) changed, result = wait_for_task(task) @@ -407,6 +425,7 @@ def main(): host_isolation_response=dict(type='str', default='none', choices=['none', 'powerOff', 'shutdown']), + advanced_settings=dict(type='dict', default=dict(), required=False), # HA VM Monitoring related parameters ha_vm_monitoring=dict(type='str', choices=['vmAndAppMonitoring', 'vmMonitoringOnly', 'vmMonitoringDisabled'], diff --git a/test/integration/targets/vmware_cluster_ha/tasks/main.yml b/test/integration/targets/vmware_cluster_ha/tasks/main.yml index d132a41d40e..bda03fd94cb 100644 --- a/test/integration/targets/vmware_cluster_ha/tasks/main.yml +++ b/test/integration/targets/vmware_cluster_ha/tasks/main.yml @@ -127,14 +127,48 @@ that: - "{{ cluster_ha_result_0006.changed == true }}" -# Delete test cluster -- name: Delete test cluster - vmware_cluster: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_ha - state: absent - when: vcsim is not defined +- when: vcsim is not defined + block: + - name: Change advanced setting "number of heartbeat datastores" (check-mode) + vmware_cluster_ha: &change_num_heartbeat_ds + validate_certs: False + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter_name: "{{ dc1 }}" + cluster_name: test_cluster_ha + advanced_settings: + 'das.heartbeatDsPerHost': '4' + check_mode: yes + register: change_num_heartbeat_ds_check + + - assert: + that: + - change_num_heartbeat_ds_check.changed + + - name: Change advanced setting "number of heartbeat datastores" + vmware_cluster_ha: *change_num_heartbeat_ds + register: change_num_heartbeat_ds + + - assert: + that: + - change_num_heartbeat_ds.changed + + - name: Change advanced setting "number of heartbeat datastores" again + vmware_cluster_ha: *change_num_heartbeat_ds + register: change_num_heartbeat_ds_again + + - assert: + that: + - not change_num_heartbeat_ds_again.changed + + # Delete test cluster + - name: Delete test cluster + vmware_cluster: + validate_certs: False + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter_name: "{{ dc1 }}" + cluster_name: test_cluster_ha + state: absent