UNPKG

iobroker.backitup

Version:

ioBroker.backitup allows you to backup and restore your ioBroker installation and other systems, such as databases, Zigbee, scripts and many more.

190 lines (170 loc) 7.91 kB
const fs = require('node:fs'); const fse = require('fs-extra'); const path = require('node:path'); function replayInfluxDB(options, tmpDir, log, callback) { const { exec } = require('node:child_process'); let dbName = options.dbName; if (options.influxDBMulti === true && fs.existsSync(tmpDir)) { const files = fs.readdirSync(tmpDir); try { files.forEach(function (file) { const currentFiletype = file.split('.').pop(); if (currentFiletype === 'manifest') { const manifest = fs.readFileSync(path.join(tmpDir, file).replace(/\\/g, '/')); const json = JSON.parse(manifest); options.dbversion = json.files ? '1.x' : json.buckets ? '2.x' : options.dbversion; dbName = options.dbversion === '1.x' ? json.files[0].database : options.dbversion === '2.x' ? json.buckets[0].bucketName : options.dbName; } }); } catch (err) { log.error(`manifest is broken: ${err}`) } try { for (let i = 0; i < options.influxDBEvents.length; i++) { if (options.influxDBEvents[i].dbName === dbName) { options.port = options.influxDBEvents[i].port ? options.influxDBEvents[i].port : ''; options.host = options.influxDBEvents[i].host ? options.influxDBEvents[i].host : ''; options.dbName = options.influxDBEvents[i].dbName ? options.influxDBEvents[i].dbName : ''; options.nameSuffix = options.influxDBEvents[i].nameSuffix ? options.influxDBEvents[i].nameSuffix : ''; options.token = options.influxDBEvents[i].token ? options.influxDBEvents[i].token : ''; options.dbversion = options.influxDBEvents[i].dbversion ? options.influxDBEvents[i].dbversion : ''; options.protocol = options.influxDBEvents[i].protocol ? options.influxDBEvents[i].protocol : ''; } } } catch (err) { log.error(`InfluxDB config not found: ${err}`) } } const cmdDelete = `influx -execute='DROP DATABASE ${dbName}'`; let cmd; if (options.dbversion === '1.x') { cmd = `${options.exe ? `"${options.exe}"` : 'influxd'} restore -portable -db ${dbName}${options.dbType === 'remote' ? ` -host ${options.host}:${options.port}` : ''} "${tmpDir}"`; } else if (options.dbversion === '2.x') { cmd = `${options.exe ? `"${options.exe}"` : 'influx'} restore --bucket ${dbName}${options.dbType === 'remote' ? ` --host ${options.protocol}://${options.host}:${options.port}` : ''} -t ${options.token} "${tmpDir}"`; } if (options.deleteDatabase && options.dbType === 'local') { try { exec(cmdDelete, (error, stdout, stderr) => { log.debug(stdout); const child = exec(cmd, (error, stdout, stderr) => { if (error) log.error(stderr); return callback && callback(error); }); }); } catch (e) { callback && callback(e); } } else { try { const child = exec(cmd, (error, stdout, stderr) => { if (error) log.error(stderr); return callback && callback(error); }); } catch (e) { callback && callback(e); } } } function restore(options, fileName, log, adapter, callback) { const tmpDir = path.join(options.backupDir, 'influxDBtmp').replace(/\\/g, '/'); // stop influxdb-Adapter before Restore let startAfterRestore = false; let enabledInstances = []; adapter.getObjectView('system', 'instance', { startkey: 'system.adapter.influxdb.', endkey: 'system.adapter.influxdb.\u9999' }, async (err, instances) => { let resultInstances = []; if (!err && instances && instances.rows) { instances.rows.forEach(row => resultInstances.push({ id: row.id.replace('system.adapter.', ''), config: row.value.native.type })); for (let i = 0; i < resultInstances.length; i++) { let _id = resultInstances[i].id; // Stop influxdb Instances adapter.getForeignObject(`system.adapter.${_id}`, (err, obj) => { if (obj?.common?.enabled) { adapter.setForeignState(`system.adapter.${_id}.alive`, false); log.debug(`${_id} is stopped`); enabledInstances.push(_id); startAfterRestore = true; } }); } } else { log.debug('Could not retrieve influxdb instances!'); } }); const desiredMode = '0o2775'; if (!fs.existsSync(tmpDir)) { fse.ensureDirSync(tmpDir, desiredMode); // fs.mkdirSync(tmpDir); log.debug('Created tmp directory'); } else { try { log.debug('Try deleting the old InfluxDB tmp directory'); fse.removeSync(tmpDir); if (!fs.existsSync(tmpDir)) { log.debug('InfluxDB old tmp directory was successfully deleted'); } fse.ensureDirSync(tmpDir, desiredMode); //fs.mkdirSync(tmpDir); log.debug('Created tmp directory'); } catch (e) { log.debug(`InfluxDB old tmp directory could not be deleted: ${e}`); } } log.debug('Start influxDB Restore ...'); const decompress = require('../targz').decompress; try { decompress({ src: fileName, dest: tmpDir, }, (err, stdout, stderr) => { if (err) { log.error(err); if (callback) { log.error('influxDB Restore not completed'); callback(err, stderr); callback = null; } } else { if (callback) { replayInfluxDB(options, tmpDir, log, err => { // Start influxDB Instances if (startAfterRestore) { enabledInstances.forEach(enabledInstance => { adapter.getForeignObject(`system.adapter.${enabledInstance}`, (err, obj) => { if (obj && !obj.common?.enabled) { adapter.setForeignState(`system.adapter.${enabledInstance}.alive`, true); log.debug(`${enabledInstance} started`); } }); }); } // delete influxDB tmpDir if (fs.existsSync(tmpDir)) { try { log.debug('Try deleting the InfluxDB tmp directory'); fse.removeSync(tmpDir); if (!fs.existsSync(tmpDir)) { log.debug('InfluxDB tmp directory was successfully deleted'); } } catch (e) { log.debug(`InfluxDB tmp directory could not be deleted: ${e}`); } } log.debug('influxDB Restore completed successfully'); callback && callback(null, 'influxDB restore done'); callback = null; }); } } }); } catch (err) { if (callback) { callback(err); callback = null; } } } module.exports = { restore, isStop: false, };