@@ -51,7 +51,7 @@ def connect_the_dots(names):
51
51
resp = requests .put (uri , data = json .dumps (doc ), auth = creds )
52
52
else :
53
53
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 )
55
55
56
56
# Run action:enable_cluster on every CouchDB cluster node
57
57
def enable_cluster (nr_of_peers ):
@@ -128,37 +128,7 @@ def finish_cluster(names):
128
128
print ("\t Request: POST http://127.0.0.1:5984/_cluster_setup , payload:" ,json .dumps (payload ))
129
129
print ("\t \t Response:" , setup_resp .status_code , setup_resp .json ())
130
130
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
+
162
132
163
133
setup_resp = requests .post ("http://127.0.0.1:5984/_cluster_setup" , json = {"action" : "finish_cluster" }, auth = creds )
164
134
if (setup_resp .status_code == 201 ):
@@ -175,19 +145,66 @@ def finish_cluster(names):
175
145
else :
176
146
print ("This pod is intentionally skipping the call to http://127.0.0.1:5984/_cluster_setup" )
177
147
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
+
178
191
def sleep_forever ():
179
192
while True :
180
193
time .sleep (5 )
181
194
182
195
if __name__ == '__main__' :
183
196
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 ))
187
197
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 )
188
204
print ('Cluster membership populated!' )
205
+
189
206
if (os .getenv ("COUCHDB_USER" ) and os .getenv ("COUCHDB_PASSWORD" )):
190
207
finish_cluster (peer_names )
191
208
else :
192
- print ('Skipping cluster setup. Username and/or password not provided' )
209
+ print ('Skipping cluster final setup. Username and/or password not provided' )
193
210
sleep_forever ()
0 commit comments