iobroker.backitup
Version:
Backitup enables the cyclic creation of backups of an IoBroker / Homematic installation
205 lines (185 loc) • 7.98 kB
JavaScript
const tools = require('./tools');
const fs = require('fs');
const path = require('path');
function writeIntoFile(fileName, text) {
if (text) {
console.log(text);
try {
fs.appendFileSync(fileName, text + '\n');
} catch (e) {
}
}
}
function getConfig(options, backupType, storageType) {
let config = options[backupType];
if (!config) {
for (const attr in options) {
if (options.hasOwnProperty(attr) &&
typeof options[attr] === 'object' &&
options[attr][backupType]) {
config = options[attr][backupType];
break;
}
}
if (!config) {
for (const attr in options) {
if (options.hasOwnProperty(attr) &&
typeof options[attr] === 'object' &&
options[attr][storageType]) {
config = options[attr][storageType];
break;
}
}
}
} else if (storageType) {
return config[storageType];
}
return config;
}
function getFile(options, storageType, fileName, toSaveName, log, callback) {
if (fs.existsSync(toSaveName)) {
callback(null, toSaveName);
} else {
const name = fileName.split('/').pop();
let backupType = name.split('_')[0];
if (name.match(/^\d\d\d\d_\d\d_\d\d-\d\d_\d\d_\d\d_backupiobroker\.tar\.gz$/)) {
backupType = 'minimal';
}
let config = getConfig(options, backupType, storageType);
if (storageType !== 'local') {
const _getFile = require('./list/' + storageType).getFile;
_getFile(config, fileName, toSaveName, log, callback);
} else {
tools.copyFile(fileName, toSaveName, callback);
}
}
}
function startDetachedRestore() {
const {spawn} = require('child_process');
//const child_process = require('child_process');
const isWin = process.platform.startsWith('win');
if (isWin == '') {
fs.writeFileSync(__dirname + '/.restore.info', 'restore');
}
/*child_process.exec(`systemctl status iobroker | grep -o "active (running)"`, (error, stdout, stderr) => {
if(stdout.indexOf('active (running)') != -1){
log.debug('systemctl status stdout: ' + stdout);
}
});*/
const cmd = spawn(isWin ? 'stop_r_IOB.bat' : 'bash', [isWin ? '' : 'stopIOB.sh'], {detached: true, cwd: __dirname, stdio: ['ignore', 'ignore', 'ignore']});
cmd.unref();
}
function startIOB() {
//const {spawn} = require('child_process');
const child_process = require('child_process');
const isWin = process.platform.startsWith('win');
child_process.exec(isWin ? 'startIOB.bat' : 'bash startIOB.sh', (error, stdout, stderr) => {
setTimeout(function() {
process.exit();
}, 1500);
});
/*
const cmd = spawn(isWin ? 'startIOB.bat' : 'bash', [isWin ? '' : 'startIOB.sh'], {detached: true, cwd: __dirname, stdio: ['ignore', 'ignore', 'ignore']});
cmd.unref();
setTimeout(function() {
adapter.terminate ? adapter.terminate() : process.exit();
}, 1000);
*/
}
function restore(adapter, options, storageType, fileName, log, callback) {
options = JSON.parse(JSON.stringify(options));
if (storageType === 'nas / copy') {
storageType = 'cifs';
}
if (adapter) {
const backupDir = path.join(tools.getIobDir(), 'backups').replace(/\\/g, '/');
const name = fileName.split('/').pop();
const toSaveName = path.join(backupDir, name);
getFile(options, storageType, fileName, toSaveName, log, err => {
if (!err && fs.existsSync(toSaveName)) {
let backupType = name.split('_')[0];
if (name.match(/^\d\d\d\d_\d\d_\d\d-\d\d_\d\d_\d\d_backupiobroker\.tar\.gz$/)) {
backupType = 'minimal';
}
let config = getConfig(options, backupType);
config.backupDir = config.backupDir || backupDir;
config.backupType = config.backupType || backupType;
config.name = config.name || backupType;
const _module = require('./restore/' + backupType);
if (_module.isStop) {
config.fileName = toSaveName;
fs.writeFileSync(__dirname + '/restore.json', JSON.stringify(config, null, 2));
startDetachedRestore();
return callback && callback({error: ''});
} else {
const log = {
debug: function (text) {
const lines = text.toString().split('\n');
lines.forEach(line => {
line = line.replace(/\r/g, ' ').trim();
line && log.debug(`[${backupType}] ${line}`);
});
adapter && adapter.setState('output.line', '[DEBUG] [' + backupType + '] - ' + text);
},
error: function (err) {
const lines = err.toString().split('\n');
lines.forEach(line => {
line = line.replace(/\r/g, ' ').trim();
line && log.error(`[${backupType}] ${line}`);
});
adapter && adapter.setState('output.line', '[ERROR] [' + backupType + '] - ' + err);
},
exit: function (exitCode) {
adapter && adapter.setState('output.line', '[EXIT] ' + (exitCode || 0));
}
};
_module.restore(config, toSaveName, log, (err, exitCode) => callback({error: err, exitCode}));
}
} else {
callback({error: err || 'File ' + toSaveName + ' not found'});
}
});
} else {
try {
const config = options;
const _module = require('./restore/' + config.backupType);
_module.restore(config, config.fileName, log, (err, exitCode) => {
log.exit(exitCode);
callback({error: err, exitCode})
});
} catch (e) {
log.error(e);
log.exit(-1);
}
}
}
if (typeof module !== "undefined" && module.parent) {
module.exports = restore;
} else {
if (fs.existsSync(__dirname + '/restore.json')) {
const config = require(__dirname + '/restore.json');
const logName = path.join(config.backupDir, 'logs.txt').replace(/\\/g, '/');
const log = {
debug: function (text) {
const lines = text.toString().split('\n');
lines.forEach(line => {
line = line.replace(/\r/g, ' ').trim();
line && writeIntoFile(logName, `[DEBUG] [${config.name}] ${line}`);
});
},
error: function (err) {
const lines = err.toString().split('\n');
lines.forEach(line => {
line = line.replace(/\r/g, ' ').trim();
line && writeIntoFile(logName, `[ERROR] [${config.name}] ${line}`);
});
},
exit: function (exitCode) {
writeIntoFile(logName, `[EXIT] ${exitCode}`);
}
};
restore(null, config, null, null, log, () => startIOB());
} else {
console.log('No config found at "' + path.normalize(path.join(__dirname, 'restore.json')) + '"');
}
}