#!/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 an inventory per each and automatically group hosts based on file name or specify a group in the ini. You can also use _HOST|USER|PASSWORD environment variables to override 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 ''' if config.has_option('cache', 'dir'): dpath = os.path.expanduser(config.get('cache', 'dir')) try: if not os.path.exists(dpath): os.makedirs(dpath) if os.path.isdir(dpath): 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 ''' inv = {} if config.has_option('cache', 'dir'): dpath = os.path.expanduser(config.get('cache', 'dir')) 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('cache', 'dir'): dpath = os.path.expanduser(config.get('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('cache', 'max_age'): maxage = config.get('cache', 'max_age') fileage = int( time.time() - existing.st_mtime ) if (maxage > fileage): return True return False def get_host_info(host): ''' Get variables about a specific host ''' hostinfo = { 'vmware_name' : host.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 ''' inv = {} if cache_available('inventory', config): inv = get_cache('inventory',config) elif client: 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) 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) inv['_meta']['hostvars'][vm.name] = get_host_info(vm) 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) elif client: 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(vm) 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() me = os.path.abspath(sys.argv[0]).rstrip('.py') for configfilename in [me + '.ini', 'vmware.ini']: if os.path.exists(configfilename): config.read(configfilename) break mename = os.path.basename(me).upper() host = os.getenv('VMWARE_' + mename + '_HOST',os.getenv('VMWARE_HOST', config.get('auth','host'))) user = os.getenv('VMWARE_' + mename + '_USER', os.getenv('VMWARE_USER', config.get('auth','user'))) password = os.getenv('VMWARE_' + mename + '_PASSWORD',os.getenv('VMWARE_PASSWORD', config.get('auth','password'))) try: client = Client( host,user,password ) except Exception, e: client = None #print >> STDERR "Unable to login (only cache available): %s", str(e) # Actually 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