VMware: Add support in VMWare modules for BIOS and instance UUID's (#44399)

* Add support for changing UUID type referenced
* Update all appropriate VMware modules to include UUID type
* Add integration test for filtering on instance UUID
This commit is contained in:
Jake Hill 2019-02-25 08:37:07 +00:00 committed by Abhijeet Kasurde
parent f135960fc2
commit e18d5ea8b3
17 changed files with 179 additions and 21 deletions

View file

@ -181,7 +181,8 @@ def find_network_by_name(content, network_name):
return find_object_by_name(content, network_name, [vim.Network])
def find_vm_by_id(content, vm_id, vm_id_type="vm_name", datacenter=None, cluster=None, folder=None, match_first=False):
def find_vm_by_id(content, vm_id, vm_id_type="vm_name", datacenter=None,
cluster=None, folder=None, match_first=False):
""" UUID is unique to a VM, every other id returns the first match. """
si = content.searchIndex
vm = None
@ -191,6 +192,8 @@ def find_vm_by_id(content, vm_id, vm_id_type="vm_name", datacenter=None, cluster
elif vm_id_type == 'uuid':
# Search By BIOS UUID rather than instance UUID
vm = si.FindByUuid(datacenter=datacenter, instanceUuid=False, uuid=vm_id, vmSearch=True)
elif vm_id_type == 'instance_uuid':
vm = si.FindByUuid(datacenter=datacenter, instanceUuid=True, uuid=vm_id, vmSearch=True)
elif vm_id_type == 'ip':
vm = si.FindByIp(datacenter=datacenter, ip=vm_id, vmSearch=True)
elif vm_id_type == 'vm_name':
@ -870,9 +873,12 @@ class PyVmomi(object):
vm_obj = None
user_desired_path = None
if self.params['uuid']:
if self.params['uuid'] and not self.params['use_instance_uuid']:
vm_obj = find_vm_by_id(self.content, vm_id=self.params['uuid'], vm_id_type="uuid")
elif self.params['uuid'] and self.params['use_instance_uuid']:
vm_obj = find_vm_by_id(self.content,
vm_id=self.params['uuid'],
vm_id_type="instance_uuid")
elif self.params['name']:
objects = self.get_managed_objects_properties(vim_type=vim.VirtualMachine, properties=['name'])
vms = []

View file

@ -82,6 +82,12 @@ options:
- This is required if C(name) is not supplied.
- If virtual machine does not exists, then this parameter is ignored.
- Please note that a supplied UUID will be ignored on virtual machine creation, as VMware creates the UUID internally.
use_instance_uuid:
description:
- Whether to use the VMWare instance UUID rather than the BIOS UUID.
default: no
type: bool
version_added: '2.8'
template:
description:
- Template or existing virtual machine used to create new virtual machine.
@ -2523,6 +2529,7 @@ def main():
name=dict(type='str'),
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'),
guest_id=dict(type='str'),
disk=dict(type='list', default=[]),

View file

@ -36,8 +36,14 @@ options:
- This is required if C(uuid) parameter is not supplied.
uuid:
description:
- UUID of the instance to manage if known, this is VMware's BIOS UUID.
- 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.
use_instance_uuid:
description:
- Whether to use the VMWare instance UUID rather than the BIOS UUID.
default: no
type: bool
version_added: '2.8'
name_match:
description:
- If multiple virtual machines matching the name, use the first or last found.
@ -93,13 +99,17 @@ class VmBootFactsManager(PyVmomi):
super(VmBootFactsManager, self).__init__(module)
self.name = self.params['name']
self.uuid = self.params['uuid']
self.use_instance_uuid = self.params['use_instance_uuid']
self.vm = None
def _get_vm(self):
vms = []
if self.uuid:
vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="uuid")
if self.use_instance_uuid:
vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="use_instance_uuid")
else:
vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="uuid")
if vm_obj is None:
self.module.fail_json(msg="Failed to find the virtual machine with UUID : %s" % self.uuid)
vms = [vm_obj]
@ -155,6 +165,7 @@ def main():
argument_spec.update(
name=dict(type='str'),
uuid=dict(type='str'),
use_instance_uuid=dict(type='bool', default=False),
name_match=dict(
choices=['first', 'last'],
default='first'

View file

@ -36,8 +36,14 @@ options:
- This is required if C(uuid) parameter is not supplied.
uuid:
description:
- UUID of the instance to manage if known, this is VMware's BIOS UUID.
- 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.
use_instance_uuid:
description:
- Whether to use the VMWare instance UUID rather than the BIOS UUID.
default: no
type: bool
version_added: '2.8'
boot_order:
description:
- List of the boot devices.
@ -152,13 +158,17 @@ class VmBootManager(PyVmomi):
super(VmBootManager, self).__init__(module)
self.name = self.params['name']
self.uuid = self.params['uuid']
self.use_instance_uuid = self.params['use_instance_uuid']
self.vm = None
def _get_vm(self):
vms = []
if self.uuid:
vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="uuid")
if self.use_instance_uuid:
vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="instance_uuid")
else:
vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="uuid")
if vm_obj is None:
self.module.fail_json(msg="Failed to find the virtual machine with UUID : %s" % self.uuid)
vms = [vm_obj]
@ -314,6 +324,7 @@ def main():
argument_spec.update(
name=dict(type='str'),
uuid=dict(type='str'),
use_instance_uuid=dict(type='bool', default=False),
boot_order=dict(
type='list',
default=[],

View file

@ -48,6 +48,12 @@ options:
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.
use_instance_uuid:
description:
- Whether to use the VMWare instance UUID rather than the BIOS UUID.
default: no
type: bool
version_added: '2.8'
folder:
description:
- Absolute path to find an existing guest.
@ -180,6 +186,7 @@ def main():
name=dict(required=True, type='str'),
folder=dict(type='str'),
uuid=dict(type='str'),
use_instance_uuid=dict(type='bool', default=False),
state=dict(type='str', default='present',
choices=['absent', 'present']),
attributes=dict(

View file

@ -39,6 +39,12 @@ options:
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.
use_instance_uuid:
description:
- Whether to use the VMWare instance UUID rather than the BIOS UUID.
default: no
type: bool
version_added: '2.8'
folder:
description:
- Destination folder, absolute or relative path to find an existing guest.
@ -166,6 +172,7 @@ def main():
argument_spec.update(
name=dict(type='str'),
uuid=dict(type='str'),
use_instance_uuid=dict(type='bool', default=False),
folder=dict(type='str'),
datacenter=dict(type='str', required=True),
)

View file

@ -43,6 +43,12 @@ options:
description:
- UUID of the instance to manage if known, this is VMware's unique identifier.
- This is required if name 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'
folder:
description:
- Destination folder, absolute or relative path to find an existing guest.
@ -155,6 +161,7 @@ from ansible.module_utils._text import to_text
from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec
from ansible.module_utils.vmware_rest_client import VmwareRestClient
try:
from com.vmware.vapi.std_client import DynamicID
from com.vmware.cis.tagging_client import Tag, TagAssociation
HAS_VCLOUD = True
except ImportError:
@ -179,6 +186,7 @@ def main():
name=dict(type='str'),
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'),
datacenter=dict(type='str', required=True),
tags=dict(type='bool', default=False)

View file

@ -65,6 +65,7 @@ options:
default: vm_name
choices:
- 'uuid'
- 'instance_uuid'
- 'dns_name'
- 'inventory_path'
- 'vm_name'
@ -194,8 +195,11 @@ class VmwareGuestFileManager(PyVmomi):
if module.params['vm_id_type'] == 'inventory_path':
vm = find_vm_by_id(self.content, vm_id=module.params['vm_id'], vm_id_type="inventory_path", folder=folder)
else:
vm = find_vm_by_id(self.content, vm_id=module.params['vm_id'], vm_id_type=module.params['vm_id_type'],
datacenter=datacenter, cluster=cluster)
vm = find_vm_by_id(self.content,
vm_id=module.params['vm_id'],
vm_id_type=module.params['vm_id_type'],
datacenter=datacenter,
cluster=cluster)
if not vm:
module.fail_json(msg='Unable to find virtual machine.')
@ -391,7 +395,7 @@ def main():
vm_id_type=dict(
default='vm_name',
type='str',
choices=['inventory_path', 'uuid', 'dns_name', 'vm_name']),
choices=['inventory_path', 'uuid', 'instance_uuid', 'dns_name', 'vm_name']),
vm_username=dict(type='str', required=True),
vm_password=dict(type='str', no_log=True, required=True),
directory=dict(

View file

@ -34,8 +34,14 @@ options:
- This is required if C(uuid) parameter is not supplied.
uuid:
description:
- UUID of the instance to manage if known, this is VMware's BIOS UUID.
- 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.
use_instance_uuid:
description:
- Whether to use the VMWare instance UUID rather than the BIOS UUID.
default: no
type: bool
version_added: '2.8'
datacenter:
description:
- Destination datacenter for the find operation.
@ -90,13 +96,17 @@ class PyVmomiHelper(PyVmomi):
super(PyVmomiHelper, self).__init__(module)
self.name = self.params['name']
self.uuid = self.params['uuid']
self.use_instance_uuid = self.params['use_instance_uuid']
def getvm_folder_paths(self):
results = []
vms = []
if self.uuid:
vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="uuid")
if self.use_instance_uuid:
vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="instance_uuid")
else:
vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="uuid")
if vm_obj is None:
self.module.fail_json(msg="Failed to find the virtual machine with UUID : %s" % self.uuid)
vms = [vm_obj]
@ -119,6 +129,7 @@ def main():
argument_spec.update(
name=dict(type='str'),
uuid=dict(type='str'),
use_instance_uuid=dict(type='bool', default=False),
datacenter=dict(removed_in_version=2.9, type='str')
)

