Skip to content

Commit

Permalink
Add a VM DRS Override module (#2229)
Browse files Browse the repository at this point in the history
Fixes #2026
SUMMARY
This PR contains a new Ansible module, vmware_drs_override, to the community.vmware collection. The module allows users to configure Distributed Resource Scheduler (DRS) behavior overrides for individual VMs within a VMware vSphere cluster. This provides users with enhanced control over VM placement, resource allocation, and automation behavior by enabling DRS settings specific to each VM rather than relying solely on cluster-wide configurations.
Key design decisions include:

Encapsulating functionality in a class to streamline the connection, VM lookup, and DRS configuration processes.
Ensuring the module aligns with other community.vmware modules in terms of structure, error handling, and documentation.

ISSUE TYPE

New Module Pull Request

COMPONENT NAME
vmware_drs_override
ADDITIONAL INFORMATION
The vmware_drs_override module provides the following parameters:

hostname, username, password, and port for vCenter server access.
validate_certs to handle SSL verification.
vm_name and drs_behavior to specify the VM and desired DRS configuration (options include manual, partiallyAutomated, and fullyAutomated).

This module was tested using a local vCenter environment to verify correct DRS behavior application and task handling. Example playbook and command output are provided below to demonstrate module functionality.
# Example playbook:
- name: Test VMware DRS Override Module
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Apply DRS override to VM
      community.vmware.vmware_drs_override:
        hostname: "vcenter.example.com"
        username: "[email protected]"
        password: "yourpassword"
        port: 443
        validate_certs: False
        vm_name: "my_vm_name"
        drs_behavior: "manual"
      register: result

    - name: Show Result
      debug:
        var: result

Reviewed-by: Alexander Nikitin <[email protected]>
Reviewed-by: svg1007
Reviewed-by: Mario Lenz <[email protected]>
  • Loading branch information
svg1007 authored Nov 28, 2024
1 parent 37cd1ba commit 3bcd926
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 0 deletions.
1 change: 1 addition & 0 deletions meta/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ action_groups:
- vmware_drs_group
- vmware_drs_group_info
- vmware_drs_group_manager
- vmware_drs_override
- vmware_drs_rule_info
- vmware_dvs_host
- vmware_dvs_portgroup
Expand Down
123 changes: 123 additions & 0 deletions plugins/modules/vmware_drs_override.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# 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

DOCUMENTATION = '''
---
module: vmware_drs_override
version_added: '5.2.0'
short_description: Configure DRS behavior for a specific VM in vSphere
description:
- This module allows setting a DRS behavior override for individual VMs within a DRS-enabled VMware vSphere cluster.
options:
vm_name:
description:
- Name of the VM for which the DRS override is set.
required: true
type: str
drs_behavior:
description:
- Desired DRS behavior for the VM.
choices: ['manual', 'partiallyAutomated', 'fullyAutomated']
default: 'manual'
type: str
extends_documentation_fragment:
- community.vmware.vmware.documentation
author:
- Sergey Goncharov (@svg1007)
'''

EXAMPLES = '''
- name: Set DRS behavior for a VM
vmware_drs_override:
hostname: "vcenter.example.com"
username: "[email protected]"
password: "yourpassword"
port: 443
validate_certs: False
vm_name: "my_vm_name"
drs_behavior: "manual"
'''

RETURN = '''
changed:
description: Whether the DRS behavior was changed.
type: bool
returned: always
msg:
description: A message describing the outcome of the task.
type: str
returned: always
'''

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

from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.vmware.plugins.module_utils.vmware import vmware_argument_spec, wait_for_task, PyVmomi


class VmwareDrsOverride(PyVmomi):
def __init__(self, module):
super(VmwareDrsOverride, self).__init__(module)
self.vm_name = self.params.get('vm_name', None)
self.drs_behavior = module.params['drs_behavior']
self.params['name'] = self.vm_name
self.vm = self.get_vm()
if not self.vm:
self.module.fail_json(msg="VM '%s' not found." % self.vm_name)

if not self.is_vcenter():
self.module.fail_json(msg="DRS configuration is only supported in vCenter environments.")

def set_drs_override(self):
cluster = self.vm.runtime.host.parent

# Check current DRS settings
existing_config = next((config for config in cluster.configuration.drsVmConfig if config.key == self.vm), None)
if existing_config and existing_config.behavior == self.drs_behavior:
self.module.exit_json(changed=False, msg="DRS behavior is already set to the desired state.")

# Create DRS VM config spec
drs_vm_config_spec = vim.cluster.DrsVmConfigSpec(
operation='add',
info=vim.cluster.DrsVmConfigInfo(
key=self.vm,
enabled=True,
behavior=self.drs_behavior
)
)

# Apply the cluster reconfiguration
cluster_config_spec = vim.cluster.ConfigSpec()
cluster_config_spec.drsVmConfigSpec = [drs_vm_config_spec]
try:
task = cluster.ReconfigureCluster_Task(spec=cluster_config_spec, modify=True)
wait_for_task(task)
self.module.exit_json(changed=True, msg="DRS override applied successfully.")
except vmodl.MethodFault as error:
self.module.fail_json(msg="Failed to set DRS override: %s" % error.msg)


def main():
argument_spec = vmware_argument_spec()
argument_spec.update(dict(
vm_name=dict(type='str', required=True),
drs_behavior=dict(type='str', choices=['manual', 'partiallyAutomated', 'fullyAutomated'], default='manual')
))

module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True
)

