From 8a13b4182370dc9966f24ba671ee2c6a586c65c1 Mon Sep 17 00:00:00 2001 From: Abhijeet Kasurde Date: Thu, 18 Jul 2019 07:38:12 +0530 Subject: [PATCH] VMware: Use managed object id to find VM (#59143) * Based upon partial work of wilmardo * Now, user can specify managed object id of virtual machine to find an existing virtual machine Signed-off-by: Abhijeet Kasurde --- lib/ansible/module_utils/vmware.py | 4 +- .../modules/cloud/vmware/vmware_export_ovf.py | 13 +++- .../cloud/vmware/vmware_guest_boot_facts.py | 38 ++++++++--- .../cloud/vmware/vmware_guest_boot_manager.py | 43 +++++++++++-- .../vmware/vmware_guest_custom_attributes.py | 28 +++++++- .../modules/cloud/vmware/vmware_guest_disk.py | 41 ++++++++++-- .../cloud/vmware/vmware_guest_disk_facts.py | 31 +++++++-- .../cloud/vmware/vmware_guest_facts.py | 32 ++++++++-- .../modules/cloud/vmware/vmware_guest_move.py | 31 +++++++-- .../cloud/vmware/vmware_guest_network.py | 40 +++++++++--- .../cloud/vmware/vmware_guest_powerstate.py | 37 ++++++++--- .../cloud/vmware/vmware_guest_screenshot.py | 35 ++++++++-- .../cloud/vmware/vmware_guest_sendkey.py | 40 ++++++++++-- .../cloud/vmware/vmware_guest_snapshot.py | 54 +++++++++++----- .../vmware/vmware_guest_snapshot_facts.py | 64 +++++++++++++------ .../vmware/vmware_guest_tools_upgrade.py | 34 ++++++++-- .../cloud/vmware/vmware_guest_tools_wait.py | 31 +++++++-- .../cloud/vmware/vmware_guest_video.py | 42 ++++++++++-- .../modules/cloud/vmware/vmware_guest_vnc.py | 29 +++++++-- .../modules/cloud/vmware/vmware_vmotion.py | 48 ++++++++++---- .../targets/vmware_guest_facts/tasks/main.yml | 42 +++++++++++- 21 files changed, 604 insertions(+), 153 deletions(-) diff --git a/lib/ansible/module_utils/vmware.py b/lib/ansible/module_utils/vmware.py index a889591a7d2..94bf7aefb75 100644 --- a/lib/ansible/module_utils/vmware.py +++ b/lib/ansible/module_utils/vmware.py @@ -880,7 +880,7 @@ class PyVmomi(object): # Virtual Machine related functions def get_vm(self): """ - Find unique virtual machine either by UUID or Name. + Find unique virtual machine either by UUID, MoID or Name. Returns: virtual machine object if found, else None. """ @@ -959,6 +959,8 @@ class PyVmomi(object): elif vms: # Unique virtual machine found. vm_obj = vms[0] + elif self.params['moid']: + vm_obj = VmomiSupport.templateOf('VirtualMachine')(self.params['moid'], self.si._stub) if vm_obj: self.current_vm_obj = vm_obj diff --git a/lib/ansible/modules/cloud/vmware/vmware_export_ovf.py b/lib/ansible/modules/cloud/vmware/vmware_export_ovf.py index 7f2f0dcbbb2..176266c8514 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_export_ovf.py +++ b/lib/ansible/modules/cloud/vmware/vmware_export_ovf.py @@ -28,11 +28,17 @@ options: name: description: - Name of the virtual machine to export. - - This is a required parameter, if parameter C(uuid) is not supplied. + - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. uuid: description: - Uuid of the virtual machine to export. - - This is a required parameter, if parameter C(name) is not supplied. + - This is a required parameter, if parameter C(name) or C(moid) is not supplied. + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str datacenter: default: ha-datacenter description: @@ -304,6 +310,7 @@ def main(): argument_spec.update( name=dict(type='str'), uuid=dict(type='str'), + moid=dict(type='str'), folder=dict(type='str'), datacenter=dict(type='str', default='ha-datacenter'), export_dir=dict(type='str'), @@ -313,7 +320,7 @@ def main(): module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True, required_one_of=[ - ['name', 'uuid'], + ['name', 'uuid', 'moid'], ], ) pyv = VMwareExportVmOvf(module) diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_boot_facts.py b/lib/ansible/modules/cloud/vmware/vmware_guest_boot_facts.py index d4f8b9892bd..8942ed4b546 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_boot_facts.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_boot_facts.py @@ -20,10 +20,10 @@ DOCUMENTATION = ''' module: vmware_guest_boot_facts short_description: Gather facts about boot options for the given virtual machine description: - - This module can be used to gather facts aboyt boot options for the given virtual machine. + - Gather facts about boot options for the given virtual machine. version_added: 2.7 author: - - Abhijeet Kasurde (@Akasurde) + - Abhijeet Kasurde (@Akasurde) notes: - Tested on vSphere 6.5 requirements: @@ -33,11 +33,17 @@ options: name: description: - Name of the VM to work with. - - This is required if C(uuid) parameter is not supplied. + - This is required if C(uuid) or C(moid) parameter is not supplied. uuid: description: - UUID of the instance to manage if known, this is VMware's BIOS UUID by default. - - This is required if C(name) parameter is not supplied. + - This is required if C(name) or C(moid) parameter is not supplied. + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str use_instance_uuid: description: - Whether to use the VMware instance UUID rather than the BIOS UUID. @@ -61,6 +67,15 @@ EXAMPLES = r''' validate_certs: no name: "{{ vm_name }}" register: vm_boot_order_facts + +- name: Gather facts about virtual machine's boot order using MoID + vmware_guest_boot_facts: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + validate_certs: no + moid: "vm-42" + register: vm_moid_boot_order_facts ''' RETURN = r""" @@ -89,7 +104,7 @@ from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, find_vm_by_id try: - from pyVmomi import vim + from pyVmomi import vim, VmomiSupport except ImportError: pass @@ -99,6 +114,7 @@ class VmBootFactsManager(PyVmomi): super(VmBootFactsManager, self).__init__(module) self.name = self.params['name'] self.uuid = self.params['uuid'] + self.moid = self.params['moid'] self.use_instance_uuid = self.params['use_instance_uuid'] self.vm = None @@ -120,13 +136,18 @@ class VmBootFactsManager(PyVmomi): if temp_vm_object.obj.name == self.name: vms.append(temp_vm_object.obj) + elif self.moid: + vm_obj = VmomiSupport.templateOf('VirtualMachine')(self.module.params['moid'], self.si._stub) + if vm_obj: + vms.append(vm_obj) + if vms: if self.params.get('name_match') == 'first': self.vm = vms[0] elif self.params.get('name_match') == 'last': self.vm = vms[-1] else: - self.module.fail_json(msg="Failed to find virtual machine using %s" % (self.name or self.uuid)) + self.module.fail_json(msg="Failed to find virtual machine using %s" % (self.name or self.uuid or self.moid)) @staticmethod def humanize_boot_order(boot_order): @@ -165,6 +186,7 @@ def main(): argument_spec.update( name=dict(type='str'), uuid=dict(type='str'), + moid=dict(type='str'), use_instance_uuid=dict(type='bool', default=False), name_match=dict( choices=['first', 'last'], @@ -175,10 +197,10 @@ def main(): module = AnsibleModule( argument_spec=argument_spec, required_one_of=[ - ['name', 'uuid'] + ['name', 'uuid', 'moid'] ], mutually_exclusive=[ - ['name', 'uuid'] + ['name', 'uuid', 'moid'] ], supports_check_mode=True, ) diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_boot_manager.py b/lib/ansible/modules/cloud/vmware/vmware_guest_boot_manager.py index 51d51bec096..5de18ef6702 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_boot_manager.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_boot_manager.py @@ -33,11 +33,17 @@ options: name: description: - Name of the VM to work with. - - This is required if C(uuid) parameter is not supplied. + - This is required if C(uuid) or C(moid) parameter is not supplied. uuid: description: - UUID of the instance to manage if known, this is VMware's BIOS UUID by default. - - This is required if C(name) parameter is not supplied. + - This is required if C(name) or C(moid) parameter is not supplied. + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str use_instance_uuid: description: - Whether to use the VMware instance UUID rather than the BIOS UUID. @@ -107,6 +113,26 @@ EXAMPLES = r''' - disk delegate_to: localhost register: vm_boot_order + +- name: Change virtual machine's boot order using Virtual Machine MoID + vmware_guest_boot_manager: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + moid: vm-42 + boot_delay: 2000 + enter_bios_setup: True + boot_retry_enabled: True + boot_retry_delay: 22300 + boot_firmware: bios + secure_boot_enabled: False + boot_order: + - floppy + - cdrom + - ethernet + - disk + delegate_to: localhost + register: vm_boot_order ''' RETURN = r""" @@ -148,7 +174,7 @@ from ansible.module_utils._text import to_native from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, find_vm_by_id, wait_for_task, TaskError try: - from pyVmomi import vim + from pyVmomi import vim, VmomiSupport except ImportError: pass @@ -158,6 +184,7 @@ class VmBootManager(PyVmomi): super(VmBootManager, self).__init__(module) self.name = self.params['name'] self.uuid = self.params['uuid'] + self.moid = self.params['moid'] self.use_instance_uuid = self.params['use_instance_uuid'] self.vm = None @@ -179,6 +206,11 @@ class VmBootManager(PyVmomi): if temp_vm_object.obj.name == self.name: vms.append(temp_vm_object.obj) + elif self.moid: + vm_obj = VmomiSupport.templateOf('VirtualMachine')(self.module.params['moid'], self.si._stub) + if vm_obj: + vms.append(vm_obj) + if vms: if self.params.get('name_match') == 'first': self.vm = vms[0] @@ -324,6 +356,7 @@ def main(): argument_spec.update( name=dict(type='str'), uuid=dict(type='str'), + moid=dict(type='str'), use_instance_uuid=dict(type='bool', default=False), boot_order=dict( type='list', @@ -362,10 +395,10 @@ def main(): module = AnsibleModule( argument_spec=argument_spec, required_one_of=[ - ['name', 'uuid'] + ['name', 'uuid', 'moid'] ], mutually_exclusive=[ - ['name', 'uuid'] + ['name', 'uuid', 'moid'] ], ) diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py b/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py index 3fa24ae03b9..89a0ef96eb4 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py @@ -36,6 +36,7 @@ options: name: description: - Name of the virtual machine to work with. + - This is required parameter, if C(uuid) or C(moid) is not supplied. required: True state: description: @@ -47,7 +48,13 @@ options: uuid: description: - UUID of the virtual machine to manage if known. This is VMware's unique identifier. - - This is required parameter, if C(name) is not supplied. + - This is required parameter, if C(name) or C(moid) is not supplied. + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str use_instance_uuid: description: - Whether to use the VMware instance UUID rather than the BIOS UUID. @@ -111,6 +118,17 @@ EXAMPLES = ''' delegate_to: localhost register: attributes +- name: Remove virtual machine Attribute using Virtual Machine MoID + vmware_guest_custom_attributes: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + moid: vm-42 + state: absent + attributes: + - name: MyAttribute + delegate_to: localhost + register: attributes ''' RETURN = """ @@ -185,6 +203,7 @@ def main(): name=dict(required=True, type='str'), folder=dict(type='str'), uuid=dict(type='str'), + moid=dict(type='str'), use_instance_uuid=dict(type='bool', default=False), state=dict(type='str', default='present', choices=['absent', 'present']), @@ -201,7 +220,9 @@ def main(): module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, - required_one_of=[['name', 'uuid']], + required_one_of=[ + ['name', 'uuid', 'moid'] + ], ) if module.params.get('folder'): @@ -224,8 +245,9 @@ def main(): module.exit_json(**results) else: # virtual machine does not exists + vm_id = (module.params.get('name') or module.params.get('uuid') or module.params.get('moid')) module.fail_json(msg="Unable to manage custom attributes for non-existing" - " virtual machine %s" % (module.params.get('name') or module.params.get('uuid'))) + " virtual machine %s" % vm_id) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_disk.py b/lib/ansible/modules/cloud/vmware/vmware_guest_disk.py index 6ce800189bb..679b38cb314 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_disk.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_disk.py @@ -36,11 +36,17 @@ options: name: description: - Name of the virtual machine. - - This is a required parameter, if parameter C(uuid) is not supplied. + - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. uuid: description: - UUID of the instance to gather facts if known, this is VMware's unique identifier. - - This is a required parameter, if parameter C(name) is not supplied. + - This is a required parameter, if parameter C(name) or C(moid) is not supplied. + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str folder: description: - Destination folder, absolute or relative path to find an existing guest. @@ -74,7 +80,7 @@ options: - 'Valid attributes are:' - ' - C(size[_tb,_gb,_mb,_kb]) (integer): Disk storage size in specified unit.' - ' If C(size) specified then unit must be specified. There is no space allowed in between size number and unit.' - - ' Only first occurance in disk element will be considered, even if there are multiple size* parameters available.' + - ' Only first occurrence in disk element will be considered, even if there are multiple size* parameters available.' - ' - C(type) (string): Valid values are:' - ' - C(thin) thin disk' - ' - C(eagerzeroedthick) eagerzeroedthick disk' @@ -147,6 +153,21 @@ EXAMPLES = ''' unit_number: 1 delegate_to: localhost register: disk_facts + +- name: Remove disks from virtual machine using moid + vmware_guest_disk: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter: "{{ datacenter_name }}" + validate_certs: no + moid: vm-42 + disk: + - state: absent + scsi_controller: 1 + unit_number: 1 + delegate_to: localhost + register: disk_facts ''' RETURN = """ @@ -578,7 +599,7 @@ class PyVmomiHelper(PyVmomi): rec = self.content.storageResourceManager.RecommendDatastores(storageSpec=storage_spec) rec_action = rec.recommendations[0].action[0] return rec_action.destination.name - except Exception as e: + except Exception: # There is some error so we fall back to general workflow pass datastore = None @@ -633,13 +654,18 @@ def main(): argument_spec.update( name=dict(type='str'), uuid=dict(type='str'), + moid=dict(type='str'), folder=dict(type='str'), datacenter=dict(type='str', required=True), disk=dict(type='list', default=[]), use_instance_uuid=dict(type='bool', default=False), ) - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=[['name', 'uuid']]) + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=[ + ['name', 'uuid', 'moid'] + ] + ) if module.params['folder']: # FindByInventoryPath() does not require an absolute path @@ -653,8 +679,9 @@ def main(): if not vm: # We unable to find the virtual machine user specified # Bail out + vm_id = (module.params.get('name') or module.params.get('uuid') or module.params.get('moid')) module.fail_json(msg="Unable to manage disks for non-existing" - " virtual machine '%s'." % (module.params.get('uuid') or module.params.get('name'))) + " virtual machine '%s'." % vm_id) # VM exists try: diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_disk_facts.py b/lib/ansible/modules/cloud/vmware/vmware_guest_disk_facts.py index b4507186c2f..13fea155e07 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_disk_facts.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_disk_facts.py @@ -36,11 +36,17 @@ options: name: description: - Name of the virtual machine. - - This is required parameter, if parameter C(uuid) is not supplied. + - This is required parameter, if parameter C(uuid) or C(moid) is not supplied. uuid: description: - UUID of the instance to gather facts if known, this is VMware's unique identifier. - - This is required parameter, if parameter C(name) is not supplied. + - This is required parameter, if parameter C(name) or C(moid) is not supplied. + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str use_instance_uuid: description: - Whether to use the VMware instance UUID rather than the BIOS UUID. @@ -62,8 +68,6 @@ options: - ' folder: /folder1/datacenter1/vm' - ' folder: folder1/datacenter1/vm' - ' folder: /folder1/datacenter1/vm/folder2' - - ' folder: vm/folder2' - - ' folder: folder2' datacenter: description: - The datacenter name to which virtual machine belongs to. @@ -93,6 +97,17 @@ EXAMPLES = ''' name: VM_225 delegate_to: localhost register: disk_facts + +- name: Gather disk facts from virtual machine using moid + vmware_guest_disk_facts: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter: ha-datacenter + validate_certs: no + moid: vm-42 + delegate_to: localhost + register: disk_facts ''' RETURN = """ @@ -270,13 +285,16 @@ def main(): argument_spec.update( name=dict(type='str'), uuid=dict(type='str'), + moid=dict(type='str'), use_instance_uuid=dict(type='bool', default=False), folder=dict(type='str'), datacenter=dict(type='str', required=True), ) module = AnsibleModule( argument_spec=argument_spec, - required_one_of=[['name', 'uuid']], + required_one_of=[ + ['name', 'uuid', 'moid'] + ], supports_check_mode=True, ) @@ -298,7 +316,8 @@ def main(): else: # We unable to find the virtual machine user specified # Bail out - module.fail_json(msg="Unable to gather disk facts for non-existing VM %s" % (module.params.get('uuid') or module.params.get('name'))) + vm_id = (module.params.get('uuid') or module.params.get('moid') or module.params.get('name')) + module.fail_json(msg="Unable to gather disk facts for non-existing VM %s" % vm_id) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_facts.py b/lib/ansible/modules/cloud/vmware/vmware_guest_facts.py index 055c557599d..a500c41dd4f 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_facts.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_facts.py @@ -34,7 +34,7 @@ options: name: description: - Name of the VM to work with - - This is required if UUID is not supplied. + - This is required if C(uuid) or C(moid) is not supplied. name_match: description: - If multiple VMs matching the name, use the first or last found @@ -43,13 +43,19 @@ options: uuid: description: - UUID of the instance to manage if known, this is VMware's unique identifier. - - This is required if name is not supplied. + - This is required if C(name) or C(moid) is not supplied. use_instance_uuid: description: - Whether to use the VMware instance UUID rather than the BIOS UUID. default: no type: bool version_added: '2.8' + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str folder: description: - Destination folder, absolute or relative path to find an existing guest. @@ -65,8 +71,6 @@ options: - ' folder: /folder1/datacenter1/vm' - ' folder: folder1/datacenter1/vm' - ' folder: /folder1/datacenter1/vm/folder2' - - ' folder: vm/folder2' - - ' folder: folder2' datacenter: description: - Destination datacenter for the deploy operation @@ -134,6 +138,19 @@ EXAMPLES = ''' delegate_to: localhost register: facts +- name: Gather some facts from a guest using MoID + vmware_guest_facts: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + validate_certs: no + datacenter: "{{ datacenter_name }}" + moid: vm-42 + schema: "vsphere" + properties: ["config.hardware.memoryMB", "guest.disk", "overallStatus"] + delegate_to: localhost + register: vm_moid_facts + - name: Gather Managed object ID (moid) from a guest using the vSphere API output schema for REST Calls vmware_guest_facts: hostname: "{{ vcenter_hostname }}" @@ -237,6 +254,7 @@ def main(): name_match=dict(type='str', choices=['first', 'last'], default='first'), uuid=dict(type='str'), use_instance_uuid=dict(type='bool', default=False), + moid=dict(type='str'), folder=dict(type='str'), datacenter=dict(type='str', required=True), tags=dict(type='bool', default=False), @@ -244,7 +262,7 @@ def main(): properties=dict(type='list') ) module = AnsibleModule(argument_spec=argument_spec, - required_one_of=[['name', 'uuid']], + required_one_of=[['name', 'uuid', 'moid']], supports_check_mode=True) if module.params.get('folder'): @@ -282,8 +300,8 @@ def main(): except Exception as exc: module.fail_json(msg="Fact gather failed with exception %s" % to_text(exc)) else: - module.fail_json(msg="Unable to gather facts for non-existing VM %s" % (module.params.get('uuid') or - module.params.get('name'))) + vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) + module.fail_json(msg="Unable to gather facts for non-existing VM %s" % vm_id) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_move.py b/lib/ansible/modules/cloud/vmware/vmware_guest_move.py index 5eb908b0da3..eea4b0c1d44 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_move.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_move.py @@ -32,11 +32,17 @@ options: name: description: - Name of the existing virtual machine to move. - - This is required if C(UUID) is not supplied. + - This is required if C(uuid) or C(moid) is not supplied. uuid: description: - UUID of the virtual machine to manage if known, this is VMware's unique identifier. - - This is required if C(name) is not supplied. + - This is required if C(name) or C(moid) is not supplied. + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str use_instance_uuid: description: - Whether to use the VMware instance UUID rather than the BIOS UUID. @@ -83,6 +89,17 @@ EXAMPLES = r''' dest_folder: "/{{ datacenter }}/vm" delegate_to: localhost +- name: Move Virtual Machine using MoID + vmware_guest_move: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter: datacenter + validate_certs: no + moid: vm-42 + dest_folder: "/{{ datacenter }}/vm" + delegate_to: localhost + - name: Get VM UUID vmware_guest_facts: hostname: "{{ vcenter_hostname }}" @@ -175,6 +192,7 @@ def main(): name_match=dict( type='str', choices=['first', 'last'], default='first'), uuid=dict(type='str'), + moid=dict(type='str'), use_instance_uuid=dict(type='bool', default=False), dest_folder=dict(type='str', required=True), datacenter=dict(type='str', required=True), @@ -182,10 +200,10 @@ def main(): module = AnsibleModule( argument_spec=argument_spec, required_one_of=[ - ['name', 'uuid'] + ['name', 'uuid', 'moid'] ], mutually_exclusive=[ - ['name', 'uuid'] + ['name', 'uuid', 'moid'] ], supports_check_mode=True ) @@ -229,9 +247,8 @@ def main(): else: if module.check_mode: module.exit_json(changed=False) - module.fail_json(msg="Unable to find VM %s to move to %s" % ( - (module.params.get('uuid') or module.params.get('name')), - module.params.get('dest_folder'))) + vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) + module.fail_json(msg="Unable to find VM %s to move to %s" % (vm_id, module.params.get('dest_folder'))) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_network.py b/lib/ansible/modules/cloud/vmware/vmware_guest_network.py index bba2eb98e15..328b070e1c0 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_network.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_network.py @@ -32,12 +32,17 @@ options: name: description: - Name of the virtual machine. - - This is a required parameter, if parameter C(uuid) is not supplied. + - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. type: str uuid: description: - UUID of the instance to gather facts if known, this is VMware's unique identifier. - - This is a required parameter, if parameter C(name) is not supplied. + - This is a required parameter, if parameter C(name) or C(moid) is not supplied. + type: str + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. type: str folder: description: @@ -134,6 +139,20 @@ EXAMPLES = ''' mac: "00:50:56:44:55:77" delegate_to: localhost register: network_facts + +- name: Change network adapter settings of virtual machine using MoID + vmware_guest_network: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter: "{{ datacenter_name }}" + validate_certs: no + moid: vm-42 + gather_network_facts: false + networks: + - state: absent + mac: "00:50:56:44:55:77" + delegate_to: localhost ''' RETURN = """ @@ -156,8 +175,6 @@ network_data: } """ -import re - try: from pyVmomi import vim except ImportError: @@ -166,7 +183,7 @@ except ImportError: from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.common.network import is_mac from ansible.module_utils._text import to_native, to_text -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task, find_obj, get_all_objs, get_parent_datacenter +from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task, get_all_objs, get_parent_datacenter class PyVmomiHelper(PyVmomi): @@ -435,6 +452,7 @@ def main(): argument_spec.update( name=dict(type='str'), uuid=dict(type='str'), + moid=dict(type='str'), folder=dict(type='str'), datacenter=dict(type='str', default='ha-datacenter'), esxi_hostname=dict(type='str'), @@ -443,12 +461,18 @@ def main(): networks=dict(type='list', default=[]) ) - module = AnsibleModule(argument_spec=argument_spec, required_one_of=[['name', 'uuid']]) + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=[ + ['name', 'uuid', 'moid'] + ] + ) + pyv = PyVmomiHelper(module) vm = pyv.get_vm() if not vm: - module.fail_json(msg='Unable to find the specified virtual machine uuid: %s, name: %s ' - % ((module.params.get('uuid')), (module.params.get('name')))) + vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) + module.fail_json(msg='Unable to find the specified virtual machine using %s' % vm_id) result = pyv.reconfigure_vm_network(vm) if result['failed']: diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_powerstate.py b/lib/ansible/modules/cloud/vmware/vmware_guest_powerstate.py index 4c5ce21e0d3..0a0bc9efef0 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_powerstate.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_powerstate.py @@ -41,7 +41,13 @@ options: uuid: description: - UUID of the instance to manage if known, this is VMware's unique identifier. - - This is required if name is not supplied. + - This is required if C(name) or C(moid) is not supplied. + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str use_instance_uuid: description: - Whether to use the VMware instance UUID rather than the BIOS UUID. @@ -118,6 +124,18 @@ EXAMPLES = r''' delegate_to: localhost register: deploy +- name: Set the state of a virtual machine to poweron using MoID + vmware_guest_powerstate: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + validate_certs: no + folder: "/{{ datacenter_name }}/vm/my_folder" + moid: vm-42 + state: powered-on + delegate_to: localhost + register: deploy + - name: Set the state of a virtual machine to poweroff at given scheduled time vmware_guest_powerstate: hostname: "{{ vcenter_hostname }}" @@ -167,6 +185,7 @@ def main(): name=dict(type='str'), name_match=dict(type='str', choices=['first', 'last'], default='first'), uuid=dict(type='str'), + moid=dict(type='str'), use_instance_uuid=dict(type='bool', default=False), folder=dict(type='str'), force=dict(type='bool', default=False), @@ -177,12 +196,13 @@ def main(): state_change_timeout=dict(type='int', default=0), ) - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=False, - mutually_exclusive=[ - ['name', 'uuid'], - ], - ) + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=False, + mutually_exclusive=[ + ['name', 'uuid', 'moid'], + ], + ) result = dict(changed=False,) @@ -244,7 +264,8 @@ def main(): else: result = set_vm_power_state(pyv.content, vm, module.params['state'], module.params['force'], module.params['state_change_timeout']) else: - module.fail_json(msg="Unable to set power state for non-existing virtual machine : '%s'" % (module.params.get('uuid') or module.params.get('name'))) + id = module.params.get('uuid') or module.params.get('moid') or module.params.get('name') + module.fail_json(msg="Unable to set power state for non-existing virtual machine : '%s'" % id) if result.get('failed') is True: module.fail_json(**result) diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_screenshot.py b/lib/ansible/modules/cloud/vmware/vmware_guest_screenshot.py index b830a6e8f4b..ab9d3c37b88 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_screenshot.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_screenshot.py @@ -32,12 +32,18 @@ options: name: description: - Name of the virtual machine. - - This is a required parameter, if parameter C(uuid) is not supplied. + - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. type: str uuid: description: - UUID of the instance to gather facts if known, this is VMware's unique identifier. - - This is a required parameter, if parameter C(name) is not supplied. + - This is a required parameter, if parameter C(name) or C(moid) is not supplied. + type: str + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' type: str folder: description: @@ -95,6 +101,19 @@ EXAMPLES = ''' local_path: "/tmp/" delegate_to: localhost register: take_screenshot + +- name: Take a screenshot of the virtual machine console using MoID + vmware_guest_screenshot: + validate_certs: no + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter: "{{ datacenter_name }}" + folder: "{{ folder_name }}" + moid: vm-42 + local_path: "/tmp/" + delegate_to: localhost + register: take_screenshot ''' RETURN = """ @@ -244,18 +263,24 @@ def main(): argument_spec.update( name=dict(type='str'), uuid=dict(type='str'), + moid=dict(type='str'), folder=dict(type='str'), datacenter=dict(type='str'), esxi_hostname=dict(type='str'), cluster=dict(type='str'), local_path=dict(type='str'), ) - module = AnsibleModule(argument_spec=argument_spec, required_one_of=[['name', 'uuid']]) + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=[ + ['name', 'uuid', 'moid'] + ] + ) pyv = PyVmomiHelper(module) vm = pyv.get_vm() if not vm: - module.fail_json(msg='Unable to find the specified virtual machine uuid: %s, name: %s ' - % ((module.params.get('uuid')), (module.params.get('name')))) + vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) + module.fail_json(msg='Unable to find the specified virtual machine : %s' % vm_id) result = pyv.take_vm_screenshot() if result['failed']: diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_sendkey.py b/lib/ansible/modules/cloud/vmware/vmware_guest_sendkey.py index 8d4bc3edd83..6a52239be90 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_sendkey.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_sendkey.py @@ -32,12 +32,17 @@ options: name: description: - Name of the virtual machine. - - This is a required parameter, if parameter C(uuid) is not supplied. + - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. type: str uuid: description: - UUID of the instance to gather facts if known, this is VMware's unique identifier. - - This is a required parameter, if parameter C(name) is not supplied. + - This is a required parameter, if parameter C(name) or C(moid) is not supplied. + type: str + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. type: str folder: description: @@ -87,7 +92,7 @@ extends_documentation_fragment: vmware.documentation ''' EXAMPLES = ''' -- name: send list of keys to virtual machine +- name: Send list of keys to virtual machine vmware_guest_sendkey: validate_certs: no hostname: "{{ vcenter_hostname }}" @@ -103,7 +108,21 @@ EXAMPLES = ''' delegate_to: localhost register: keys_num_sent -- name: send a string to virtual machine +- name: Send list of keys to virtual machine using MoID + vmware_guest_sendkey: + validate_certs: no + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter: "{{ datacenter_name }}" + folder: "{{ folder_name }}" + moid: vm-42 + keys_send: + - CTRL_ALT_DEL + delegate_to: localhost + register: ctrl_alt_del_sent + +- name: Send a string to virtual machine vmware_guest_sendkey: validate_certs: no hostname: "{{ vcenter_hostname }}" @@ -336,6 +355,7 @@ def main(): argument_spec.update( name=dict(type='str'), uuid=dict(type='str'), + moid=dict(type='str'), folder=dict(type='str'), datacenter=dict(type='str'), esxi_hostname=dict(type='str'), @@ -344,12 +364,18 @@ def main(): string_send=dict(type='str') ) - module = AnsibleModule(argument_spec=argument_spec, required_one_of=[['name', 'uuid']]) + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=[ + ['name', 'uuid', 'moid'] + ] + ) + pyv = PyVmomiHelper(module) vm = pyv.get_vm() if not vm: - module.fail_json(msg='Unable to find the specified virtual machine uuid: %s, name: %s ' - % ((module.params.get('uuid')), (module.params.get('name')))) + vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) + module.fail_json(msg='Unable to find the specified virtual machine : %s ' % vm_id) result = pyv.send_key_to_vm(vm) if result['failed']: diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot.py b/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot.py index 4d47a5417aa..c6c0da07a89 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot.py @@ -44,7 +44,7 @@ options: name: description: - Name of the virtual machine to work with. - - This is required parameter, if C(uuid) is not supplied. + - This is required parameter, if C(uuid) or C(moid) is not supplied. name_match: description: - If multiple VMs matching the name, use the first or last found. @@ -53,7 +53,13 @@ options: uuid: description: - UUID of the instance to manage if known, this is VMware's BIOS UUID by default. - - This is required if C(name) parameter is not supplied. + - This is required if C(name) or C(moid) parameter is not supplied. + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str use_instance_uuid: description: - Whether to use the VMware instance UUID rather than the BIOS UUID. @@ -75,8 +81,6 @@ options: - ' folder: /folder1/datacenter1/vm' - ' folder: folder1/datacenter1/vm' - ' folder: /folder1/datacenter1/vm/folder2' - - ' folder: vm/folder2' - - ' folder: folder2' datacenter: description: - Destination datacenter for the deploy operation. @@ -175,6 +179,17 @@ EXAMPLES = ''' state: remove_all delegate_to: localhost + - name: Remove all snapshots of a VM using MoID + vmware_guest_snapshot: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter: "{{ datacenter_name }}" + folder: "/{{ datacenter_name }}/vm/" + moid: vm-42 + state: remove_all + delegate_to: localhost + - name: Take snapshot of a VM using quiesce and memory flag on vmware_guest_snapshot: hostname: "{{ vcenter_hostname }}" @@ -314,8 +329,8 @@ class PyVmomiHelper(PyVmomi): def rename_snapshot(self, vm): if vm.snapshot is None: - self.module.fail_json(msg="virtual machine - %s doesn't have any" - " snapshots" % (self.module.params.get('uuid') or self.module.params.get('name'))) + vm_id = self.module.params.get('uuid') or self.module.params.get('name') or self.params.get('moid') + self.module.fail_json(msg="virtual machine - %s doesn't have any snapshots" % vm_id) snap_obj = self.get_snapshots_by_name_recursively(vm.snapshot.rootSnapshotList, self.module.params["snapshot_name"]) @@ -330,10 +345,10 @@ class PyVmomiHelper(PyVmomi): else: task = snap_obj.RenameSnapshot(description=self.module.params["new_description"]) else: + vm_id = self.module.params.get('uuid') or self.module.params.get('name') or self.params.get('moid') self.module.exit_json( msg="Couldn't find any snapshots with specified name: %s on VM: %s" % - (self.module.params["snapshot_name"], - self.module.params.get('uuid') or self.module.params.get('name'))) + (self.module.params["snapshot_name"], vm_id)) return task def remove_or_revert_snapshot(self, vm): @@ -357,9 +372,9 @@ class PyVmomiHelper(PyVmomi): elif self.module.params["state"] == "revert": task = snap_obj.RevertToSnapshot_Task() else: + vm_id = self.module.params.get('uuid') or self.module.params.get('name') or self.params.get('moid') self.module.exit_json(msg="Couldn't find any snapshots with" - " specified name: %s on VM: %s" % (self.module.params["snapshot_name"], - self.module.params.get('uuid') or self.module.params.get('name'))) + " specified name: %s on VM: %s" % (self.module.params["snapshot_name"], vm_id)) return task @@ -397,6 +412,7 @@ def main(): name=dict(type='str'), name_match=dict(type='str', choices=['first', 'last'], default='first'), uuid=dict(type='str'), + moid=dict(type='str'), use_instance_uuid=dict(type='bool', default=False), folder=dict(type='str'), datacenter=dict(required=True, type='str'), @@ -408,10 +424,15 @@ def main(): new_snapshot_name=dict(type='str'), new_description=dict(type='str'), ) - module = AnsibleModule(argument_spec=argument_spec, - required_together=[['name', 'folder']], - required_one_of=[['name', 'uuid']], - ) + module = AnsibleModule( + argument_spec=argument_spec, + required_together=[ + ['name', 'folder'] + ], + required_one_of=[ + ['name', 'uuid', 'moid'] + ], + ) if module.params['folder']: # FindByInventoryPath() does not require an absolute path @@ -423,9 +444,8 @@ def main(): vm = pyv.get_vm() if not vm: - # If UUID is set, getvm select UUID, show error message accordingly. - module.fail_json(msg="Unable to manage snapshots for non-existing VM %s" % (module.params.get('uuid') or - module.params.get('name'))) + vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) + module.fail_json(msg="Unable to manage snapshots for non-existing VM %s" % vm_id) if not module.params['snapshot_name'] and module.params['state'] != 'remove_all': module.fail_json(msg="snapshot_name param is required when state is '%(state)s'" % module.params) diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot_facts.py b/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot_facts.py index 957b161377c..a329b228cff 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot_facts.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot_facts.py @@ -22,7 +22,7 @@ description: - This module can be used to gather facts about virtual machine's snapshots. version_added: 2.6 author: - - Abhijeet Kasurde (@Akasurde) + - Abhijeet Kasurde (@Akasurde) notes: - Tested on vSphere 6.0 and 6.5 requirements: @@ -32,12 +32,18 @@ options: name: description: - Name of the VM to work with. - - This is required if C(uuid) is not supplied. + - This is required if C(uuid) or C(moid) is not supplied. uuid: description: - UUID of the instance to manage if known, this is VMware's BIOS UUID by default. - - This is required if C(name) parameter is not supplied. + - This is required if C(name) or C(moid) parameter is not supplied. - The C(folder) is ignored, if C(uuid) is provided. + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str use_instance_uuid: description: - Whether to use the VMware instance UUID rather than the BIOS UUID. @@ -67,15 +73,25 @@ extends_documentation_fragment: vmware.documentation ''' EXAMPLES = ''' - - name: Gather snapshot facts about the virtual machine in the given vCenter - vmware_guest_snapshot_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - name: "{{ guest_name }}" - delegate_to: localhost - register: snapshot_facts +- name: Gather snapshot facts about the virtual machine in the given vCenter + vmware_guest_snapshot_facts: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter: "{{ datacenter_name }}" + name: "{{ guest_name }}" + delegate_to: localhost + register: snapshot_facts + +- name: Gather snapshot facts about the virtual machine using MoID + vmware_guest_snapshot_facts: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter: "{{ datacenter_name }}" + moid: vm-42 + delegate_to: localhost + register: snapshot_facts ''' RETURN = """ @@ -114,7 +130,7 @@ class PyVmomiHelper(PyVmomi): @staticmethod def gather_guest_snapshot_facts(vm_obj=None): """ - Function to return snpashot related facts about given virtual machine + Return snapshot related facts about given virtual machine Args: vm_obj: Virtual Machine Managed object @@ -131,15 +147,21 @@ def main(): argument_spec.update( name=dict(type='str'), uuid=dict(type='str'), + moid=dict(type='str'), use_instance_uuid=dict(type='bool', default=False), folder=dict(type='str'), datacenter=dict(required=True, type='str'), ) - module = AnsibleModule(argument_spec=argument_spec, - required_together=[['name', 'folder']], - required_one_of=[['name', 'uuid']], - supports_check_mode=True, - ) + module = AnsibleModule( + argument_spec=argument_spec, + required_together=[ + ['name', 'folder'] + ], + required_one_of=[ + ['name', 'uuid', 'moid'] + ], + supports_check_mode=True, + ) if module.params['folder']: # FindByInventoryPath() does not require an absolute path @@ -151,10 +173,10 @@ def main(): vm = pyv.get_vm() if not vm: - # If UUID is set, getvm select UUID, show error message accordingly. + # If UUID is set, get_vm select UUID, show error message accordingly. + vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) module.fail_json(msg="Unable to gather facts about snapshots for" - " non-existing VM ['%s']" % (module.params.get('uuid') or - module.params.get('name'))) + " non-existing VM ['%s']" % vm_id) results = dict(changed=False, guest_snapshots=pyv.gather_guest_snapshot_facts(vm_obj=vm)) module.exit_json(**results) diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_tools_upgrade.py b/lib/ansible/modules/cloud/vmware/vmware_guest_tools_upgrade.py index 34c627ebd5c..ffb0191c3ee 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_tools_upgrade.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_tools_upgrade.py @@ -30,7 +30,7 @@ options: name: description: - Name of the virtual machine to work with. - - This is required if C(UUID) is not supplied. + - This is required if C(uuid) or C(moid) is not supplied. name_match: description: - If multiple virtual machines matching the name, use the first or last found. @@ -39,7 +39,13 @@ options: uuid: description: - UUID of the instance to manage if known, this is VMware's unique identifier. - - This is required if C(name) is not supplied. + - This is required if C(name) or C(moid) is not supplied. + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str folder: description: - Destination folder, absolute or relative path to find an existing guest. @@ -55,7 +61,6 @@ options: - ' folder: /folder1/datacenter1/vm' - ' folder: folder1/datacenter1/vm' - ' folder: /folder1/datacenter1/vm/folder2' - - ' folder: vm/folder2' datacenter: description: - Destination datacenter where the virtual machine exists. @@ -66,7 +71,7 @@ author: ''' EXAMPLES = ''' -- name: Upgrade VMware Tools +- name: Upgrade VMware Tools using uuid vmware_guest_tools_upgrade: hostname: "{{ vcenter_hostname }}" username: "{{ vcenter_username }}" @@ -74,6 +79,15 @@ EXAMPLES = ''' datacenter: "{{ datacenter_name }}" uuid: 421e4592-c069-924d-ce20-7e7533fab926 delegate_to: localhost + +- name: Upgrade VMware Tools using MoID + vmware_guest_tools_upgrade: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter: "{{ datacenter_name }}" + moid: vm-42 + delegate_to: localhost ''' RETURN = ''' # ''' @@ -145,11 +159,16 @@ def main(): name=dict(type='str'), name_match=dict(type='str', choices=['first', 'last'], default='first'), uuid=dict(type='str'), + moid=dict(type='str'), folder=dict(type='str'), datacenter=dict(type='str', required=True), ) - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=[['name', 'uuid']]) + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=[ + ['name', 'uuid', 'moid'] + ] + ) if module.params['folder']: # FindByInventoryPath() does not require an absolute path @@ -173,7 +192,8 @@ def main(): except Exception as exc: module.fail_json(msg='Unknown error: %s' % to_native(exc)) else: - module.fail_json(msg='Unable to find VM %s' % (module.params.get('uuid') or module.params.get('name'))) + vm_id = module.params.get('uuid') or module.params.get('name') or module.params.get('moid') + module.fail_json(msg='Unable to find VM %s' % vm_id) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_tools_wait.py b/lib/ansible/modules/cloud/vmware/vmware_guest_tools_wait.py index 81212959a33..a0ddd37162b 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_tools_wait.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_tools_wait.py @@ -31,7 +31,7 @@ options: name: description: - Name of the VM for which to wait until the tools become available. - - This is required if uuid is not supplied. + - This is required if C(uuid) or C(moid) is not supplied. name_match: description: - If multiple VMs match the name, use the first or last found. @@ -55,7 +55,13 @@ options: uuid: description: - UUID of the VM for which to wait until the tools become available, if known. This is VMware's unique identifier. - - This is required, if C(name) is not supplied. + - This is required, if C(name) or C(moid) is not supplied. + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str use_instance_uuid: description: - Whether to use the VMware instance UUID rather than the BIOS UUID. @@ -89,6 +95,16 @@ EXAMPLES = ''' register: facts +- name: Wait for VMware tools to become available by MoID + vmware_guest_tools_wait: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + validate_certs: no + moid: vm-42 + delegate_to: localhost + register: facts + - name: Wait for VMware tools to become available by name vmware_guest_tools_wait: hostname: "{{ vcenter_hostname }}" @@ -152,11 +168,15 @@ def main(): name_match=dict(type='str', default='first', choices=['first', 'last']), folder=dict(type='str'), uuid=dict(type='str'), + moid=dict(type='str'), use_instance_uuid=dict(type='bool', default=False), ) module = AnsibleModule( argument_spec=argument_spec, - required_one_of=[['name', 'uuid']]) + required_one_of=[ + ['name', 'uuid', 'moid'] + ] + ) if module.params['folder']: # FindByInventoryPath() does not require an absolute path @@ -168,9 +188,8 @@ def main(): vm = pyv.get_vm() if not vm: - module.fail_json(msg="Unable to wait for VMware tools for " - "non-existing VM '%s'." % (module.params.get('name') or - module.params.get('uuid'))) + vm_id = module.params.get('name') or module.params.get('uuid') or module.params.get('moid') + module.fail_json(msg="Unable to wait for VMware tools for non-existing VM '%s'." % vm_id) result = dict(changed=False) try: diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_video.py b/lib/ansible/modules/cloud/vmware/vmware_guest_video.py index 5a1a602aff6..7f14e326900 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_video.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_video.py @@ -32,11 +32,17 @@ options: name: description: - Name of the virtual machine. - - This is a required parameter, if parameter C(uuid) is not supplied. + - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. uuid: description: - UUID of the instance to gather facts if known, this is VMware's unique identifier. - - This is a required parameter, if parameter C(name) is not supplied. + - This is a required parameter, if parameter C(name) or C(moid) is not supplied. + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str folder: description: - Destination folder, absolute or relative path to find an existing guest. @@ -110,6 +116,24 @@ EXAMPLES = ''' memory_3D_mb: 512 delegate_to: localhost register: video_facts + +- name: Change video card settings of virtual machine using MoID + vmware_guest_video: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter: "{{ datacenter_name }}" + validate_certs: no + moid: vm-42 + gather_video_facts: false + use_auto_detect: false + display_number: 2 + video_memory_mb: 8.0 + enable_3D: true + renderer_3D: automatic + memory_3D_mb: 512 + delegate_to: localhost + register: video_facts ''' RETURN = """ @@ -294,6 +318,7 @@ def main(): argument_spec.update( name=dict(type='str'), uuid=dict(type='str'), + moid=dict(type='str'), folder=dict(type='str'), datacenter=dict(type='str', default='ha-datacenter'), gather_video_facts=dict(type='bool', default=False), @@ -304,12 +329,19 @@ def main(): renderer_3D=dict(type='str', choices=['automatic', 'software', 'hardware']), memory_3D_mb=dict(type='int'), ) - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=[['name', 'uuid']]) + + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=[ + ['name', 'uuid', 'moid'] + ] + ) + pyv = PyVmomiHelper(module) vm = pyv.get_vm() if not vm: - module.fail_json(msg='Unable to find the specified virtual machine : %s' % (module.params.get('uuid') or module.params.get('name'))) + vm_id = module.params.get('uuid') or module.params.get('name') or module.params.get('moid') + module.fail_json(msg='Unable to find the specified virtual machine : %s' % vm_id) vm_facts = pyv.gather_facts(vm) vm_power_state = vm_facts['hw_power_status'].lower() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_vnc.py b/lib/ansible/modules/cloud/vmware/vmware_guest_vnc.py index 74d899d51b6..fc7867a0891 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_vnc.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_vnc.py @@ -51,8 +51,14 @@ options: uuid: description: - UUID of the instance to manage if known, this is VMware's unique identifier. - - This is required, if C(name) is not supplied. + - This is required, if C(name) or C(moid) is not supplied. required: false + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(name) or C(uuid) is not supplied. + version_added: '2.9' + type: str folder: description: - Destination folder, absolute or relative path to find an existing guest. @@ -106,6 +112,18 @@ EXAMPLES = ''' state: absent delegate_to: localhost register: vnc_result + +- name: Disable VNC remote display on the VM using MoID + vmware_guest_vnc: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + validate_certs: no + datacenter: "{{ datacenter_name }}" + moid: vm-42 + state: absent + delegate_to: localhost + register: vnc_result ''' RETURN = ''' @@ -195,6 +213,7 @@ def main(): name=dict(type='str'), name_match=dict(type='str', choices=['first', 'last'], default='first'), uuid=dict(type='str'), + moid=dict(type='str'), folder=dict(type='str'), vnc_ip=dict(type='str', default='0.0.0.0'), vnc_port=dict(type='int', default=0), @@ -206,10 +225,10 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_one_of=[ - ['name', 'uuid'] + ['name', 'uuid', 'moid'] ], mutually_exclusive=[ - ['name', 'uuid'] + ['name', 'uuid', 'moid'] ] ) @@ -227,8 +246,8 @@ def main(): module.params['vnc_password'] ) else: - module.fail_json(msg="Unable to set VNC config for non-existing virtual machine : '%s'" % (module.params.get('uuid') or - module.params.get('name'))) + vm_id = module.params.get('uuid') or module.params.get('name') or module.params.get('moid') + module.fail_json(msg="Unable to set VNC config for non-existing virtual machine : '%s'" % vm_id) if result.get('failed') is True: module.fail_json(**result) diff --git a/lib/ansible/modules/cloud/vmware/vmware_vmotion.py b/lib/ansible/modules/cloud/vmware/vmware_vmotion.py index 6f5ef2d540f..952ce20de4d 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_vmotion.py +++ b/lib/ansible/modules/cloud/vmware/vmware_vmotion.py @@ -44,9 +44,15 @@ options: vm_uuid: description: - UUID of the virtual machine to perform a vMotion operation on. - - This is a required parameter, if C(vm_name) is not set. + - This is a required parameter, if C(vm_name) or C(moid) is not set. aliases: ['uuid'] version_added: 2.7 + moid: + description: + - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. + - This is required if C(vm_name) or C(vm_uuid) is not supplied. + version_added: '2.9' + type: str use_instance_uuid: description: - Whether to use the VMware instance UUID rather than the BIOS UUID. @@ -77,6 +83,16 @@ EXAMPLES = ''' destination_host: 'destination_host_as_per_vcenter' delegate_to: localhost +- name: Perform vMotion of virtual machine + vmware_vmotion: + hostname: '{{ vcenter_hostname }}' + username: '{{ vcenter_username }}' + password: '{{ vcenter_password }}' + validate_certs: no + moid: vm-42 + destination_host: 'destination_host_as_per_vcenter' + delegate_to: localhost + - name: Perform storage vMotion of of virtual machine vmware_vmotion: hostname: '{{ vcenter_hostname }}' @@ -108,7 +124,7 @@ running_host: ''' try: - from pyVmomi import vim + from pyVmomi import vim, VmomiSupport except ImportError: pass @@ -126,12 +142,13 @@ class VmotionManager(PyVmomi): self.vm_uuid = self.params.get('vm_uuid', None) self.use_instance_uuid = self.params.get('use_instance_uuid', False) self.vm_name = self.params.get('vm_name', None) + self.moid = self.params.get('moid') or None result = dict() self.get_vm() if self.vm is None: - self.module.fail_json(msg="Failed to find the virtual" - " machine with %s" % (self.vm_uuid or self.vm_name)) + vm_id = self.vm_uuid or self.vm_name or self.moid + self.module.fail_json(msg="Failed to find the virtual machine with %s" % vm_id) # Get Destination Host System if specified by user dest_host_name = self.params.get('destination_host', None) @@ -147,7 +164,7 @@ class VmotionManager(PyVmomi): self.datastore_object = find_datastore_by_name(content=self.content, datastore_name=dest_datastore) - # Atleast one of datastore, host system is required to migrate + # At-least one of datastore, host system is required to migrate if self.datastore_object is None and self.host_object is None: self.module.fail_json(msg="Unable to find destination datastore" " and destination host system.") @@ -261,13 +278,11 @@ class VmotionManager(PyVmomi): """ vms = [] - if self.vm_uuid and not self.use_instance_uuid: - vm_obj = find_vm_by_id(self.content, vm_id=self.params['vm_uuid'], vm_id_type="uuid") - vms = [vm_obj] - elif self.vm_uuid and self.use_instance_uuid: - vm_obj = find_vm_by_id(self.content, - vm_id=self.params['vm_uuid'], - vm_id_type="instance_uuid") + if self.vm_uuid: + if not self.use_instance_uuid: + vm_obj = find_vm_by_id(self.content, vm_id=self.params['vm_uuid'], vm_id_type="uuid") + elif self.use_instance_uuid: + vm_obj = find_vm_by_id(self.content, vm_id=self.params['vm_uuid'], vm_id_type="instance_uuid") vms = [vm_obj] elif self.vm_name: objects = self.get_managed_objects_properties(vim_type=vim.VirtualMachine, properties=['name']) @@ -277,6 +292,10 @@ class VmotionManager(PyVmomi): if temp_vm_object.obj.name == self.vm_name: vms.append(temp_vm_object.obj) break + elif self.moid: + vm_obj = VmomiSupport.templateOf('VirtualMachine')(self.moid, self.si._stub) + if vm_obj: + vms.append(vm_obj) if len(vms) > 1: self.module.fail_json(msg="Multiple virtual machines with same name %s found." @@ -291,6 +310,7 @@ def main(): dict( vm_name=dict(aliases=['vm']), vm_uuid=dict(aliases=['uuid']), + moid=dict(type='str'), use_instance_uuid=dict(type='bool', default=False), destination_host=dict(aliases=['destination']), destination_datastore=dict(aliases=['datastore']) @@ -302,10 +322,10 @@ def main(): supports_check_mode=True, required_one_of=[ ['destination_host', 'destination_datastore'], - ['vm_uuid', 'vm_name'], + ['vm_uuid', 'vm_name', 'moid'], ], mutually_exclusive=[ - ['vm_uuid', 'vm_name'], + ['vm_uuid', 'vm_name', 'moid'], ], ) diff --git a/test/integration/targets/vmware_guest_facts/tasks/main.yml b/test/integration/targets/vmware_guest_facts/tasks/main.yml index 13dc8ba50ab..187e7c7f481 100644 --- a/test/integration/targets/vmware_guest_facts/tasks/main.yml +++ b/test/integration/targets/vmware_guest_facts/tasks/main.yml @@ -48,6 +48,8 @@ - set_fact: vm1_instance_uuid="{{ guest_facts_0001['instance']['instance_uuid'] }}" +- set_fact: vm1_moid="{{ guest_facts_0001['instance']['moid'] }}" + - debug: var: vm1_uuid @@ -153,7 +155,7 @@ - "guest_facts_0004['instance']['snapshots'][0]['name'] == 'snap1'" - "guest_facts_0004['instance']['snapshots'][1]['name'] == 'snap2'" - "guest_facts_0004['instance']['current_snapshot']['name'] == 'snap2'" - - "guest_facts_0002['instance']['hw_folder'] is defined" + - "guest_facts_0004['instance']['hw_folder'] is defined" # Testcase 0005: Get details about virtual machines using UUID - name: get list of facts about virtual machines using instance UUID @@ -186,5 +188,39 @@ - "guest_facts_0005['instance']['guest_consolidation_needed'] is defined" - "guest_facts_0005['instance']['instance_uuid'] is defined" - "guest_facts_0005['instance']['instance_uuid'] == vm1_instance_uuid" - - "guest_facts_0001['instance']['moid'] is defined" - - "guest_facts_0001['instance']['vimref'] is defined" + - "guest_facts_0005['instance']['moid'] is defined" + - "guest_facts_0005['instance']['vimref'] is defined" + +# Testcase 0006: Get details about virtual machines using MoID +- name: get list of facts about virtual machines using instance MoID + vmware_guest_facts: + validate_certs: False + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter: "{{ dc1 }}" + moid: "{{ vm1_moid }}" + use_instance_uuid: True + register: guest_facts_0006 + +- debug: + msg: "{{ guest_facts_0006 }}" + +- assert: + that: + - "guest_facts_0006['instance']['hw_name'] == virtual_machines[0].name" + - "guest_facts_0006['instance']['hw_product_uuid'] is defined" + - "guest_facts_0006['instance']['hw_product_uuid'] == vm1_uuid" + - "guest_facts_0006['instance']['hw_cores_per_socket'] is defined" + - "guest_facts_0006['instance']['hw_datastores'] is defined" + - "guest_facts_0006['instance']['hw_esxi_host'] is defined" + - "guest_facts_0006['instance']['hw_files'] is defined" + - "guest_facts_0006['instance']['hw_guest_ha_state'] is defined" + - "guest_facts_0006['instance']['hw_is_template'] is defined" + - "guest_facts_0006['instance']['hw_folder'] is defined" + - "guest_facts_0006['instance']['guest_question'] is defined" + - "guest_facts_0006['instance']['guest_consolidation_needed'] is defined" + - "guest_facts_0006['instance']['instance_uuid'] is defined" + - "guest_facts_0006['instance']['instance_uuid'] == vm1_instance_uuid" + - "guest_facts_0006['instance']['moid'] is defined" + - "guest_facts_0006['instance']['vimref'] is defined"