-
Notifications
You must be signed in to change notification settings - Fork 2
/
make_inventory_openstack.py
executable file
·112 lines (93 loc) · 3.32 KB
/
make_inventory_openstack.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
#!/usr/bin/env python3
import sys
import os
import novaclient.client
import cinderclient.client
import keystoneclient.client
import keystoneauth1.identity.v3
import keystoneauth1.session
import heatclient.client
import yaml
from collections import defaultdict
if len(sys.argv) != 2:
sys.stderr.write('Usage: {0} <stack_name>\n'.format(sys.argv[0]))
exit(2)
stack_name = sys.argv[1]
auth = keystoneauth1.identity.v3.Password(
auth_url=os.environ['OS_AUTH_URL'],
username=os.environ['OS_USERNAME'],
password=os.environ['OS_PASSWORD'],
project_name=os.environ['OS_PROJECT_NAME'],
user_domain_name=os.environ['OS_USER_DOMAIN_NAME'],
#project_domain_name=os.environ['OS_PROJECT_DOMAIN_NAME']
project_domain_id=os.environ['OS_PROJECT_DOMAIN_ID']
)
sess = keystoneauth1.session.Session(auth=auth)
keystone = keystoneclient.client.Client(session=sess)
heat = heatclient.client.Client(version=1, session=sess)
nova = novaclient.client.Client(version=2, session=sess)
cinder = cinderclient.client.Client(version=2, session=sess)
stacks = [s for s in heat.stacks.list(filters={'stack_name': stack_name})]
if len(stacks) == 0:
print('No such stack', file=sys.stderr)
exit(1)
stack = stacks[0]
def get_all_servers(heat, stack_id, servers):
#print('get_all_servers({0})'.format(stack_id))
resources = [r for r in heat.resources.list(stack_id)]
for res in resources:
#print('type = {0}'.format(res.resource_type))
if res.resource_type == 'OS::Nova::Server':
servers.append(res.physical_resource_id)
elif res.resource_type in [
'OS::Neutron::FloatingIP',
'OS::Neutron::Port',
'OS::Neutron::Net',
'OS::Neutron::Router',
'OS::Heat::CloudConfig',
'OS::Heat::MultipartMime',
'OS::Cinder::Volume',
'OS::Cinder::VolumeAttachment',
'OS::Neutron::RouterInterface',
'OS::Neutron::Subnet'
]:
continue
else:
#print(res.resource_type)
#print(res.physical_resource_id)
get_all_servers(heat, res.physical_resource_id, servers)
servers_ids = []
get_all_servers(heat, stack.id, servers_ids)
groups = defaultdict(set)
hostvars = defaultdict(dict)
servers = [s for s in nova.servers.list(search_opts={'id': servers_ids})]
for s in servers:
if 'ansible_host_groups' not in s.metadata:
continue
for group in s.metadata['ansible_host_groups'].split(','):
groups[group].add(s.name)
hvars = hostvars[s.name]
hvars['ansible_ssh_user'] = s.metadata['ansible_ssh_user']
hvars['initial_ssh_user'] = s.metadata['initial_ssh_user']
networks = s.networks.keys()
for network in networks:
# special case @QRISCloud
if network == 'qld-data':
continue
else:
hvars['ansible_ssh_host'] = s.networks[network][0]
volumes = [v for v in nova.volumes.get_server_volumes(s.id) if v.device != '/dev/vda']
if len(volumes) == 0:
continue
hvars['ansible_host_volumes'] = {cinder.volumes.get(vol.volumeId).name:{'dev': vol.device, 'uuid': vol.volumeId} for vol in volumes}
inventory = {g:{'hosts':{h:None for h in groups[g]}} for g in groups}
inventory['all'] = {
'hosts': dict(hostvars),
'vars': {o['output_key']:stack.output_show(o['output_key'])['output']['output_value'] for o in stack.output_list()['outputs']}
}
# So we get "host:" instead of "host: {}"
yaml.SafeDumper.add_representer(
type(None),
lambda dumper, value: dumper.represent_scalar(u'tag:yaml.org,2002:null', '')
)
print(yaml.safe_dump(inventory, default_flow_style=False))