diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_disk_facts.py b/lib/ansible/modules/cloud/vmware/vmware_guest_disk_facts.py new file mode 100644 index 0000000000..1781ce29a1 --- /dev/null +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_disk_facts.py @@ -0,0 +1,196 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = { + 'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community' +} + + +DOCUMENTATION = ''' +--- +module: vmware_guest_disk_facts +short_description: Gather facts about disks of given virtual machine +description: + - This module can be used to gather facts about disks belonging to given virtual machine. + - All parameters and VMware object names are case sensitive. +version_added: 2.6 +author: + - Abhijeet Kasurde (@akasurde) +notes: + - Tested on vSphere 6.0 and 6.5 +requirements: + - "python >= 2.6" + - PyVmomi +options: + name: + description: + - Name of the virtual machine. + - This is required parameter, if parameter C(uuid) 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. + folder: + description: + - Destination folder, absolute or relative path to find an existing guest. + - This is required parameter, only if multiple VMs are found with same name. + - The folder should include the datacenter. ESX's datacenter is ha-datacenter + - 'Examples:' + - ' folder: /ha-datacenter/vm' + - ' folder: ha-datacenter/vm' + - ' folder: /datacenter1/vm' + - ' folder: datacenter1/vm' + - ' folder: /datacenter1/vm/folder1' + - ' folder: datacenter1/vm/folder1' + - ' 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. + required: True +extends_documentation_fragment: vmware.documentation +''' + +EXAMPLES = ''' +- name: Gather disk facts from virtual machine using UUID + vmware_guest_disk_facts: + hostname: 192.168.1.209 + username: administrator@vsphere.local + password: vmware + datacenter: ha-datacenter + validate_certs: no + uuid: 421e4592-c069-924d-ce20-7e7533fab926 + delegate_to: localhost + register: disk_facts + +- name: Gather disk facts from virtual machine using name + vmware_guest_disk_facts: + hostname: 192.168.1.209 + username: administrator@vsphere.local + password: vmware + datacenter: ha-datacenter + validate_certs: no + name: VM_225 + delegate_to: localhost + register: disk_facts +''' + +RETURN = """ +guest_disk_facts: + description: metadata about the virtual machine's disks + returned: always + type: dict + sample: { + "0": { + "backing_datastore": "datastore2", + "backing_disk_mode": "persistent", + "backing_eagerlyscrub": false, + "backing_filename": "[datastore2] VM_225/VM_225.vmdk", + "backing_thinprovisioned": false, + "backing_writethrough": false, + "capacity_in_bytes": 10485760, + "capacity_in_kb": 10240, + "controller_key": 1000, + "key": 2000, + "label": "Hard disk 1", + "summary": "10,240 KB", + "unit_number": 0 + }, + } +""" + +try: + from pyVmomi import vim +except ImportError: + pass + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_text +from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec + + +class PyVmomiHelper(PyVmomi): + def __init__(self, module): + super(PyVmomiHelper, self).__init__(module) + + def gather_disk_facts(self, vm_obj): + """ + Function to gather facts about VM's disks + Args: + vm_obj: Managed object of virtual machine + + Returns: A list of dict containing disks information + + """ + disks_facts = dict() + if vm_obj is None: + return disks_facts + + disk_index = 0 + for disk in vm_obj.config.hardware.device: + if isinstance(disk, vim.vm.device.VirtualDisk): + disks_facts[disk_index] = dict( + key=disk.key, + label=disk.deviceInfo.label, + summary=disk.deviceInfo.summary, + backing_filename=disk.backing.fileName, + backing_datastore=disk.backing.datastore.name, + backing_disk_mode=disk.backing.diskMode, + backing_writethrough=disk.backing.writeThrough, + backing_thinprovisioned=disk.backing.thinProvisioned, + backing_eagerlyscrub=bool(disk.backing.eagerlyScrub), + controller_key=disk.controllerKey, + unit_number=disk.unitNumber, + capacity_in_kb=disk.capacityInKB, + capacity_in_bytes=disk.capacityInBytes, + ) + disk_index += 1 + return disks_facts + + +def main(): + argument_spec = vmware_argument_spec() + argument_spec.update( + name=dict(type='str'), + uuid=dict(type='str'), + folder=dict(type='str'), + datacenter=dict(type='str', required=True), + ) + module = AnsibleModule(argument_spec=argument_spec, + required_one_of=[['name', 'uuid']]) + + if module.params['folder']: + # FindByInventoryPath() does not require an absolute path + # so we should leave the input folder path unmodified + module.params['folder'] = module.params['folder'].rstrip('/') + + pyv = PyVmomiHelper(module) + # Check if the VM exists before continuing + vm = pyv.get_vm() + + if vm: + # VM exists + try: + module.exit_json(guest_disk_facts=pyv.gather_disk_facts(vm)) + except Exception as exc: + module.fail_json(msg="Failed to gather facts with exception : %s" % to_text(exc)) + 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'))) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/vmware_guest_disk_facts/aliases b/test/integration/targets/vmware_guest_disk_facts/aliases new file mode 100644 index 0000000000..6ee4e3d4f9 --- /dev/null +++ b/test/integration/targets/vmware_guest_disk_facts/aliases @@ -0,0 +1,3 @@ +posix/ci/cloud/group4/vcenter +cloud/vcenter + diff --git a/test/integration/targets/vmware_guest_disk_facts/tasks/main.yml b/test/integration/targets/vmware_guest_disk_facts/tasks/main.yml new file mode 100644 index 0000000000..a58c7e080d --- /dev/null +++ b/test/integration/targets/vmware_guest_disk_facts/tasks/main.yml @@ -0,0 +1,54 @@ +# Test code for the vmware_guest_disk_facts module. +# Copyright: (c) 2018, Abhijeet Kasurde +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# TODO: vcsim does not support disk information +#- name: Wait for Flask controller to come up online +# wait_for: +# host: "{{ vcsim }}" +# port: 5000 +# state: started +# +#- name: kill vcsim +# uri: +# url: http://{{ vcsim }}:5000/killall +#- name: start vcsim with no folders +# uri: +# url: http://{{ vcsim }}:5000/spawn?datacenter=1&cluster=1&folder=0 +# register: vcsim_instance +# +#- name: Wait for Flask controller to come up online +# wait_for: +# host: "{{ vcsim }}" +# port: 443 +# state: started +# +#- name: get a list of VMS from vcsim +# uri: +# url: http://{{ vcsim }}:5000/govc_find?filter=VM +# register: vmlist +# +#- debug: var=vcsim_instance +# +#- debug: var=vmlist +# +#- set_fact: +# vm1: "{{ vmlist['json'][0] }}" +# +#- debug: var=vm1 +# +#- name: create new VMs with non-existent network +# vmware_guest_disk_facts: +# validate_certs: False +# hostname: "{{ vcsim }}" +# username: "{{ vcsim_instance['json']['username'] }}" +# password: "{{ vcsim_instance['json']['password'] }}" +# name: "{{ vm1 }}" +# datacenter: "{{ (vm1 | basename).split('_')[0] }}" +# register: disk_facts +#- debug: var=disk_facts +# +#- name: assert that no changes were made +# assert: +# that: +# - "not disk_facts.changed"