From cf78759f5bdbab5ebe77a8f9999a52cfae1155de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A9ri=20Le=20Bouder?= Date: Fri, 3 May 2019 18:08:42 -0400 Subject: [PATCH] vmware_vm_facts: fix the support with regular ESXi Ensure the module still work with the ESXi where CustomFieldsManager does not exist. From: https://www.vmware.com/support/developer/converter-sdk/conv60_apireference/vim.CustomFieldsManager.html The CustomFieldsManager object is used to add and remove custom fields to managed entities. The custom fields values set on managed entities are available through the customValue property and through the summary objects for VirtualMachine and HostSystem. They are not available directly through this managed object. This functionality is only available through VirtualCenter. Fixes: #56071 --- lib/ansible/module_utils/vmware.py | 3 ++ .../vmware_guest_custom_attribute_defs.py | 1 - .../vmware/vmware_guest_custom_attributes.py | 1 - .../modules/cloud/vmware/vmware_vm_facts.py | 7 ++--- .../plugins/inventory/vmware_vm_inventory.py | 4 ++- .../targets/vmware_vm_facts/tasks/main.yml | 31 +++++++++++++------ test/units/module_utils/test_vmware.py | 4 ++- 7 files changed, 33 insertions(+), 18 deletions(-) diff --git a/lib/ansible/module_utils/vmware.py b/lib/ansible/module_utils/vmware.py index 626374e8dc..98863a45b3 100644 --- a/lib/ansible/module_utils/vmware.py +++ b/lib/ansible/module_utils/vmware.py @@ -807,6 +807,9 @@ class PyVmomi(object): self.si = None self.current_vm_obj = None self.content = connect_to_api(self.module) + self.custom_field_mgr = [] + if self.content.customFieldsManager: # not an ESXi + self.custom_field_mgr = self.content.customFieldsManager.field def is_vcenter(self): """ diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attribute_defs.py b/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attribute_defs.py index a8421bc03b..9953bcfadf 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attribute_defs.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attribute_defs.py @@ -91,7 +91,6 @@ except ImportError: class VmAttributeDefManager(PyVmomi): def __init__(self, module): super(VmAttributeDefManager, self).__init__(module) - self.custom_field_mgr = self.content.customFieldsManager.field def remove_custom_def(self, field): changed = False 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 1ae4e31605..d0cc50e498 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py @@ -139,7 +139,6 @@ from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec class VmAttributeManager(PyVmomi): def __init__(self, module): super(VmAttributeManager, self).__init__(module) - self.custom_field_mgr = self.content.customFieldsManager.field def set_custom_field(self, vm, user_fields): result_fields = dict() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vm_facts.py b/lib/ansible/modules/cloud/vmware/vmware_vm_facts.py index 0241ef0cf2..ae5e1164d1 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_vm_facts.py +++ b/lib/ansible/modules/cloud/vmware/vmware_vm_facts.py @@ -18,9 +18,9 @@ ANSIBLE_METADATA = { DOCUMENTATION = r''' --- module: vmware_vm_facts -short_description: Return basic facts pertaining to a vSphere virtual machine guest +short_description: Return basic facts pertaining to a VMware machine guest description: -- Return basic facts pertaining to a vSphere virtual machine guest. +- Return basic facts pertaining to a vSphere or ESXi virtual machine guest. - Cluster name as fact is added in version 2.7. version_added: '2.0' author: @@ -28,7 +28,7 @@ author: - Abhijeet Kasurde (@Akasurde) - Fedor Vompe (@sumkincpp) notes: -- Tested on vSphere 5.5 and vSphere 6.5 +- Tested on ESXi 6.7, vSphere 5.5 and vSphere 6.5 - From 2.8 and onwards, facts are returned as list of dict instead of dict. requirements: - python >= 2.6 @@ -165,7 +165,6 @@ from ansible.module_utils.vmware import PyVmomi, get_all_objs, vmware_argument_s class VmwareVmFacts(PyVmomi): def __init__(self, module): super(VmwareVmFacts, self).__init__(module) - self.custom_field_mgr = self.content.customFieldsManager.field def get_vm_attributes(self, vm): return dict((x.name, v.value) for x in self.custom_field_mgr diff --git a/lib/ansible/plugins/inventory/vmware_vm_inventory.py b/lib/ansible/plugins/inventory/vmware_vm_inventory.py index 559c666faf..a6e0bb34e1 100644 --- a/lib/ansible/plugins/inventory/vmware_vm_inventory.py +++ b/lib/ansible/plugins/inventory/vmware_vm_inventory.py @@ -447,7 +447,9 @@ class InventoryModule(BaseInventoryPlugin, Cacheable): 'runtime.maxMemoryUsage', 'customValue', ] - field_mgr = self.pyv.content.customFieldsManager.field + field_mgr = [] + if self.content.customFieldsManager: + field_mgr = self.pyv.content.customFieldsManager.field for vm_prop in vm_properties: if vm_prop == 'customValue': diff --git a/test/integration/targets/vmware_vm_facts/tasks/main.yml b/test/integration/targets/vmware_vm_facts/tasks/main.yml index 06caaf31a0..276448d2d5 100644 --- a/test/integration/targets/vmware_vm_facts/tasks/main.yml +++ b/test/integration/targets/vmware_vm_facts/tasks/main.yml @@ -3,6 +3,15 @@ # Copyright, (c) 2018, Fedor Vompe # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +- when: vcsim is not defined + block: + - name: Get facts from a given ESXi + vmware_vm_facts: + validate_certs: false + hostname: '{{ esxi1 }}' + username: '{{ hostvars[esxi1].ansible_user }}' + password: '{{ hostvars[esxi1].ansible_password }}' + - import_role: name: prepare_vmware_tests vars: @@ -20,20 +29,22 @@ register: vm_facts_0001 - debug: var=vm_facts_0001 -- set_fact: - first_vm: "{{ vm_facts_0001['virtual_machines'][0] }}" - &vm_fact_check name: Verify if VM facts exist assert: that: - - first_vm.esxi_hostname is defined - - first_vm.guest_fullname is defined - - first_vm.ip_address is defined - - first_vm.mac_address is defined - - first_vm.power_state is defined - - first_vm.uuid is defined - - first_vm.vm_network is defined + - "item.esxi_hostname is defined" + - "item.guest_fullname is defined" + - "item.ip_address is defined" + - "item.mac_address is defined" + - "item.power_state is defined" + - "item.uuid is defined" + - "item.vm_network is defined" + with_items: + - "{{ vm_facts_0001.virtual_machines | json_query(query) }}" + vars: + query: "[?guest_name=='DC0_H0_VM0']" - <<: *vm_data name: Get facts about available vms in check mode @@ -48,7 +59,7 @@ hostname: "{{ vcenter_hostname }}" username: "{{ vcenter_username }}" password: "{{ vcenter_password }}" - name: "{{ first_vm.guest_name }}" + name: "DC0_H0_VM0" register: folder_path_info - set_fact: diff --git a/test/units/module_utils/test_vmware.py b/test/units/module_utils/test_vmware.py index e3905e40a3..9836f13396 100644 --- a/test/units/module_utils/test_vmware.py +++ b/test/units/module_utils/test_vmware.py @@ -89,7 +89,9 @@ class FakeAnsibleModule: def fake_connect_to_api(module): - pass + class MyContent(): + customFieldsManager = None + return MyContent def test_pyvmomi_lib_exists(mocker, fake_ansible_module):