mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Improvements to OpenStack inventory script
This commit is contained in:
parent
e6fcd90342
commit
eccb48c8da
2 changed files with 122 additions and 49 deletions
|
@ -14,7 +14,7 @@ api_key =
|
||||||
auth_url =
|
auth_url =
|
||||||
|
|
||||||
# Authentication system
|
# Authentication system
|
||||||
auth_system =
|
auth_system = keystone
|
||||||
|
|
||||||
# OpenStack nova project_id
|
# OpenStack nova project_id
|
||||||
project_id =
|
project_id =
|
||||||
|
@ -22,6 +22,13 @@ project_id =
|
||||||
# Serverarm region name to use
|
# Serverarm region name to use
|
||||||
region_name =
|
region_name =
|
||||||
|
|
||||||
|
# Specify a preference for public or private IPs (public is default)
|
||||||
|
prefer_private = False
|
||||||
|
|
||||||
|
# What service type (required for newer nova client)
|
||||||
|
service_type = compute
|
||||||
|
|
||||||
|
|
||||||
# TODO: Some other options
|
# TODO: Some other options
|
||||||
# insecure =
|
# insecure =
|
||||||
# endpoint_type =
|
# endpoint_type =
|
||||||
|
|
162
plugins/inventory/nova.py
Executable file → Normal file
162
plugins/inventory/nova.py
Executable file → Normal file
|
@ -25,11 +25,9 @@ from novaclient import client as nova_client
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import json
|
import json
|
||||||
except:
|
except ImportError:
|
||||||
import simplejson as json
|
import simplejson as json
|
||||||
|
|
||||||
from ansible.module_utils.openstack import *
|
|
||||||
|
|
||||||
###################################################
|
###################################################
|
||||||
# executed with no parameters, return the list of
|
# executed with no parameters, return the list of
|
||||||
# all groups and hosts
|
# all groups and hosts
|
||||||
|
@ -54,45 +52,129 @@ def nova_load_config_file():
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_fallback(config, value, section="openstack"):
|
||||||
|
"""
|
||||||
|
Get value from config object and return the value
|
||||||
|
or false
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return config.get(section, value)
|
||||||
|
except ConfigParser.NoOptionError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def push(data, key, element):
|
||||||
|
"""
|
||||||
|
Assist in items to a dictionary of lists
|
||||||
|
"""
|
||||||
|
if (not element) or (not key):
|
||||||
|
return
|
||||||
|
|
||||||
|
if key in data:
|
||||||
|
data[key].append(element)
|
||||||
|
else:
|
||||||
|
data[key] = [element]
|
||||||
|
|
||||||
|
|
||||||
|
def to_safe(word):
|
||||||
|
'''
|
||||||
|
Converts 'bad' characters in a string to underscores so they can
|
||||||
|
be used as Ansible groups
|
||||||
|
'''
|
||||||
|
return re.sub(r"[^A-Za-z0-9\-]", "_", word)
|
||||||
|
|
||||||
|
|
||||||
|
def get_ips(server, access_ip=True):
|
||||||
|
"""
|
||||||
|
Returns a list of the server's IPs, or the preferred
|
||||||
|
access IP
|
||||||
|
"""
|
||||||
|
private = []
|
||||||
|
public = []
|
||||||
|
address_list = []
|
||||||
|
# Iterate through each servers network(s), get addresses and get type
|
||||||
|
addresses = getattr(server, 'addresses', {})
|
||||||
|
if len(addresses) > 0:
|
||||||
|
for network in addresses.itervalues():
|
||||||
|
for address in network:
|
||||||
|
if address.get('OS-EXT-IPS:type', False) == 'fixed':
|
||||||
|
private.append(address['addr'])
|
||||||
|
elif address.get('OS-EXT-IPS:type', False) == 'floating':
|
||||||
|
public.append(address['addr'])
|
||||||
|
|
||||||
|
if not access_ip:
|
||||||
|
address_list.append(server.accessIPv4)
|
||||||
|
address_list.extend(private)
|
||||||
|
address_list.extend(public)
|
||||||
|
return address_list
|
||||||
|
|
||||||
|
access_ip = None
|
||||||
|
# Append group to list
|
||||||
|
if server.accessIPv4:
|
||||||
|
access_ip = server.accessIPv4
|
||||||
|
if (not access_ip) and public and not (private and prefer_private):
|
||||||
|
access_ip = public[0]
|
||||||
|
if private and not access_ip:
|
||||||
|
access_ip = private[0]
|
||||||
|
|
||||||
|
return access_ip
|
||||||
|
|
||||||
|
|
||||||
|
def get_metadata(server):
|
||||||
|
"""Returns dictionary of all host metadata"""
|
||||||
|
get_ips(server, False)
|
||||||
|
results = {}
|
||||||
|
for key in vars(server):
|
||||||
|
# Extract value
|
||||||
|
value = getattr(server, key)
|
||||||
|
|
||||||
|
# Generate sanitized key
|
||||||
|
key = 'os_' + re.sub(r"[^A-Za-z0-9\-]", "_", key).lower()
|
||||||
|
|
||||||
|
# Att value to instance result (exclude manager class)
|
||||||
|
#TODO: maybe use value.__class__ or similar inside of key_name
|
||||||
|
if key != 'os_manager':
|
||||||
|
results[key] = value
|
||||||
|
return results
|
||||||
|
|
||||||
config = nova_load_config_file()
|
config = nova_load_config_file()
|
||||||
if not config:
|
if not config:
|
||||||
sys.exit('Unable to find configfile in %s' % ', '.join(NOVA_CONFIG_FILES))
|
sys.exit('Unable to find configfile in %s' % ', '.join(NOVA_CONFIG_FILES))
|
||||||
|
|
||||||
client = nova_client.Client(
|
client = nova_client.Client(
|
||||||
config.get('openstack', 'version'),
|
version = config.get('openstack', 'version'),
|
||||||
config.get('openstack', 'username'),
|
username = config.get('openstack', 'username'),
|
||||||
config.get('openstack', 'api_key'),
|
api_key = config.get('openstack', 'api_key'),
|
||||||
config.get('openstack', 'project_id'),
|
auth_url = config.get('openstack', 'auth_url'),
|
||||||
config.get('openstack', 'auth_url'),
|
|
||||||
region_name = config.get('openstack', 'region_name'),
|
region_name = config.get('openstack', 'region_name'),
|
||||||
|
project_id = config.get('openstack', 'project_id'),
|
||||||
auth_system = config.get('openstack', 'auth_system')
|
auth_system = config.get('openstack', 'auth_system')
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(sys.argv) == 2 and (sys.argv[1] == '--list'):
|
# Default or added list option
|
||||||
groups = {}
|
if (len(sys.argv) == 2 and sys.argv[1] == '--list') or len(sys.argv) == 1:
|
||||||
|
groups = {'_meta': {'hostvars': {}}}
|
||||||
# Cycle on servers
|
# Cycle on servers
|
||||||
for server in client.servers.list():
|
for server in client.servers.list():
|
||||||
private = openstack_find_nova_addresses(getattr(server, 'addresses'), 'fixed', 'private')
|
access_ip = get_ips(server)
|
||||||
public = openstack_find_nova_addresses(getattr(server, 'addresses'), 'floating', 'public')
|
|
||||||
|
|
||||||
# Define group (or set to empty string)
|
|
||||||
group = server.metadata['group'] if server.metadata.has_key('group') else 'undefined'
|
|
||||||
|
|
||||||
# Create group if not exist
|
# Push to name group of 1
|
||||||
if group not in groups:
|
push(groups, server.name, access_ip)
|
||||||
groups[group] = []
|
|
||||||
|
|
||||||
# Append group to list
|
# Run through each metadata item and add instance to it
|
||||||
if server.accessIPv4:
|
for key, value in server.metadata.iteritems():
|
||||||
groups[group].append(server.accessIPv4)
|
composed_key = to_safe('tag_{0}_{1}'.format(key, value))
|
||||||
continue
|
push(groups, composed_key, access_ip)
|
||||||
if public:
|
|
||||||
groups[group].append(''.join(public))
|
# Do special handling of group for backwards compat
|
||||||
continue
|
# inventory groups
|
||||||
if private:
|
group = server.metadata['group'] if 'group' in server.metadata else 'undefined'
|
||||||
groups[group].append(''.join(private))
|
push(groups, group, access_ip)
|
||||||
continue
|
|
||||||
|
# Add vars to _meta key for performance optimization in
|
||||||
|
# Ansible 1.3+
|
||||||
|
groups['_meta']['hostvars'][access_ip] = get_metadata(server)
|
||||||
|
|
||||||
# Return server list
|
# Return server list
|
||||||
print(json.dumps(groups, sort_keys=True, indent=2))
|
print(json.dumps(groups, sort_keys=True, indent=2))
|
||||||
|
@ -105,25 +187,9 @@ if len(sys.argv) == 2 and (sys.argv[1] == '--list'):
|
||||||
elif len(sys.argv) == 3 and (sys.argv[1] == '--host'):
|
elif len(sys.argv) == 3 and (sys.argv[1] == '--host'):
|
||||||
results = {}
|
results = {}
|
||||||
ips = []
|
ips = []
|
||||||
for instance in client.servers.list():
|
for server in client.servers.list():
|
||||||
private = openstack_find_nova_addresses(getattr(instance, 'addresses'), 'fixed', 'private')
|
if sys.argv[2] in (get_ips(server) or []):
|
||||||
public = openstack_find_nova_addresses(getattr(instance, 'addresses'), 'floating', 'public')
|
results = get_metadata(server)
|
||||||
ips.append( instance.accessIPv4)
|
|
||||||
ips.append(''.join(private))
|
|
||||||
ips.append(''.join(public))
|
|
||||||
if sys.argv[2] in ips:
|
|
||||||
for key in vars(instance):
|
|
||||||
# Extract value
|
|
||||||
value = getattr(instance, key)
|
|
||||||
|
|
||||||
# Generate sanitized key
|
|
||||||
key = 'os_' + re.sub("[^A-Za-z0-9\-]", "_", key).lower()
|
|
||||||
|
|
||||||
# Att value to instance result (exclude manager class)
|
|
||||||
#TODO: maybe use value.__class__ or similar inside of key_name
|
|
||||||
if key != 'os_manager':
|
|
||||||
results[key] = value
|
|
||||||
|
|
||||||
print(json.dumps(results, sort_keys=True, indent=2))
|
print(json.dumps(results, sort_keys=True, indent=2))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue