diff --git a/changelogs/fragments/33156-vmware_guest-resource_pool.yaml b/changelogs/fragments/33156-vmware_guest-resource_pool.yaml new file mode 100644 index 00000000000..e772ced73de --- /dev/null +++ b/changelogs/fragments/33156-vmware_guest-resource_pool.yaml @@ -0,0 +1,2 @@ +bugfixes: +- Rewrite get_resource_pool method for correct resource_pool selection. diff --git a/lib/ansible/module_utils/vmware.py b/lib/ansible/module_utils/vmware.py index 8b32500e2aa..52b6d1ca474 100644 --- a/lib/ansible/module_utils/vmware.py +++ b/lib/ansible/module_utils/vmware.py @@ -76,28 +76,20 @@ def wait_for_vm_ip(content, vm, timeout=300): return facts -def find_obj(content, vimtype, name, first=True): - container = content.viewManager.CreateContainerView(container=content.rootFolder, recursive=True, type=vimtype) - obj_list = container.view +def find_obj(content, vimtype, name, first=True, folder=None): + container = content.viewManager.CreateContainerView(folder or content.rootFolder, recursive=True, type=vimtype) + # Get all objects matching type (and name if given) + obj_list = [obj for obj in container.view if not name or to_text(obj.name) == to_text(name)] container.Destroy() - # Backward compatible with former get_obj() function - if name is None: + # Return first match or None + if first: if obj_list: return obj_list[0] return None - # Select the first match - if first is True: - for obj in obj_list: - if to_text(obj.name) == to_text(name): - return obj - - # If no object found, return None - return None - - # Return all matching objects if needed - return [obj for obj in obj_list if obj.name == name] + # Return all matching objects or empty list + return obj_list def find_dvspg_by_name(dv_switch, portgroup_name): diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest.py b/lib/ansible/modules/cloud/vmware/vmware_guest.py index 92c5cacfee0..37c24853e4a 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest.py @@ -1850,33 +1850,6 @@ class PyVmomiHelper(PyVmomi): if current_parent is None: return False - def select_resource_pool_by_name(self, resource_pool_name): - resource_pool = self.cache.find_obj(self.content, [vim.ResourcePool], resource_pool_name) - if resource_pool is None: - self.module.fail_json(msg='Could not find resource_pool "%s"' % resource_pool_name) - return resource_pool - - def select_resource_pool_by_host(self, host): - resource_pools = self.cache.get_all_objs(self.content, [vim.ResourcePool]) - for rp in resource_pools.items(): - if not rp[0]: - continue - - if not hasattr(rp[0], 'parent') or not rp[0].parent: - continue - - # Find resource pool on host - if self.obj_has_parent(rp[0].parent, host.parent): - # If no resource_pool selected or it's the selected pool, return it - if self.module.params['resource_pool'] is None or rp[0].name == self.module.params['resource_pool']: - return rp[0] - - if self.module.params['resource_pool'] is not None: - self.module.fail_json(msg="Could not find resource_pool %s for selected host %s" - % (self.module.params['resource_pool'], host.name)) - else: - self.module.fail_json(msg="Failed to find a resource group for %s" % host.name) - def get_scsi_type(self): disk_controller_type = "paravirtual" # set cpu/memory/etc @@ -1921,28 +1894,39 @@ class PyVmomiHelper(PyVmomi): return root - def get_resource_pool(self): - resource_pool = None - # highest priority, resource_pool given. - if self.params['resource_pool']: - resource_pool = self.select_resource_pool_by_name(self.params['resource_pool']) - # next priority, esxi hostname given. - elif self.params['esxi_hostname']: - host = self.select_host() - resource_pool = self.select_resource_pool_by_host(host) - # next priority, cluster given, take the root of the pool - elif self.params['cluster']: - cluster = self.cache.get_cluster(self.params['cluster']) - if cluster is None: - self.module.fail_json(msg="Unable to find cluster '%(cluster)s'" % self.params) - resource_pool = cluster.resourcePool - # fallback, pick any RP + def get_resource_pool(self, cluster=None, host=None, resource_pool=None): + """ Get a resource pool, filter on cluster, esxi_hostname or resource_pool if given """ + + cluster_name = cluster or self.params.get('cluster', None) + host_name = host or self.params.get('esxi_hostname', None) + resource_pool_name = resource_pool or self.params.get('resource_pool', None) + + # get the datacenter object + datacenter = find_obj(self.content, [vim.Datacenter], self.params['datacenter']) + if not datacenter: + self.module.fail_json(msg='Unable to find datacenter "%s"' % self.params['datacenter']) + + # if cluster is given, get the cluster object + if cluster_name: + cluster = find_obj(self.content, [vim.ComputeResource], cluster_name, folder=datacenter) + if not cluster: + self.module.fail_json(msg='Unable to find cluster "%s"' % cluster_name) + # if host is given, get the cluster object using the host + elif host_name: + host = find_obj(self.content, [vim.HostSystem], host_name, folder=datacenter) + if not host: + self.module.fail_json(msg='Unable to find host "%s"' % host_name) + cluster = host.parent else: - resource_pool = self.select_resource_pool_by_name(self.params['resource_pool']) - - if resource_pool is None: - self.module.fail_json(msg='Unable to find resource pool, need esxi_hostname, resource_pool, or cluster') + cluster = None + # get resource pools limiting search to cluster or datacenter + resource_pool = find_obj(self.content, [vim.ResourcePool], resource_pool_name, folder=cluster or datacenter) + if not resource_pool: + if resource_pool_name: + self.module.fail_json(msg='Unable to find resource_pool "%s"' % resource_pool_name) + else: + self.module.fail_json(msg='Unable to find resource pool, need esxi_hostname, resource_pool, or cluster') return resource_pool def deploy_vm(self): @@ -2189,12 +2173,9 @@ class PyVmomiHelper(PyVmomi): relospec = vim.vm.RelocateSpec() if self.params['resource_pool']: - relospec.pool = self.select_resource_pool_by_name(self.params['resource_pool']) + relospec.pool = self.get_resource_pool() - if relospec.pool is None: - self.module.fail_json(msg='Unable to find resource pool "%(resource_pool)s"' % self.params) - - elif relospec.pool != self.current_vm_obj.resourcePool: + if relospec.pool != self.current_vm_obj.resourcePool: task = self.current_vm_obj.RelocateVM_Task(spec=relospec) self.wait_for_task(task) change_applied = True diff --git a/test/integration/targets/vmware_guest/tasks/cdrom_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/cdrom_d1_c1_f0.yml index e39bb61f1a8..822fa0b08d2 100644 --- a/test/integration/targets/vmware_guest/tasks/cdrom_d1_c1_f0.yml +++ b/test/integration/targets/vmware_guest/tasks/cdrom_d1_c1_f0.yml @@ -35,7 +35,7 @@ folder: "/{{ (clusterlist['json'][0]|basename).split('_')[0] }}/vm" name: CDROM-Test datacenter: "{{ (clusterlist['json'][0]|basename).split('_')[0] }}" - cluster: "{{ clusterlist['json'][0] }}" + cluster: "{{ clusterlist['json'][0]|basename }}" resource_pool: Resources guest_id: centos64Guest hardware: diff --git a/test/integration/targets/vmware_guest/tasks/vapp_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/vapp_d1_c1_f0.yml index 8e0d6bc81bb..76b304e8667 100644 --- a/test/integration/targets/vmware_guest/tasks/vapp_d1_c1_f0.yml +++ b/test/integration/targets/vmware_guest/tasks/vapp_d1_c1_f0.yml @@ -35,7 +35,7 @@ folder: "/{{ (clusterlist['json'][0]|basename).split('_')[0] }}/vm" name: vApp-Test datacenter: "{{ (clusterlist['json'][0]|basename).split('_')[0] }}" - cluster: "{{ clusterlist['json'][0] }}" + cluster: "{{ clusterlist['json'][0]|basename }}" resource_pool: Resources guest_id: centos64Guest hardware: