From f3c22565547a0b24ffdb564ded022f07090c6b19 Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Tue, 24 Dec 2013 14:29:30 -0500 Subject: [PATCH] vsphere/vmware inventory plugin Signed-off-by: Brian Coca --- plugins/inventory/vmware.ini | 15 +++ plugins/inventory/vmware.py | 205 +++++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+) create mode 100644 plugins/inventory/vmware.ini create mode 100755 plugins/inventory/vmware.py diff --git a/plugins/inventory/vmware.ini b/plugins/inventory/vmware.ini new file mode 100644 index 0000000000..13b8384bf6 --- /dev/null +++ b/plugins/inventory/vmware.ini @@ -0,0 +1,15 @@ +# Ansible vmware external inventory script settings +# +[defaults] +guests_only = True +#vm_group = +#hw_group = + +[cache] +cache_max_age = 3600 +cache_dir = /var/tmp + +[auth] +host = vcenter.example.com +user = ihasaccess +password = ssshverysecret diff --git a/plugins/inventory/vmware.py b/plugins/inventory/vmware.py new file mode 100755 index 0000000000..6ed7386589 --- /dev/null +++ b/plugins/inventory/vmware.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +''' +VMWARE external inventory script +================================= + +shamelessly copied from existing inventory scripts. + +This script and it's ini can be used more than once, + +i.e vmware.py/vmware_colo.ini vmware_idf.py/vmware_idf.ini +(script can be link) + +so if you don't have clustered vcenter but multiple esx machines or +just diff clusters you can have a inventory per each and automatically +group hosts based on file name or specify a group in the ini. +''' + +import os +import sys +import time +import ConfigParser +from psphere.client import Client +from psphere.managedobjects import HostSystem + +try: + import json +except ImportError: + import simplejson as json + + +def save_cache(cache_item, data, config): + ''' saves item to cache ''' + dpath = config.get('defaults', 'cache_dir') + try: + cache = open('/'.join([dpath,cache_item]), 'w') + cache.write(json.dumps(data)) + cache.close() + except IOError, e: + pass # not really sure what to do here + + +def get_cache(cache_item, config): + ''' returns cached item ''' + dpath = config.get('defaults', 'cache_dir') + inv = {} + try: + cache = open('/'.join([dpath,cache_item]), 'r') + inv = json.loads(cache.read()) + cache.close() + except IOError, e: + pass # not really sure what to do here + + return inv + +def cache_available(cache_item, config): + ''' checks if we have a 'fresh' cache available for item requested ''' + + if config.has_option('defaults', 'cache_dir'): + dpath = config.get('defaults', 'cache_dir') + + try: + existing = os.stat( '/'.join([dpath,cache_item])) + except: + # cache doesn't exist or isn't accessible + return False + + if config.has_option('defaults', 'cache_max_age'): + maxage = config.get('defaults', 'cache_max_age') + + if (existing.st_mtime - int(time.time())) <= maxage: + return True + + return False + +def get_host_info(host): + ''' Get variables about a specific host ''' + + hostinfo = { + 'vmware_name' : host.name, + 'vmware_tag' : host.tag, + 'vmware_parent': host.parent.name, + } + for k in host.capability.__dict__.keys(): + if k.startswith('_'): + continue + try: + hostinfo['vmware_' + k] = str(host.capability[k]) + except: + continue + + return hostinfo + + +def get_inventory(client, config): + ''' Reads the inventory from cache or vmware api ''' + + if cache_available('inventory', config): + inv = get_cache('inventory',config) + else: + inv= { 'all': {'hosts': []}, '_meta': { 'hostvars': {} } } + default_group = os.path.basename(sys.argv[0]).rstrip('.py') + + if config.has_option('defaults', 'guests_only'): + guests_only = config.get('defaults', 'guests_only') + else: + guests_only = True + + if not guests_only: + if config.has_option('defaults','hw_group'): + hw_group = config.get('defaults','hw_group') + else: + hw_group = default_group + '_hw' + inv[hw_group] = [] + + if config.has_option('defaults','vm_group'): + vm_group = config.get('defaults','vm_group') + else: + vm_group = default_group + '_vm' + inv[vm_group] = [] + + # Loop through physical hosts: + hosts = HostSystem.all(client) + for host in hosts: + if not guests_only: + inv['all']['hosts'].append(host.name) + inv[hw_group].append(host.name) + if host.tag: + taggroup = 'vmware_' + host.tag + if taggroup in inv: + inv[taggroup].append(host.name) + else: + inv[taggroup] = [ host.name ] + + inv['_meta']['hostvars'][host.name] = get_host_info(host) + save_cache(vm.name, inv['_meta']['hostvars'][host.name], config) + + for vm in host.vm: + inv['all']['hosts'].append(vm.name) + inv[vm_group].append(vm.name) + if vm.tag: + taggroup = 'vmware_' + vm.tag + if taggroup in inv: + inv[taggroup].append(vm.name) + else: + inv[taggroup] = [ vm.name ] + + inv['_meta']['hostvars'][vm.name] = get_host_info(host) + save_cache(vm.name, inv['_meta']['hostvars'][vm.name], config) + + save_cache('inventory', inv, config) + return json.dumps(inv) + +def get_single_host(client, config, hostname): + + inv = {} + + if cache_available(hostname, config): + inv = get_cache(hostname,config) + else: + hosts = HostSystem.all(client) #TODO: figure out single host getter + for host in hosts: + if hostname == host.name: + inv = get_host_info(host) + break + for vm in host.vm: + if hostname == vm.name: + inv = get_host_info(host) + break + save_cache(hostname,inv,config) + + return json.dumps(inv) + +if __name__ == '__main__': + inventory = {} + hostname = None + + if len(sys.argv) > 1: + if sys.argv[1] == "--host": + hostname = sys.argv[2] + + # Read config + config = ConfigParser.SafeConfigParser() + for configfilename in [os.path.abspath(sys.argv[0]).rstrip('.py') + '.ini', 'vmware.ini']: + if os.path.exists(configfilename): + config.read(configfilename) + break + + try: + client = Client( config.get('auth','host'), + config.get('auth','user'), + config.get('auth','password'), + ) + except Exception, e: + client = None + #print >> STDERR "Unable to login (only cache avilable): %s", str(e) + + # acitually do the work + if hostname is None: + inventory = get_inventory(client, config) + else: + inventory = get_single_host(client, config, hostname) + + # return to ansible + print inventory