#!/usr/bin/python # -*- coding: utf-8 -*- # Copyright: (c) 2017, Tim Rightnour # Copyright: (c) 2018, Ansible Project # 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_datastore_facts short_description: Gather facts about datastores available in given vCenter description: - This module can be used to gather facts about datastores in VMWare infrastructure. - All values and VMware object names are case sensitive. version_added: 2.5 author: - Tim Rightnour (@garbled1) notes: - Tested on vSphere 5.5, 6.0 and 6.5 requirements: - "python >= 2.6" - PyVmomi options: name: description: - Name of the datastore to match. - If set, facts of specific datastores are returned. required: False datacenter: description: - Datacenter to search for datastores. - This parameter is required, if C(cluster) is not supplied. required: False cluster: description: - Cluster to search for datastores. - If set, facts of datastores belonging this clusters will be returned. - This parameter is required, if C(datacenter) is not supplied. required: False extends_documentation_fragment: vmware.documentation ''' EXAMPLES = ''' - name: Gather facts from standalone ESXi server having datacenter as 'ha-datacenter' vmware_datastore_facts: hostname: '{{ vcenter_hostname }}' username: '{{ vcenter_username }}' password: '{{ vcenter_password }}' datacenter: '{{ datacenter_name }}' validate_certs: no delegate_to: localhost register: facts - name: Gather facts from datacenter about specific datastore vmware_datastore_facts: hostname: '{{ vcenter_hostname }}' username: '{{ vcenter_username }}' password: '{{ vcenter_password }}' datacenter: '{{ datacenter_name }}' name: datastore1 delegate_to: localhost register: facts ''' RETURN = """ datastores: description: metadata about the available datastores returned: always type: list sample: [ { "accessible": false, "capacity": 42681237504, "datastore_cluster": "datacluster0", "freeSpace": 39638269952, "maintenanceMode": "normal", "multipleHostAccess": false, "name": "datastore2", "provisioned": 12289211488, "type": "VMFS", "uncommitted": 9246243936, "url": "ds:///vmfs/volumes/5a69b18a-c03cd88c-36ae-5254001249ce/" }, ] """ try: from pyVmomi import vim except ImportError: pass from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.vmware import (PyVmomi, vmware_argument_spec, get_all_objs, find_cluster_by_name, get_parent_datacenter) class PyVmomiCache(object): """ This class caches references to objects which are requested multiples times but not modified """ def __init__(self, content, dc_name=None): self.content = content self.dc_name = dc_name self.clusters = {} self.parent_datacenters = {} def get_all_objs(self, content, types, confine_to_datacenter=True): """ Wrapper around get_all_objs to set datacenter context """ objects = get_all_objs(content, types) if confine_to_datacenter: if hasattr(objects, 'items'): # resource pools come back as a dictionary for k, v in objects.items(): parent_dc = get_parent_datacenter(k) if parent_dc.name != self.dc_name: objects.pop(k, None) else: # everything else should be a list objects = [x for x in objects if get_parent_datacenter(x).name == self.dc_name] return objects class PyVmomiHelper(PyVmomi): def __init__(self, module): super(PyVmomiHelper, self).__init__(module) self.cache = PyVmomiCache(self.content, dc_name=self.params['datacenter']) def lookup_datastore(self): datastores = self.cache.get_all_objs(self.content, [vim.Datastore], confine_to_datacenter=True) return datastores def lookup_datastore_by_cluster(self): cluster = find_cluster_by_name(self.content, self.params['cluster']) if not cluster: self.module.fail_json(msg='Failed to find cluster "%(cluster)s"' % self.params) c_dc = cluster.datastore return c_dc def main(): argument_spec = vmware_argument_spec() argument_spec.update( name=dict(type='str'), datacenter=dict(type='str'), cluster=dict(type='str') ) module = AnsibleModule(argument_spec=argument_spec, required_one_of=[ ['cluster', 'datacenter'], ], ) result = dict(changed=False) pyv = PyVmomiHelper(module) if module.params['cluster']: dxs = pyv.lookup_datastore_by_cluster() else: dxs = pyv.lookup_datastore() datastores = list() for ds in dxs: summary = ds.summary dds = dict() dds['accessible'] = summary.accessible dds['capacity'] = summary.capacity dds['name'] = summary.name dds['freeSpace'] = summary.freeSpace dds['maintenanceMode'] = summary.maintenanceMode dds['multipleHostAccess'] = summary.multipleHostAccess dds['type'] = summary.type # vcsim does not return uncommitted if not summary.uncommitted: summary.uncommitted = 0 dds['uncommitted'] = summary.uncommitted dds['url'] = summary.url # Calculated values dds['provisioned'] = summary.capacity - summary.freeSpace + summary.uncommitted dds['datastore_cluster'] = 'N/A' if isinstance(ds.parent, vim.StoragePod): dds['datastore_cluster'] = ds.parent.name if module.params['name']: if dds['name'] == module.params['name']: datastores.extend([dds]) else: datastores.extend([dds]) result['datastores'] = datastores # found a datastore if datastores: module.exit_json(**result) else: msg = "Unable to gather datastore facts" if module.params['name']: msg += " for %(name)s" % module.params msg += " in datacenter %(datacenter)s" % module.params module.fail_json(msg=msg) if __name__ == '__main__': main()