diff --git a/lib/ansible/modules/cloud/vmware/vmware_vm_vm_drs_rule.py b/lib/ansible/modules/cloud/vmware/vmware_vm_vm_drs_rule.py index 10e8cf240b6..38a6d594ad9 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_vm_vm_drs_rule.py +++ b/lib/ansible/modules/cloud/vmware/vmware_vm_vm_drs_rule.py @@ -62,7 +62,7 @@ options: state: description: - If set to C(present), then the DRS rule is created if not present. - - If set to C(present), then the DRS rule is deleted and created if present already. + - If set to C(present), then the DRS rule is already present, it updates to the given configurations. - If set to C(absent), then the DRS rule is deleted if present. required: False default: present @@ -94,11 +94,11 @@ EXAMPLES = r''' password: "{{ esxi_password }}" cluster_name: "{{ cluster_name }}" validate_certs: no + enabled: True vms: - vm1 - vm2 drs_rule_name: vm1-vm2-affinity-rule-001 - enabled: True mandatory: True affinity_rule: False delegate_to: localhost @@ -169,7 +169,7 @@ class VmwareDrs(PyVmomi): # Getter def get_all_vms_info(self, vms_list=None): """ - Function to get all VM objects using name from given cluster + Get all VM objects using name from given cluster Args: vms_list: List of VM names @@ -192,7 +192,7 @@ class VmwareDrs(PyVmomi): def get_rule_key_by_name(self, cluster_obj=None, rule_name=None): """ - Function to get a specific DRS rule key by name + Get a specific DRS rule key by name Args: rule_name: Name of rule cluster_obj: Cluster managed object @@ -213,7 +213,7 @@ class VmwareDrs(PyVmomi): @staticmethod def normalize_rule_spec(rule_obj=None): """ - Function to return human readable rule spec + Return human readable rule spec Args: rule_obj: Rule managed object @@ -234,29 +234,26 @@ class VmwareDrs(PyVmomi): # Create def create(self): """ - Function to create a DRS rule if rule does not exist + Create a DRS rule if rule does not exist """ rule_obj = self.get_rule_key_by_name(rule_name=self.rule_name) if rule_obj is not None: - # Rule already exists, remove and create again - # Cluster does not allow editing existing rule existing_rule = self.normalize_rule_spec(rule_obj=rule_obj) if ((sorted(existing_rule['rule_vms']) == sorted(self.vm_list)) and (existing_rule['rule_enabled'] == self.enabled) and (existing_rule['rule_mandatory'] == self.mandatory) and (existing_rule['rule_affinity'] == self.affinity_rule)): - # Rule is same as existing rule, evacuate - self.module.exit_json(changed=False, result=existing_rule) - # Delete existing rule as we cannot edit it - changed, result = self.delete(rule_name=self.rule_name) - if not changed: - self.module.fail_json(msg="Failed to delete while updating rule %s due to %s" % (self.rule_name, result)) - changed, result = self.create_rule_spec() - return changed, result + self.module.exit_json(changed=False, result=existing_rule, msg="Rule already exists with the same configuration") + else: + changed, result = self.update_rule_spec(rule_obj) + return changed, result + else: + changed, result = self.create_rule_spec() + return changed, result def create_rule_spec(self): """ - Function to create DRS rule + Create DRS rule """ changed = False if self.affinity_rule: @@ -286,10 +283,41 @@ class VmwareDrs(PyVmomi): return changed, result + def update_rule_spec(self, rule_obj=None): + """ + Update DRS rule + """ + changed = False + + rule_obj.vm = self.vm_obj_list + + if (rule_obj.mandatory != self.mandatory): + rule_obj.mandatory = self.mandatory + + if (rule_obj.enabled != self.enabled): + rule_obj.enabled = self.enabled + + rule_spec = vim.cluster.RuleSpec(info=rule_obj, operation='edit') + config_spec = vim.cluster.ConfigSpec(rulesSpec=[rule_spec]) + + try: + task = self.cluster_obj.ReconfigureCluster_Task(config_spec, modify=True) + changed, result = wait_for_task(task) + except vmodl.fault.InvalidRequest as e: + result = to_native(e.msg) + except Exception as e: + result = to_native(e) + + if changed: + rule_obj = self.get_rule_key_by_name(rule_name=self.rule_name) + result = self.normalize_rule_spec(rule_obj) + + return changed, result + # Delete def delete(self, rule_name=None): """ - Function to delete DRS rule using name + Delete DRS rule using name """ changed = False if rule_name is None: @@ -326,7 +354,7 @@ def main(): ) required_if = [ - ['state', 'present', ['vms']], + ['state', 'present', ['vms']] ] module = AnsibleModule(argument_spec=argument_spec, required_if=required_if, @@ -347,7 +375,6 @@ def main(): else: results['failed'] = True results['msg'] = "Failed to create DRS rule %s" % vm_drs.rule_name - results['result'] = result elif state == 'absent': # Delete Rule diff --git a/test/integration/targets/vmware_vm_vm_drs_rule/tasks/main.yml b/test/integration/targets/vmware_vm_vm_drs_rule/tasks/main.yml index 7db11af7d11..8f049f7002b 100644 --- a/test/integration/targets/vmware_vm_vm_drs_rule/tasks/main.yml +++ b/test/integration/targets/vmware_vm_vm_drs_rule/tasks/main.yml @@ -11,7 +11,9 @@ setup_attach_host: true setup_datastore: true setup_virtualmachines: true - - name: Create a DRS Affinity rule for vms + + - &create_drs_rule + name: Create a DRS Affinity rule for vms vmware_vm_vm_drs_rule: validate_certs: False hostname: "{{ vcenter_hostname }}" @@ -24,12 +26,24 @@ affinity_rule: True mandatory: True register: drs_rule_0001_results - - debug: var=drs_rule_0001_results - - assert: - that: - - "{{ drs_rule_0001_results.changed }}" - - name: Create a DRS Anti-Affinity rule for vms + - debug: var=drs_rule_0001_results + + - name: Check if changes are made + assert: + that: + - drs_rule_0001_results.changed + + - <<: *create_drs_rule + name: Create a DRS Affinity rule for vms again + + - name: Check if no changes are made if drs rule is created again + assert: + that: + - not drs_rule_0001_results.changed + + - &update_drs_rule + name: Update a DRS Affinity rule for vms vmware_vm_vm_drs_rule: validate_certs: False hostname: "{{ vcenter_hostname }}" @@ -37,12 +51,94 @@ password: "{{ vcenter_password }}" drs_rule_name: drs_rule_0001 cluster_name: "{{ ccr1 }}" - vms: "{{ virtual_machines | map(attribute='name') | list }}" + vms: "{{ virtual_machines_in_cluster | map(attribute='name') | list }}" enabled: False + affinity_rule: True + mandatory: False + register: drs_rule_0001_results + + - name: Check if changes are made if drs rule is created + assert: + that: + - drs_rule_0001_results.changed + + - <<: *update_drs_rule + name: Update a DRS Affinity rule for vms again + + - name: Check if no changes are made if drs rule is created again + assert: + that: + - not drs_rule_0001_results.changed + + - &delete_drs_rule + name: Delete a DRS Affinity rule for vms + vmware_vm_vm_drs_rule: + validate_certs: False + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + drs_rule_name: drs_rule_0001 + cluster_name: "{{ ccr1 }}" + state: absent + register: drs_rule_0001_results + + - name: Check if DRS rule is delete + assert: + that: + - drs_rule_0001_results.changed + + - <<: *delete_drs_rule + name: Delete a DRS Affinity rule for vms again + + - name: Check if DRS rule is not delete again + assert: + that: + - not drs_rule_0001_results.changed + + - &create_anti_drs_rule + name: Create a DRS Anti-Affinity rule for vms + vmware_vm_vm_drs_rule: + validate_certs: False + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + drs_rule_name: drs_rule_0002 + cluster_name: "{{ ccr1 }}" + vms: "{{ virtual_machines_in_cluster | map(attribute='name') | list }}" + enabled: True affinity_rule: False mandatory: False register: drs_rule_0002_results + - debug: var=drs_rule_0002_results - - assert: + + - name: Check if DRS Anti-Affinity rule is created + assert: that: - - "{{ drs_rule_0002_results.changed }}" + - drs_rule_0002_results.changed + + - <<: *create_anti_drs_rule + name: Create a DRS Anti-Affinity rule for vms again + + - debug: var=drs_rule_0002_results + + - name: Check if no changes are made if DRS Anti-Affinity rule is created again + assert: + that: + - not drs_rule_0002_results.changed + + - name: Delete a DRS Anti-Affinity rule for vms + vmware_vm_vm_drs_rule: + validate_certs: False + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + drs_rule_name: drs_rule_0002 + cluster_name: "{{ ccr1 }}" + state: absent + register: drs_rule_0002_results + + - name: Check if DRS rule is not delete + assert: + that: + - drs_rule_0002_results.changed