commit | 616789bac1bcdf9897e6725baaf0249f742389fd | [log] [tgz] |
---|---|---|
author | Robert Kowalski <rok@kowalski.gd> | Tue May 26 02:33:50 2015 +0200 |
committer | Robert Kowalski <robertkowalski@apache.org> | Wed Jun 24 15:37:16 2015 +0200 |
tree | 4de15fa47756e6edadbfcc62133347c05916f241 | |
parent | ecb601b2004f33f396530a6ae974f2f0bff4d816 [diff] |
cluster_enable: add remote_node feature this feature makes it easier to setup a cluster for browser applications like fauxton as browsers follow the same-origin policy. Before this PR you had to open the wizard in Fauxton on all three nodes and enter your data there, which was quite confusing and hard to explain. Now you can stay in the same tab at the same address. This PR enables three new params in the body: `remote_node`: ip of the remote node where we want to send the `enable_cluster` request `remote_current_user`: the current admin username of the remote node `remote_current_password`: the current admin password of the remote node To test, I run: ``` rm -rf dev/lib/ && ./dev/run --no-join --admin=a:b ``` and then run the test script: ``` ./src/setup/test/t-frontend-setup.sh ``` COUCHDB-2598 PR: #2 PR-URL: https://github.com/apache/couchdb-setup/pull/2 Reviewed-By: Jan Lehnardt <jan@apache.org> Reviewed-By: Alexander Shorin <kxepal@apache.org>
This module implements /_cluster_setup and manages the setting up, duh, of a CouchDB cluster.
git clone https://git-wip-us.apache.org/repos/asf/couchdb.git cd couchdb git checkout setup ./configure make # in dev/run comment out the line `connect_nodes("127.0.0.1", 15984)` dev/run --admin a:b # in a new terminal src/setup/test/t.sh
The Plan:
N. End User Action
$ couchdb
, or init.d, or any other way, exactly like it is done in 1.x.x.From here on, there are two paths, one is via Fauxton (a) the other is using a HTTP endpoint (b). Fauxton just uses the HTTP endpoint in (b). (b) can be used to set up a cluster programmatically.
2.a. Go to Fauxton. There is a “Cluster Setup” tab in the sidebar. Go to the tab and get presented with a form that asks you to enter an admin username, admin password and optionally a bind_address and port to bind to publicly. Submit the form with the [Enable Cluster] button.
If this is a single node install that already has an admin set up, there is no need to ask for admin credentials here. If the bind_address is != 127.0.0.1, we can skip this entirely and Fauxton can show the add_node UI right away.
{ "action": "enable_cluster", "admin": { "user": "username", "pass": "password" }, ["bind_address": "xxxx",] ["port": yyyy] }
This sets up the admin user on the current node and binds to 0.0.0.0:5984 or the specified ip:port. Logs admin user into Fauxton automatically.
2.b. POST to /_setup as shown above.
Repeat on all nodes.
a. Go to Fauxton / Cluster Setup, once we have enabled the cluster, the UI shows an “Add Node” interface with the fields admin, and node:
{ "action": "add_node", "admin": { // should be auto-filled from Fauxton, store plaintext PW in // localStorage until we finish_cluster or timeout. "user": "username", "pass": "password" }, "node": { "host": "hostname", ["port": 5984] } }
b. as in a, but without the Fauxton bits, just POST to /_setup
{ "action": "receive_cookie", "cookie": "<secretcookie>", }
when the request to node B returns, we know the Erlang-level inter-cluster communication is enabled and we can start adding the node on the CouchDB level. To do that, the “setup coordination node” does this to it’s own HTTP endpoint: PUT /nodes/node_b:5984 or the same thing with internal APIs.
Repeat for all nodes.
Fauxton keeps a list of all set up nodes for users to see.
4.a. When all nodes are added, click the [Finish Cluster Setup] button in Fauxton.
{ "action": "finish_setup" }
b. Same as in a.
This is not a REST-y endpoint, it is a simple state machine operated by HTTP POST with JSON bodies that have an action
field.
This is right after starting a node for the first time, and any time before the cluster is enabled as outlined above.
GET /_setup {"state": "cluster_disabled"} POST /_setup {"action":"enable_cluster"...} -> Transition to State 2 POST /_setup {"action":"enable_cluster"...} with empty admin user/pass or invalid host/post or host/port not available -> Error POST /_setup {"action":"anything_but_enable_cluster"...} -> Error
GET /_setup {"state":"cluster_enabled","nodes":[]} POST /_setup {"action":"enable_cluster"...} -> Error POST /_setup {"action":"add_node"...} -> Stay in State 2, but return "nodes":["node B"}] on GET POST /_setup {"action":"add_node"...} -> if target node not available, Error POST /_setup {"action":"finish_cluster"} with no nodes set up -> Error POST /_setup {"action":"finish_cluster"} -> Transition to State 3 POST /_setup {"action":"delete_node"...} -> Stay in State 2, but delete node from /nodes, reflect the change in GET /_setup POST /_setup {"action":"delete_node","node":"unknown"} -> Error Unknown Node
GET /_setup {"state":"cluster_finished","nodes":["node a", "node b", ...]} POST /_setup {"action":"enable_cluster"...} -> Error POST /_setup {"action":"finish_cluster"...} -> Stay in State 3, do nothing POST /_setup {"action":"add_node"...} -> Error POST /_setup?i_know_what_i_am_doing=true {"action":"add_node"...} -> Add node, stay in State 3. POST /_setup {"action":"delete_node"...} -> Stay in State 3, but delete node from /nodes, reflect the change in GET /_setup POST /_setup {"action":"delete_node","node":"unknown"} -> Error Unknown Node
// TBD: we need to persist the setup state somewhere.