View file

@ -37,6 +37,12 @@ options:
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.
use_instance_uuid:
description:
- Whether to use the VMWare instance UUID rather than the BIOS UUID.
default: no
type: bool
version_added: '2.8'
name_match:
description:
- If multiple virtual machines matching the name, use the first or last found.
@ -169,6 +175,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),
dest_folder=dict(type='str', required=True),
datacenter=dict(type='str', required=True),
)

View file

@ -42,6 +42,12 @@ options:
description:
- UUID of the instance to manage if known, this is VMware's unique identifier.
- This is required if name 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'
folder:
description:
- Destination folder, absolute or relative path to find an existing guest or create the new guest.
@ -139,6 +145,7 @@ def main():
name=dict(type='str'),
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'),
force=dict(type='bool', default=False),
scheduled_at=dict(type='str'),

View file

@ -52,8 +52,14 @@ options:
choices: ['first', 'last']
uuid:
description:
- UUID of the instance to manage if known, this is VMware's unique identifier.
- This is required parameter, if C(name) is not supplied.
- 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.
use_instance_uuid:
description:
- Whether to use the VMWare instance UUID rather than the BIOS UUID.
default: no
type: bool
version_added: '2.8'
folder:
description:
- Destination folder, absolute or relative path to find an existing guest.
@ -367,6 +373,7 @@ def main():
name=dict(type='str'),
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'),
datacenter=dict(required=True, type='str'),
snapshot_name=dict(type='str'),