drs_override = VmwareDrsOverride(module)
drs_override.set_drs_override()


if __name__ == '__main__':
main()
3 changes: 3 additions & 0 deletions tests/integration/targets/vmware_drs_override/aliases
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cloud/vcenter
needs/target/prepare_vmware_tests
zuul/vmware/vcenter_1esxi
79 changes: 79 additions & 0 deletions tests/integration/targets/vmware_drs_override/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Test code for the vmware_drs_override module

- import_role:
name: prepare_vmware_tests
vars:
setup_attach_host: true
setup_virtualmachines: true

# Gather information about available VMs
- name: Get info about available VMs
vmware_vm_info:
validate_certs: false
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
register: vm_info

- name: Set fact for the first VM name
set_fact:
first_vm_name: "{{ vm_info.virtual_machines[0].guest_name }}"

# Test case: Add DRS Override - DRS enabled
- name: Add DRS override 'manual' for a VM in a DRS-enabled cluster
vmware_drs_override:
validate_certs: false
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
vm_name: "{{ first_vm_name }}"
drs_behavior: "manual"
register: drs_override_result
when: drs_enabled is defined and drs_enabled

- name: Assert DRS override applied successfully
assert:
that:
- drs_override_result.changed == true
- "'DRS override applied successfully' in drs_override_result.msg"
when: drs_enabled is defined and drs_enabled

# Test case: Ensure proper error for standalone ESXi without DRS
- name: Attempt to add DRS override for VM in a non-DRS environment
vmware_drs_override:
validate_certs: false
hostname: "{{ standalone_esxi_hostname }}"
username: "{{ esxi_username }}"
password: "{{ esxi_password }}"
vm_name: "{{ first_vm_name }}"
drs_behavior: "manual"
register: drs_override_non_drs_result
ignore_errors: true
when: standalone_esxi_hostname is defined

- name: Assert error for non-DRS environment
assert:
that:
- drs_override_non_drs_result.failed == true
- "'DRS configuration is only supported in vCenter environments' in drs_override_non_drs_result.msg"
when: standalone_esxi_hostname is defined

# Test case: Check behavior for a vCenter cluster with DRS disabled
- name: Attempt to add DRS override for VM in a vCenter cluster with DRS disabled
vmware_drs_override:
validate_certs: false
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
vm_name: "{{ first_vm_name }}"
drs_behavior: "manual"
register: drs_override_drs_disabled_result
ignore_errors: true
when: drs_disabled is defined and drs_disabled

- name: Assert error for DRS-disabled cluster
assert:
that:
- drs_override_drs_disabled_result.failed == true
- "'DRS is not enabled on the cluster' in drs_override_drs_disabled_result.msg"
when: drs_disabled is defined and drs_disabled

0 comments on commit 3bcd926

Please sign in to comment.