blob: f4e05ce09a65f69bdae5079bacd68f22cf5922ce [file] [log] [blame]
% Licensed under the Apache License, Version 2.0 (the "License"); you may not
% use this file except in compliance with the License. You may obtain a copy of
% the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
% License for the specific language governing permissions and limitations under
% the License.
-module(setup_httpd).
-include_lib("couch/include/couch_db.hrl").
-export([handle_setup_req/1]).
handle_setup_req(#httpd{method='POST'}=Req) ->
ok = chttpd:verify_is_server_admin(Req),
couch_httpd:validate_ctype(Req, "application/json"),
Setup = get_body(Req),
couch_log:notice("Setup: ~p~n", [Setup]),
Action = binary_to_list(couch_util:get_value(<<"action">>, Setup, <<"missing">>)),
case handle_action(Action, Setup) of
ok ->
chttpd:send_json(Req, 201, {[{ok, true}]});
{error, Message} ->
couch_httpd:send_error(Req, 400, <<"bad_request">>, Message)
end;
handle_setup_req(#httpd{method='GET'}=Req) ->
ok = chttpd:verify_is_server_admin(Req),
Dbs = chttpd:qs_json_value(Req, "ensure_dbs_exist", setup:cluster_system_dbs()),
couch_log:notice("Dbs: ~p~n", [Dbs]),
case erlang:list_to_integer(config:get("cluster", "n", undefined)) of
1 ->
case setup:is_single_node_enabled(Dbs) of
false ->
chttpd:send_json(Req, 200, {[{state, single_node_disabled}]});
true ->
chttpd:send_json(Req, 200, {[{state, single_node_enabled}]})
end;
_ ->
case setup:is_cluster_enabled() of
false ->
chttpd:send_json(Req, 200, {[{state, cluster_disabled}]});
true ->
case setup:has_cluster_system_dbs(Dbs) of
false ->
chttpd:send_json(Req, 200, {[{state, cluster_enabled}]});
true ->
chttpd:send_json(Req, 200, {[{state, cluster_finished}]})
end
end
end;
handle_setup_req(#httpd{}=Req) ->
chttpd:send_method_not_allowed(Req, "GET,POST").
get_options(Options, Setup) ->
ExtractValues = fun({Tag, Option}, OptionsAcc) ->
case couch_util:get_value(Option, Setup) of
undefined -> OptionsAcc;
Value -> [{Tag, Value} | OptionsAcc]
end
end,
lists:foldl(ExtractValues, [], Options).
handle_action("enable_cluster", Setup) ->
Options = get_options([
{username, <<"username">>},
{password, <<"password">>},
{password_hash, <<"password_hash">>},
{bind_address, <<"bind_address">>},
{port, <<"port">>},
{remote_node, <<"remote_node">>},
{remote_current_user, <<"remote_current_user">>},
{remote_current_password, <<"remote_current_password">>},
{node_count, <<"node_count">>}
], Setup),
case setup:enable_cluster(Options) of
{error, cluster_enabled} ->
{error, <<"Cluster is already enabled">>};
_ -> ok
end;
handle_action("finish_cluster", Setup) ->
couch_log:notice("finish_cluster: ~p~n", [Setup]),
Options = get_options([
{ensure_dbs_exist, <<"ensure_dbs_exist">>}
], Setup),
case setup:finish_cluster(Options) of
{error, cluster_finished} ->
{error, <<"Cluster is already finished">>};
Else ->
couch_log:notice("finish_cluster: ~p~n", [Else]),
ok
end;
handle_action("enable_single_node", Setup) ->
couch_log:notice("enable_single_node: ~p~n", [Setup]),
Options = get_options([
{ensure_dbs_exist, <<"ensure_dbs_exist">>},
{username, <<"username">>},
{password, <<"password">>},
{password_hash, <<"password_hash">>},
{bind_address, <<"bind_address">>},
{port, <<"port">>}
], Setup),
case setup:enable_single_node(Options) of
{error, cluster_finished} ->
{error, <<"Cluster is already finished">>};
Else ->
couch_log:notice("Else: ~p~n", [Else]),
ok
end;
handle_action("add_node", Setup) ->
couch_log:notice("add_node: ~p~n", [Setup]),
Options = get_options([
{username, <<"username">>},
{password, <<"password">>},
{host, <<"host">>},
{port, <<"port">>},
{name, <<"name">>}
], Setup),
case setup:add_node(Options) of
{error, cluster_not_enabled} ->
{error, <<"Cluster is not enabled.">>};
{error, {conn_failed, {error, econnrefused}}} ->
{error, <<"Add node failed. Invalid Host and/or Port.">>};
{error, wrong_credentials} ->
{error, <<"Add node failed. Invalid admin credentials,">>};
{error, Message} ->
{error, Message};
_ -> ok
end;
handle_action("remove_node", Setup) ->
couch_log:notice("remove_node: ~p~n", [Setup]);
handle_action("receive_cookie", Setup) ->
couch_log:notice("receive_cookie: ~p~n", [Setup]),
Options = get_options([
{cookie, <<"cookie">>}
], Setup),
case setup:receive_cookie(Options) of
{error, Error} ->
{error, Error};
_ -> ok
end;
handle_action(_, _) ->
couch_log:notice("invalid_action: ~n", []),
{error, <<"Invalid Action'">>}.
get_body(Req) ->
case catch couch_httpd:json_body_obj(Req) of
{Body} ->
Body;
Else ->
couch_log:notice("Body Fail: ~p~n", [Else]),
couch_httpd:send_error(Req, 400, <<"bad_request">>, <<"Missing JSON body'">>)
end.