1
0
Fork 0

Change names in files.

This commit is contained in:
Max Neunhoeffer 2014-02-06 09:14:16 +01:00
parent 00b03f8bf1
commit d6a5825fe4
2 changed files with 208 additions and 78 deletions

View File

@ -2,9 +2,9 @@
/*global module, require, exports, ArangoAgency, SYS_TEST_PORT */ /*global module, require, exports, ArangoAgency, SYS_TEST_PORT */
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief Cluster startup functionality by dispatchers /// @brief Cluster kickstarting functionality using dispatchers
/// ///
/// @file js/server/modules/org/arangodb/cluster/dispatcher.js /// @file js/server/modules/org/arangodb/cluster/kickstarter.js
/// ///
/// DISCLAIMER /// DISCLAIMER
/// ///
@ -29,7 +29,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- Dispatcher functionality // --SECTION-- Kickstarter functionality
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
var download = require("internal").download; var download = require("internal").download;
@ -37,6 +37,8 @@ var executeExternal = require("internal").executeExternal;
var fs = require("fs"); var fs = require("fs");
var wait = require("internal").wait; var wait = require("internal").wait;
var exchangePort = require("org/arangodb/cluster/planner").exchangePort;
var print = require("internal").print; var print = require("internal").print;
var actions = {}; var actions = {};
@ -58,17 +60,32 @@ function getAddr (endpoint) {
return addrPort; return addrPort;
} }
function getPort (endpoint) {
var pos = endpoint.lastIndexOf(":");
if (pos !== -1) {
return parseInt(endpoint.substr(pos+1),10);
}
return 8529;
}
actions.startAgent = function (dispatchers, cmd) { actions.startAgent = function (dispatchers, cmd) {
var agentDataDir = fs.join(cmd.dataPath, var agentDataDir = fs.join(cmd.dataPath,
"agent"+cmd.agencyPrefix+cmd.extPort); "agent"+cmd.agencyPrefix+cmd.extPort);
if (fs.exists(agentDataDir)) { if (fs.exists(agentDataDir)) {
fs.removeDirectoryRecursive(agentDataDir,true); fs.removeDirectoryRecursive(agentDataDir,true);
} }
// FIXME: could distinguish cases and sometimes only bind to 127.0.0.1???
var args = ["-data-dir", agentDataDir, var args = ["-data-dir", agentDataDir,
"-name", "agent"+cmd.agencyPrefix+cmd.extPort, "-name", "agent"+cmd.agencyPrefix+cmd.extPort,
"-addr", "0.0.0.0:"+cmd.extPort, "-bind-addr", (cmd.onlyLocalhost ? "127.0.0.1:"
"-peer-addr", "0.0.0.0:"+cmd.intPort]; : "0.0.0.0:")+cmd.extPort,
"-addr", getAddrPort(
exchangePort(dispatchers[cmd.dispatcher].endpoint,
cmd.extPort)),
"-peer-bind-addr", (cmd.onlyLocalhost ? "127.0.0.1:"
: "0.0.0.0:")+cmd.intPort,
"-peer-addr", getAddrPort(
exchangePort(dispatchers[cmd.dispatcher].endpoint,
cmd.intPort)) ];
var i; var i;
if (cmd.peers.length > 0) { if (cmd.peers.length > 0) {
args.push("-peers"); args.push("-peers");
@ -78,33 +95,157 @@ actions.startAgent = function (dispatchers, cmd) {
} }
args.push(getAddrPort(cmd.peers[0])); args.push(getAddrPort(cmd.peers[0]));
} }
print("Starting agent: command: ",cmd.agentPath);
for (i = 0;i < args.length;i++) {
print(args[i]);
}
var pid = executeExternal(cmd.agentPath, args); var pid = executeExternal(cmd.agentPath, args);
wait(3); // Wait a bit, such that the next one will be able to connect var res;
return {"error":false, "pid": pid}; while (true) {
wait(0.5); // Wait a bit to give it time to startup
res = download("http://localhost:"+cmd.extPort+"/v2/keys/");
if (res.code === 200) {
return {"error":false, "isAgent": true, "pid": pid};
}
}
}; };
function encode (st) {
var st2 = "";
var i;
for (i = 0; i < st.length; i++) {
if (st[i] === "_") {
st2 += "@U";
}
else if (st[i] === "@") {
st2 += "@@";
}
else {
st2 += st[i];
}
}
return encodeURIComponent(st2);
}
function sendToAgency (agencyURL, path, obj) {
var res;
var body;
print("Sending ",path," to agency...");
if (typeof obj === "string") {
var count = 0;
while (count++ <= 2) {
body = "value="+encodeURIComponent(obj);
//print("sending:",agencyURL+path,"\nwith body",body);
res = download(agencyURL+path,body,
{"method":"PUT", "followRedirects": true,
"headers": { "Content-Type": "application/x-www-form-urlencoded"}});
//print("Code ", res.code);
if (res.code === 201) {
return true;
}
}
return res;
}
if (typeof obj !== "object") {
return "Strange object found: not a string or object";
}
var keys = Object.keys(obj);
var i;
if (keys.length !== 0) {
for (i = 0; i < keys.length; i++) {
res = sendToAgency (agencyURL, path+"/"+encode(keys[i]), obj[keys[i]]);
if (res !== true) {
return res;
}
}
return true;
}
// Create a directory
var count2 = 0;
while (count2++ <= 2) {
body = "dir=true";
res = download(agencyURL+path,body,
{"method": "PUT", "followRedirects": true,
"headers": { "Content-Type": "application/x-www-form-urlencoded"}});
if (res.code === 201) {
return true;
}
}
return res;
}
actions.sendConfiguration = function (dispatchers, cmd) { actions.sendConfiguration = function (dispatchers, cmd) {
print("Sending configuration..."); var url = "http://"+getAddrPort(cmd.agency.endpoints[0])+"/v2/keys";
return {"error":false}; var res = sendToAgency(url, "", cmd.data);
if (res === true) {
return {"error":false, "isAgencyConfiguration": true};
}
return {"error":true, "isAgencyConfiguration": true, "suberror": res};
}; };
actions.startLauncher = function (dispatchers, cmd) { actions.startLauncher = function (dispatchers, cmd) {
print("Starting launcher..."); var url = "http://"+getAddrPort(cmd.agency.endpoints[0])+"/v2/keys/"+
return {"error":false}; cmd.agency.agencyPrefix+"/";
print("Downloading ",url+"Launchers/"+cmd.name);
var res = download(url+"Launchers/"+cmd.name,"",{method:"GET",
followRedirects:true});
if (res.code !== 200) {
return {"error": true, "isStartLauncher": true, "suberror": res};
}
var body = JSON.parse( res.body );
var info = JSON.parse(body.node.value);
var id,ep,args,pids,port;
print("Starting servers...");
var i;
print(info);
var servers = info.DBservers.concat(info.Coordinators);
pids = [];
for (i = 0; i < servers.length; i++) {
id = servers[i];
print("Downloading ",url+"Target/MapIDToEndpoint/"+id);
res = download(url+"Target/MapIDToEndpoint/"+id);
if (res.code !== 200) {
return {"error": true, "pids": pids,
"isStartLauncher": true, "suberror": res};
}
print("Starting server ",id);
body = JSON.parse(res.body);
ep = JSON.parse(body.node.value);
port = getPort(ep);
args = ["--cluster.my-id", id,
"--cluster.agency-prefix", cmd.agency.agencyPrefix,
"--cluster.agency-endpoint", cmd.agency.endpoints[0],
"--server.endpoint"];
if (cmd.onlyLocalhost) {
args.push("tcp://127.0.0.1:"+port);
}
else {
args.push("tcp://0.0.0.0:"+port);
}
args.push("--log.file");
var logfile = fs.join(cmd.dataPath,"log-"+cmd.agency.agencyPrefix+"-"+id);
if (fs.exists(logfile)) {
fs.remove(logfile);
}
args.push(logfile);
var datadir = fs.join(cmd.dataPath,"data-"+cmd.agency.agencyPrefix+"-"+id);
if (fs.exists(datadir)) {
fs.removeDirectoryRecursive(datadir,true);
}
fs.makeDirectory(datadir);
args.push(datadir);
pids.push(executeExternal(cmd.arangodPath, args));
}
return {"error": false, "pids": pids};
}; };
function dispatch (startupPlan) { function Kickstarter (startupPlan) {
var myname; this.startupPlan = startupPlan;
if (!startupPlan.hasOwnProperty("myname")) { if (!startupPlan.hasOwnProperty("myname")) {
myname = "me"; startupPlan.myname = "me";
}
else {
myname = startupPlan.myname;
} }
}
Kickstarter.prototype.launch = function () {
var startupPlan = this.startupPlan;
var myname = startupPlan.myname;
var dispatchers = startupPlan.dispatchers; var dispatchers = startupPlan.dispatchers;
var cmds = startupPlan.commands; var cmds = startupPlan.commands;
var results = []; var results = [];
@ -143,14 +284,14 @@ function dispatch (startupPlan) {
} }
} }
if (error) { if (error) {
return {"error": true, "errorMessage": "some error during dispatch", return {"error": true, "errorMessage": "some error during launch",
"results": results}; "results": results};
} }
return {"error": false, "errorMessage": "none", return {"error": false, "errorMessage": "none",
"results": results}; "results": results};
} };
exports.dispatch = dispatch; exports.Kickstarter = Kickstarter;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE // --SECTION-- END-OF-FILE

