Improved MongoDB autobackup and error handling.
Ylian Saint-Hilaire committed
Dec 28, 2020 at 19:25 UTC
cce68922d798b892a517407e0139724ab7e9e03b
2 files changed
+37
-4
db.js
+34
-4
@@ -1329,6 +1329,30 @@ module.exports.CreateDB = function (parent, func) {
1329
return r;
1330
}
1331
1332
+ // Check that the server is capable of performing a backup
1333
+ obj.checkBackupCapability = function (func) {
1334
+ if ((obj.databaseType == 2) || (obj.databaseType == 3)) {
1335
+ // Check that we have access to MongoDump
1336
+ var backupPath = parent.backuppath;
1337
+ if (parent.config.settings.autobackup && parent.config.settings.autobackup.backuppath) { backupPath = parent.config.settings.autobackup.backuppath; }
1338
+ var mongoDumpPath = 'mongodump';
1339
+ if (parent.config.settings.autobackup && parent.config.settings.autobackup.mongodumppath) { mongoDumpPath = parent.config.settings.autobackup.mongodumppath; }
1340
+ const child_process = require('child_process');
1341
+ child_process.exec('"' + mongoDumpPath + '"', { cwd: backupPath }, function (error, stdout, stderr) {
1342
+ try {
1343
+ if ((error != null) && (error != '')) {
1344
+ func(1, "Unable to find mongodump.exe, MongoDB database auto-backup will not be performed.");
1345
+ } else {
1346
+ func();
1347
+ }
1348
+ } catch (ex) { console.log(ex); }
1349
+ });
1350
+ } else {
1351
+ func();
1352
+ }
1353
+ }
1354
+
1355
+ // Perform a server backup
1356
obj.performingBackup = false;
1357
obj.performBackup = function (func) {
1358
try {
@@ -1354,11 +1378,12 @@ module.exports.CreateDB = function (parent, func) {
1378
if (parent.config.settings.autobackup && parent.config.settings.autobackup.mongodumppath) { mongoDumpPath = parent.config.settings.autobackup.mongodumppath; }
1379
const child_process = require('child_process');
1380
var cmd = '\"' + mongoDumpPath + '\" --db=\"' + dbname + '\" --archive=\"' + newBackupPath + '.archive\"';
1357
- if (dburl) { cmd = '\"' + mongoDumpPath + '\" --uri=\"' + dburl + '\" --archive=\"' + newBackupPath + '.archive\"'; }
1381
+ if (dburl) { cmd = '\"' + mongoDumpPath + '\" --uri=\"' + dburl.replace('?', '/?') + '\" --archive=\"' + newBackupPath + '.archive\"'; }
1382
var backupProcess = child_process.exec(cmd, { cwd: backupPath }, function (error, stdout, stderr) {
1383
try {
1384
+ var mongoDumpSuccess = true;
1385
backupProcess = null;
1361
- if ((error != null) && (error != '')) { console.log('ERROR: Unable to perform database backup: ' + error + '\r\n'); obj.performingBackup = false; return; }
1386
+ if ((error != null) && (error != '')) { mongoDumpSuccess = false; console.log('ERROR: Unable to perform MongoDB backup: ' + error + '\r\n'); }
1387
1388
// Perform archive compression
1389
var archiver = require('archiver');
@@ -1370,12 +1395,17 @@ module.exports.CreateDB = function (parent, func) {
1395
} else {
1396
archive = archiver('zip', { zlib: { level: 9 } });
1397
}
1373
- output.on('close', function () { obj.performingBackup = false; if (func) { func('Auto-backup completed.'); } obj.performCloudBackup(newAutoBackupPath + '.zip', func); setTimeout(function () { try { parent.fs.unlink(newBackupPath + '.archive', function () { }); } catch (ex) { console.log(ex); } }, 5000); });
1398
+ output.on('close', function () {
1399
+ obj.performingBackup = false;
1400
+ if (func) { if (mongoDumpSuccess) { func('Auto-backup completed.'); } else { func('Auto-backup completed without mongodb database: ' + error); } }
1401
+ obj.performCloudBackup(newAutoBackupPath + '.zip', func);
1402
+ setTimeout(function () { try { parent.fs.unlink(newBackupPath + '.archive', function () { }); } catch (ex) { console.log(ex); } }, 5000);
1403
+ });
1404
output.on('end', function () { });
1405
archive.on('warning', function (err) { console.log('Backup warning: ' + err); if (func) { func('Backup warning: ' + err); } });
1406
archive.on('error', function (err) { console.log('Backup error: ' + err); if (func) { func('Backup error: ' + err); } });
1407
archive.pipe(output);
1378
- archive.file(newBackupPath + '.archive', { name: newBackupFile + '.archive' });
1408
+ if (mongoDumpSuccess == true) { archive.file(newBackupPath + '.archive', { name: newBackupFile + '.archive' }); }
1409
archive.directory(parent.datapath, 'meshcentral-data');
1410
archive.finalize();
1411
} catch (ex) { console.log(ex); }
meshcentral.js
+3
@@ -987,6 +987,9 @@ function CreateMeshCentralServer(config, args) {
987
return;
988
}
989
990
+ // Check if the database is capable of performing a backup
991
+ obj.db.checkBackupCapability(function (err, msg) { if (msg != null) { obj.addServerWarning(msg, true) } });
992
+
993
// Load configuration for database if needed
994
if (obj.args.loadconfigfromdb) {
995
var key = null;