-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathopenstack_inventory.py
executable file
·130 lines (111 loc) · 4.61 KB
/
openstack_inventory.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/env python
################################################################################
# Dynamic inventory generation for Ansible
# In orignal version found here: https://github.com/lukaspustina/dynamic-inventory-for-ansible-with-openstack
# Author lukas.pustina@codecentric.de
# With additions from Johan Dahlberg - johan.dahlberg@medsci.uu.se
#
# This Python script generates a dynamic inventory based on OpenStack instances.
#
# The script is passed via -i <script name> to ansible-playbook. Ansible
# recognizes the execute bit of the file and executes the script. It then
# queries nova via the novaclient module and credentials passed via environment
# variables -- see below.
#
# The script iterates over all instances of the given tenant and checks if the
# instances' metadata have set keys OS_METADATA_KEY -- see below. These keys shall
# contain all Ansible host groups comma separated an instance shall be part of,
# e.g., u'ansible_host_groups': u'admin_v_infrastructure,apt_repos'.
# It is also possible to set Ansible host variables, e.g.,
# u'ansible_host_vars': u'dns_server_for_domains->domain1,domain2;key2->value2'
# Values with a comma will be transformed into a list.
#
# Metadata of an instance may be set during boot, e.g.,
# > nova boot --meta <key=value>
# , or to a running instance, e.g.,
# nova meta <instance name> set <key=value>
#
# *** Requirements ***
# * Python: novaclient module be installed which is part of the nova ubuntu
# package.
# * The environment variables OS_USERNAME, OS_PASSWORD, OS_TENANT_NAME,
# OS_AUTH_URL and OS_NETWORK_NAME must be set according to nova.
#
################################################################################
from __future__ import print_function
from novaclient.v2 import client
import os, sys, json
OS_METADATA_KEY = {
'host_groups': 'ansible_host_groups',
'host_vars': 'ansible_host_vars'
}
try:
OS_NETWORK_NAME = os.environ['OS_NETWORK_NAME']
except KeyError as e:
print("ERROR: environment variable %s is not defined" % e, file=sys.stderr)
sys.exit(-1)
def main(args):
credentials = getOsCredentialsFromEnvironment()
nt = client.Client(credentials['USERNAME'], credentials['PASSWORD'], credentials['TENANT_NAME'], credentials['AUTH_URL'], service_type="compute")
inventory = {}
inventory['_meta'] = { 'hostvars': {} }
for server in nt.servers.list():
floatingIp = getFloatingIpFromServerForNetwork(server, OS_NETWORK_NAME)
if floatingIp:
for group in getAnsibleHostGroupsFromServer(nt, server.id):
addServerToHostGroup(group, floatingIp, inventory)
host_vars = getAnsibleHostVarsFromServer(nt, server.id)
if host_vars:
addServerHostVarsToHostVars(host_vars, floatingIp, inventory)
dumpInventoryAsJson(inventory)
def getOsCredentialsFromEnvironment():
credentials = {}
try:
credentials['USERNAME'] = os.environ['OS_USERNAME']
credentials['PASSWORD'] = os.environ['OS_PASSWORD']
credentials['TENANT_NAME'] = os.environ['OS_TENANT_NAME']
credentials['AUTH_URL'] = os.environ['OS_AUTH_URL']
except KeyError as e:
print("ERROR: environment variable %s is not defined" % e, file=sys.stderr)
sys.exit(-1)
return credentials
def getAnsibleHostGroupsFromServer(novaClient, serverId):
metadata = getMetaDataFromServer(novaClient, serverId, OS_METADATA_KEY['host_groups'])
if metadata:
return metadata.split(',')
else:
return []
def getMetaDataFromServer(novaClient, serverId, key):
return novaClient.servers.get(serverId).metadata.get(key, None)
def getAnsibleHostVarsFromServer(novaClient, serverId):
metadata = getMetaDataFromServer(novaClient, serverId, OS_METADATA_KEY['host_vars'])
if metadata:
host_vars = {}
for kv in metadata.split(';'):
key, values = kv.split('->')
values = values.split(',')
host_vars[key] = values
return host_vars
else:
return None
def getFloatingIpFromServerForNetwork(server, network):
for addr in server.addresses.get(network):
if addr.get('OS-EXT-IPS:type') == 'floating':
return addr['addr']
if addr.get('OS-EXT-IPS:type') == 'fixed':
return addr['addr']
return None
def addServerToHostGroup(group, floatingIp, inventory):
host_group = inventory.get(group, {})
hosts = host_group.get('hosts', [])
hosts.append(floatingIp)
host_group['hosts'] = hosts
inventory[group] = host_group
def addServerHostVarsToHostVars(host_vars, floatingIp, inventory):
inventory_host_vars = inventory['_meta']['hostvars'].get(floatingIp, {})
inventory_host_vars.update(host_vars)
inventory['_meta']['hostvars'][floatingIp] = inventory_host_vars
def dumpInventoryAsJson(inventory):
print(json.dumps(inventory, indent=4))
if __name__ == "__main__":
main(sys.argv)