2015-07-20 00:09:47 -07:00
'use strict' ;
exports = module . exports = {
2020-08-15 22:54:32 -07:00
initialize ,
uninitialize ,
getConfig ,
getLogs ,
2015-07-20 00:09:47 -07:00
2020-08-15 22:54:32 -07:00
reboot ,
isRebootRequired ,
2015-10-27 16:00:31 -07:00
2020-08-15 22:54:32 -07:00
onActivated ,
2018-01-29 15:47:26 -08:00
2020-08-15 23:17:29 -07:00
setupDnsAndCert ,
2020-08-15 22:54:32 -07:00
prepareDashboardDomain ,
setDashboardDomain ,
updateDashboardDomain ,
renewCerts ,
2021-02-24 18:42:39 -08:00
syncDnsRecords ,
2018-11-11 09:29:11 -08:00
2022-10-12 10:26:21 +02:00
updateDiskUsage ,
2023-01-23 17:56:01 +01:00
runSystemChecks ,
getBlockDevices
2015-09-28 23:10:09 -07:00
} ;
2015-07-20 00:09:47 -07:00
2021-01-21 11:31:35 -08:00
const apps = require ( './apps.js' ) ,
2020-02-14 12:20:15 +01:00
appstore = require ( './appstore.js' ) ,
2019-03-18 19:13:44 -07:00
assert = require ( 'assert' ) ,
2021-09-30 09:50:30 -07:00
AuditSource = require ( './auditsource.js' ) ,
2019-10-22 14:06:19 -07:00
BoxError = require ( './boxerror.js' ) ,
2020-10-18 10:15:36 -07:00
branding = require ( './branding.js' ) ,
2018-12-14 09:57:28 -08:00
constants = require ( './constants.js' ) ,
2017-01-09 11:00:09 -08:00
cron = require ( './cron.js' ) ,
2015-07-20 00:09:47 -07:00
debug = require ( 'debug' ) ( 'box:cloudron' ) ,
2022-04-15 07:52:35 -05:00
delay = require ( './delay.js' ) ,
2021-08-13 17:22:28 -07:00
dns = require ( './dns.js' ) ,
2022-02-09 17:28:46 -08:00
dockerProxy = require ( './dockerproxy.js' ) ,
2019-02-04 20:24:28 -08:00
eventlog = require ( './eventlog.js' ) ,
2023-01-23 17:56:01 +01:00
execSync = require ( 'child_process' ) . execSync ,
2018-11-25 17:02:01 +01:00
fs = require ( 'fs' ) ,
2022-11-06 13:44:47 +01:00
LogStream = require ( './log-stream.js' ) ,
2019-02-04 14:49:51 -08:00
mail = require ( './mail.js' ) ,
2019-02-06 15:47:56 +01:00
notifications = require ( './notifications.js' ) ,
2015-07-20 00:09:47 -07:00
path = require ( 'path' ) ,
paths = require ( './paths.js' ) ,
2017-01-07 23:33:20 -08:00
platform = require ( './platform.js' ) ,
2018-01-30 12:23:27 -08:00
reverseProxy = require ( './reverseproxy.js' ) ,
2019-08-03 13:59:11 -07:00
safe = require ( 'safetydance' ) ,
2021-01-21 11:31:35 -08:00
services = require ( './services.js' ) ,
2015-07-20 00:09:47 -07:00
settings = require ( './settings.js' ) ,
shell = require ( './shell.js' ) ,
2017-04-18 15:15:35 -07:00
spawn = require ( 'child_process' ) . spawn ,
2020-08-15 23:17:29 -07:00
sysinfo = require ( './sysinfo.js' ) ,
2018-12-10 20:20:53 -08:00
tasks = require ( './tasks.js' ) ,
2021-09-17 09:22:46 -07:00
users = require ( './users.js' ) ;
2015-07-20 00:09:47 -07:00
2021-04-14 22:37:01 -07:00
const REBOOT _CMD = path . join ( _ _dirname , 'scripts/reboot.sh' ) ;
2015-07-20 00:09:47 -07:00
2021-06-03 11:42:32 -07:00
async function initialize ( ) {
2021-11-02 13:58:32 -07:00
safe ( runStartupTasks ( ) , { debug } ) ; // background
2019-05-08 15:24:37 -07:00
2021-06-03 11:42:32 -07:00
await notifyUpdate ( ) ;
2015-07-20 00:09:47 -07:00
}
2021-09-07 09:57:49 -07:00
async function uninitialize ( ) {
await cron . stopJobs ( ) ;
2022-02-09 17:28:46 -08:00
await dockerProxy . stop ( ) ;
2021-09-07 09:57:49 -07:00
await platform . stopAllTasks ( ) ;
2015-07-20 00:09:47 -07:00
}
2021-09-17 09:22:46 -07:00
async function onActivated ( options ) {
2021-02-24 15:03:49 -08:00
assert . strictEqual ( typeof options , 'object' ) ;
2017-11-22 21:31:30 -08:00
2021-05-02 23:28:41 -07:00
debug ( 'onActivated: running post activation tasks' ) ;
2017-11-22 21:31:30 -08:00
// Starting the platform after a user is available means:
// 1. mail bounces can now be sent to the cloudron owner
// 2. the restore code path can run without sudo (since mail/ is non-root)
2021-09-17 09:22:46 -07:00
await platform . start ( options ) ;
await cron . startJobs ( ) ;
2022-02-09 17:28:46 -08:00
await dockerProxy . start ( ) ; // this relies on the 'cloudron' docker network interface to be available
2021-09-17 09:22:46 -07:00
// disable responding to api calls via IP to not leak domain info. this is carefully placed as the last item, so it buys
// the UI some time to query the dashboard domain in the restore code path
await delay ( 30000 ) ;
await reverseProxy . writeDefaultConfig ( { activated : true } ) ;
2018-11-10 18:21:15 -08:00
}
2021-06-03 11:42:32 -07:00
async function notifyUpdate ( ) {
2019-08-03 13:59:11 -07:00
const version = safe . fs . readFileSync ( paths . VERSION _FILE , 'utf8' ) ;
2021-06-03 11:42:32 -07:00
if ( version === constants . VERSION ) return ;
2019-08-03 13:59:11 -07:00
2022-04-01 13:44:46 -07:00
if ( ! version ) {
await eventlog . add ( eventlog . ACTION _INSTALL _FINISH , AuditSource . CRON , { version : constants . VERSION } ) ;
} else {
await eventlog . add ( eventlog . ACTION _UPDATE _FINISH , AuditSource . CRON , { errorMessage : '' , oldVersion : version || 'dev' , newVersion : constants . VERSION } ) ;
const [ error ] = await safe ( tasks . setCompletedByType ( tasks . TASK _UPDATE , { error : null } ) ) ;
if ( error && error . reason !== BoxError . NOT _FOUND ) throw error ; // when hotfixing, task may not exist
}
2019-08-03 13:59:11 -07:00
2021-07-12 23:35:30 -07:00
safe . fs . writeFileSync ( paths . VERSION _FILE , constants . VERSION , 'utf8' ) ;
2019-08-03 13:59:11 -07:00
}
2018-11-10 18:21:15 -08:00
// each of these tasks can fail. we will add some routes to fix/re-run them
2021-09-17 09:22:46 -07:00
async function runStartupTasks ( ) {
const tasks = [ ] ;
2020-08-06 22:04:46 -07:00
2021-09-17 09:22:46 -07:00
// stop all the systemd tasks
tasks . push ( platform . stopAllTasks ) ;
2018-11-11 08:19:24 -08:00
2021-09-17 09:22:46 -07:00
// always generate webadmin config since we have no versioning mechanism for the ejs
tasks . push ( async function ( ) {
if ( ! settings . dashboardDomain ( ) ) return ;
2020-09-02 17:32:31 -07:00
2022-11-28 22:32:34 +01:00
await reverseProxy . writeDashboardConfig ( settings . dashboardDomain ( ) ) ;
2021-09-17 09:22:46 -07:00
} ) ;
tasks . push ( async function ( ) {
2020-09-02 17:32:31 -07:00
// check activation state and start the platform
2021-09-17 09:22:46 -07:00
const activated = await users . isActivated ( ) ;
// configure nginx to be reachable by IP when not activated. for the moment, the IP based redirect exists even after domain is setup
// just in case user forgot or some network error happenned in the middle (then browser refresh takes you to activation page)
// we remove the config as a simple security measure to not expose IP <-> domain
if ( ! activated ) {
debug ( 'runStartupTasks: not activated. generating IP based redirection config' ) ;
return await reverseProxy . writeDefaultConfig ( { activated : false } ) ;
2020-08-13 14:00:55 -07:00
}
2017-11-22 21:31:30 -08:00
2021-09-17 09:22:46 -07:00
await onActivated ( { } ) ;
2017-11-22 21:31:30 -08:00
} ) ;
2021-09-17 09:22:46 -07:00
// we used to run tasks in parallel but simultaneous nginx reloads was causing issues
for ( let i = 0 ; i < tasks . length ; i ++ ) {
2021-11-02 22:30:38 -07:00
const [ error ] = await safe ( tasks [ i ] ( ) ) ;
2022-08-10 22:07:05 +02:00
if ( error ) debug ( ` Startup task at index ${ i } failed: ${ error . message } ${ error . stack } ` ) ;
2021-09-17 09:22:46 -07:00
}
2017-11-22 21:31:30 -08:00
}
2021-08-18 13:25:42 -07:00
async function getConfig ( ) {
2021-05-18 14:37:11 -07:00
const release = safe . fs . readFileSync ( '/etc/lsb-release' , 'utf-8' ) ;
2021-08-18 13:25:42 -07:00
if ( release === null ) throw new BoxError ( BoxError . FS _ERROR , safe . error . message ) ;
2021-05-18 14:37:11 -07:00
const ubuntuVersion = release . match ( /DISTRIB_DESCRIPTION="(.*)"/ ) [ 1 ] ;
2021-08-18 13:25:42 -07:00
const allSettings = await settings . list ( ) ;
// be picky about what we send out here since this is sent for 'normal' users as well
return {
apiServerOrigin : settings . apiServerOrigin ( ) ,
webServerOrigin : settings . webServerOrigin ( ) ,
2022-05-05 16:51:18 +02:00
consoleServerOrigin : settings . consoleServerOrigin ( ) ,
2021-08-18 13:25:42 -07:00
adminDomain : settings . dashboardDomain ( ) ,
adminFqdn : settings . dashboardFqdn ( ) ,
mailFqdn : settings . mailFqdn ( ) ,
version : constants . VERSION ,
ubuntuVersion ,
isDemo : settings . isDemo ( ) ,
cloudronName : allSettings [ settings . CLOUDRON _NAME _KEY ] ,
footer : branding . renderFooter ( allSettings [ settings . FOOTER _KEY ] || constants . FOOTER ) ,
features : appstore . getFeatures ( ) ,
2022-01-13 14:34:02 -08:00
profileLocked : allSettings [ settings . PROFILE _CONFIG _KEY ] . lockUserProfiles ,
2022-11-30 19:54:32 +01:00
mandatory2FA : allSettings [ settings . PROFILE _CONFIG _KEY ] . mandatory2FA ,
2021-08-18 13:25:42 -07:00
} ;
2015-07-20 00:09:47 -07:00
}
2021-07-12 15:44:49 -07:00
async function reboot ( ) {
await notifications . alert ( notifications . ALERT _REBOOT , 'Reboot Required' , '' ) ;
2020-03-06 00:39:37 -08:00
2021-07-12 15:44:49 -07:00
const [ error ] = await safe ( shell . promises . sudo ( 'reboot' , [ REBOOT _CMD ] , { } ) ) ;
if ( error ) debug ( 'reboot: could not reboot' , error ) ;
2015-07-20 00:09:47 -07:00
}
2021-07-12 15:44:49 -07:00
async function isRebootRequired ( ) {
2018-11-25 17:02:01 +01:00
// https://serverfault.com/questions/92932/how-does-ubuntu-keep-track-of-the-system-restart-required-flag-in-motd
2021-07-12 15:44:49 -07:00
return fs . existsSync ( '/var/run/reboot-required' ) ;
2018-11-25 17:02:01 +01:00
}
2021-09-17 09:22:46 -07:00
async function runSystemChecks ( ) {
2021-06-17 13:51:29 -07:00
debug ( 'runSystemChecks: checking status' ) ;
2021-09-17 09:22:46 -07:00
const checks = [
checkMailStatus ( ) ,
checkRebootRequired ( ) ,
checkUbuntuVersion ( )
] ;
await Promise . allSettled ( checks ) ;
2019-02-06 15:47:56 +01:00
}
2021-08-17 15:45:57 -07:00
async function checkMailStatus ( ) {
const message = await mail . checkConfiguration ( ) ;
await notifications . alert ( notifications . ALERT _MAIL _STATUS , 'Email is not configured properly' , message ) ;
2019-02-06 14:58:45 -08:00
}
2021-07-12 15:44:49 -07:00
async function checkRebootRequired ( ) {
const rebootRequired = await isRebootRequired ( ) ;
await notifications . alert ( notifications . ALERT _REBOOT , 'Reboot Required' , rebootRequired ? 'To finish ubuntu security updates, a reboot is necessary.' : '' ) ;
2019-02-19 09:19:56 -08:00
}
2021-07-12 15:44:49 -07:00
async function checkUbuntuVersion ( ) {
2021-05-18 14:37:11 -07:00
const isXenial = fs . readFileSync ( '/etc/lsb-release' , 'utf-8' ) . includes ( '16.04' ) ;
2021-07-12 15:44:49 -07:00
if ( ! isXenial ) return ;
2021-05-18 14:37:11 -07:00
2021-07-12 15:44:49 -07:00
await notifications . alert ( notifications . ALERT _UPDATE _UBUNTU , 'Ubuntu upgrade required' , 'Ubuntu 16.04 has reached end of life and will not receive security and maintenance updates. Please follow https://docs.cloudron.io/guides/upgrade-ubuntu-18/ to upgrade to Ubuntu 18 at the earliest.' ) ;
2021-05-18 14:37:11 -07:00
}
2021-09-07 09:57:49 -07:00
async function getLogs ( unit , options ) {
2018-06-11 20:09:38 +02:00
assert . strictEqual ( typeof unit , 'string' ) ;
2017-04-18 20:32:57 -07:00
assert ( options && typeof options === 'object' ) ;
2019-01-08 12:10:53 -08:00
assert . strictEqual ( typeof options . lines , 'number' ) ;
assert . strictEqual ( typeof options . format , 'string' ) ;
assert . strictEqual ( typeof options . follow , 'boolean' ) ;
2017-04-18 15:15:35 -07:00
2022-04-14 17:41:41 -05:00
const lines = options . lines === - 1 ? '+1' : options . lines ,
2019-01-08 12:10:53 -08:00
format = options . format || 'json' ,
follow = options . follow ;
2017-04-18 15:15:35 -07:00
2018-06-11 20:09:38 +02:00
debug ( 'Getting logs for %s as %s' , unit , format ) ;
2018-11-16 13:05:11 +01:00
let args = [ '--lines=' + lines ] ;
if ( follow ) args . push ( '--follow' ) ;
2017-04-18 15:15:35 -07:00
2018-11-16 13:05:11 +01:00
// need to handle box.log without subdir
if ( unit === 'box' ) args . push ( path . join ( paths . LOG _DIR , 'box.log' ) ) ;
2019-03-01 15:45:44 -08:00
else if ( unit . startsWith ( 'crash-' ) ) args . push ( path . join ( paths . CRASH _LOG _DIR , unit . slice ( 6 ) + '.log' ) ) ;
2022-02-07 13:19:59 -08:00
else throw new BoxError ( BoxError . BAD _FIELD , ` No such unit ' ${ unit } ' ` ) ;
2017-04-18 15:15:35 -07:00
2021-09-07 09:57:49 -07:00
const cp = spawn ( '/usr/bin/tail' , args ) ;
2017-04-18 20:32:57 -07:00
2022-11-06 13:44:47 +01:00
const logStream = new LogStream ( { format , source : unit } ) ;
logStream . close = cp . kill . bind ( cp , 'SIGKILL' ) ; // hook for caller. closing stream kills the child process
2017-04-18 15:15:35 -07:00
2022-11-06 13:44:47 +01:00
cp . stdout . pipe ( logStream ) ;
2018-11-16 13:05:11 +01:00
2022-11-06 13:44:47 +01:00
return logStream ;
2017-04-18 15:15:35 -07:00
}
2018-11-11 09:29:11 -08:00
2021-08-20 09:19:44 -07:00
async function prepareDashboardDomain ( domain , auditSource ) {
2018-12-14 09:57:28 -08:00
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof auditSource , 'object' ) ;
2018-12-15 15:27:16 -08:00
debug ( ` prepareDashboardDomain: ${ domain } ` ) ;
2018-12-14 09:57:28 -08:00
2021-08-20 09:19:44 -07:00
if ( settings . isDemo ( ) ) throw new BoxError ( BoxError . CONFLICT , 'Not allowed in demo mode' ) ;
2019-03-18 19:13:44 -07:00
2022-11-28 21:23:06 +01:00
const fqdn = dns . fqdn ( constants . DASHBOARD _SUBDOMAIN , domain ) ;
2019-03-18 19:13:44 -07:00
2021-08-30 14:00:50 -07:00
const result = await apps . list ( ) ;
2021-08-30 14:42:07 -07:00
if ( result . some ( app => app . fqdn === fqdn ) ) throw new BoxError ( BoxError . BAD _STATE , 'Dashboard location conflicts with an existing app' ) ;
2019-03-18 19:13:44 -07:00
2022-07-14 15:18:17 +05:30
const taskId = await tasks . add ( tasks . TASK _SETUP _DNS _AND _CERT , [ constants . DASHBOARD _SUBDOMAIN , domain , auditSource ] ) ;
2019-08-27 22:39:59 -07:00
2021-09-17 09:22:46 -07:00
tasks . startTask ( taskId , { } ) ;
2019-08-27 22:39:59 -07:00
2021-08-20 09:19:44 -07:00
return taskId ;
2018-12-14 09:57:28 -08:00
}
2019-02-26 19:43:18 -08:00
// call this only pre activation since it won't start mail server
2021-08-19 13:24:38 -07:00
async function setDashboardDomain ( domain , auditSource ) {
2018-12-07 16:15:21 -08:00
assert . strictEqual ( typeof domain , 'string' ) ;
2019-02-04 20:24:28 -08:00
assert . strictEqual ( typeof auditSource , 'object' ) ;
2018-12-07 16:15:21 -08:00
2018-12-08 18:18:45 -08:00
debug ( ` setDashboardDomain: ${ domain } ` ) ;
2018-12-07 16:15:21 -08:00
2022-11-28 22:32:34 +01:00
await reverseProxy . writeDashboardConfig ( domain ) ;
2022-11-28 21:23:06 +01:00
const fqdn = dns . fqdn ( constants . DASHBOARD _SUBDOMAIN , domain ) ;
2018-12-07 16:15:21 -08:00
2021-08-19 13:24:38 -07:00
await settings . setDashboardLocation ( domain , fqdn ) ;
2019-01-16 21:36:48 -08:00
2022-03-31 22:46:14 -07:00
await safe ( appstore . updateCloudron ( { domain } ) , { debug } ) ;
2021-04-13 14:19:45 -07:00
2021-08-19 13:24:38 -07:00
await eventlog . add ( eventlog . ACTION _DASHBOARD _DOMAIN _UPDATE , auditSource , { domain , fqdn } ) ;
2018-12-07 16:15:21 -08:00
}
2018-12-10 20:20:53 -08:00
2019-02-26 19:43:18 -08:00
// call this only post activation because it will restart mail server
2021-08-19 13:24:38 -07:00
async function updateDashboardDomain ( domain , auditSource ) {
2019-02-26 19:43:18 -08:00
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof auditSource , 'object' ) ;
2020-08-15 22:53:05 -07:00
debug ( ` updateDashboardDomain: ${ domain } ` ) ;
2019-02-26 19:43:18 -08:00
2021-08-19 13:24:38 -07:00
if ( settings . isDemo ( ) ) throw new BoxError ( BoxError . CONFLICT , 'Not allowed in demo mode' ) ;
2019-02-26 19:43:18 -08:00
2021-08-19 13:24:38 -07:00
await setDashboardDomain ( domain , auditSource ) ;
2019-02-26 19:43:18 -08:00
2021-09-24 10:22:45 -07:00
safe ( services . rebuildService ( 'turn' , auditSource ) , { debug } ) ; // to update the realm variable
2019-02-26 19:43:18 -08:00
}
2022-11-29 18:11:22 +01:00
async function renewCerts ( options , auditSource ) {
assert . strictEqual ( typeof options , 'object' ) ;
2018-12-10 20:20:53 -08:00
assert . strictEqual ( typeof auditSource , 'object' ) ;
2019-08-27 22:39:59 -07:00
2022-11-29 18:11:22 +01:00
const taskId = await tasks . add ( tasks . TASK _CHECK _CERTS , [ options , auditSource ] ) ;
2021-09-17 09:22:46 -07:00
tasks . startTask ( taskId , { } ) ;
2021-07-12 23:35:30 -07:00
return taskId ;
2018-12-10 20:20:53 -08:00
}
2020-08-15 23:17:29 -07:00
2021-08-27 09:52:24 -07:00
async function setupDnsAndCert ( subdomain , domain , auditSource , progressCallback ) {
2020-08-15 23:17:29 -07:00
assert . strictEqual ( typeof subdomain , 'string' ) ;
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof auditSource , 'object' ) ;
assert . strictEqual ( typeof progressCallback , 'function' ) ;
2022-11-28 21:23:06 +01:00
const dashboardFqdn = dns . fqdn ( subdomain , domain ) ;
2020-08-15 23:17:29 -07:00
2022-01-06 17:02:16 -08:00
const ipv4 = await sysinfo . getServerIPv4 ( ) ;
2022-02-15 12:31:55 -08:00
const ipv6 = await sysinfo . getServerIPv6 ( ) ;
2020-08-15 23:17:29 -07:00
2022-02-06 11:21:32 -08:00
progressCallback ( { percent : 20 , message : ` Updating DNS of ${ dashboardFqdn } ` } ) ;
2022-01-06 17:02:16 -08:00
await dns . upsertDnsRecords ( subdomain , domain , 'A' , [ ipv4 ] ) ;
2022-02-15 12:31:55 -08:00
if ( ipv6 ) await dns . upsertDnsRecords ( subdomain , domain , 'AAAA' , [ ipv6 ] ) ;
2022-02-06 11:21:32 -08:00
progressCallback ( { percent : 40 , message : ` Waiting for DNS of ${ dashboardFqdn } ` } ) ;
2022-01-06 17:02:16 -08:00
await dns . waitForDnsRecord ( subdomain , domain , 'A' , ipv4 , { interval : 30000 , times : 50000 } ) ;
2022-02-15 12:31:55 -08:00
if ( ipv6 ) await dns . waitForDnsRecord ( subdomain , domain , 'AAAA' , ipv6 , { interval : 30000 , times : 50000 } ) ;
2022-02-06 11:21:32 -08:00
progressCallback ( { percent : 60 , message : ` Getting certificate of ${ dashboardFqdn } ` } ) ;
2022-11-28 22:32:34 +01:00
const location = { subdomain , domain , fqdn : dashboardFqdn , type : apps . LOCATION _TYPE _DASHBOARD , certificate : null } ;
2023-01-31 23:45:17 +01:00
await reverseProxy . ensureCertificate ( location , { } , auditSource ) ;
2020-08-15 23:17:29 -07:00
}
2021-02-24 18:42:39 -08:00
2021-07-12 23:35:30 -07:00
async function syncDnsRecords ( options ) {
2021-02-24 18:42:39 -08:00
assert . strictEqual ( typeof options , 'object' ) ;
2021-07-12 23:35:30 -07:00
const taskId = await tasks . add ( tasks . TASK _SYNC _DNS _RECORDS , [ options ] ) ;
2021-09-17 09:22:46 -07:00
tasks . startTask ( taskId , { } ) ;
2021-07-12 23:35:30 -07:00
return taskId ;
2021-02-24 18:42:39 -08:00
}
2022-10-12 10:26:21 +02:00
async function updateDiskUsage ( ) {
const taskId = await tasks . add ( tasks . TASK _UPDATE _DISK _USAGE , [ ] ) ;
tasks . startTask ( taskId , { } ) ;
return taskId ;
}
2023-01-23 17:56:01 +01:00
async function getBlockDevices ( ) {
let info ;
try {
2023-01-23 19:45:16 +01:00
info = JSON . parse ( execSync ( 'lsblk --paths --json --list --fs' , { encoding : 'utf8' } ) ) ;
2023-01-23 17:56:01 +01:00
} catch ( e ) {
console . error ( 'Failed to list disks:' , e ) ;
throw new BoxError ( BoxError . INTERNAL _ERROR , e ) ;
}
2023-01-24 14:40:23 +01:00
// filter only for ext4 and xfs disks
const devices = info . blockdevices . filter ( d => d . fstype === 'ext4' || d . fstype === 'xfs' ) ;
2023-01-23 17:56:01 +01:00
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 ,
2023-01-24 14:40:23 +01:00
size : d . fsavail || 0 ,
type : d . fstype ,
2023-01-23 18:43:34 +01:00
mountpoint : d . mountpoints ? d . mountpoints [ 0 ] : d . mountpoint // we only support one mountpoint here old lsblk only exposed one via .mountpoint
2023-01-23 17:56:01 +01:00
} ;
} ) ;
}