From a6fdb96fbf4e70d29cb5a5e18e04dac6919f5dd1 Mon Sep 17 00:00:00 2001 From: Johannes Zellner Date: Mon, 23 Jan 2023 17:56:01 +0100 Subject: [PATCH] Add route to list all blockdevices --- src/cloudron.js | 30 +++++++++++++++++++++++++++++- src/routes/cloudron.js | 10 +++++++++- src/routes/test/cloudron-test.js | 12 ++++++++++++ src/server.js | 1 + 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/cloudron.js b/src/cloudron.js index 748b7197b..cc037b678 100644 --- a/src/cloudron.js +++ b/src/cloudron.js @@ -21,7 +21,9 @@ exports = module.exports = { updateDiskUsage, - runSystemChecks + runSystemChecks, + + getBlockDevices }; const apps = require('./apps.js'), @@ -37,6 +39,7 @@ const apps = require('./apps.js'), dns = require('./dns.js'), dockerProxy = require('./dockerproxy.js'), eventlog = require('./eventlog.js'), + execSync = require('child_process').execSync, fs = require('fs'), LogStream = require('./log-stream.js'), mail = require('./mail.js'), @@ -331,3 +334,28 @@ async function updateDiskUsage() { tasks.startTask(taskId, {}); return taskId; } + +async function getBlockDevices() { + let info; + + try { + info = JSON.parse(execSync('lsblk --paths --json --list --noempty', { encoding: 'utf8' })); + } catch (e) { + console.error('Failed to list disks:', e); + throw new BoxError(BoxError.INTERNAL_ERROR, e); + } + + const devices = info.blockdevices; + + debug(`getBlockDevices: Found ${devices.length} devices. ${devices.map(d => d.name).join(', ')}`); + + // convert to fixed format + return devices.map(function (d) { + return { + path: d.name, + size: d.size, + type: d.type, + mountpoint: d.mountpoints[0] // we only support one mountpoint here + }; + }); +} diff --git a/src/routes/cloudron.js b/src/routes/cloudron.js index 4331b7ca3..282ac8303 100644 --- a/src/routes/cloudron.js +++ b/src/routes/cloudron.js @@ -27,7 +27,8 @@ exports = module.exports = { syncExternalLdap, syncDnsRecords, getSystemGraphs, - getPlatformStatus + getPlatformStatus, + getBlockDevices }; const assert = require('assert'), @@ -365,3 +366,10 @@ async function getSystemGraphs(req, res, next) { async function getPlatformStatus(req, res, next) { next(new HttpSuccess(200, platform.getStatus())); } + +async function getBlockDevices(req, res, next) { + const [error, devices] = await safe(cloudron.getBlockDevices()); + if (error) return next(new HttpError(500, error)); + + next(new HttpSuccess(200, { devices })); +} diff --git a/src/routes/test/cloudron-test.js b/src/routes/test/cloudron-test.js index b2c406a6b..05f69b14a 100644 --- a/src/routes/test/cloudron-test.js +++ b/src/routes/test/cloudron-test.js @@ -439,4 +439,16 @@ describe('Cloudron API', function () { expect(response.body.languages.indexOf('en')).to.not.equal(-1); }); }); + + describe('blockdevices', function () { + it('succeeds', async function () { + const response = await superagent.get(`${serverUrl}/api/v1/cloudron/block_devices`) + .query({ access_token: owner.token }); + + expect(response.statusCode).to.equal(200); + expect(response.body.devices).to.be.ok(); + + expect(response.body.devices.some(d => d.mountpoint === '/')).to.be(true); + }); + }); }); diff --git a/src/server.js b/src/server.js index 2a2abbd0c..c1b4b77cf 100644 --- a/src/server.js +++ b/src/server.js @@ -120,6 +120,7 @@ function initializeExpressSync() { router.get ('/api/v1/cloudron/disks', token, authorizeAdmin, routes.cloudron.getDisks); router.get ('/api/v1/cloudron/disk_usage', token, authorizeAdmin, routes.cloudron.getDiskUsage); router.post('/api/v1/cloudron/disk_usage', token, authorizeAdmin, routes.cloudron.updateDiskUsage); + router.get ('/api/v1/cloudron/block_devices', token, authorizeAdmin, routes.cloudron.getBlockDevices); router.get ('/api/v1/cloudron/memory', token, authorizeAdmin, routes.cloudron.getMemory); router.get ('/api/v1/cloudron/logs/:unit', token, authorizeAdmin, routes.cloudron.getLogs); router.get ('/api/v1/cloudron/logstream/:unit', token, authorizeAdmin, routes.cloudron.getLogStream);