View file

@ -35,9 +35,15 @@ options:
- This is required if C(uuid) is not supplied.
uuid:
description:
- UUID of the instance to manage if known, this value is VMware's unique identifier.
- This is required if C(name) is not supplied.
- 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.
- The C(folder) is ignored, if C(uuid) is provided.
use_instance_uuid:
description:
- Whether to use the VMWare instance UUID rather than the BIOS UUID.
default: no
type: bool
version_added: '2.8'
folder:
description:
- Destination folder, absolute or relative path to find an existing guest.
@ -125,6 +131,7 @@ def main():
argument_spec.update(
name=dict(type='str'),
uuid=dict(type='str'),
use_instance_uuid=dict(type='bool', default=False),
folder=dict(type='str'),
datacenter=dict(required=True, type='str'),
)

View file

@ -56,6 +56,12 @@ options:
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.
use_instance_uuid:
description:
- Whether to use the VMWare instance UUID rather than the BIOS UUID.
default: no
type: bool
version_added: '2.8'
extends_documentation_fragment: vmware.documentation
'''
@ -146,6 +152,7 @@ def main():
name_match=dict(type='str', default='first', choices=['first', 'last']),
folder=dict(type='str'),
uuid=dict(type='str'),
use_instance_uuid=dict(type='bool', default=False),
)
module = AnsibleModule(
argument_spec=argument_spec,

View file

@ -62,7 +62,7 @@ options:
description:
- The VMware identification method by which the virtual machine will be identified.
default: vm_name
choices: ['uuid', 'dns_name', 'inventory_path', 'vm_name']
choices: ['uuid', 'instance_uuid', 'dns_name', 'inventory_path', 'vm_name']
vm_username:
description:
- The user to login-in to the virtual machine.
@ -230,7 +230,8 @@ class VMwareShellManager(PyVmomi):
vm = find_vm_by_id(self.content,
vm_id=module.params['vm_id'],
vm_id_type=module.params['vm_id_type'],
datacenter=datacenter, cluster=cluster)
datacenter=datacenter,
cluster=cluster)
if not vm:
module.fail_json(msg='Unable to find virtual machine.')
@ -327,7 +328,11 @@ def main():
folder=dict(type='str'),
vm_id=dict(type='str', required=True),
vm_id_type=dict(default='vm_name', type='str',
choices=['inventory_path', 'uuid', 'dns_name', 'vm_name']),
choices=['inventory_path',
'uuid',
'instance_uuid',
'dns_name',
'vm_name']),
vm_username=dict(type='str', required=True),
vm_password=dict(type='str', no_log=True, required=True),
vm_shell=dict(type='str', required=True),

View file

@ -47,6 +47,12 @@ options:
- This is a required parameter, if C(vm_name) is not set.
aliases: ['uuid']
version_added: 2.7
use_instance_uuid:
description:
- Whether to use the VMWare instance UUID rather than the BIOS UUID.
default: no
type: bool
version_added: '2.8'
destination_host:
description:
- Name of the destination host the virtual machine should be running on.
@ -118,6 +124,7 @@ class VmotionManager(PyVmomi):
super(VmotionManager, self).__init__(module)
self.vm = None
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)
result = dict()
@ -254,10 +261,14 @@ class VmotionManager(PyVmomi):
"""
vms = []
if self.vm_uuid:
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")
vms = [vm_obj]
elif self.vm_name:
objects = self.get_managed_objects_properties(vim_type=vim.VirtualMachine, properties=['name'])
for temp_vm_object in objects:
@ -280,6 +291,7 @@ def main():
dict(
vm_name=dict(aliases=['vm']),
vm_uuid=dict(aliases=['uuid']),
use_instance_uuid=dict(type='bool', default=False),
destination_host=dict(aliases=['destination']),
destination_datastore=dict(aliases=['datastore'])
)

View file

@ -79,9 +79,12 @@
- "guest_facts_0001['instance']['guest_consolidation_needed'] is defined"
- "'portgroup_portkey' in guest_facts_0001['instance']['hw_eth0']"
- "'portgroup_key' in guest_facts_0001['instance']['hw_eth0']"
- "guest_facts_0001['instance']['instance_uuid'] is defined"
- set_fact: vm1_uuid="{{ guest_facts_0001['instance']['hw_product_uuid'] }}"
- set_fact: vm1_instance_uuid="{{ guest_facts_0001['instance']['instance_uuid'] }}"
- debug: var=vm1_uuid
# Testcase 0002: Get details about virtual machines using UUID
@ -175,3 +178,34 @@
# - "guest_facts_0004['instance']['snapshots'][1]['name'] == 'snap2'"
# - "guest_facts_0004['instance']['current_snapshot']['name'] == 'snap2'"
# - "guest_facts_0002['instance']['hw_folder'] == vm1 | dirname"
# Testcase 0005: Get details about virtual machines using UUID
- name: get list of facts about virtual machines using instance UUID
vmware_guest_facts:
validate_certs: False
hostname: "{{ vcsim }}"
username: "{{ vcsim_instance['json']['username'] }}"
password: "{{ vcsim_instance['json']['password'] }}"
datacenter: "{{ dc1 | basename }}"
uuid: "{{ vm1_instance_uuid }}"
use_instance_uuid: True
register: guest_facts_0005
- debug: msg="{{ guest_facts_0005 }}"
- assert:
that:
- "guest_facts_0005['instance']['hw_name'] == vm1 | basename"
- "guest_facts_0005['instance']['hw_product_uuid'] is defined"
- "guest_facts_0005['instance']['hw_product_uuid'] == vm1_uuid"
- "guest_facts_0005['instance']['hw_cores_per_socket'] is defined"
- "guest_facts_0005['instance']['hw_datastores'] is defined"
- "guest_facts_0005['instance']['hw_esxi_host'] == h1 | basename"
- "guest_facts_0005['instance']['hw_files'] is defined"
- "guest_facts_0005['instance']['hw_guest_ha_state'] is defined"
- "guest_facts_0005['instance']['hw_is_template'] is defined"
- "guest_facts_0005['instance']['hw_folder'] is defined"
- "guest_facts_0005['instance']['guest_question'] is defined"
- "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"