diff --git a/lib/ansible/module_utils/vmware.py b/lib/ansible/module_utils/vmware.py index ffca309ef09..dc63e66f81f 100644 --- a/lib/ansible/module_utils/vmware.py +++ b/lib/ansible/module_utils/vmware.py @@ -316,19 +316,7 @@ def gather_vm_facts(content, vm): except: pass - folder = vm.parent - if folder: - foldername = folder.name - fp = folder.parent - # climb back up the tree to find our path, stop before the root folder - while fp is not None and fp.name is not None and fp != content.rootFolder: - foldername = fp.name + '/' + foldername - try: - fp = fp.parent - except: - break - foldername = '/' + foldername - facts['hw_folder'] = foldername + facts['hw_folder'] = PyVmomi.get_vm_path(content, vm) cfm = content.customFieldsManager # Resolve custom values @@ -824,6 +812,23 @@ class PyVmomi(object): def gather_facts(self, vm): return gather_vm_facts(self.content, vm) + @staticmethod + def get_vm_path(content, vm): + foldername = None + folder = vm.parent + if folder: + foldername = folder.name + fp = folder.parent + # climb back up the tree to find our path, stop before the root folder + while fp is not None and fp.name is not None and fp != content.rootFolder: + foldername = fp.name + '/' + foldername + try: + fp = fp.parent + except: + break + foldername = '/' + foldername + return foldername + # Cluster related functions def find_cluster_by_name(self, cluster_name, datacenter_name=None): """ diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_find.py b/lib/ansible/modules/cloud/vmware/vmware_guest_find.py index f4651fa48d9..6dd360daf6d 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_find.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_find.py @@ -16,12 +16,13 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', DOCUMENTATION = ''' --- module: vmware_guest_find -short_description: Find the folder path(s) for a VM by name or UUID +short_description: Find the folder path(s) for a virtual machine by name or UUID description: - - Find the folder path(s) for a VM by name or UUID + - Find the folder path(s) for a virtual machine by name or UUID version_added: 2.4 author: - James Tanner + - Abhijeet Kasurde notes: - Tested on vSphere 6.5 requirements: @@ -39,6 +40,7 @@ options: datacenter: description: - Destination datacenter for the find operation. + - Deprecated in 2.5, will be removed in 2.9 release. required: True extends_documentation_fragment: vmware.documentation ''' @@ -47,7 +49,6 @@ EXAMPLES = ''' - name: Find Guest's Folder using name vmware_guest_find: hostname: 192.168.1.209 - datacenter: datacenter-name username: administrator@vsphere.local password: vmware validate_certs: no @@ -57,7 +58,6 @@ EXAMPLES = ''' - name: Find Guest's Folder using UUID vmware_guest_find: hostname: 192.168.1.209 - datacenter: datacenter-name username: administrator@vsphere.local password: vmware validate_certs: no @@ -65,55 +65,37 @@ EXAMPLES = ''' register: vm_folder ''' -RETURN = """ +RETURN = r""" +folders: + description: List of folders for user specified virtual machine + returned: on success + type: list """ -import os + from ansible.module_utils.basic import AnsibleModule from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import ( - connect_to_api, - gather_vm_facts, - get_all_objs, - compile_folder_path_for_object, - vmware_argument_spec, - find_datacenter_by_name -) +from ansible.module_utils.vmware import PyVmomi, get_all_objs, vmware_argument_spec + try: import pyVmomi from pyVmomi import vim - - HAS_PYVMOMI = True except ImportError: - HAS_PYVMOMI = False + pass -class PyVmomiHelper(object): +class PyVmomiHelper(PyVmomi): def __init__(self, module): - if not HAS_PYVMOMI: - module.fail_json(msg='pyvmomi module required') - + super(PyVmomiHelper, self).__init__(module) self.datacenter = None self.folders = None - self.foldermap = { - 'fvim_by_path': {}, - 'path_by_fvim': {}, - 'path_by_vvim': {}, - 'paths': {}, - 'uuids': {} - } - self.module = module - self.params = module.params - self.content = connect_to_api(self.module) - - def getvm_folder_paths(self, name=None, uuid=None): + self.name = self.params['name'] + self.uuid = self.params['uuid'] + def getvm_folder_paths(self): results = [] - if not self.folders: - self.getfolders() - # compare the folder path of each VM against the search path vmList = get_all_objs(self.content, [vim.VirtualMachine]) for item in vmList.items(): @@ -121,101 +103,26 @@ class PyVmomiHelper(object): if not isinstance(vobj.parent, vim.Folder): continue # Match by name or uuid - if vobj.config.name == name or vobj.config.uuid == uuid: - folderpath = compile_folder_path_for_object(vobj) + if vobj.config.name == self.name or vobj.config.uuid == self.uuid: + folderpath = self.get_vm_path(self.content, vobj) results.append(folderpath) - return results - def gather_facts(self, vm): - return gather_vm_facts(self.content, vm) - - def _build_folder_tree(self, folder): - - tree = {'virtualmachines': [], - 'subfolders': {}, - 'vimobj': folder, - 'name': folder.name} - - children = None - if hasattr(folder, 'childEntity'): - children = folder.childEntity - - if children: - for child in children: - if child == folder or child in tree: - continue - if isinstance(child, vim.Folder): - ctree = self._build_folder_tree(child) - tree['subfolders'][child] = dict.copy(ctree) - elif isinstance(child, vim.VirtualMachine): - tree['virtualmachines'].append(child) - else: - if isinstance(folder, vim.VirtualMachine): - return folder - return tree - - def _build_folder_map(self, folder, inpath='/'): - """ Build a searchable index for vms+uuids+folders """ - if isinstance(folder, tuple): - folder = folder[1] - - thispath = os.path.join(inpath, folder['name']) - - if thispath not in self.foldermap['paths']: - self.foldermap['paths'][thispath] = [] - - # store object by path and store path by object - self.foldermap['fvim_by_path'][thispath] = folder['vimobj'] - self.foldermap['path_by_fvim'][folder['vimobj']] = thispath - - for item in folder.items(): - k = item[0] - v = item[1] - - if k == 'name': - pass - elif k == 'subfolders': - for x in v.items(): - self._build_folder_map(x, inpath=thispath) - elif k == 'virtualmachines': - for x in v: - # Apparently x.config can be None on corrupted VMs - if x.config is None: - continue - self.foldermap['uuids'][x.config.uuid] = x.config.name - self.foldermap['paths'][thispath].append(x.config.uuid) - - if x not in self.foldermap['path_by_vvim']: - self.foldermap['path_by_vvim'][x] = thispath - - def getfolders(self): - if not self.datacenter: - self.datacenter = find_datacenter_by_name(self.content, self.params['datacenter']) - - if self.datacenter is None: - self.module.fail_json(msg="Unable to find datacenter %(datacenter)s" % self.params) - - self.folders = self._build_folder_tree(self.datacenter.vmFolder) - self._build_folder_map(self.folders) - def main(): argument_spec = vmware_argument_spec() argument_spec.update( name=dict(type='str'), uuid=dict(type='str'), - datacenter=dict(type='str', required=True) + datacenter=dict(removed_in_version=2.9, type='str', required=True) ) module = AnsibleModule(argument_spec=argument_spec, required_one_of=[['name', 'uuid']]) + pyv = PyVmomiHelper(module) # Check if the VM exists before continuing - folders = pyv.getvm_folder_paths( - name=module.params['name'], - uuid=module.params['uuid'] - ) + folders = pyv.getvm_folder_paths() # VM already exists if folders: @@ -224,12 +131,8 @@ def main(): except Exception as exc: module.fail_json(msg="Folder enumeration failed with exception %s" % to_native(exc)) else: - msg = "Unable to find folders for VM " - if module.params['name']: - msg += "%(name)s" % module.params - elif module.params['uuid']: - msg += "%(uuid)s" % module.params - module.fail_json(msg=msg) + module.fail_json(msg="Unable to find folders for virtual machine %s" % (module.params.get('name') or + module.params.get('uuid'))) if __name__ == '__main__':