|
10 | 10 | import time
|
11 | 11 | import dns.resolver
|
12 | 12 | import socket
|
| 13 | +import backoff |
13 | 14 |
|
14 |
| -def discover_peers_dns(retries=5): |
| 15 | +def construct_service_record(): |
15 | 16 | # Drop our Pod's unique identity and replace with '_couchdb._tcp'
|
16 |
| - # to form the name of the SRV record |
17 |
| - resource = '.'.join(['_couchdb', '_tcp'] + socket.getfqdn().split('.')[1:]) |
18 |
| - print ('SRV record', resource) |
19 |
| - if retries > 0: |
20 |
| - try: |
21 |
| - answers = dns.resolver.query(resource, 'SRV') |
22 |
| - except dns.resolver.NXDOMAIN: |
23 |
| - print('DNS query for SRV records failed with NXDOMAIN error') |
24 |
| - time.sleep(5) |
25 |
| - discover_peers_dns(retries - 1) |
26 |
| - # Erlang requires that we drop the trailing period from the absolute DNS |
27 |
| - # name to form the hostname used for the Erlang node. This feels hacky |
28 |
| - # but not sure of a more official answer |
29 |
| - hostnames = [rdata.target.to_text()[:-1] for rdata in answers] |
30 |
| - print(hostnames) |
31 |
| - connect_the_dots(hostnames) |
32 |
| - else: |
33 |
| - print('Could not resolve resource ', resource) |
| 17 | + return '.'.join(['_couchdb', '_tcp'] + socket.getfqdn().split('.')[1:]) |
| 18 | + |
| 19 | +@backoff.on_exception( |
| 20 | + backoff.expo, |
| 21 | + dns.resolver.NXDOMAIN, |
| 22 | + max_tries=10 |
| 23 | +) |
| 24 | +def discover_peers(service_record): |
| 25 | + print ('Resolving SRV record', service_record) |
| 26 | + answers = dns.resolver.query(service_record, 'SRV') |
| 27 | + # Erlang requires that we drop the trailing period from the absolute DNS |
| 28 | + # name to form the hostname used for the Erlang node. This feels hacky |
| 29 | + # but not sure of a more official answer |
| 30 | + return [rdata.target.to_text()[:-1] for rdata in answers] |
34 | 31 |
|
35 |
| -def connect_the_dots(names, retries=5): |
36 |
| - if retries > 0: |
37 |
| - for name in names: |
38 |
| - uri = "http://127.0.0.1:5986/_nodes/couchdb@{0}".format(name) |
39 |
| - doc = {} |
40 |
| - try: |
41 |
| - resp = requests.put(uri, data=json.dumps(doc)) |
42 |
| - if resp.status_code == 404: |
43 |
| - print('CouchDB nodes DB does not exist yet') |
44 |
| - time.sleep(5) |
45 |
| - connect_the_dots(names, retries - 1) |
46 |
| - print(name, resp.status_code) |
47 |
| - except requests.exceptions.ConnectionError: |
48 |
| - print('CouchDB admin port not up yet') |
49 |
| - time.sleep(5) |
50 |
| - connect_the_dots(names, retries - 1) |
51 |
| - sleep_forever() |
52 |
| - else: |
53 |
| - print('Could not connect to local admin port to supply node names') |
| 32 | +@backoff.on_exception( |
| 33 | + backoff.expo, |
| 34 | + requests.exceptions.ConnectionError, |
| 35 | + max_tries=10 |
| 36 | +) |
| 37 | +def connect_the_dots(names): |
| 38 | + for name in names: |
| 39 | + uri = "http://127.0.0.1:5986/_nodes/couchdb@{0}".format(name) |
| 40 | + doc = {} |
| 41 | + resp = requests.put(uri, data=json.dumps(doc)) |
| 42 | + while resp.status_code == 404: |
| 43 | + print('Waiting for _nodes DB to be created ...') |
| 44 | + time.sleep(5) |
| 45 | + resp = requests.put(uri, data=json.dumps(doc)) |
| 46 | + print('Adding cluster member', name, resp.status_code) |
54 | 47 |
|
55 | 48 | def sleep_forever():
|
56 | 49 | while True:
|
57 | 50 | time.sleep(5)
|
58 | 51 |
|
59 | 52 | if __name__ == '__main__':
|
60 |
| - discover_peers_dns() |
| 53 | + connect_the_dots(discover_peers(construct_service_record())) |
| 54 | + print('Cluster membership populated!') |
| 55 | + sleep_forever() |
0 commit comments