vmware.py 6.11 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
#!/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,

11
i.e. vmware.py/vmware_colo.ini vmware_idf.py/vmware_idf.ini
12 13 14
(script can be link)

so if you don't have clustered vcenter  but multiple esx machines or
15
just diff clusters you can have an inventory  per each and automatically
16
group hosts based on file name or specify a group in the ini.
17 18 19

You can also use <SCRIPT_NAME>_HOST|USER|PASSWORD environment variables
to override the ini.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
'''

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 '''
37 38 39 40 41 42 43 44 45 46 47 48

    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
49 50 51 52


def get_cache(cache_item, config):
    ''' returns cached item  '''
53

54
    inv = {}
55 56 57 58 59 60 61 62
    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
63 64 65 66 67 68

    return inv

def cache_available(cache_item, config):
    ''' checks if we have a 'fresh' cache available for item requested '''

69 70
    if config.has_option('cache', 'dir'):
        dpath = os.path.expanduser(config.get('cache', 'dir'))
71 72

        try:
73
            existing = os.stat('/'.join([dpath,cache_item]))
74 75 76 77
        except:
            # cache doesn't exist or isn't accessible
            return False

78 79
        if config.has_option('cache', 'max_age'):
            maxage = config.get('cache', 'max_age')
80 81
            fileage = int( time.time() - existing.st_mtime )
            if (maxage > fileage):
82 83 84 85 86 87 88 89
                return True

    return False

def get_host_info(host):
    ''' Get variables about a specific host '''

    hostinfo = {
90 91
        'vmware_name' : host.name,
    }
92 93 94 95 96 97 98 99 100 101 102 103 104 105
    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 '''

106 107
    inv = {}

108 109
    if cache_available('inventory', config):
        inv = get_cache('inventory',config)
110
    elif client:
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
        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)
144
                inv['_meta']['hostvars'][vm.name] = get_host_info(vm)
145 146
                save_cache(vm.name, inv['_meta']['hostvars'][vm.name], config)

147 148
        save_cache('inventory', inv, config)

149 150 151 152 153 154 155
    return json.dumps(inv)

def get_single_host(client, config, hostname):

    inv = {}
    if cache_available(hostname, config):
        inv = get_cache(hostname,config)
156
    elif client:
157 158 159 160 161 162 163
        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:
164
                    inv = get_host_info(vm)
165 166 167 168 169 170
                    break
        save_cache(hostname,inv,config)

    return json.dumps(inv)

if __name__ == '__main__':
171

172 173 174 175 176 177 178 179 180
    inventory = {}
    hostname = None

    if len(sys.argv) > 1:
        if sys.argv[1] == "--host":
            hostname = sys.argv[2]

    # Read config
    config = ConfigParser.SafeConfigParser()
181 182
    me = os.path.abspath(sys.argv[0]).rstrip('.py')
    for configfilename in [me + '.ini', 'vmware.ini']:
183 184 185 186
        if os.path.exists(configfilename):
            config.read(configfilename)
            break

187 188 189 190 191
    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')))

192
    try:
193
        client =  Client( host,user,password )
194 195
    except Exception, e:
        client = None
196
        #print >> STDERR "Unable to login (only cache available): %s", str(e)
197

198
    # Actually do the work
199 200 201 202 203
    if hostname is None:
        inventory = get_inventory(client, config)
    else:
        inventory = get_single_host(client, config, hostname)

204
    # Return to ansible
205
    print inventory