View File

@ -2,9 +2,9 @@
/*global module, require, exports, ArangoAgency, SYS_TEST_PORT */ /*global module, require, exports, ArangoAgency, SYS_TEST_PORT */
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief Cluster kickstart functionality /// @brief Cluster planning functionality
/// ///
/// @file js/server/modules/org/arangodb/cluster/kickstarter.js /// @file js/server/modules/org/arangodb/cluster/planner.js
/// ///
/// DISCLAIMER /// DISCLAIMER
/// ///
@ -29,7 +29,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- Kickstarter functionality // --SECTION-- Planner functionality
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// possible config attributes (for defaults see below): // possible config attributes (for defaults see below):
@ -46,8 +46,8 @@
// all the data directories of agents or servers // all the data directories of agents or servers
// live, this can be relative or even empty, which // live, this can be relative or even empty, which
// is equivalent to "./", it will be made into // is equivalent to "./", it will be made into
// an absolute path by the kickstarter, using // an absolute path by the planner, using
// the current directory when the kickstarter // the current directory when the planner
// runs, use with caution! // runs, use with caution!
// .logPath path where the log files are written, same // .logPath path where the log files are written, same
// comments as for .dataPath apply // comments as for .dataPath apply
@ -59,15 +59,15 @@
// .arangodPath path to the arangod executable on // .arangodPath path to the arangod executable on
// all machines in the cluster, will be made // all machines in the cluster, will be made
// absolute (if it is not already absolute) // absolute (if it is not already absolute)
// in the process running the kickstarter // in the process running the planner
// .agentPath path to the agent executable on // .agentPath path to the agent executable on
// all machines in the cluster, will be made // all machines in the cluster, will be made
// absolute (if it is not already absolute) // absolute (if it is not already absolute)
// in the process running the kickstarter // in the process running the planner
// some port lists: // some port lists:
// for these the following rules apply: // for these the following rules apply:
// every list overwrites the default list // every list overwrites the default list
// when running out of numbers the kickstarter increments the last one // when running out of numbers the planner increments the last one
// used by one for every port needed // used by one for every port needed
// //
// .agentExtPorts a list port numbers to use for the // .agentExtPorts a list port numbers to use for the
@ -79,11 +79,10 @@
// //
var fs = require("fs"); var fs = require("fs");
var dispatch = require("org/arangodb/cluster/dispatcher").dispatch;
// Our default configurations: // Our default configurations:
var KickstarterLocalDefaults = { var PlannerLocalDefaults = {
"agencyPrefix" : "meier", "agencyPrefix" : "meier",
"numberOfAgents" : 3, "numberOfAgents" : 3,
"numberOfDBservers" : 2, "numberOfDBservers" : 2,
@ -105,7 +104,7 @@ var KickstarterLocalDefaults = {
"avoidPorts": {}}} "avoidPorts": {}}}
}; };
var KickstarterDistributedDefaults = { var PlannerDistributedDefaults = {
"agencyPrefix" : "mueller", "agencyPrefix" : "mueller",
"numberOfAgents" : 3, "numberOfAgents" : 3,
"numberOfDBservers" : 3, "numberOfDBservers" : 3,
@ -238,22 +237,22 @@ function fillConfigWithDefaults (config, defaultConfig) {
} }
} }
// Our Kickstarter class: // Our Planner class:
function Kickstarter (userConfig) { function Planner (userConfig) {
"use strict"; "use strict";
if (typeof userConfig !== "object") { if (typeof userConfig !== "object") {
throw "userConfig must be an object"; throw "userConfig must be an object";
} }
var defaultConfig = userConfig.defaultConfig; var defaultConfig = userConfig.defaultConfig;
if (defaultConfig === undefined) { if (defaultConfig === undefined) {
defaultConfig = KickstarterLocalDefaults; defaultConfig = PlannerLocalDefaults;
} }
if (defaultConfig === "local") { if (defaultConfig === "local") {
defaultConfig = KickstarterLocalDefaults; defaultConfig = PlannerLocalDefaults;
} }
else if (defaultConfig === "distributed") { else if (defaultConfig === "distributed") {
defaultConfig = KickstarterDistributedDefaults; defaultConfig = PlannerDistributedDefaults;
} }
this.config = copy(userConfig); this.config = copy(userConfig);
fillConfigWithDefaults(this.config, defaultConfig); fillConfigWithDefaults(this.config, defaultConfig);
@ -267,7 +266,7 @@ function Kickstarter (userConfig) {
this.makePlan(); this.makePlan();
} }
Kickstarter.prototype.makePlan = function() { Planner.prototype.makePlan = function() {
// This sets up the plan for the cluster according to the options // This sets up the plan for the cluster according to the options
var config = this.config; var config = this.config;
@ -277,6 +276,15 @@ Kickstarter.prototype.makePlan = function() {
if (Object.keys(dispatchers).length === 0) { if (Object.keys(dispatchers).length === 0) {
dispatchers.me = { "id": "me", "endpoint": "tcp://localhost:", dispatchers.me = { "id": "me", "endpoint": "tcp://localhost:",
"avoidPorts": {} }; "avoidPorts": {} };
config.onlyLocalhost = true;
}
else {
config.onlyLocalhost = false;
var k = Object.keys(dispatchers);
if (k.length === 1 &&
dispatchers[k[0]].endpoint.substr(0,16) === "tcp://localhost:") {
config.onlyLocalhost = true;
}
} }
var dispList = Object.keys(dispatchers); var dispList = Object.keys(dispatchers);
@ -364,30 +372,18 @@ Kickstarter.prototype.makePlan = function() {
var s; var s;
for (i = 0; i < DBservers.length; i++) { for (i = 0; i < DBservers.length; i++) {
s = DBservers[i]; s = DBservers[i];
if (dispatchers[s.dispatcher].endpoint === "tcp://localhost:") { dbs[s.id] = map[s.id]
dbs[s.id] = map[s.id] = '"'+exchangePort(dispatchers[s.dispatcher].endpoint,s.port)+'"';
= '"'+exchangePort("tcp://127.0.0.1:0",s.port)+'"';
}
else {
dbs[s.id] = map[s.id]
= '"'+exchangePort(dispatchers[s.dispatcher].endpoint,s.port)+'"';
}
launchers[s.dispatcher].DBservers.push(s.id); launchers[s.dispatcher].DBservers.push(s.id);
} }
var coo = tmp.Coordinators = {}; var coo = tmp.Coordinators = {};
for (i = 0; i < coordinators.length; i++) { for (i = 0; i < coordinators.length; i++) {
s = coordinators[i]; s = coordinators[i];
if (dispatchers[s.dispatcher].endpoint === "tcp://localhost:") { coo[s.id] = map[s.id]
coo[s.id] = map[s.id] = '"'+exchangePort(dispatchers[s.dispatcher].endpoint,s.port)+'"';
= '"'+exchangePort("tcp://127.0.0.1:0",s.port)+'"';
}
else {
coo[s.id] = map[s.id]
= '"'+exchangePort(dispatchers[s.dispatcher].endpoint,s.port)+'"';
}
launchers[s.dispatcher].Coordinators.push(s.id); launchers[s.dispatcher].Coordinators.push(s.id);
} }
tmp.Databases = { "_system" : {} }; tmp.Databases = { "_system" : '{"name":"_system"}' };
tmp.Collections = { "_system" : {} }; tmp.Collections = { "_system" : {} };
// Now Plan: // Now Plan:
@ -429,14 +425,15 @@ Kickstarter.prototype.makePlan = function() {
"agencyPrefix": config.agencyPrefix, "agencyPrefix": config.agencyPrefix,
"dataPath": config.dataPath, "dataPath": config.dataPath,
"logPath": config.logPath, "logPath": config.logPath,
"agentPath": config.agentPath }; "agentPath": config.agentPath,
"onlyLocalhost": config.onlyLocalhost };
for (j = 0; j < i; j++) { for (j = 0; j < i; j++) {
var ep = dispatchers[agents[j].dispatcher].endpoint; var ep = dispatchers[agents[j].dispatcher].endpoint;
tmp2.peers.push( exchangePort( ep, agents[j].intPort ) ); tmp2.peers.push( exchangePort( ep, agents[j].intPort ) );
} }
tmp.push(tmp2); tmp.push(tmp2);
} }
var agencyPos = { "prefix": config.agencyPrefix, var agencyPos = { "agencyPrefix": config.agencyPrefix,
"endpoints": agents.map(function(a) { "endpoints": agents.map(function(a) {
return exchangePort(dispatchers[a.dispatcher].endpoint, return exchangePort(dispatchers[a.dispatcher].endpoint,
a.extPort);}) }; a.extPort);}) };
@ -449,48 +446,40 @@ Kickstarter.prototype.makePlan = function() {
"dataPath": config.dataPath, "dataPath": config.dataPath,
"logPath": config.logPath, "logPath": config.logPath,
"arangodPath": config.arangodPath, "arangodPath": config.arangodPath,
"onlyLocalhost": config.onlyLocalhost,
"agency": copy(agencyPos) } ); "agency": copy(agencyPos) } );
} }
this.myname = "me"; this.myname = "me";
}; };
Kickstarter.prototype.checkDispatchers = function() { Planner.prototype.checkDispatchers = function() {
// Checks that all dispatchers are active, if none is configured, // Checks that all dispatchers are active, if none is configured,
// a local one is started. // a local one is started.
throw "not yet implemented"; throw "not yet implemented";
}; };
Kickstarter.prototype.getStartupProgram = function() { Planner.prototype.getStartupProgram = function() {
// Computes the dispatcher commands and returns them as JSON // Computes the dispatcher commands and returns them as JSON
return { "dispatchers": this.dispatchers, return { "dispatchers": this.dispatchers,
"commands": this.commands }; "commands": this.commands };
}; };
Kickstarter.prototype.launch = function() { Planner.prototype.launch = function() {
// Starts the cluster according to startup plan // Starts the cluster according to startup plan
dispatch(this); //dispatch(this);
}; };
Kickstarter.prototype.shutdown = function() { Planner.prototype.shutdown = function() {
throw "not yet implemented"; throw "not yet implemented";
}; };
Kickstarter.prototype.isHealthy = function() { Planner.prototype.isHealthy = function() {
throw "not yet implemented"; throw "not yet implemented";
}; };
exports.PortFinder = PortFinder; exports.PortFinder = PortFinder;
exports.Kickstarter = Kickstarter; exports.Planner = Planner;
exports.exchangePort = exchangePort;
// TODO for kickstarting:
//
// * finden des Pfads zum eigenen Executable in JS
// * etcd in distribution
// * JS function zum Ausführen von Startup-Programmen (lokal u. delegation)
// * REST interface zum Ausführen von Startup-Programmen
// * arangod-Rolle "Launcher" per Kommandozeile
// * REST interface to SYS_TEST_PORT, ev. mit auth
// * Dokumentation
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE // --SECTION-- END-OF-FILE