File: pg_sr_cluster_nodes.py

package info (click to toggle)
check-pgbackrest 2.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,396 kB
  • sloc: perl: 972; sh: 488; python: 145; makefile: 33
file content (136 lines) | stat: -rw-r--r-- 5,410 bytes parent folder | download
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
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

DOCUMENTATION = """
    name: pg_sr_cluster_nodes
    author: Julien Tachoires
    short_description: Lookup Postgres SR cluster nodes
    description:
      - "Retrieves the Postgres streaming replication nodes list, based on
        node's private IP"
    options:
      _terms:
        description: The private IP of one member of the SR cluster.
        required: False
      default:
        description: The private IP of the current node is used.
"""

EXAMPLES = """
- name: Show all members of the SR cluster that the current node is part of
  debug: msg="{{ lookup('pg_sr_cluster_nodes') }}"

- name: Show all members of the SR cluster that the {{ primary_private_ip }} is part of
  debug: msg="{{ lookup('pg_sr_cluster_nodes', primary_private_ip) }}"
"""

RETURN = """
_value:
  description:
    - List of Postgres nodes
  type: list
  elements: dict
"""

from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase

class LookupModule(LookupBase):
    def run(self, terms, variables=None, **kwargs):

        pg_clusters = {}
        pg_standbys = {}
        pg_primary_map = {}

        myvars = getattr(self._templar, '_available_variables', {})

        # If no terms, we'll used the current private IP
        if len(terms) == 0:
            node_private_ip = myvars['hostvars'][variables['inventory_hostname']]['private_ip']
        else:
            node_private_ip = terms[0]

        # If no primary found in the inventory we return an empty list
        if 'primary' not in variables['groups']:
            return []

        # Initiate pg_clusters and pg_primary_map for each primary node we have
        # in the inventory.
        for host in variables['groups']['primary']:
            hostvars = myvars['hostvars'][host]
            private_ip = hostvars['private_ip']

            pg_clusters[private_ip] = []
            pg_clusters[private_ip].append(
                dict(
                    node_type='primary',
                    ansible_host=hostvars['ansible_host'],
                    hostname=hostvars.get('hostname',
                                          hostvars.get('ansible_hostname')),
                    private_ip=hostvars['private_ip'],
                    upstream_node_private_ip=None,
                    replication_type=None,
                    inventory_hostname=hostvars['inventory_hostname']
                )
            )
            pg_primary_map[private_ip] = private_ip

        # Populate pg_standbys dict if we have standby nodes in the inventory
        if 'standby' in variables['groups']:
            for host in variables['groups']['standby']:
                hostvars = myvars['hostvars'][host]
                pg_standbys[host] = dict(
                    node_type='standby',
                    ansible_host=hostvars['ansible_host'],
                    hostname=hostvars.get('hostname',
                                          hostvars.get('ansible_hostname')),
                    private_ip=hostvars['private_ip'],
                    upstream_node_private_ip=hostvars['upstream_node_private_ip'],
                    replication_type=hostvars.get('replication_type',
                                                  'asynchronous'),
                    inventory_hostname=hostvars['inventory_hostname']
                )

        pg_standbys_len = len(pg_standbys.keys())

        # Append the standby nodes into the right pg_clusters item, based on
        # standby's upstream node.
        while pg_standbys_len != 0:

            for k in list(pg_standbys.keys()):
                sby = pg_standbys[k]

                if sby['upstream_node_private_ip'] in pg_primary_map:
                    upstream_private_ip = sby['upstream_node_private_ip']
                    primary_private_ip = pg_primary_map[upstream_private_ip]
                    pg_primary_map[sby['private_ip']] = primary_private_ip
                    pg_clusters[primary_private_ip].append(sby)
                    del(pg_standbys[k])

            # Case when at least one host has not been handled in this loop
            # iteration.
            if pg_standbys_len == len(pg_standbys.keys()):
                raise AnsibleError(
                    "Inventory error with the following standbys nodes %s. "
                    "Upstream node is not configured or not found"
                    % [s for s in pg_standbys.keys()]
                )

            pg_standbys_len = len(pg_standbys.keys())

        if node_private_ip in pg_primary_map:
            # Current node is part of one of the SR clusters found
            return pg_clusters[pg_primary_map[node_private_ip]]
        else:
            primary_private_ips = list(pg_clusters.keys())
            # If the current node is not part of any SR cluster found, but,
            # only one SR cluster has been found, then we return this SR
            # cluster because there is no doubt.
            if len(primary_private_ips) == 1:
                return pg_clusters[primary_private_ips[0]]
            else:
                raise AnsibleError(
                    "Unable to find the SR cluster topology because multiple "
                    "SR clusters were found and this current node does not "
                    "appear to be part of any of them"
                )