Skip to content

Commit 4a89685

Browse files
author
Robert Gartman
committed
Automate _cluster_setup
1 parent 76e116c commit 4a89685

File tree

1 file changed

+53
-36
lines changed

1 file changed

+53
-36
lines changed

mem3_helper.py

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def connect_the_dots(names):
5151
resp = requests.put(uri, data=json.dumps(doc), auth=creds)
5252
else:
5353
resp = requests.put(uri, data=json.dumps(doc))
54-
print('Adding CouchDB cluster node', name, "to this pod's CouchDB", flush=True)
54+
print('Adding CouchDB cluster node', name, "to this pod's CouchDB. Response code:", resp.status_code ,flush=True)
5555

5656
# Run action:enable_cluster on every CouchDB cluster node
5757
def enable_cluster(nr_of_peers):
@@ -128,37 +128,7 @@ def finish_cluster(names):
128128
print ("\tRequest: POST http://127.0.0.1:5984/_cluster_setup , payload:",json.dumps(payload))
129129
print ("\t\tResponse:", setup_resp.status_code, setup_resp.json())
130130

131-
# Make sure that ALL CouchDB cluster peers have been
132-
# primed with _nodes data before /_cluster_setup
133-
# Use the _membership of "this" pod's CouchDB as reference
134-
local_membership_uri = "http://127.0.0.1:5984/_membership"
135-
print ("Fetching CouchDB node mebership from this pod: {0}".format(local_membership_uri),flush=True)
136-
if creds[0] and creds[1]:
137-
local_resp = requests.get(local_membership_uri, auth=creds)
138-
else:
139-
local_resp = requests.get(local_membership_uri)
140-
# Step through every peer. Ensure they are "ready" before progressing.
141-
for name in names:
142-
print("Probing {0} for cluster membership".format(name))
143-
remote_membership_uri = "http://{0}:5984/_membership".format(name)
144-
if creds[0] and creds[1]:
145-
remote_resp = requests.get(remote_membership_uri, auth=creds)
146-
# Compare local and remote _mebership data. Make sure the set
147-
# of nodes match. This will ensure that the remote nodes
148-
# are fully primed with nodes data before progressing with
149-
# _cluster_setup
150-
while (remote_resp.status_code != 200) or (ordered(local_resp.json()) != ordered(remote_resp.json())):
151-
# print ("remote_resp.status_code",remote_resp.status_code)
152-
# print (ordered(local_resp.json()))
153-
# print (ordered(remote_resp.json()))
154-
print('Waiting for node {0} to have all node members populated'.format(name),flush=True)
155-
time.sleep(5)
156-
if creds[0] and creds[1]:
157-
remote_resp = requests.get(remote_membership_uri, auth=creds)
158-
print("Node {0} has all node members in place!".format(name))
159-
160-
print('CouchDB cluster peer {} added to "setup coordination node"'.format(name))
161-
# At this point ALL peers have _nodes populated. Finish the cluster setup!
131+
162132

163133
setup_resp=requests.post("http://127.0.0.1:5984/_cluster_setup", json={"action": "finish_cluster"}, auth=creds)
164134
if (setup_resp.status_code == 201):
@@ -175,19 +145,66 @@ def finish_cluster(names):
175145
else:
176146
print("This pod is intentionally skipping the call to http://127.0.0.1:5984/_cluster_setup")
177147

148+
def diff(first, second):
149+
second = set(second)
150+
return [item for item in first if item not in second]
151+
152+
# Check if the _membership API on all (known) CouchDB nodes have the same values.
153+
# Returns true if sam. False in any other situation.
154+
def are_nodes_in_sync(names):
155+
# Make sure that ALL (known) CouchDB cluster peers have been
156+
# have the same _membership data.Use "this" nodes memebership as
157+
# "source"
158+
local_membership_uri = "http://127.0.0.1:5984/_membership"
159+
print ("Fetching CouchDB node mebership from this pod: {0}".format(local_membership_uri),flush=True)
160+
if creds[0] and creds[1]:
161+
local_resp = requests.get(local_membership_uri, auth=creds)
162+
else:
163+
local_resp = requests.get(local_membership_uri)
164+
165+
# If any difference is found - set to true
166+
is_different = False;
167+
# Step through every peer. Ensure they are "ready" before progressing.
168+
for name in names:
169+
print("Probing {0} for cluster membership".format(name))
170+
remote_membership_uri = "http://{0}:5984/_membership".format(name)
171+
if creds[0] and creds[1]:
172+
remote_resp = requests.get(remote_membership_uri, auth=creds)
173+
# Compare local and remote _mebership data. Make sure the set
174+
# of nodes match. This will ensure that the remote nodes
175+
# are fully primed with nodes data before progressing with
176+
# _cluster_setup
177+
if (remote_resp.status_code == 200) and (local_resp.status_code == 200):
178+
if ordered(local_resp.json()) != ordered(remote_resp.json()):
179+
is_different = True
180+
print ("Fetching CouchDB node mebership from this pod: {0}".format(local_membership_uri),flush=True)
181+
records_in_local_but_not_in_remote = diff(local_resp.json().cluster_nodes, remote_resp.json().cluster_nodes)
182+
records_in_remote_but_not_in_local = diff(remote_resp.json().cluster_nodes, local_resp.json().cluster_nodes)
183+
if records_in_local_but_not_in_remote:
184+
print ("Cluster members in {0} not yet present in {1}: {2}".format(os.getenv("HOSTNAME"), name.split(".",1)[0], records_in_local_but_not_in_remote))
185+
if records_in_remote_but_not_in_local:
186+
print ("Cluster members in {0} not yet present in {1}: {2}".format(name.split(".",1)[0], os.getenv("HOSTNAME"), records_in_remote_but_not_in_local))
187+
else:
188+
is_different = True
189+
return not is_different
190+
178191
def sleep_forever():
179192
while True:
180193
time.sleep(5)
181194

182195
if __name__ == '__main__':
183196
peer_names = discover_peers(construct_service_record())
184-
print("Got the following peers' fqdm from DNS lookup:",peer_names,flush=True)
185-
if (os.getenv("COUCHDB_USER") and os.getenv("COUCHDB_PASSWORD")):
186-
enable_cluster(len(peer_names))
187197
connect_the_dots(peer_names)
198+
print("Got the following peers' fqdm from DNS lookup:",peer_names,flush=True)
199+
# loop until all CouchDB nodes discovered
200+
while not are_nodes_in_sync(names):
201+
time.sleep(5)
202+
peer_names = discover_peers(construct_service_record())
203+
connect_the_dots(peer_names)
188204
print('Cluster membership populated!')
205+
189206
if (os.getenv("COUCHDB_USER") and os.getenv("COUCHDB_PASSWORD")):
190207
finish_cluster(peer_names)
191208
else:
192-
print ('Skipping cluster setup. Username and/or password not provided')
209+
print ('Skipping cluster final setup. Username and/or password not provided')
193210
sleep_forever()

0 commit comments

Comments
 (0)