diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_powerstate.py b/lib/ansible/modules/cloud/vmware/vmware_guest_powerstate.py index 151e4b7aa2..a7f7f48e29 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_powerstate.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_powerstate.py @@ -50,7 +50,7 @@ options: version_added: '2.8' folder: description: - - Destination folder, absolute or relative path to find an existing guest or create the new guest. + - Destination folder, absolute or relative path to find an existing guest. - The folder should include the datacenter. ESX's datacenter is ha-datacenter - 'Examples:' - ' folder: /ha-datacenter/vm' @@ -62,14 +62,32 @@ options: - ' folder: /folder1/datacenter1/vm' - ' folder: folder1/datacenter1/vm' - ' folder: /folder1/datacenter1/vm/folder2' - - ' folder: vm/folder2' - - ' folder: folder2' - default: /vm scheduled_at: description: - Date and time in string format at which specificed task needs to be performed. - "The required format for date and time - 'dd/mm/yyyy hh:mm'." - Scheduling task requires vCenter server. A standalone ESXi server does not support this option. + schedule_task_name: + description: + - Name of schedule task. + - Valid only if C(scheduled_at) is specified. + type: str + required: False + version_added: '2.9' + schedule_task_description: + description: + - Description of schedule task. + - Valid only if C(scheduled_at) is specified. + type: str + required: False + version_added: '2.9' + schedule_task_enabled: + description: + - Flag to indicate whether the scheduled task is enabled or disabled. + type: bool + required: False + default: True + version_added: '2.9' force: description: - Ignore warnings and complete the actions. @@ -109,6 +127,9 @@ EXAMPLES = r''' name: "{{ guest_name }}" state: powered-off scheduled_at: "09/01/2018 10:18" + schedule_task_name: "task_00001" + schedule_task_description: "Sample task to poweroff VM" + schedule_task_enabled: True delegate_to: localhost register: deploy_at_schedule_datetime @@ -131,6 +152,7 @@ try: except ImportError: pass +from random import randint from datetime import datetime from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.vmware import PyVmomi, set_vm_power_state, vmware_argument_spec @@ -146,9 +168,12 @@ def main(): name_match=dict(type='str', choices=['first', 'last'], default='first'), uuid=dict(type='str'), use_instance_uuid=dict(type='bool', default=False), - folder=dict(type='str', default='/vm'), + folder=dict(type='str'), force=dict(type='bool', default=False), scheduled_at=dict(type='str'), + schedule_task_name=dict(), + schedule_task_description=dict(), + schedule_task_enabled=dict(type='bool', default=True), state_change_timeout=dict(type='int', default=0), ) @@ -174,6 +199,7 @@ def main(): module.fail_json(msg="Scheduling task requires vCenter, hostname %s " "is an ESXi server." % module.params.get('hostname')) powerstate = { + 'present': vim.VirtualMachine.PowerOn, 'powered-off': vim.VirtualMachine.PowerOff, 'powered-on': vim.VirtualMachine.PowerOn, 'reboot-guest': vim.VirtualMachine.RebootGuest, @@ -188,16 +214,18 @@ def main(): module.fail_json(msg="Failed to convert given date and time string to Python datetime object," "please specify string in 'dd/mm/yyyy hh:mm' format: %s" % to_native(e)) schedule_task_spec = vim.scheduler.ScheduledTaskSpec() - schedule_task_desc = 'Schedule task for vm %s for operation %s at %s' % (vm.name, - module.params.get('state'), - scheduled_at) - schedule_task_spec.name = schedule_task_desc + schedule_task_name = module.params['schedule_task_name'] or 'task_%s' % str(randint(10000, 99999)) + schedule_task_desc = module.params['schedule_task_description'] + if schedule_task_desc is None: + schedule_task_desc = 'Schedule task for vm %s for ' \ + 'operation %s at %s' % (vm.name, module.params['state'], scheduled_at) + schedule_task_spec.name = schedule_task_name schedule_task_spec.description = schedule_task_desc schedule_task_spec.scheduler = vim.scheduler.OnceTaskScheduler() schedule_task_spec.scheduler.runAt = dt schedule_task_spec.action = vim.action.MethodAction() - schedule_task_spec.action.name = powerstate[module.params.get('state')] - schedule_task_spec.enabled = True + schedule_task_spec.action.name = powerstate[module.params['state']] + schedule_task_spec.enabled = module.params['schedule_task_enabled'] try: pyv.content.scheduledTaskManager.CreateScheduledTask(vm, schedule_task_spec) diff --git a/test/integration/targets/vmware_guest_powerstate/tasks/main.yml b/test/integration/targets/vmware_guest_powerstate/tasks/main.yml index 06b865cee6..fe1eb4dfb5 100644 --- a/test/integration/targets/vmware_guest_powerstate/tasks/main.yml +++ b/test/integration/targets/vmware_guest_powerstate/tasks/main.yml @@ -8,6 +8,7 @@ setup_attach_host: true setup_datastore: true setup_virtualmachines: true + - name: set state to poweroff the first VM vmware_guest_powerstate: validate_certs: False @@ -19,9 +20,29 @@ state: powered-off register: poweroff_d1_c1_f0 -- debug: var=poweroff_d1_c1_f0 +- debug: + var: poweroff_d1_c1_f0 - name: make sure change was made assert: that: - poweroff_d1_c1_f0.changed + +- when: vcsim is not defined + block: + - name: Set a schedule task for first VM + vmware_guest_powerstate: + validate_certs: False + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + name: "{{ virtual_machines[0].name }}" + folder: "{{ virtual_machines[0].folder }}" + scheduled_at: "10/10/2030 10:10" + state: powered-on + register: poweron_d1_c1_f0 + + - name: Check that task is schedule + assert: + that: + - poweron_d1_c1_f0.changed diff --git a/test/integration/targets/vmware_guest_powerstate/tasks/poweroff_d1_c1_f0.yml b/test/integration/targets/vmware_guest_powerstate/tasks/poweroff_d1_c1_f0.yml deleted file mode 100644 index 8a65d8b0bb..0000000000 --- a/test/integration/targets/vmware_guest_powerstate/tasks/poweroff_d1_c1_f0.yml +++ /dev/null @@ -1,52 +0,0 @@ -# Test code for the vmware_guest_powerstate module. -# Copyright: (c) 2017, Abhijeet Kasurde -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Wait for Flask controller to come up online - wait_for: - host: "{{ vcsim }}" - port: 5000 - state: started - -- name: kill vcsim - uri: - url: http://{{ vcsim }}:5000/killall - -- name: start vcsim with no folders - uri: - url: http://{{ vcsim }}:5000/spawn?datacenter=1&cluster=1&folder=0 - register: vcsim_instance - -- name: Wait for Flask controller to come up online - wait_for: - host: "{{ vcsim }}" - port: 443 - state: started - -- name: get a list of VMS from vcsim - uri: - url: http://{{ vcsim }}:5000/govc_find?filter=VM - register: vmlist - -- debug: var=vcsim_instance -- debug: var=vmlist - -- name: set state to poweroff on all VMs - vmware_guest_powerstate: - validate_certs: False - hostname: "{{ vcsim }}" - username: "{{ vcsim_instance['json']['username'] }}" - password: "{{ vcsim_instance['json']['password'] }}" - name: "{{ item|basename }}" - state: powered-off - folder: "{{ item|dirname }}" - with_items: "{{ virtual_machines }}" - register: poweroff_d1_c1_f0 - -- debug: var=poweroff_d1_c1_f0 - -# vcsim (v0.18.0) VMs are spawned PoweredOn -- name: make sure changes were made - assert: - that: - - "poweroff_d1_c1_f0.results|map(attribute='changed')|unique|list == [True]" diff --git a/test/integration/targets/vmware_guest_powerstate/tasks/poweroff_d1_c1_f1.yml b/test/integration/targets/vmware_guest_powerstate/tasks/poweroff_d1_c1_f1.yml deleted file mode 100644 index 2d35940a29..0000000000 --- a/test/integration/targets/vmware_guest_powerstate/tasks/poweroff_d1_c1_f1.yml +++ /dev/null @@ -1,58 +0,0 @@ -# Test code for the vmware_guest_powerstate module. -# Copyright: (c) 2017, Abhijeet Kasurde -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Wait for Flask controller to come up online - wait_for: - host: "{{ vcsim }}" - port: 5000 - state: started - -- name: kill vcsim - uri: - url: http://{{ vcsim }}:5000/killall - -- name: start vcsim with folders - uri: - url: http://{{ vcsim }}:5000/spawn?datacenter=1&cluster=1&folder=1 - register: vcsim_instance - -- name: Wait for Flask controller to come up online - wait_for: - host: "{{ vcsim }}" - port: 443 - state: started - -- name: get a list of VMS from vcsim - uri: - url: http://{{ vcsim }}:5000/govc_find?filter=VM - register: vmlist - -- debug: var=vcsim_instance -- debug: var=vmlist - -# https://github.com/ansible/ansible/issues/25011 -# Sending "-folders 1" to vcsim nests the datacenter under -# the folder so that the path prefix is no longer /vm -# -# /F0/DC0/vm/F0/DC0_H0_VM0 - -- name: set state to poweredoff on all VMs - vmware_guest_powerstate: - validate_certs: False - hostname: "{{ vcsim }}" - username: "{{ vcsim_instance['json']['username'] }}" - password: "{{ vcsim_instance['json']['password'] }}" - name: "{{ item|basename }}" - state: powered-off - folder: "{{ item|dirname }}" - with_items: "{{ vmlist['json'] }}" - register: poweroff_d1_c1_f1 - -- debug: var=poweroff_d1_c1_f1 - -# vcsim (v0.18.0) VMs are spawned PoweredOn -- name: make sure changes were made - assert: - that: - - "poweroff_d1_c1_f1.results|map(attribute='changed')|unique|list == [True]"