'use strict'; exports = module.exports = { reboot, isRebootRequired, getDisks, getDiskUsage, updateDiskUsage, getMemory, getLogs, getLogStream, getSystemGraphs, getBlockDevices, getCpus, getDmi }; const assert = require('assert'), BoxError = require('../boxerror.js'), graphs = require('../graphs.js'), HttpError = require('connect-lastmile').HttpError, HttpSuccess = require('connect-lastmile').HttpSuccess, safe = require('safetydance'), system = require('../system.js'); async function reboot(req, res, next) { // Finish the request, to let the appstore know we triggered the reboot next(new HttpSuccess(202, {})); await safe(system.reboot()); } async function isRebootRequired(req, res, next) { const [error, rebootRequired] = await safe(system.isRebootRequired()); if (error) return next(BoxError.toHttpError(error)); next(new HttpSuccess(200, { rebootRequired })); } async function getDisks(req, res, next) { const [getDisksError, disks] = await safe(system.getDisks()); if (getDisksError) return next(BoxError.toHttpError(getDisksError)); let [getSwapsError, swaps] = await safe(system.getSwaps()); if (getSwapsError) return next(BoxError.toHttpError(getSwapsError)); next(new HttpSuccess(200, { disks, swaps })); } async function getDiskUsage(req, res, next) { const [error, result] = await safe(system.getDiskUsage()); if (error) return next(BoxError.toHttpError(error)); next(new HttpSuccess(200, { usage: result })); } async function updateDiskUsage(req, res, next) { const [error, taskId] = await safe(system.startUpdateDiskUsage()); if (error) return next(BoxError.toHttpError(error)); next(new HttpSuccess(201, { taskId })); } async function getMemory(req, res, next) { const [error, result] = await safe(system.getMemory()); if (error) return next(BoxError.toHttpError(error)); next(new HttpSuccess(200, result)); } async function getLogs(req, res, next) { assert.strictEqual(typeof req.params.unit, 'string'); const lines = 'lines' in req.query ? parseInt(req.query.lines, 10) : 10; // we ignore last-event-id if (isNaN(lines)) return next(new HttpError(400, 'lines must be a number')); const options = { lines: lines, follow: false, format: req.query.format || 'json' }; const [error, logStream] = await safe(system.getLogs(req.params.unit, options)); if (error) return next(BoxError.toHttpError(error)); res.writeHead(200, { 'Content-Type': 'application/x-logs', 'Content-Disposition': `attachment; filename="${req.params.unit}.log"`, 'Cache-Control': 'no-cache', 'X-Accel-Buffering': 'no' // disable nginx buffering }); logStream.pipe(res); } async function getLogStream(req, res, next) { assert.strictEqual(typeof req.params.unit, 'string'); const lines = 'lines' in req.query ? parseInt(req.query.lines, 10) : 10; // we ignore last-event-id if (isNaN(lines)) return next(new HttpError(400, 'lines must be a valid number')); function sse(id, data) { return 'id: ' + id + '\ndata: ' + data + '\n\n'; } if (req.headers.accept !== 'text/event-stream') return next(new HttpError(400, 'This API call requires EventStream')); const options = { lines: lines, follow: true, format: req.query.format || 'json' }; const [error, logStream] = await safe(system.getLogs(req.params.unit, options)); if (error) return next(BoxError.toHttpError(error)); res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'X-Accel-Buffering': 'no', // disable nginx buffering 'Access-Control-Allow-Origin': '*' }); res.write('retry: 3000\n'); res.on('close', logStream.close); logStream.on('data', function (data) { const obj = JSON.parse(data); res.write(sse(obj.realtimeTimestamp, JSON.stringify(obj))); // send timestamp as id }); logStream.on('end', res.end.bind(res)); logStream.on('error', res.end.bind(res, null)); } async function getSystemGraphs(req, res, next) { if (!req.query.fromMinutes || !parseInt(req.query.fromMinutes)) return next(new HttpError(400, 'fromMinutes must be a number')); const fromMinutes = parseInt(req.query.fromMinutes); const noNullPoints = !!req.query.noNullPoints; const [error, result] = await safe(graphs.getSystem(fromMinutes, noNullPoints)); if (error) return next(new HttpError(500, error)); next(new HttpSuccess(200, result)); } async function getBlockDevices(req, res, next) { const [error, devices] = await safe(system.getBlockDevices()); if (error) return next(new HttpError(500, error)); next(new HttpSuccess(200, { devices })); } async function getCpus(req, res, next) { const [error, cpus] = await safe(system.getCpus()); if (error) return next(BoxError.toHttpError(error)); next(new HttpSuccess(200, { cpus })); } async function getDmi(req, res, next) { const [error, dmi] = await safe(system.getDmi()); if (error) return next(BoxError.toHttpError(error)); next(new HttpSuccess(200, { dmi })); }