mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-24 06:05:53 -05:00
Server memory instrumentation and fixes.
This commit is contained in:
parent
aa35384810
commit
ff663b630d
2139467
heapdump-1982251193.610099.heapsnapshot
Normal file
2139467
heapdump-1982251193.610099.heapsnapshot
Normal file
File diff suppressed because it is too large
Load Diff
10
meshagent.js
10
meshagent.js
@ -714,6 +714,16 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
||||
obj.close(1);
|
||||
}
|
||||
|
||||
obj.sendUpdatedIntelAmtPolicy = function() {
|
||||
var mesh = obj.parent.meshes[obj.dbMeshKey];
|
||||
if (mesh != null) {
|
||||
// Send Intel AMT policy
|
||||
var amtPolicy = null;
|
||||
if (mesh.amt != null) { amtPolicy = mesh.amt; }
|
||||
obj.send(JSON.stringify({ action: 'amtPolicy', amtPolicy: amtPolicy }));
|
||||
}
|
||||
}
|
||||
|
||||
function agentCoreIsStable() {
|
||||
// Check that the mesh exists
|
||||
var mesh = obj.parent.meshes[obj.dbMeshKey];
|
||||
|
@ -96,7 +96,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
try { require('./pass').hash('test', function () { }); } catch (e) { console.log('Old version of node, must upgrade.'); return; } // TODO: Not sure if this test works or not.
|
||||
|
||||
// Check for invalid arguments
|
||||
var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpsdebug', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbexportmin', 'dbimport', 'dbmerge', 'dbencryptkey', 'selfupdate', 'tlsoffload', 'userallowedip', 'userblockedip', 'swarmallowedip', 'agentallowedip', 'agentblockedip', 'fastcert', 'swarmport', 'swarmdebug', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore', 'dblistconfigfiles', 'dbshowconfigfile', 'dbpushconfigfiles', 'dbpullconfigfiles', 'dbdeleteconfigfiles', 'configkey', 'loadconfigfromdb', 'npmpath'];
|
||||
var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpsdebug', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbexportmin', 'dbimport', 'dbmerge', 'dbencryptkey', 'selfupdate', 'tlsoffload', 'userallowedip', 'userblockedip', 'swarmallowedip', 'agentallowedip', 'agentblockedip', 'fastcert', 'swarmport', 'swarmdebug', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore', 'dblistconfigfiles', 'dbshowconfigfile', 'dbpushconfigfiles', 'dbpullconfigfiles', 'dbdeleteconfigfiles', 'configkey', 'loadconfigfromdb', 'npmpath', 'memorytracking'];
|
||||
for (var arg in obj.args) { obj.args[arg.toLocaleLowerCase()] = obj.args[arg]; if (validArguments.indexOf(arg.toLocaleLowerCase()) == -1) { console.log('Invalid argument "' + arg + '", use --help.'); return; } }
|
||||
if (obj.args.mongodb == true) { console.log('Must specify: --mongodb [connectionstring] \r\nSee https://docs.mongodb.com/manual/reference/connection-string/ for MongoDB connection string.'); return; }
|
||||
for (i in obj.config.settings) { obj.args[i] = obj.config.settings[i]; } // Place all settings into arguments, arguments have already been placed into settings so arguments take precedence.
|
||||
@ -200,6 +200,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
// Get current and latest MeshCentral server versions using NPM
|
||||
obj.getLatestServerVersion = function (callback) {
|
||||
if (callback == null) return;
|
||||
try {
|
||||
if (typeof obj.args.selfupdate == 'string') { callback(obj.currentVer, obj.args.selfupdate); return; } // If we are targetting a specific version, return that one as current.
|
||||
var child_process = require('child_process');
|
||||
var npmpath = ((typeof obj.args.npmpath == 'string') ? obj.args.npmpath : 'npm');
|
||||
@ -212,6 +213,7 @@ function CreateMeshCentralServer(config, args) {
|
||||
if (code == 0) { try { latestVer = xprocess.data.split(' ').join('').split('\r').join('').split('\n').join(''); } catch (e) { } }
|
||||
callback(obj.currentVer, latestVer);
|
||||
});
|
||||
} catch (ex) { callback(obj.currentVer, null); } // If the system is running out of memory, an exception here can easily happen.
|
||||
};
|
||||
|
||||
// Initiate server self-update
|
||||
@ -510,6 +512,20 @@ function CreateMeshCentralServer(config, args) {
|
||||
// Write the server state
|
||||
obj.updateServerState('state', 'starting');
|
||||
|
||||
// Start memory tracking if requested
|
||||
if (typeof obj.args.memorytracking == 'number') {
|
||||
var info = process.memoryUsage(), txt = [];
|
||||
info.time = Date.now();
|
||||
for (var i in info) { txt.push(i); }
|
||||
obj.fs.appendFile(obj.getConfigFilePath('memorytracking.txt'), txt.join(',') + '\r\n', function (err) { });
|
||||
setInterval(function () {
|
||||
var info = process.memoryUsage(), txt = [];
|
||||
info.time = Date.now();
|
||||
for (var i in info) { txt.push(info[i]); }
|
||||
obj.fs.appendFile(obj.getConfigFilePath('memorytracking.txt'), txt.join(',') + '\r\n', function (err) { });
|
||||
}, (obj.args.memorytracking * 1000));
|
||||
}
|
||||
|
||||
// Look to see if data and/or file path is specified
|
||||
if (obj.args.datapath) { obj.datapath = obj.args.datapath; }
|
||||
if (obj.args.filespath) { obj.filespath = obj.args.filespath; }
|
||||
|
35
meshuser.js
35
meshuser.js
@ -470,7 +470,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
|
||||
switch (cmd) {
|
||||
case 'help': {
|
||||
r = 'Available commands: help, info, versions, args, resetserver, showconfig, usersessions, tasklimiter, setmaxtasks, cores, migrationagents, swarmstats, nodeconfig.';
|
||||
r = 'Available commands: help, info, versions, args, resetserver, showconfig, usersessions, tasklimiter, setmaxtasks, cores,\r\n'
|
||||
r += 'migrationagents, swarmstats, nodeconfig.';
|
||||
break;
|
||||
}
|
||||
case 'info': {
|
||||
@ -580,6 +581,22 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'heapdump': {
|
||||
var heapdump = null;
|
||||
try { heapdump = require('heapdump'); } catch (ex) { }
|
||||
if (heapdump == null) {
|
||||
r = 'Heapdump module not installed, run "npm install heapdump".';
|
||||
} else {
|
||||
heapdump.writeSnapshot(function (err, filename) {
|
||||
if (err != null) {
|
||||
try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Unable to write heapdump: ' + err })); } catch (ex) { }
|
||||
} else {
|
||||
try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Wrote heapdump at ' + filename })); } catch (ex) { }
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: { // This is an unknown command, return an error message
|
||||
r = 'Unknown command \"' + cmd + '\", type \"help\" for list of avaialble commands.';
|
||||
break;
|
||||
@ -1272,7 +1289,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
for (var i = 0; i < command.nodeids.length; i++) {
|
||||
obj.db.Get(command.nodeids[i], function (err, nodes) {
|
||||
if (nodes.length != 1) return;
|
||||
var node = nodes[0];
|
||||
const node = nodes[0];
|
||||
|
||||
// Check if already in the right mesh
|
||||
if (node.meshid == command.meshid) return;
|
||||
@ -1281,21 +1298,25 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
try { if (obj.parent.meshes[node.meshid].mtype != obj.parent.meshes[command.meshid].mtype) return; } catch (e) { return; };
|
||||
|
||||
// Make sure that we have rights on both source and destination mesh
|
||||
var sourceMeshRights = user.links[node.meshid].rights;
|
||||
var targetMeshRights = user.links[command.meshid].rights;
|
||||
const sourceMeshRights = user.links[node.meshid].rights;
|
||||
const targetMeshRights = user.links[command.meshid].rights;
|
||||
if (((sourceMeshRights & 4) == 0) || ((targetMeshRights & 4) == 0)) return;
|
||||
|
||||
// Perform the switch, start by saving the node with the new meshid.
|
||||
var oldMeshId = node.meshid;
|
||||
const oldMeshId = node.meshid;
|
||||
node.meshid = command.meshid;
|
||||
obj.db.Set(node);
|
||||
|
||||
// If the device is connected on this server, switch it now.
|
||||
var agentSession = obj.parent.wsagents[node._id];
|
||||
if (agentSession != null) { agentSession.dbMeshKey = command.meshid; agentSession.meshid = command.meshid.split('/')[2]; }
|
||||
if (agentSession != null) {
|
||||
agentSession.dbMeshKey = command.meshid; // Switch the agent mesh
|
||||
agentSession.meshid = command.meshid.split('/')[2]; // Switch the agent mesh
|
||||
agentSession.sendUpdatedIntelAmtPolicy(); // Send the new Intel AMT policy
|
||||
}
|
||||
|
||||
// Add the connection state
|
||||
var state = obj.parent.parent.GetConnectivityState(node._id);
|
||||
const state = obj.parent.parent.GetConnectivityState(node._id);
|
||||
if (state) {
|
||||
node.conn = state.connectivity;
|
||||
node.pwr = state.powerState;
|
||||
|
1961
package-lock.json
generated
Normal file
1961
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.2.9-q",
|
||||
"version": "0.2.9-r",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
@ -35,6 +35,7 @@
|
||||
"express": "^4.16.4",
|
||||
"express-handlebars": "^3.0.0",
|
||||
"express-ws": "^4.0.0",
|
||||
"heapdump": "^0.3.12",
|
||||
"ipcheck": "^0.1.0",
|
||||
"meshcentral": "*",
|
||||
"minimist": "^1.2.0",
|
||||
@ -42,6 +43,7 @@
|
||||
"multiparty": "^4.2.1",
|
||||
"nedb": "^1.8.0",
|
||||
"node-forge": "^0.7.6",
|
||||
"node-windows": "^0.1.14",
|
||||
"otplib": "^10.0.1",
|
||||
"util.promisify": "^1.0.0",
|
||||
"ws": "^6.1.2",
|
||||
|
@ -23,7 +23,7 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
||||
obj.legacyAgentConnections = {};
|
||||
obj.migrationAgents = {};
|
||||
obj.agentActionCount = {};
|
||||
obj.stats = { blockedConnect: 0, connectCount: 0, clientCertConnectCount: 0, noCertConnectCount: 0, bytesIn: 0, bytesOut: 0, httpGetRequest: 0, pushedAgents: {}, close: 0, onclose: 0 }
|
||||
obj.stats = { blockedConnect: 0, connectCount: 0, clientCertConnectCount: 0, noCertConnectCount: 0, bytesIn: 0, bytesOut: 0, httpGetRequest: 0, pushedAgents: {}, close: 0, onclose: 0, agentType: {} }
|
||||
const tls = require('tls');
|
||||
const forge = require('node-forge');
|
||||
const common = require('./common.js');
|
||||
@ -178,7 +178,7 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
||||
if ((this.tag.clientCert == null) || (this.tag.clientCert.subject == null)) {
|
||||
/*console.log("Swarm Connection, no client cert: " + socket.remoteAddress);*/
|
||||
this.write('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nMeshCentral2 legacy swarm server.\r\nNo client certificate given.');
|
||||
this.end();
|
||||
//this.end(); // If we don't close the connection, it may lead to less reconnection traffic.
|
||||
return;
|
||||
}
|
||||
|
||||
@ -209,6 +209,9 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
||||
if (socket.pingTimer == null) { socket.pingTimer = setInterval(function () { obj.SendCommand(socket, LegacyMeshProtocol.PING); }, 20000); }
|
||||
Debug(3, 'Swarm:NODEPUSH:' + JSON.stringify(nodeblock));
|
||||
|
||||
// Log the agent type
|
||||
if (obj.stats.agenttype[nodeblock.agenttype] == null) { obj.stats.agenttype[nodeblock.agenttype] = 1; } else { obj.stats.agenttype[nodeblock.agenttype]++; }
|
||||
|
||||
// Check if this agent is asking of updates over and over again.
|
||||
var actionCount = obj.agentActionCount[nodeblock.nodeidhex];
|
||||
if (actionCount == null) { actionCount = 0; }
|
||||
@ -230,7 +233,7 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
|
||||
|
||||
// Update stats
|
||||
if (obj.stats.pushedAgents[nodeblock.agenttype] == null) { obj.stats.pushedAgents[nodeblock.agenttype] = {}; }
|
||||
if (obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion] == null) { obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion] = 0; } else { obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion]++; }
|
||||
if (obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion] == null) { obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion] = 1; } else { obj.stats.pushedAgents[nodeblock.agenttype][nextAgentVersion]++; }
|
||||
|
||||
// Start the agent download using the task limiter so not to flood the server. Low priority task
|
||||
obj.parent.taskLimiter.launch(function (socket, taskid, taskLimiterQueue) {
|
||||
|
File diff suppressed because one or more lines are too long
@ -6359,7 +6359,7 @@
|
||||
// Display the users using the sorted list
|
||||
var x = '<table style=width:100% cellpadding=0 cellspacing=0>', addHeader = true;
|
||||
|
||||
x += '<th style=color:gray>Name<th style=color:gray>Groups<th style=color:gray>Last Access<th style=color:gray>Permissions';
|
||||
x += '<th style=color:gray>Name<th style=color:gray;width:80px>Groups<th style=color:gray;width:120px>Last Access<th style=color:gray;width:120px>Permissions';
|
||||
|
||||
// Online users
|
||||
for (var i in sortedUserIds) {
|
||||
@ -6408,12 +6408,12 @@
|
||||
msg = "<span style=float:right;margin-top:1px;margin-right:4px title=Chat><a onclick=userChat(event,\"" + encodeURIComponent(user._id) + "\",\"" + encodeURIComponent(user.name) + "\")><img src='images/icon-chat.png' height=16 width=16 style=padding-top:2px /></a></span>";
|
||||
msg += "<span style=float:right;margin-top:1px;margin-left:4px;margin-right:4px title=Notify><a onclick=showUserAlertDialog(event,\"" + encodeURIComponent(user._id) + "\")><img src='images/icon-notify.png' height=16 width=16 style=padding-top:2px /></a></span>";
|
||||
}
|
||||
if (sessions == 1) { lastAccess += '1 session'; } else { lastAccess += sessions + ' sessions'; }
|
||||
if (sessions == 1) { lastAccess += '1 session'; } else { lastAccess += sessions + ' sessions'; }
|
||||
} else {
|
||||
if (user.login) { lastAccess += '<span title="Last login: ' + new Date(user.login * 1000).toLocaleString() + '">' + new Date(user.login * 1000).toLocaleDateString() + '</span>'; }
|
||||
}
|
||||
if (self) { permissions += "<a style=cursor:pointer onclick=showUserAdminDialog(event,\"" + encodeURIComponent(user._id) + "\")>"; }
|
||||
if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { permissions += "Locked, "; }
|
||||
if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { permissions += "Locked, "; }
|
||||
permissions += "<span title='Server Permissions'>";
|
||||
if ((user.siteadmin == null) || (user.siteadmin == 0) || (user.siteadmin == 32)) {
|
||||
permissions += "User";
|
||||
|
Loading…
Reference in New Issue
Block a user