summaryrefslogtreecommitdiffstats
path: root/playbooks/openstack/inventory.py
blob: c16a9e2284f1f2764c3efb3257f5704e9b66708a (plain)
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python
"""
This is an Ansible dynamic inventory for OpenStack.

It requires your OpenStack credentials to be set in clouds.yaml or your shell
environment.

"""

from __future__ import print_function

from collections import Mapping
import json

import shade


def base_openshift_inventory(cluster_hosts):
    '''Set the base openshift inventory.'''
    inventory = {}

    masters = [server.name for server in cluster_hosts
               if server.metadata['host-type'] == 'master']

    etcd = [server.name for server in cluster_hosts
            if server.metadata['host-type'] == 'etcd']
    if not etcd:
        etcd = masters

    infra_hosts = [server.name for server in cluster_hosts
                   if server.metadata['host-type'] == 'node' and
                   server.metadata['sub-host-type'] == 'infra']

    app = [server.name for server in cluster_hosts
           if server.metadata['host-type'] == 'node' and
           server.metadata['sub-host-type'] == 'app']

    cns = [server.name for server in cluster_hosts
           if server.metadata['host-type'] == 'cns']

    nodes = list(set(masters + infra_hosts + app + cns))

    dns = [server.name for server in cluster_hosts
           if server.metadata['host-type'] == 'dns']

    load_balancers = [server.name for server in cluster_hosts
                      if server.metadata['host-type'] == 'lb']

    osev3 = list(set(nodes + etcd + load_balancers))

    inventory['cluster_hosts'] = {'hosts': [s.name for s in cluster_hosts]}
    inventory['OSEv3'] = {'hosts': osev3}
    inventory['masters'] = {'hosts': masters}
    inventory['etcd'] = {'hosts': etcd}
    inventory['nodes'] = {'hosts': nodes}
    inventory['infra_hosts'] = {'hosts': infra_hosts}
    inventory['app'] = {'hosts': app}
    inventory['glusterfs'] = {'hosts': cns}
    inventory['dns'] = {'hosts': dns}
    inventory['lb'] = {'hosts': load_balancers}

    return inventory


def get_docker_storage_mountpoints(volumes):
    '''Check volumes to see if they're being used for docker storage'''
    docker_storage_mountpoints = {}
    for volume in volumes:
        if volume.metadata.get('purpose') == "openshift_docker_storage":
            for attachment in volume.attachments:
                if attachment.server_id in docker_storage_mountpoints:
                    docker_storage_mountpoints[attachment.server_id].append(attachment.device)
                else:
                    docker_storage_mountpoints[attachment.server_id] = [attachment.device]
    return docker_storage_mountpoints


def build_inventory():
    '''Build the dynamic inventory.'''
    cloud = shade.openstack_cloud()

    # TODO(shadower): filter the servers based on the `OPENSHIFT_CLUSTER`
    # environment variable.
    cluster_hosts = [
        server for server in cloud.list_servers()
        if 'metadata' in server and 'clusterid' in server.metadata]

    inventory = base_openshift_inventory(cluster_hosts)

    for server in cluster_hosts:
        if 'group' in server.metadata:
            group = server.metadata.get('group')
            if group not in inventory:
                inventory[group] = {'hosts': []}
            inventory[group]['hosts'].append(server.name)

    inventory['_meta'] = {'hostvars': {}}

    # cinder volumes used for docker storage
    docker_storage_mountpoints = get_docker_storage_mountpoints(cloud.list_volumes())

    for server in cluster_hosts:
        ssh_ip_address = server.public_v4 or server.private_v4
        hostvars = {
            'ansible_host': ssh_ip_address
        }

        public_v4 = server.public_v4 or server.private_v4
        if public_v4:
            hostvars['public_v4'] = server.public_v4
            hostvars['openshift_public_ip'] = server.public_v4
        # TODO(shadower): what about multiple networks?
        if server.private_v4:
            hostvars['private_v4'] = server.private_v4
            hostvars['openshift_ip'] = server.private_v4

            # NOTE(shadower): Yes, we set both hostname and IP to the private
            # IP address for each node. OpenStack doesn't resolve nodes by
            # name at all, so using a hostname here would require an internal
            # DNS which would complicate the setup and potentially introduce
            # performance issues.
            hostvars['openshift_hostname'] = server.metadata.get(
                'openshift_hostname', server.private_v4)
        hostvars['openshift_public_hostname'] = server.name

        if server.metadata['host-type'] == 'cns':
            hostvars['glusterfs_devices'] = ['/dev/nvme0n1']

        node_labels = server.metadata.get('node_labels')
        # NOTE(shadower): the node_labels value must be a dict not string
        if not isinstance(node_labels, Mapping):
            node_labels = json.loads(node_labels)

        if node_labels:
            hostvars['openshift_node_labels'] = node_labels

        # check for attached docker storage volumes
        if 'os-extended-volumes:volumes_attached' in server:
            if server.id in docker_storage_mountpoints:
                hostvars['docker_storage_mountpoints'] = ' '.join(docker_storage_mountpoints[server.id])

        inventory['_meta']['hostvars'][server.name] = hostvars
    return inventory


if __name__ == '__main__':
    print(json.dumps(build_inventory(), indent=4, sort_keys=True))