mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of https://github.com/arangodb/arangodb into devel
This commit is contained in:
commit
5566e6bb8f
|
@ -56,6 +56,8 @@ edge attribute `label`.
|
|||
v3.1.9 (XXXX-XX-XX)
|
||||
-------------------
|
||||
|
||||
* ui: fixed re-login issue within a non system db, when tab was closed
|
||||
|
||||
* fixed a race in the VelocyStream Commtask implementation
|
||||
|
||||
* fixed issue #2256
|
||||
|
|
|
@ -650,6 +650,8 @@ trans_ret_t Agent::transact(query_t const& queries) {
|
|||
|
||||
// Non-persistent write to non-persisted key-value store
|
||||
write_ret_t Agent::vacillant(query_t const& query) {
|
||||
write_ret_t ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -304,7 +304,7 @@ bool CleanOutServer::scheduleMoveShards() {
|
|||
// Among those a random destination
|
||||
std::string toServer;
|
||||
if (servers.empty()) {
|
||||
LOG_TOPIC(ERR, Logger::AGENCY)
|
||||
LOG_TOPIC(DEBUG, Logger::AGENCY)
|
||||
<< "No servers remain as target for MoveShard";
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -692,12 +692,16 @@ void Supervision::enforceReplication() {
|
|||
|
||||
// Shrink cluster if applicable, guarded by caller
|
||||
void Supervision::shrinkCluster() {
|
||||
// Get servers from plan
|
||||
std::vector<std::string> availServers;
|
||||
Node::Children const& dbservers = _snapshot("/Plan/DBServers").children();
|
||||
for (auto const& srv : dbservers) {
|
||||
availServers.push_back(srv.first);
|
||||
|
||||
auto const& todo = _snapshot(toDoPrefix).children();
|
||||
auto const& pending = _snapshot(pendingPrefix).children();
|
||||
|
||||
if (!todo.empty() || !pending.empty()) { // This is low priority
|
||||
return;
|
||||
}
|
||||
|
||||
// Get servers from plan
|
||||
std::vector<std::string> availServers = Job::availableServers(_snapshot);
|
||||
|
||||
size_t targetNumDBServers;
|
||||
try {
|
||||
|
@ -708,50 +712,6 @@ void Supervision::shrinkCluster() {
|
|||
return;
|
||||
}
|
||||
|
||||
// If there are any cleanOutServer jobs todo or pending do nothing
|
||||
Node::Children const& todos = _snapshot(toDoPrefix).children();
|
||||
Node::Children const& pends = _snapshot(pendingPrefix).children();
|
||||
|
||||
for (auto const& job : todos) {
|
||||
try {
|
||||
if ((*job.second)("type").getString() == "cleanOutServer") {
|
||||
return;
|
||||
}
|
||||
if ((*job.second)("type").getString() == "removeServer") {
|
||||
return;
|
||||
}
|
||||
} catch (std::exception const& e) {
|
||||
LOG_TOPIC(WARN, Logger::AGENCY) << "Failed to get job type of job "
|
||||
<< job.first << ": " << e.what();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const& job : pends) {
|
||||
try {
|
||||
if ((*job.second)("type").getString() == "cleanOutServer") {
|
||||
return;
|
||||
}
|
||||
if ((*job.second)("type").getString() == "removeServer") {
|
||||
return;
|
||||
}
|
||||
} catch (std::exception const& e) {
|
||||
LOG_TOPIC(WARN, Logger::AGENCY) << "Failed to get job type of job "
|
||||
<< job.first << ": " << e.what();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove cleaned from ist
|
||||
if (_snapshot.exists("/Target/CleanedServers").size() == 2) {
|
||||
for (auto const& srv :
|
||||
VPackArrayIterator(_snapshot("/Target/CleanedServers").slice())) {
|
||||
availServers.erase(std::remove(availServers.begin(), availServers.end(),
|
||||
srv.copyString()),
|
||||
availServers.end());
|
||||
}
|
||||
}
|
||||
|
||||
// Only if number of servers in target is smaller than the available
|
||||
if (targetNumDBServers < availServers.size()) {
|
||||
// Minimum 1 DB server must remain
|
||||
|
|
|
@ -48,8 +48,13 @@
|
|||
return localStorage.getItem('jwt');
|
||||
},
|
||||
|
||||
setCurrentJwt: function (jwt) {
|
||||
getCurrentJwtUsername: function () {
|
||||
return localStorage.getItem('jwtUser');
|
||||
},
|
||||
|
||||
setCurrentJwt: function (jwt, username) {
|
||||
localStorage.setItem('jwt', jwt);
|
||||
localStorage.setItem('jwtUser', username);
|
||||
},
|
||||
|
||||
lastNotificationMessage: null,
|
||||
|
|
|
@ -51,9 +51,8 @@ window.ArangoUsers = Backbone.Collection.extend({
|
|||
dataType: 'json'
|
||||
}).success(
|
||||
function (data) {
|
||||
arangoHelper.setCurrentJwt(data.jwt);
|
||||
|
||||
var jwtParts = data.jwt.split('.');
|
||||
|
||||
if (!jwtParts[1]) {
|
||||
throw new Error('Invalid JWT');
|
||||
}
|
||||
|
@ -61,14 +60,21 @@ window.ArangoUsers = Backbone.Collection.extend({
|
|||
if (!window.atob) {
|
||||
throw new Error('base64 support missing in browser');
|
||||
}
|
||||
var payload = JSON.parse(atob(jwtParts[1]));
|
||||
|
||||
var payload = JSON.parse(atob(jwtParts[1]));
|
||||
self.activeUser = payload.preferred_username;
|
||||
|
||||
if (self.activeUser === undefined) {
|
||||
arangoHelper.setCurrentJwt(data.jwt, null);
|
||||
} else {
|
||||
arangoHelper.setCurrentJwt(data.jwt, self.activeUser);
|
||||
}
|
||||
|
||||
callback(false, self.activeUser);
|
||||
}
|
||||
).error(
|
||||
function () {
|
||||
arangoHelper.setCurrentJwt(null);
|
||||
arangoHelper.setCurrentJwt(null, null);
|
||||
self.activeUser = null;
|
||||
callback(true, null);
|
||||
}
|
||||
|
|
|
@ -23,17 +23,17 @@
|
|||
|
||||
render: function (loggedIn) {
|
||||
var self = this;
|
||||
|
||||
$(this.el).html(this.template.render({}));
|
||||
$(this.el2).hide();
|
||||
$(this.el3).hide();
|
||||
|
||||
if (frontendConfig.authenticationEnabled && loggedIn !== true) {
|
||||
window.setTimeout(function () {
|
||||
$('#loginUsername').focus();
|
||||
}, 300);
|
||||
} else {
|
||||
var url = arangoHelper.databaseUrl('/_api/database/user');
|
||||
var continueRender = function (user, errCallback) {
|
||||
var url;
|
||||
if (!user) {
|
||||
url = arangoHelper.databaseUrl('/_api/database/user');
|
||||
} else {
|
||||
url = arangoHelper.databaseUrl('/_api/user/' + encodeURIComponent(user) + '/database', '_system');
|
||||
}
|
||||
|
||||
if (frontendConfig.authenticationEnabled === false) {
|
||||
$('#logout').hide();
|
||||
|
@ -47,17 +47,45 @@
|
|||
// enable db select and login button
|
||||
$('#loginDatabase').html('');
|
||||
// fill select with allowed dbs
|
||||
|
||||
_.each(permissions.result, function (db) {
|
||||
$('#loginDatabase').append(
|
||||
'<option>' + db + '</option>'
|
||||
);
|
||||
_.each(permissions.result, function (rule, db) {
|
||||
if (errCallback) {
|
||||
$('#loginDatabase').append(
|
||||
'<option>' + db + '</option>'
|
||||
);
|
||||
} else {
|
||||
$('#loginDatabase').append(
|
||||
'<option>' + rule + '</option>'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
self.renderDBS();
|
||||
}).error(function () {
|
||||
console.log('could not fetch user db data');
|
||||
if (errCallback) {
|
||||
errCallback();
|
||||
} else {
|
||||
console.log('could not fetch user db data');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (frontendConfig.authenticationEnabled && loggedIn !== true) {
|
||||
var usr = arangoHelper.getCurrentJwtUsername();
|
||||
if (usr !== null && usr !== 'undefined' && usr !== undefined) {
|
||||
// try if existent jwt is valid
|
||||
var errCallback = function () {
|
||||
window.setTimeout(function () {
|
||||
$('#loginUsername').focus();
|
||||
}, 300);
|
||||
};
|
||||
continueRender(arangoHelper.getCurrentJwtUsername(), errCallback);
|
||||
} else {
|
||||
window.setTimeout(function () {
|
||||
$('#loginUsername').focus();
|
||||
}, 300);
|
||||
}
|
||||
} else {
|
||||
continueRender();
|
||||
}
|
||||
|
||||
$('.bodyWrapper').show();
|
||||
|
@ -132,44 +160,49 @@
|
|||
'<option>_system</option>'
|
||||
);
|
||||
} else {
|
||||
var url = arangoHelper.databaseUrl('/_api/user/' + encodeURIComponent(username) + '/database', '_system');
|
||||
|
||||
if (frontendConfig.authenticationEnabled === false) {
|
||||
url = arangoHelper.databaseUrl('/_api/database/user');
|
||||
}
|
||||
|
||||
$('.wrong-credentials').hide();
|
||||
self.loggedIn = true;
|
||||
|
||||
// get list of allowed dbs
|
||||
$.ajax(url).success(function (permissions) {
|
||||
// HANDLE PERMISSIONS
|
||||
_.each(permissions.result, function (value, key) {
|
||||
if (value !== 'rw') {
|
||||
delete permissions.result[key];
|
||||
}
|
||||
});
|
||||
|
||||
$('#loginForm').hide();
|
||||
$('.login-window #databases').show();
|
||||
|
||||
// enable db select and login button
|
||||
$('#loginDatabase').html('');
|
||||
|
||||
// fill select with allowed dbs
|
||||
_.each(permissions.result, function (db, key) {
|
||||
$('#loginDatabase').append(
|
||||
'<option>' + key + '</option>'
|
||||
);
|
||||
});
|
||||
|
||||
self.renderDBS();
|
||||
}).error(function () {
|
||||
$('.wrong-credentials').show();
|
||||
});
|
||||
self.renderDBSelection(username);
|
||||
}
|
||||
},
|
||||
|
||||
renderDBSelection: function (username) {
|
||||
var self = this;
|
||||
var url = arangoHelper.databaseUrl('/_api/user/' + encodeURIComponent(username) + '/database', '_system');
|
||||
|
||||
if (frontendConfig.authenticationEnabled === false) {
|
||||
url = arangoHelper.databaseUrl('/_api/database/user');
|
||||
}
|
||||
|
||||
$('.wrong-credentials').hide();
|
||||
self.loggedIn = true;
|
||||
|
||||
// get list of allowed dbs
|
||||
$.ajax(url).success(function (permissions) {
|
||||
// HANDLE PERMISSIONS
|
||||
_.each(permissions.result, function (value, key) {
|
||||
if (value !== 'rw') {
|
||||
delete permissions.result[key];
|
||||
}
|
||||
});
|
||||
|
||||
$('#loginForm').hide();
|
||||
$('.login-window #databases').show();
|
||||
|
||||
// enable db select and login button
|
||||
$('#loginDatabase').html('');
|
||||
|
||||
// fill select with allowed dbs
|
||||
_.each(permissions.result, function (db, key) {
|
||||
$('#loginDatabase').append(
|
||||
'<option>' + key + '</option>'
|
||||
);
|
||||
});
|
||||
|
||||
self.renderDBS();
|
||||
}).error(function () {
|
||||
$('.wrong-credentials').show();
|
||||
});
|
||||
},
|
||||
|
||||
renderDBS: function () {
|
||||
if ($('#loginDatabase').children().length === 0) {
|
||||
$('#dbForm').remove();
|
||||
|
|
|
@ -46,15 +46,32 @@ function agencyTestSuite () {
|
|||
var agencyServers = instanceInfo.arangods.map(arangod => {
|
||||
return arangod.url;
|
||||
});
|
||||
var whoseTurn = 0;
|
||||
var agencyLeader = agencyServers[0];
|
||||
var request = require("@arangodb/request");
|
||||
|
||||
function accessAgency(api, list) {
|
||||
// We simply try all agency servers in turn until one gives us an HTTP
|
||||
// response:
|
||||
var res = request({url: agencyServers[whoseTurn] + "/_api/agency/" + api, method: "POST",
|
||||
followRedirects: true, body: JSON.stringify(list),
|
||||
headers: {"Content-Type": "application/json"}});
|
||||
var res;
|
||||
while (true) {
|
||||
res = request({url: agencyLeader + "/_api/agency/" + api,
|
||||
method: "POST", followRedirect: false,
|
||||
body: JSON.stringify(list),
|
||||
headers: {"Content-Type": "application/json"}});
|
||||
if(res.statusCode === 307) {
|
||||
agencyLeader = res.headers.location;
|
||||
var l = 0;
|
||||
for (var i = 0; i < 3; ++i) {
|
||||
l = agencyLeader.indexOf('/', l+1);
|
||||
}
|
||||
agencyLeader = agencyLeader.substring(0,l);
|
||||
require('internal').print('Redirected to ' + agencyLeader);
|
||||
} else if (res.statusCode !== 503) {
|
||||
break;
|
||||
} else {
|
||||
require('internal').print('Waiting for leader ... ');
|
||||
}
|
||||
}
|
||||
res.bodyParsed = JSON.parse(res.body);
|
||||
return res;
|
||||
}
|
||||
|
@ -98,17 +115,7 @@ function agencyTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testStartup : function () {
|
||||
while (true) {
|
||||
var res = request({
|
||||
url: agencyServers[whoseTurn] + "/_api/agency/config",
|
||||
method: "GET"
|
||||
});
|
||||
res.bodyParsed = JSON.parse(res.body);
|
||||
if (res.bodyParsed.leaderId !== "") {
|
||||
break;
|
||||
}
|
||||
wait(0.1);
|
||||
}
|
||||
assertEqual(readAndCheck([["/"]]), [{}]);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -78,7 +78,8 @@ function clusterRequest(req) {
|
|||
}, req);
|
||||
delete pathObj.auth;
|
||||
}
|
||||
let query = typeof req.qs === 'string' ? req.qs : querystringify(req.qs, req.useQuerystring);
|
||||
let query = typeof req.qs === 'string' ?
|
||||
req.qs : querystringify(req.qs, req.useQuerystring);
|
||||
if (query) {
|
||||
pathObj.search = query;
|
||||
}
|
||||
|
|
|
@ -116,6 +116,8 @@ function MovingShardsSuite () {
|
|||
return body;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test whether or not a server is clean
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -127,56 +129,60 @@ function MovingShardsSuite () {
|
|||
if (toCollNr === undefined) {
|
||||
toCollNr = c.length - 1;
|
||||
}
|
||||
var count;
|
||||
var ok;
|
||||
for (var i = fromCollNr; i <= toCollNr; ++i) {
|
||||
count = 100;
|
||||
ok = false;
|
||||
while (--count > 0) {
|
||||
wait(1.0);
|
||||
global.ArangoClusterInfo.flush();
|
||||
var servers = findCollectionServers("_system", c[i].name());
|
||||
console.info("Seeing servers:", i, c[i].name(), servers);
|
||||
if (servers.indexOf(id) === -1) {
|
||||
// Now check current as well:
|
||||
var collInfo = global.ArangoClusterInfo.getCollectionInfo(
|
||||
"_system", c[i].name());
|
||||
var shards = collInfo.shards;
|
||||
var collInfoCurr = Object.keys(shards).map(s =>
|
||||
global.ArangoClusterInfo.getCollectionInfoCurrent(
|
||||
"_system", c[i].name(), s).servers);
|
||||
var idxs = collInfoCurr.map(l => l.indexOf(id));
|
||||
ok = true;
|
||||
for (var j = 0; j < idxs.length; j++) {
|
||||
if (idxs[j] !== -1) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var count = 100;
|
||||
var ok = false;
|
||||
|
||||
if (checkList) {
|
||||
|
||||
// Wait until the server appears in the list of cleanedOutServers:
|
||||
count = 100;
|
||||
|
||||
while (--count > 0) {
|
||||
var obj = getCleanedOutServers();
|
||||
if (obj.cleanedServers.indexOf(id) >= 0) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
wait(1.0);
|
||||
}
|
||||
if (count <= 0) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (var i = fromCollNr; i <= toCollNr; ++i) {
|
||||
|
||||
while (--count > 0) {
|
||||
wait(1.0);
|
||||
global.ArangoClusterInfo.flush();
|
||||
var servers = findCollectionServers("_system", c[i].name());
|
||||
console.info("Seeing servers:", i, c[i].name(), servers);
|
||||
if (servers.indexOf(id) === -1) {
|
||||
// Now check current as well:
|
||||
var collInfo =
|
||||
global.ArangoClusterInfo.getCollectionInfo("_system", c[i].name());
|
||||
var shards = collInfo.shards;
|
||||
var collInfoCurr =
|
||||
Object.keys(shards).map(
|
||||
s => global.ArangoClusterInfo.getCollectionInfoCurrent(
|
||||
"_system", c[i].name(), s).servers);
|
||||
var idxs = collInfoCurr.map(l => l.indexOf(id));
|
||||
ok = true;
|
||||
for (var j = 0; j < idxs.length; j++) {
|
||||
if (idxs[j] !== -1) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -379,7 +385,7 @@ function MovingShardsSuite () {
|
|||
|
||||
testShrinkNoReplication : function() {
|
||||
assertTrue(waitForSynchronousReplication("_system"));
|
||||
var _dbservers = dbservers;
|
||||
var _dbservers = global.ArangoClusterInfo.getDBServers();
|
||||
_dbservers.sort();
|
||||
assertTrue(shrinkCluster(4));
|
||||
assertTrue(testServerEmpty(_dbservers[4], true));
|
||||
|
|
Loading…
Reference in New Issue