VMware inventory script updates from Tower.
This commit is contained in:
parent
c31831f028
commit
48a0b6fb12
2 changed files with 409 additions and 166 deletions
|
@ -1,15 +1,39 @@
|
||||||
# Ansible vmware external inventory script settings
|
# Ansible VMware external inventory script settings
|
||||||
#
|
|
||||||
[defaults]
|
|
||||||
guests_only = True
|
|
||||||
#vm_group =
|
|
||||||
#hw_group =
|
|
||||||
|
|
||||||
[cache]
|
[defaults]
|
||||||
max_age = 3600
|
|
||||||
dir = ~/.cache/ansible
|
# If true (the default), return only guest VMs. If false, also return host
|
||||||
|
# systems in the results.
|
||||||
|
guests_only = True
|
||||||
|
|
||||||
|
# Specify an alternate group name for guest VMs. If not defined, defaults to
|
||||||
|
# the basename of the inventory script + "_vm", e.g. "vmware_vm".
|
||||||
|
#vm_group = vm_group_name
|
||||||
|
|
||||||
|
# Specify an alternate group name for host systems when guests_only=false.
|
||||||
|
# If not defined, defaults to the basename of the inventory script + "_hw",
|
||||||
|
# e.g. "vmware_hw".
|
||||||
|
#hw_group = hw_group_name
|
||||||
|
|
||||||
|
# Specify the number of seconds to use the inventory cache before it is
|
||||||
|
# considered stale. If not defined, defaults to 0 seconds.
|
||||||
|
#cache_max_age = 3600
|
||||||
|
|
||||||
|
# Specify the directory used for storing the inventory cache. If not defined,
|
||||||
|
# caching will be disabled.
|
||||||
|
#cache_dir = ~/.cache/ansible
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
|
|
||||||
|
# Specify hostname or IP address of vCenter/ESXi server. A port may be
|
||||||
|
# included with the hostname, e.g.: vcenter.example.com:8443. This setting
|
||||||
|
# may also be defined via the VMWARE_HOST environment variable.
|
||||||
host = vcenter.example.com
|
host = vcenter.example.com
|
||||||
|
|
||||||
|
# Specify a username to access the vCenter host. This setting may also be
|
||||||
|
# defined with the VMWARE_USER environment variable.
|
||||||
user = ihasaccess
|
user = ihasaccess
|
||||||
|
|
||||||
|
# Specify a password to access the vCenter host. This setting may also be
|
||||||
|
# defined with the VMWARE_PASSWORD environment variable.
|
||||||
password = ssshverysecret
|
password = ssshverysecret
|
||||||
|
|
|
@ -1,205 +1,424 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
'''
|
'''
|
||||||
VMWARE external inventory script
|
VMware Inventory Script
|
||||||
=================================
|
=======================
|
||||||
|
|
||||||
shamelessly copied from existing inventory scripts.
|
Retrieve information about virtual machines from a vCenter server or
|
||||||
|
standalone ESX host. When `group_by=false` (in the INI file), host systems
|
||||||
|
are also returned in addition to VMs.
|
||||||
|
|
||||||
This script and it's ini can be used more than once,
|
This script will attempt to read configuration from an INI file with the same
|
||||||
|
base filename if present, or `vmware.ini` if not. It is possible to create
|
||||||
|
symlinks to the inventory script to support multiple configurations, e.g.:
|
||||||
|
|
||||||
i.e. vmware.py/vmware_colo.ini vmware_idf.py/vmware_idf.ini
|
* `vmware.py` (this script)
|
||||||
(script can be link)
|
* `vmware.ini` (default configuration, will be read by `vmware.py`)
|
||||||
|
* `vmware_test.py` (symlink to `vmware.py`)
|
||||||
|
* `vmware_test.ini` (test configuration, will be read by `vmware_test.py`)
|
||||||
|
* `vmware_other.py` (symlink to `vmware.py`, will read `vmware.ini` since no
|
||||||
|
`vmware_other.ini` exists)
|
||||||
|
|
||||||
so if you don't have clustered vcenter but multiple esx machines or
|
The path to an INI file may also be specified via the `VMWARE_INI` environment
|
||||||
just diff clusters you can have an inventory per each and automatically
|
variable, in which case the filename matching rules above will not apply.
|
||||||
group hosts based on file name or specify a group in the ini.
|
|
||||||
|
|
||||||
You can also use <SCRIPT_NAME>_HOST|USER|PASSWORD environment variables
|
Host and authentication parameters may be specified via the `VMWARE_HOST`,
|
||||||
to override the ini.
|
`VMWARE_USER` and `VMWARE_PASSWORD` environment variables; these options will
|
||||||
|
take precedence over options present in the INI file. An INI file is not
|
||||||
|
required if these options are specified using environment variables.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
import collections
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import optparse
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import ConfigParser
|
import ConfigParser
|
||||||
from psphere.client import Client
|
|
||||||
from psphere.managedobjects import HostSystem
|
|
||||||
|
|
||||||
|
# Disable logging message trigged by pSphere/suds.
|
||||||
try:
|
try:
|
||||||
import json
|
from logging import NullHandler
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import simplejson as json
|
from logging import Handler
|
||||||
|
class NullHandler(Handler):
|
||||||
|
def emit(self, record):
|
||||||
|
pass
|
||||||
|
logging.getLogger('psphere').addHandler(NullHandler())
|
||||||
|
logging.getLogger('suds').addHandler(NullHandler())
|
||||||
|
|
||||||
|
from psphere.client import Client
|
||||||
|
from psphere.errors import ObjectNotFoundError
|
||||||
|
from psphere.managedobjects import HostSystem, VirtualMachine, ManagedObject, Network
|
||||||
|
from suds.sudsobject import Object as SudsObject
|
||||||
|
|
||||||
|
|
||||||
def save_cache(cache_item, data, config):
|
class VMwareInventory(object):
|
||||||
''' saves item to cache '''
|
|
||||||
|
|
||||||
if config.has_option('cache', 'dir'):
|
def __init__(self, guests_only=None):
|
||||||
dpath = os.path.expanduser(config.get('cache', 'dir'))
|
self.config = ConfigParser.SafeConfigParser()
|
||||||
try:
|
if os.environ.get('VMWARE_INI', ''):
|
||||||
if not os.path.exists(dpath):
|
config_files = [os.environ['VMWARE_INI']]
|
||||||
os.makedirs(dpath)
|
else:
|
||||||
if os.path.isdir(dpath):
|
config_files = [os.path.abspath(sys.argv[0]).rstrip('.py') + '.ini', 'vmware.ini']
|
||||||
cache = open('/'.join([dpath,cache_item]), 'w')
|
for config_file in config_files:
|
||||||
cache.write(json.dumps(data))
|
if os.path.exists(config_file):
|
||||||
cache.close()
|
self.config.read(config_file)
|
||||||
except IOError, e:
|
break
|
||||||
pass # not really sure what to do here
|
|
||||||
|
|
||||||
|
# Retrieve only guest VMs, or include host systems?
|
||||||
|
if guests_only is not None:
|
||||||
|
self.guests_only = guests_only
|
||||||
|
elif self.config.has_option('defaults', 'guests_only'):
|
||||||
|
self.guests_only = self.config.getboolean('defaults', 'guests_only')
|
||||||
|
else:
|
||||||
|
self.guests_only = True
|
||||||
|
|
||||||
def get_cache(cache_item, config):
|
# Read authentication information from VMware environment variables
|
||||||
''' returns cached item '''
|
# (if set), otherwise from INI file.
|
||||||
|
auth_host = os.environ.get('VMWARE_HOST')
|
||||||
|
if not auth_host and self.config.has_option('auth', 'host'):
|
||||||
|
auth_host = self.config.get('auth', 'host')
|
||||||
|
auth_user = os.environ.get('VMWARE_USER')
|
||||||
|
if not auth_user and self.config.has_option('auth', 'user'):
|
||||||
|
auth_user = self.config.get('auth', 'user')
|
||||||
|
auth_password = os.environ.get('VMWARE_PASSWORD')
|
||||||
|
if not auth_password and self.config.has_option('auth', 'password'):
|
||||||
|
auth_password = self.config.get('auth', 'password')
|
||||||
|
|
||||||
inv = {}
|
# Create the VMware client connection.
|
||||||
if config.has_option('cache', 'dir'):
|
self.client = Client(auth_host, auth_user, auth_password)
|
||||||
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 _put_cache(self, name, value):
|
||||||
|
'''
|
||||||
|
Saves the value to cache with the name given.
|
||||||
|
'''
|
||||||
|
if self.config.has_option('defaults', 'cache_dir'):
|
||||||
|
cache_dir = self.config.get('defaults', 'cache_dir')
|
||||||
|
if not os.path.exists(cache_dir):
|
||||||
|
os.makedirs(cache_dir)
|
||||||
|
cache_file = os.path.join(cache_dir, name)
|
||||||
|
with open(cache_file, 'w') as cache:
|
||||||
|
json.dump(value, cache)
|
||||||
|
|
||||||
def cache_available(cache_item, config):
|
def _get_cache(self, name, default=None):
|
||||||
''' checks if we have a 'fresh' cache available for item requested '''
|
'''
|
||||||
|
Retrieves the value from cache for the given name.
|
||||||
|
'''
|
||||||
|
if self.config.has_option('defaults', 'cache_dir'):
|
||||||
|
cache_dir = self.config.get('defaults', 'cache_dir')
|
||||||
|
cache_file = os.path.join(cache_dir, name)
|
||||||
|
if os.path.exists(cache_file):
|
||||||
|
if self.config.has_option('defaults', 'cache_max_age'):
|
||||||
|
cache_max_age = self.config.getint('defaults', 'cache_max_age')
|
||||||
|
else:
|
||||||
|
cache_max_age = 0
|
||||||
|
cache_stat = os.stat(cache_file)
|
||||||
|
if (cache_stat.st_mtime + cache_max_age) < time.time():
|
||||||
|
with open(cache_file) as cache:
|
||||||
|
return json.load(cache)
|
||||||
|
return default
|
||||||
|
|
||||||
if config.has_option('cache', 'dir'):
|
def _flatten_dict(self, d, parent_key='', sep='_'):
|
||||||
dpath = os.path.expanduser(config.get('cache', 'dir'))
|
'''
|
||||||
|
Flatten nested dicts by combining keys with a separator. Lists with
|
||||||
try:
|
only string items are included as is; any other lists are discarded.
|
||||||
existing = os.stat('/'.join([dpath,cache_item]))
|
'''
|
||||||
except:
|
items = []
|
||||||
# cache doesn't exist or isn't accessible
|
for k, v in d.items():
|
||||||
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('_'):
|
if k.startswith('_'):
|
||||||
continue
|
continue
|
||||||
|
new_key = parent_key + sep + k if parent_key else k
|
||||||
|
if isinstance(v, collections.MutableMapping):
|
||||||
|
items.extend(self._flatten_dict(v, new_key, sep).items())
|
||||||
|
elif isinstance(v, (list, tuple)):
|
||||||
|
if all([isinstance(x, basestring) for x in v]):
|
||||||
|
items.append((new_key, v))
|
||||||
|
else:
|
||||||
|
items.append((new_key, v))
|
||||||
|
return dict(items)
|
||||||
|
|
||||||
|
def _get_obj_info(self, obj, depth=99, seen=None):
|
||||||
|
'''
|
||||||
|
Recursively build a data structure for the given pSphere object (depth
|
||||||
|
only applies to ManagedObject instances).
|
||||||
|
'''
|
||||||
|
seen = seen or set()
|
||||||
|
if isinstance(obj, ManagedObject):
|
||||||
try:
|
try:
|
||||||
hostinfo['vmware_' + k] = str(host.capability[k])
|
obj_unicode = unicode(getattr(obj, 'name'))
|
||||||
except:
|
except AttributeError:
|
||||||
|
obj_unicode = ()
|
||||||
|
if obj in seen:
|
||||||
|
return obj_unicode
|
||||||
|
seen.add(obj)
|
||||||
|
if depth <= 0:
|
||||||
|
return obj_unicode
|
||||||
|
d = {}
|
||||||
|
for attr in dir(obj):
|
||||||
|
if attr.startswith('_'):
|
||||||
continue
|
continue
|
||||||
|
try:
|
||||||
|
val = getattr(obj, attr)
|
||||||
|
obj_info = self._get_obj_info(val, depth - 1, seen)
|
||||||
|
if obj_info != ():
|
||||||
|
d[attr] = obj_info
|
||||||
|
except Exception, e:
|
||||||
|
pass
|
||||||
|
return d
|
||||||
|
elif isinstance(obj, SudsObject):
|
||||||
|
d = {}
|
||||||
|
for key, val in iter(obj):
|
||||||
|
obj_info = self._get_obj_info(val, depth, seen)
|
||||||
|
if obj_info != ():
|
||||||
|
d[key] = obj_info
|
||||||
|
return d
|
||||||
|
elif isinstance(obj, (list, tuple)):
|
||||||
|
l = []
|
||||||
|
for val in iter(obj):
|
||||||
|
obj_info = self._get_obj_info(val, depth, seen)
|
||||||
|
if obj_info != ():
|
||||||
|
l.append(obj_info)
|
||||||
|
return l
|
||||||
|
elif isinstance(obj, (type(None), bool, int, long, float, basestring)):
|
||||||
|
return obj
|
||||||
|
else:
|
||||||
|
return ()
|
||||||
|
|
||||||
return hostinfo
|
def _get_host_info(self, host, prefix='vmware'):
|
||||||
|
'''
|
||||||
|
Return a flattened dict with info about the given host system.
|
||||||
|
'''
|
||||||
|
host_info = {
|
||||||
|
'name': host.name,
|
||||||
|
}
|
||||||
|
for attr in ('datastore', 'network', 'vm'):
|
||||||
|
try:
|
||||||
|
value = getattr(host, attr)
|
||||||
|
host_info['%ss' % attr] = self._get_obj_info(value, depth=0)
|
||||||
|
except AttributeError:
|
||||||
|
host_info['%ss' % attr] = []
|
||||||
|
for k, v in self._get_obj_info(host.summary, depth=0).items():
|
||||||
|
if isinstance(v, collections.MutableMapping):
|
||||||
|
for k2, v2 in v.items():
|
||||||
|
host_info[k2] = v2
|
||||||
|
elif k != 'host':
|
||||||
|
host_info[k] = v
|
||||||
|
try:
|
||||||
|
host_info['ipAddress'] = host.config.network.vnic[0].spec.ip.ipAddress
|
||||||
|
except Exception, e:
|
||||||
|
print >> sys.stderr, e
|
||||||
|
host_info = self._flatten_dict(host_info, prefix)
|
||||||
|
if ('%s_ipAddress' % prefix) in host_info:
|
||||||
|
host_info['ansible_ssh_host'] = host_info['%s_ipAddress' % prefix]
|
||||||
|
return host_info
|
||||||
|
|
||||||
|
def _get_vm_info(self, vm, prefix='vmware'):
|
||||||
|
'''
|
||||||
|
Return a flattened dict with info about the given virtual machine.
|
||||||
|
'''
|
||||||
|
vm_info = {
|
||||||
|
'name': vm.name,
|
||||||
|
}
|
||||||
|
for attr in ('datastore', 'network'):
|
||||||
|
try:
|
||||||
|
value = getattr(vm, attr)
|
||||||
|
vm_info['%ss' % attr] = self._get_obj_info(value, depth=0)
|
||||||
|
except AttributeError:
|
||||||
|
vm_info['%ss' % attr] = []
|
||||||
|
try:
|
||||||
|
vm_info['resourcePool'] = self._get_obj_info(vm.resourcePool, depth=0)
|
||||||
|
except AttributeError:
|
||||||
|
vm_info['resourcePool'] = ''
|
||||||
|
try:
|
||||||
|
vm_info['guestState'] = vm.guest.guestState
|
||||||
|
except AttributeError:
|
||||||
|
vm_info['guestState'] = ''
|
||||||
|
for k, v in self._get_obj_info(vm.summary, depth=0).items():
|
||||||
|
if isinstance(v, collections.MutableMapping):
|
||||||
|
for k2, v2 in v.items():
|
||||||
|
if k2 == 'host':
|
||||||
|
k2 = 'hostSystem'
|
||||||
|
vm_info[k2] = v2
|
||||||
|
elif k != 'vm':
|
||||||
|
vm_info[k] = v
|
||||||
|
vm_info = self._flatten_dict(vm_info, prefix)
|
||||||
|
if ('%s_ipAddress' % prefix) in vm_info:
|
||||||
|
vm_info['ansible_ssh_host'] = vm_info['%s_ipAddress' % prefix]
|
||||||
|
return vm_info
|
||||||
|
|
||||||
def get_inventory(client, config):
|
def _add_host(self, inv, parent_group, host_name):
|
||||||
''' Reads the inventory from cache or vmware api '''
|
'''
|
||||||
|
Add the host to the parent group in the given inventory.
|
||||||
|
'''
|
||||||
|
p_group = inv.setdefault(parent_group, [])
|
||||||
|
if isinstance(p_group, dict):
|
||||||
|
group_hosts = p_group.setdefault('hosts', [])
|
||||||
|
else:
|
||||||
|
group_hosts = p_group
|
||||||
|
if host_name not in group_hosts:
|
||||||
|
group_hosts.append(host_name)
|
||||||
|
|
||||||
inv = {}
|
def _add_child(self, inv, parent_group, child_group):
|
||||||
|
'''
|
||||||
|
Add a child group to a parent group in the given inventory.
|
||||||
|
'''
|
||||||
|
if parent_group != 'all':
|
||||||
|
p_group = inv.setdefault(parent_group, {})
|
||||||
|
if not isinstance(p_group, dict):
|
||||||
|
inv[parent_group] = {'hosts': p_group}
|
||||||
|
p_group = inv[parent_group]
|
||||||
|
group_children = p_group.setdefault('children', [])
|
||||||
|
if child_group not in group_children:
|
||||||
|
group_children.append(child_group)
|
||||||
|
inv.setdefault(child_group, [])
|
||||||
|
|
||||||
|
def get_inventory(self, meta_hostvars=True):
|
||||||
|
'''
|
||||||
|
Reads the inventory from cache or VMware API via pSphere.
|
||||||
|
'''
|
||||||
|
# Use different cache names for guests only vs. all hosts.
|
||||||
|
if self.guests_only:
|
||||||
|
cache_name = '__inventory_guests__'
|
||||||
|
else:
|
||||||
|
cache_name = '__inventory_all__'
|
||||||
|
|
||||||
|
inv = self._get_cache(cache_name, None)
|
||||||
|
if inv is not None:
|
||||||
|
return inv
|
||||||
|
|
||||||
|
inv = {'all': {'hosts': []}}
|
||||||
|
if meta_hostvars:
|
||||||
|
inv['_meta'] = {'hostvars': {}}
|
||||||
|
|
||||||
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')
|
default_group = os.path.basename(sys.argv[0]).rstrip('.py')
|
||||||
|
|
||||||
if config.has_option('defaults', 'guests_only'):
|
if not self.guests_only:
|
||||||
guests_only = config.get('defaults', 'guests_only')
|
if self.config.has_option('defaults', 'hw_group'):
|
||||||
else:
|
hw_group = self.config.get('defaults', 'hw_group')
|
||||||
guests_only = True
|
|
||||||
|
|
||||||
if not guests_only:
|
|
||||||
if config.has_option('defaults','hw_group'):
|
|
||||||
hw_group = config.get('defaults','hw_group')
|
|
||||||
else:
|
else:
|
||||||
hw_group = default_group + '_hw'
|
hw_group = default_group + '_hw'
|
||||||
inv[hw_group] = []
|
|
||||||
|
|
||||||
if config.has_option('defaults','vm_group'):
|
if self.config.has_option('defaults', 'vm_group'):
|
||||||
vm_group = config.get('defaults','vm_group')
|
vm_group = self.config.get('defaults', 'vm_group')
|
||||||
else:
|
else:
|
||||||
vm_group = default_group + '_vm'
|
vm_group = default_group + '_vm'
|
||||||
inv[vm_group] = []
|
|
||||||
|
|
||||||
# Loop through physical hosts:
|
# Loop through physical hosts:
|
||||||
hosts = HostSystem.all(client)
|
for host in HostSystem.all(self.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)
|
|
||||||
|
|
||||||
|
if not self.guests_only:
|
||||||
|
self._add_host(inv, 'all', host.name)
|
||||||
|
self._add_host(inv, hw_group, host.name)
|
||||||
|
host_info = self._get_host_info(host)
|
||||||
|
if meta_hostvars:
|
||||||
|
inv['_meta']['hostvars'][host.name] = host_info
|
||||||
|
self._put_cache(host.name, host_info)
|
||||||
|
|
||||||
|
# Loop through all VMs on physical host.
|
||||||
for vm in host.vm:
|
for vm in host.vm:
|
||||||
inv['all']['hosts'].append(vm.name)
|
self._add_host(inv, 'all', vm.name)
|
||||||
inv[vm_group].append(vm.name)
|
self._add_host(inv, vm_group, vm.name)
|
||||||
inv['_meta']['hostvars'][vm.name] = get_host_info(vm)
|
vm_info = self._get_vm_info(vm)
|
||||||
save_cache(vm.name, inv['_meta']['hostvars'][vm.name], config)
|
if meta_hostvars:
|
||||||
|
inv['_meta']['hostvars'][vm.name] = vm_info
|
||||||
|
self._put_cache(vm.name, vm_info)
|
||||||
|
|
||||||
save_cache('inventory', inv, config)
|
# Group by resource pool.
|
||||||
|
vm_resourcePool = vm_info.get('vmware_resourcePool', None)
|
||||||
|
if vm_resourcePool:
|
||||||
|
self._add_child(inv, vm_group, 'resource_pools')
|
||||||
|
self._add_child(inv, 'resource_pools', vm_resourcePool)
|
||||||
|
self._add_host(inv, vm_resourcePool, vm.name)
|
||||||
|
|
||||||
return json.dumps(inv)
|
# Group by datastore.
|
||||||
|
for vm_datastore in vm_info.get('vmware_datastores', []):
|
||||||
|
self._add_child(inv, vm_group, 'datastores')
|
||||||
|
self._add_child(inv, 'datastores', vm_datastore)
|
||||||
|
self._add_host(inv, vm_datastore, vm.name)
|
||||||
|
|
||||||
def get_single_host(client, config, hostname):
|
# Group by network.
|
||||||
|
for vm_network in vm_info.get('vmware_networks', []):
|
||||||
|
self._add_child(inv, vm_group, 'networks')
|
||||||
|
self._add_child(inv, 'networks', vm_network)
|
||||||
|
self._add_host(inv, vm_network, vm.name)
|
||||||
|
|
||||||
inv = {}
|
# Group by guest OS.
|
||||||
if cache_available(hostname, config):
|
vm_guestId = vm_info.get('vmware_guestId', None)
|
||||||
inv = get_cache(hostname,config)
|
if vm_guestId:
|
||||||
elif client:
|
self._add_child(inv, vm_group, 'guests')
|
||||||
hosts = HostSystem.all(client) #TODO: figure out single host getter
|
self._add_child(inv, 'guests', vm_guestId)
|
||||||
for host in hosts:
|
self._add_host(inv, vm_guestId, vm.name)
|
||||||
if hostname == host.name:
|
|
||||||
inv = get_host_info(host)
|
# Group all VM templates.
|
||||||
break
|
vm_template = vm_info.get('vmware_template', False)
|
||||||
for vm in host.vm:
|
if vm_template:
|
||||||
if hostname == vm.name:
|
self._add_child(inv, vm_group, 'templates')
|
||||||
inv = get_host_info(vm)
|
self._add_host(inv, 'templates', vm.name)
|
||||||
break
|
|
||||||
save_cache(hostname,inv,config)
|
self._put_cache(cache_name, inv)
|
||||||
|
return inv
|
||||||
|
|
||||||
|
def get_host(self, hostname):
|
||||||
|
'''
|
||||||
|
Read info about a specific host or VM from cache or VMware API.
|
||||||
|
'''
|
||||||
|
inv = self._get_cache(hostname, None)
|
||||||
|
if inv is not None:
|
||||||
|
return inv
|
||||||
|
|
||||||
|
if not self.guests_only:
|
||||||
|
try:
|
||||||
|
host = HostSystem.get(self.client, name=hostname)
|
||||||
|
inv = self._get_host_info(host)
|
||||||
|
except ObjectNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if inv is None:
|
||||||
|
try:
|
||||||
|
vm = VirtualMachine.get(self.client, name=hostname)
|
||||||
|
inv = self._get_vm_info(vm)
|
||||||
|
except ObjectNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if inv is not None:
|
||||||
|
self._put_cache(hostname, inv)
|
||||||
|
return inv or {}
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = optparse.OptionParser()
|
||||||
|
parser.add_option('--list', action='store_true', dest='list',
|
||||||
|
default=False, help='Output inventory groups and hosts')
|
||||||
|
parser.add_option('--host', dest='host', default=None, metavar='HOST',
|
||||||
|
help='Output variables only for the given hostname')
|
||||||
|
# Additional options for use when running the script standalone, but never
|
||||||
|
# used by Ansible.
|
||||||
|
parser.add_option('--pretty', action='store_true', dest='pretty',
|
||||||
|
default=False, help='Output nicely-formatted JSON')
|
||||||
|
parser.add_option('--include-host-systems', action='store_true',
|
||||||
|
dest='include_host_systems', default=False,
|
||||||
|
help='Include host systems in addition to VMs')
|
||||||
|
parser.add_option('--no-meta-hostvars', action='store_false',
|
||||||
|
dest='meta_hostvars', default=True,
|
||||||
|
help='Exclude [\'_meta\'][\'hostvars\'] with --list')
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
|
if options.include_host_systems:
|
||||||
|
vmware_inventory = VMwareInventory(guests_only=False)
|
||||||
|
else:
|
||||||
|
vmware_inventory = VMwareInventory()
|
||||||
|
if options.host is not None:
|
||||||
|
inventory = vmware_inventory.get_host(options.host)
|
||||||
|
else:
|
||||||
|
inventory = vmware_inventory.get_inventory(options.meta_hostvars)
|
||||||
|
|
||||||
|
json_kwargs = {}
|
||||||
|
if options.pretty:
|
||||||
|
json_kwargs.update({'indent': 4, 'sort_keys': True})
|
||||||
|
json.dump(inventory, sys.stdout, **json_kwargs)
|
||||||
|
|
||||||
return json.dumps(inv)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
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
|
|
||||||
|
|
Loading…
Reference in a new issue