mirror of https://gitee.com/bigwinds/arangodb
397 lines
11 KiB
JavaScript
397 lines
11 KiB
JavaScript
/*global applicationContext*/
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief A Foxx.Controller to show all Foxx Applications
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2010-2013 triagens GmbH, Cologne, Germany
|
|
///
|
|
/// 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.
|
|
///
|
|
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// @author Michael Hackstein
|
|
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
(function() {
|
|
"use strict";
|
|
|
|
// Initialise a new FoxxController called controller under the urlPrefix: "cluster".
|
|
var FoxxController = require("org/arangodb/foxx").Controller,
|
|
controller = new FoxxController(applicationContext),
|
|
cluster = require("org/arangodb/cluster"),
|
|
load = require("internal").download,
|
|
_ = require("underscore");
|
|
|
|
/** Plan and start a new cluster
|
|
*
|
|
* This will plan a new cluster with the information
|
|
* given in the body
|
|
*/
|
|
controller.get("/amICoordinator", function(req, res) {
|
|
res.json(cluster.isCoordinator());
|
|
});
|
|
|
|
controller.get("/amIDispatcher", function(req, res) {
|
|
res.json(!cluster.dispatcherDisabled());
|
|
});
|
|
|
|
if (!cluster.dispatcherDisabled()) {
|
|
var Plans = require("./repositories/plans.js"),
|
|
plans = new Plans.Repository(
|
|
require("internal").db._collection(
|
|
"_cluster_kickstarter_plans"
|
|
)),
|
|
getStarter = function() {
|
|
var config = plans.loadConfig(),
|
|
k;
|
|
if (!config) {
|
|
return;
|
|
}
|
|
k = new cluster.Kickstarter(config.plan);
|
|
k.runInfo = config.runInfo;
|
|
return k;
|
|
},
|
|
parseUser = function(header) {
|
|
if (header && header.authorization) {
|
|
var auth = require("internal").base64Decode(
|
|
header.authorization.substr(6)
|
|
);
|
|
return {
|
|
username: auth.substr(0, auth.indexOf(":")),
|
|
passwd: auth.substr(auth.indexOf(":")+1) || ""
|
|
};
|
|
}
|
|
return {
|
|
username: "root",
|
|
passwd: ""
|
|
};
|
|
},
|
|
startUp = function(req, res) {
|
|
cleanUp();
|
|
var config = {},
|
|
input = req.body(),
|
|
result = {},
|
|
starter,
|
|
i,
|
|
tmp,
|
|
planner,
|
|
auth,
|
|
uname,
|
|
pwd;
|
|
auth = parseUser(req.headers);
|
|
uname = auth.username;
|
|
pwd = auth.passwd;
|
|
if (input.type === "testSetup") {
|
|
config.dispatchers = {
|
|
"d1": {
|
|
"username": uname,
|
|
"passwd": pwd,
|
|
"endpoint": "tcp://" + input.dispatchers
|
|
}
|
|
};
|
|
config.numberOfDBservers = input.numberDBServers;
|
|
config.numberOfCoordinators = input.numberCoordinators;
|
|
} else {
|
|
i = 0;
|
|
config.dispatchers = {};
|
|
config.numberOfDBservers = 0;
|
|
config.numberOfCoordinators = 0;
|
|
_.each(input.dispatchers, function(d) {
|
|
i++;
|
|
var inf = {};
|
|
inf.username = d.username;
|
|
inf.passwd = d.passwd;
|
|
inf.endpoint = "tcp://" + d.host;
|
|
if (d.isCoordinator) {
|
|
config.numberOfCoordinators++;
|
|
} else {
|
|
inf.allowCoordinators = false;
|
|
}
|
|
if (d.isDBServer) {
|
|
config.numberOfDBservers++;
|
|
} else {
|
|
inf.allowDBservers = false;
|
|
}
|
|
config.dispatchers["d" + i] = inf;
|
|
});
|
|
config.useSSLonDBservers = input.useSSLonDBservers;
|
|
config.useSSLonCoordinators = input.useSSLonCoordinators;
|
|
}
|
|
result.config = config;
|
|
planner = new cluster.Planner(config);
|
|
result.plan = planner.getPlan();
|
|
starter = new cluster.Kickstarter(planner.getPlan());
|
|
tmp = starter.launch();
|
|
result.runInfo = tmp.runInfo;
|
|
result.user = {
|
|
name: "root",
|
|
passwd: ""
|
|
};
|
|
plans.storeConfig(result);
|
|
res.json(result);
|
|
},
|
|
cleanUp = function() {
|
|
var k = getStarter();
|
|
if (k) {
|
|
k.cleanup();
|
|
}
|
|
};
|
|
// only make these functions available in dispatcher mode!
|
|
controller.post("/plan", startUp);
|
|
controller.put("/plan", startUp);
|
|
|
|
controller.put("/plan/credentials", function(req, res) {
|
|
var body = req.body(),
|
|
u = body.user,
|
|
p = body.passwd;
|
|
plans.saveCredentials(u, p);
|
|
});
|
|
|
|
controller.get("/plan", function(req, res) {
|
|
res.json(plans.loadConfig());
|
|
});
|
|
|
|
controller.del("/plan/cleanUp", function(req, res) {
|
|
cleanUp();
|
|
res.json("ok");
|
|
});
|
|
|
|
controller.post("/communicationCheck", function(req, res) {
|
|
var list = req.body();
|
|
var options = {};
|
|
var result = [];
|
|
var base64Encode = require("internal").base64Encode;
|
|
_.each(list, function(info) {
|
|
var host = info.host;
|
|
var port = info.port;
|
|
if (info.user) {
|
|
options.headers = {
|
|
"Authorization": "Basic " + base64Encode(info.user + ":" +
|
|
info.passwd)
|
|
};
|
|
}
|
|
var url = "http://" + host + ":" + port + "/_api/version";
|
|
var resi = load(url, "", options);
|
|
if (resi.code !== 200) {
|
|
result.push(false);
|
|
} else {
|
|
result.push(true);
|
|
}
|
|
delete options.headers;
|
|
});
|
|
res.json(result);
|
|
});
|
|
|
|
controller.del("/plan", function(req, res) {
|
|
plans.clear();
|
|
res.json("ok");
|
|
});
|
|
|
|
controller.get("/healthcheck", function(req, res) {
|
|
var out = getStarter().isHealthy();
|
|
var answer = true;
|
|
if (out.error) {
|
|
_.each(out.results, function(res) {
|
|
if (res.answering) {
|
|
answer = (_.any(res.answering, function(i) {
|
|
return i === true;
|
|
}));
|
|
}
|
|
});
|
|
}
|
|
res.json(answer);
|
|
});
|
|
|
|
controller.get("/shutdown", function(req, res) {
|
|
var k = getStarter();
|
|
var shutdownInfo = k.shutdown();
|
|
if (shutdownInfo.error) {
|
|
require("console").log("%s", JSON.stringify(shutdownInfo.results));
|
|
}
|
|
plans.removeRunInfo();
|
|
});
|
|
|
|
controller.get("/upgrade", function(req, res) {
|
|
//uname pswd
|
|
|
|
var k = getStarter();
|
|
var u = plans.getCredentials();
|
|
var r = k.upgrade(u.name, u.passwd);
|
|
if (r.error === true) {
|
|
res.json(r);
|
|
res.status = 500;
|
|
}
|
|
else {
|
|
plans.replaceRunInfo(r.runInfo);
|
|
res.json("ok");
|
|
}
|
|
|
|
});
|
|
|
|
controller.get("/cleanup", function(req, res) {
|
|
var k = getStarter();
|
|
var shutdownInfo = k.shutdown();
|
|
cleanUp();
|
|
if (shutdownInfo.error) {
|
|
require("console").log("%s", JSON.stringify(shutdownInfo.results));
|
|
return;
|
|
}
|
|
});
|
|
|
|
controller.get("/relaunch", function(req, res) {
|
|
var k = getStarter();
|
|
var u = plans.getCredentials();
|
|
var r = k.relaunch(u.name, u.passwd);
|
|
if (r.error) {
|
|
res.json("Unable to relaunch cluster");
|
|
res.status(409);
|
|
return;
|
|
}
|
|
var result = {
|
|
plan: r.plan,
|
|
runInfo: r.runInfo
|
|
};
|
|
result = plans.updateConfig(result);
|
|
res.json(result);
|
|
});
|
|
}
|
|
if (cluster.isCluster()) {
|
|
// only make these functions available in cluster mode!
|
|
var Communication = require("org/arangodb/cluster/agency-communication"),
|
|
comm = new Communication.Communication(),
|
|
beats = comm.sync.Heartbeats(),
|
|
diff = comm.diff.current,
|
|
servers = comm.current.DBServers(),
|
|
dbs = comm.current.Databases(),
|
|
coords = comm.current.Coordinators();
|
|
|
|
|
|
/** Get the type of the cluster
|
|
*
|
|
* Returns a string containing the cluster type
|
|
* Possible anwers:
|
|
* - testSetup
|
|
* - symmetricalSetup
|
|
* - asymmetricalSetup
|
|
*
|
|
*/
|
|
controller.get("/ClusterType", function(req, res) {
|
|
// Not yet implemented
|
|
res.json({
|
|
type: "symmetricSetup"
|
|
});
|
|
});
|
|
|
|
/** Get all DBServers
|
|
*
|
|
* Get a list of all running and expected DBServers
|
|
* within the cluster
|
|
*/
|
|
controller.get("/DBServers", function(req, res) {
|
|
var resList = [],
|
|
list = servers.getList(),
|
|
diffList = diff.DBServers(),
|
|
didBeat = beats.didBeat(),
|
|
serving = beats.getServing();
|
|
|
|
_.each(list, function(v, k) {
|
|
v.name = k;
|
|
resList.push(v);
|
|
if (!_.contains(didBeat, k)) {
|
|
v.status = "critical";
|
|
return;
|
|
}
|
|
if (v.role === "primary" && !_.contains(serving, k)) {
|
|
v.status = "warning";
|
|
return;
|
|
}
|
|
v.status = "ok";
|
|
});
|
|
_.each(diffList.missing, function(v) {
|
|
v.status = "missing";
|
|
resList.push(v);
|
|
});
|
|
res.json(resList);
|
|
});
|
|
|
|
controller.get("/Coordinators", function(req, res) {
|
|
var resList = [],
|
|
list = coords.getList(),
|
|
diffList = diff.Coordinators(),
|
|
didBeat = beats.didBeat();
|
|
|
|
_.each(list, function(v, k) {
|
|
v.name = k;
|
|
resList.push(v);
|
|
if (!_.contains(didBeat, k)) {
|
|
v.status = "critical";
|
|
return;
|
|
}
|
|
v.status = "ok";
|
|
});
|
|
_.each(diffList.missing, function(v) {
|
|
v.status = "missing";
|
|
resList.push(v);
|
|
});
|
|
res.json(resList);
|
|
});
|
|
|
|
controller.get("/Databases", function(req, res) {
|
|
var list = dbs.getList();
|
|
res.json(_.map(list, function(d) {
|
|
return {name: d};
|
|
}));
|
|
});
|
|
|
|
controller.get("/:dbname/Collections", function(req, res) {
|
|
var dbname = req.params("dbname"),
|
|
selected = dbs.select(dbname);
|
|
try {
|
|
res.json(_.map(selected.getCollections(),
|
|
function(c) {
|
|
return {name: c};
|
|
})
|
|
);
|
|
} catch(e) {
|
|
res.json([]);
|
|
}
|
|
});
|
|
|
|
controller.get("/:dbname/:colname/Shards", function(req, res) {
|
|
var dbname = req.params("dbname"),
|
|
colname = req.params("colname"),
|
|
selected = dbs.select(dbname).collection(colname);
|
|
res.json(selected.getShardsByServers());
|
|
});
|
|
|
|
controller.get("/:dbname/:colname/Shards/:servername", function(req, res) {
|
|
var dbname = req.params("dbname"),
|
|
colname = req.params("colname"),
|
|
servername = req.params("servername"),
|
|
selected = dbs.select(dbname).collection(colname);
|
|
res.json(_.map(selected.getShardsForServer(servername),
|
|
function(c) {
|
|
return {id: c};
|
|
})
|
|
);
|
|
});
|
|
|
|
} // end isCluster()
|
|
|
|
}());
|