diff --git a/services/appsService.js b/services/appsService.js index 8130b8a3..91a68689 100644 --- a/services/appsService.js +++ b/services/appsService.js @@ -1041,6 +1041,9 @@ async function appStats(req, res) { const authorized = await verificationHelper.verifyPrivilege('appownerabove', req, mainAppName); if (authorized === true) { const response = await dockerService.dockerContainerStats(appname); + // eslint-disable-next-line no-use-before-define + const containerStorageInfo = await getContainerStorage(appname); + response.disk_stats = containerStorageInfo; const appResponse = messageHelper.createDataMessage(response); res.json(appResponse); } else { @@ -1077,11 +1080,7 @@ async function appMonitor(req, res) { const authorized = await verificationHelper.verifyPrivilege('appownerabove', req, mainAppName); if (authorized === true) { if (appsMonitored[appname]) { - const response = { - lastHour: appsMonitored[appname].oneMinuteStatsStore, - lastDay: appsMonitored[appname].fifteenMinStatsStore, - }; - + const response = appsMonitored[appname].statsStore; const appResponse = messageHelper.createDataMessage(response); res.json(appResponse); } else throw new Error('No data available'); @@ -1154,35 +1153,70 @@ async function getAppFolderSize(appName) { } /** - * Returns total app container storage in bytes - * @param {string} appName - name or id of the container - * @returns {Promise} + * Retrieves the storage usage of a specified Docker container, including bind mounts and volume mounts. + * @param {string} appName The name of the Docker container to inspect. + * @returns {Promise} An object containing the sizes of bind mounts, volume mounts, root filesystem, total used storage, and status. + * - bind: Size of bind mounts in bytes. + * - volume: Size of volume mounts in bytes. + * - rootfs: Size of the container's root filesystem in bytes. + * - used: Total used size (sum of bind, volume, and rootfs sizes) in bytes. + * - status: 'success' if the operation succeeded, 'error' otherwise. + * - message: An error message if the operation failed. */ async function getContainerStorage(appName) { try { const containerInfo = await dockerService.dockerContainerInspect(appName, { size: true }); - let containerTotalSize = serviceHelper.ensureNumber(containerInfo.SizeRootFs) || 0; - // traverse mounts/volumes to find size used on host + let bindMountsSize = 0; + let volumeMountsSize = 0; + const containerRootFsSize = serviceHelper.ensureNumber(containerInfo.SizeRootFs) || 0; if (containerInfo?.Mounts?.length) { await Promise.all(containerInfo.Mounts.map(async (mount) => { let source = mount?.Source; + const mountType = mount?.Type; if (source) { - // remove /appdata to get true size of the app folder - source = source.replace('/appdata', ''); - const exec = `sudo du -sb ${source}`; - const mountInfo = await cmdAsync(exec); - const mountSize = serviceHelper.ensureNumber(mountInfo?.split(source)[0]) || 0; - if (typeof mountSize === 'number' && !Number.isNaN(mountSize)) { - containerTotalSize += mountSize; + if (mountType === 'bind') { + source = source.replace('/appdata', ''); + const exec = `sudo du -sb ${source}`; + const mountInfo = await cmdAsync(exec); + if (mountInfo) { + const sizeNum = serviceHelper.ensureNumber(mountInfo.split('\t')[0]) || 0; + bindMountsSize += sizeNum; + } else { + log.warn(`No mount info returned for source: ${source}`); + } + } else if (mountType === 'volume') { + const exec = `sudo du -sb ${source}`; + const mountInfo = await cmdAsync(exec); + if (mountInfo) { + const sizeNum = serviceHelper.ensureNumber(mountInfo.split('\t')[0]) || 0; + volumeMountsSize += sizeNum; + } else { + log.warn(`No mount info returned for source: ${source}`); + } + } else { + log.warn(`Unsupported mount type or source: Type: ${mountType}, Source: ${source}`); } } })); - return containerTotalSize; } - return containerTotalSize; + const usedSize = bindMountsSize + volumeMountsSize + containerRootFsSize; + return { + bind: bindMountsSize, + volume: volumeMountsSize, + rootfs: containerRootFsSize, + used: usedSize, + status: 'success', + }; } catch (error) { - log.error(error); - return 0; + log.error(`Error fetching container storage: ${error.message}`); + return { + bind: 0, + volume: 0, + rootfs: 0, + used: 0, + status: 'error', + message: error.message, + }; } } @@ -1194,14 +1228,17 @@ function startAppMonitoring(appName) { if (!appName) { throw new Error('No App specified'); } else { - appsMonitored[appName] = {}; // oneMinuteInterval, fifteenMinInterval, oneMinuteStatsStore, fifteenMinStatsStore - if (!appsMonitored[appName].fifteenMinStatsStore) { - appsMonitored[appName].fifteenMinStatsStore = []; + log.info('Initialize Monitoring...'); + appsMonitored[appName] = {}; // Initialize the app's monitoring object + if (!appsMonitored[appName].statsStore) { + appsMonitored[appName].statsStore = []; } - if (!appsMonitored[appName].oneMinuteStatsStore) { - appsMonitored[appName].oneMinuteStatsStore = []; + if (!appsMonitored[appName].lastHourstatsStore) { + appsMonitored[appName].lastHourstatsStore = []; } + // Clear previous interval for this app to prevent multiple intervals clearInterval(appsMonitored[appName].oneMinuteInterval); + appsMonitored[appName].run = 0; appsMonitored[appName].oneMinuteInterval = setInterval(async () => { try { if (!appsMonitored[appName]) { @@ -1216,53 +1253,28 @@ function startAppMonitoring(appName) { stopAppMonitoring(appName, true); return; } + appsMonitored[appName].run += 1; const statsNow = await dockerService.dockerContainerStats(appName); - const containerTotalSize = await getContainerStorage(appName); - - // const appFolderName = dockerService.getAppDockerNameIdentifier(appName).substring(1); - // const folderSize = await getAppFolderSize(appFolderName); - statsNow.disk_stats = { - used: containerTotalSize ?? 0, - }; - appsMonitored[appName].oneMinuteStatsStore.unshift({ timestamp: Date.now(), data: statsNow }); // Most recent stats object is at position 0 in the array - if (appsMonitored[appName].oneMinuteStatsStore.length > 60) { - appsMonitored[appName].oneMinuteStatsStore.length = 60; // Store stats every 1 min for the last hour only + const containerStorageInfo = await getContainerStorage(appName); + statsNow.disk_stats = containerStorageInfo; + const now = Date.now(); + if (appsMonitored[appName].run % 3 === 0) { + appsMonitored[appName].statsStore.push({ timestamp: now, data: statsNow }); + const statsStoreSizeInBytes = new TextEncoder().encode(JSON.stringify(appsMonitored[appName].statsStore)).length; + const estimatedSizeInMB = statsStoreSizeInBytes / (1024 * 1024); + log.info(`Size of stats for ${appName}: ${estimatedSizeInMB.toFixed(2)} MB`); + appsMonitored[appName].statsStore = appsMonitored[appName].statsStore.filter( + (stat) => now - stat.timestamp <= 7 * 24 * 60 * 60 * 1000, + ); } + appsMonitored[appName].lastHourstatsStore.push({ timestamp: now, data: statsNow }); + appsMonitored[appName].lastHourstatsStore = appsMonitored[appName].lastHourstatsStore.filter( + (stat) => now - stat.timestamp <= 60 * 60 * 1000, + ); } catch (error) { log.error(error); } }, 1 * 60 * 1000); - clearInterval(appsMonitored[appName].fifteenMinInterval); - appsMonitored[appName].fifteenMinInterval = setInterval(async () => { - try { - if (!appsMonitored[appName]) { - log.error(`Monitoring of ${appName} already stopped`); - clearInterval(appsMonitored[appName].fifteenMinInterval); - return; - } - const dockerContainer = await dockerService.getDockerContainerOnly(appName); - if (!dockerContainer) { - log.error(`Monitoring of ${appName} not possible. App does not exist. Forcing stopping of monitoring`); - // eslint-disable-next-line no-use-before-define - stopAppMonitoring(appName, true); - return; - } - const statsNow = await dockerService.dockerContainerStats(appName); - const containerTotalSize = await getContainerStorage(appName); - - // const appFolderName = dockerService.getAppDockerNameIdentifier(appName).substring(1); - // const folderSize = await getAppFolderSize(appFolderName); - statsNow.disk_stats = { - used: containerTotalSize ?? 0, - }; - appsMonitored[appName].fifteenMinStatsStore.unshift({ timestamp: Date.now(), data: statsNow }); // Most recent stats object is at position 0 in the array - if (appsMonitored[appName].oneMinuteStatsStore.length > 96) { - appsMonitored[appName].fifteenMinStatsStore.length = 96; // Store stats every 15 mins for the last day only - } - } catch (error) { - log.error(error); - } - }, 15 * 60 * 1000); } } @@ -1275,7 +1287,6 @@ function startAppMonitoring(appName) { function stopAppMonitoring(appName, deleteData) { if (appsMonitored[appName]) { clearInterval(appsMonitored[appName].oneMinuteInterval); - clearInterval(appsMonitored[appName].fifteenMinInterval); } if (deleteData) { delete appsMonitored[appName]; @@ -8965,6 +8976,8 @@ function getAppPorts(appSpecs) { * @returns {void} Return statement is only used here to interrupt the function and nothing is returned. */ let firstExecutionAfterItsSynced = true; +let fluxNodeWasAlreadyConfirmed = false; +let fluxNodeWasNotConfirmedOnLastCheck = false; async function trySpawningGlobalApplication() { try { // how do we continue with this function? @@ -8987,10 +9000,21 @@ async function trySpawningGlobalApplication() { const isNodeConfirmed = await generalService.isNodeStatusConfirmed(); if (!isNodeConfirmed) { log.info('Flux Node not Confirmed. Global applications will not be installed'); + fluxNodeWasNotConfirmedOnLastCheck = true; await serviceHelper.delay(config.fluxapps.installation.delay * 1000); trySpawningGlobalApplication(); return; } + if (fluxNodeWasAlreadyConfirmed && fluxNodeWasNotConfirmedOnLastCheck) { + fluxNodeWasNotConfirmedOnLastCheck = false; + setTimeout(() => { + // after 125 minutes of running ok and to make sure we are connected for enough time for receiving all apps running on other nodes + // 125 minutes should give enough time for node receive currently two times the apprunning messages + trySpawningGlobalApplication(); + }, 125 * 60 * 1000); + return; + } + fluxNodeWasAlreadyConfirmed = true; const benchmarkResponse = await benchmarkService.getBenchmarks(); if (benchmarkResponse.status === 'error') { @@ -9619,27 +9643,34 @@ async function checkApplicationsCpuUSage() { // eslint-disable-next-line no-restricted-syntax for (const app of appsInstalled) { if (app.version <= 3) { - stats = appsMonitored[app.name].oneMinuteStatsStore; + stats = appsMonitored[app.name].lastHourstatsStore; // eslint-disable-next-line no-await-in-loop const inspect = await dockerService.dockerContainerInspect(app.name); - if (inspect && stats.length > 55) { + if (inspect && stats && stats.length > 4) { const nanoCpus = inspect.HostConfig.NanoCpus; - let cpuThrottling = true; + let cpuThrottlingRuns = 0; + let cpuThrottling = false; + const cpuPercentage = nanoCpus / app.cpu / 1e9; // eslint-disable-next-line no-restricted-syntax for (const stat of stats) { const cpuUsage = stat.data.cpu_stats.cpu_usage.total_usage - stat.data.precpu_stats.cpu_usage.total_usage; const systemCpuUsage = stat.data.cpu_stats.system_cpu_usage - stat.data.precpu_stats.system_cpu_usage; const cpu = ((cpuUsage / systemCpuUsage) * stat.data.cpu_stats.online_cpus * 100) / app.cpu || 0; - const realCpu = cpu / (nanoCpus / app.cpu / 1e9); - if (realCpu < 92) { - cpuThrottling = false; - break; + const realCpu = cpu / cpuPercentage; + if (realCpu >= 92) { + cpuThrottlingRuns += 1; } } - log.info(`checkApplicationsCpuUSage ${app.name} cpu high load: : ${cpuThrottling}`); + if (cpuThrottlingRuns >= stats.length * 0.8) { + // cpu was high on 80% of the checks + cpuThrottling = true; + } + appsMonitored[app.name].lastHourstatsStore = []; + log.info(`checkApplicationsCpuUSage ${app.name} cpu high load: ${cpuThrottling}`); + log.info(`checkApplicationsCpuUSage ${cpuPercentage}`); if (cpuThrottling && app.cpu > 1) { - if (nanoCpus / app.cpu / 1e9 === 1) { - if (cpuThrottling && app.cpu > 2) { + if (cpuPercentage === 1) { + if (app.cpu > 2) { // eslint-disable-next-line no-await-in-loop await dockerService.appDockerUpdateCpu(app.name, Math.round(app.cpu * 1e9 * 0.8)); } else { @@ -9648,36 +9679,55 @@ async function checkApplicationsCpuUSage() { } log.info(`checkApplicationsCpuUSage ${app.name} lowering cpu.`); } - } else if (nanoCpus / app.cpu / 1e9 < 1) { + } else if (cpuPercentage <= 0.8) { + // eslint-disable-next-line no-await-in-loop + await dockerService.appDockerUpdateCpu(app.name, Math.round(app.cpu * 1e9 * 0.85)); + log.info(`checkApplicationsCpuUSage ${app.name} increasing cpu 85.`); + } else if (cpuPercentage <= 0.85) { + // eslint-disable-next-line no-await-in-loop + await dockerService.appDockerUpdateCpu(app.name, Math.round(app.cpu * 1e9 * 0.9)); + log.info(`checkApplicationsCpuUSage ${app.name} increasing cpu 90.`); + } else if (cpuPercentage <= 0.9) { + // eslint-disable-next-line no-await-in-loop + await dockerService.appDockerUpdateCpu(app.name, Math.round(app.cpu * 1e9 * 0.95)); + log.info(`checkApplicationsCpuUSage ${app.name} increasing cpu 95.`); + } else if (cpuPercentage < 1) { // eslint-disable-next-line no-await-in-loop await dockerService.appDockerUpdateCpu(app.name, Math.round(app.cpu * 1e9)); - log.info(`checkApplicationsCpuUSage ${app.name} increasing cpu.`); + log.info(`checkApplicationsCpuUSage ${app.name} increasing cpu 100.`); } } } else { // eslint-disable-next-line no-restricted-syntax for (const appComponent of app.compose) { - stats = appsMonitored[`${appComponent.name}_${app.name}`].oneMinuteStatsStore; + stats = appsMonitored[`${appComponent.name}_${app.name}`].lastHourstatsStore; // eslint-disable-next-line no-await-in-loop const inspect = await dockerService.dockerContainerInspect(`${appComponent.name}_${app.name}`); - if (inspect && stats.length > 55) { + if (inspect && stats && stats.length > 4) { const nanoCpus = inspect.HostConfig.NanoCpus; - let cpuThrottling = true; + let cpuThrottlingRuns = 0; + let cpuThrottling = false; + const cpuPercentage = nanoCpus / appComponent.cpu / 1e9; // eslint-disable-next-line no-restricted-syntax for (const stat of stats) { const cpuUsage = stat.data.cpu_stats.cpu_usage.total_usage - stat.data.precpu_stats.cpu_usage.total_usage; const systemCpuUsage = stat.data.cpu_stats.system_cpu_usage - stat.data.precpu_stats.system_cpu_usage; const cpu = ((cpuUsage / systemCpuUsage) * 100 * stat.data.cpu_stats.online_cpus) / appComponent.cpu || 0; - const realCpu = cpu / (nanoCpus / appComponent.cpu / 1e9); - if (realCpu < 92) { - cpuThrottling = false; - break; + const realCpu = cpu / cpuPercentage; + if (realCpu >= 92) { + cpuThrottlingRuns += 1; } } - log.info(`checkApplicationsCpuUSage ${appComponent.name}_${app.name} cpu high load: : ${cpuThrottling}`); + if (cpuThrottlingRuns >= stats.length * 0.8) { + // cpu was high on 80% of the checks + cpuThrottling = true; + } + appsMonitored[`${appComponent.name}_${app.name}`].lastHourstatsStore = []; + log.info(`checkApplicationsCpuUSage ${appComponent.name}_${app.name} cpu high load: ${cpuThrottling}`); + log.info(`checkApplicationsCpuUSage ${cpuPercentage}`); if (cpuThrottling && appComponent.cpu > 1) { - if (nanoCpus / appComponent.cpu / 1e9 === 1) { - if (cpuThrottling && appComponent.cpu > 2) { + if (cpuPercentage === 1) { + if (appComponent.cpu > 2) { // eslint-disable-next-line no-await-in-loop await dockerService.appDockerUpdateCpu(`${appComponent.name}_${app.name}`, Math.round(appComponent.cpu * 1e9 * 0.8)); } else { @@ -9686,10 +9736,22 @@ async function checkApplicationsCpuUSage() { } log.info(`checkApplicationsCpuUSage ${appComponent.name}_${app.name} lowering cpu.`); } - } else if (nanoCpus / appComponent.cpu / 1e9 < 1) { + } else if (cpuPercentage <= 0.8) { + // eslint-disable-next-line no-await-in-loop + await dockerService.appDockerUpdateCpu(`${appComponent.name}_${app.name}`, Math.round(appComponent.cpu * 1e9 * 0.85)); + log.info(`checkApplicationsCpuUSage ${appComponent.name}_${app.name} increasing cpu 85.`); + } else if (cpuPercentage <= 0.85) { + // eslint-disable-next-line no-await-in-loop + await dockerService.appDockerUpdateCpu(`${appComponent.name}_${app.name}`, Math.round(appComponent.cpu * 1e9 * 0.9)); + log.info(`checkApplicationsCpuUSage ${appComponent.name}_${app.name} increasing cpu 90.`); + } else if (cpuPercentage <= 0.9) { + // eslint-disable-next-line no-await-in-loop + await dockerService.appDockerUpdateCpu(`${appComponent.name}_${app.name}`, Math.round(appComponent.cpu * 1e9 * 0.95)); + log.info(`checkApplicationsCpuUSage ${appComponent.name}_${app.name} increasing cpu 95.`); + } else if (cpuPercentage < 1) { // eslint-disable-next-line no-await-in-loop await dockerService.appDockerUpdateCpu(`${appComponent.name}_${app.name}`, Math.round(appComponent.cpu * 1e9)); - log.info(`checkApplicationsCpuUSage ${appComponent.name}_${app.name} increasing cpu.`); + log.info(`checkApplicationsCpuUSage ${appComponent.name}_${app.name} increasing cpu 100.`); } } } @@ -13100,7 +13162,7 @@ async function monitorNodeStatus() { await serviceHelper.delay(20 * 60 * 1000); // 20m delay before next check } else { nodeConfirmedOnLastCheck = false; - await serviceHelper.delay(2 * 60 * 1000); // 2m delay before next check + await serviceHelper.delay(5 * 60 * 1000); // 5m delay before next check } return monitorNodeStatus(); } diff --git a/services/benchmarkService.js b/services/benchmarkService.js index b7f75a28..fdec68cb 100644 --- a/services/benchmarkService.js +++ b/services/benchmarkService.js @@ -17,7 +17,8 @@ let response = messageHelper.createErrorMessage(); let benchdClient = null; async function buildBenchdClient() { - const fluxbenchdPath = '/dat/usr/lib/fluxbenchd'; + const homeDirPath = path.join(__dirname, '../../../../'); + const fluxbenchdPath = path.join(homeDirPath, '.fluxbenchmark'); const exists = await fs.stat(fluxbenchdPath).catch(() => false); diff --git a/services/dockerService.js b/services/dockerService.js index eacf88ef..5d25f5ef 100644 --- a/services/dockerService.js +++ b/services/dockerService.js @@ -409,15 +409,11 @@ async function dockerContainerLogs(idOrName, lines) { async function dockerContainerLogsPolling(idOrName, lineCount, sinceTimestamp, callback) { try { - console.log('Starting dockerContainerLogsPolling'); const dockerContainer = await getDockerContainerByIdOrName(idOrName); - console.log(`Retrieved container: ${idOrName}`); - const logStream = new stream.PassThrough(); let logBuffer = ''; logStream.on('data', (chunk) => { - console.log('Received chunk of data'); logBuffer += chunk.toString('utf8'); const lines = logBuffer.split('\n'); logBuffer = lines.pop(); @@ -432,14 +428,13 @@ async function dockerContainerLogsPolling(idOrName, lineCount, sinceTimestamp, c }); logStream.on('error', (error) => { - console.error('Log stream encountered an error:', error); + log.error('Log stream encountered an error:', error); if (callback) { callback(error); } }); logStream.on('end', () => { - console.log('logStream ended'); if (callback) { callback(null, 'Stream ended'); // Notify end of logs } @@ -460,7 +455,7 @@ async function dockerContainerLogsPolling(idOrName, lineCount, sinceTimestamp, c // eslint-disable-next-line consistent-return dockerContainer.logs(logOptions, (err, mystream) => { if (err) { - console.error('Error fetching logs:', err); + log.error('Error fetching logs:', err); if (callback) { callback(err); } @@ -472,13 +467,12 @@ async function dockerContainerLogsPolling(idOrName, lineCount, sinceTimestamp, c logStream.end(); }, 1500); mystream.on('end', () => { - console.log('mystream ended'); logStream.end(); resolve(); }); mystream.on('error', (error) => { - console.error('Stream error:', error); + log.error('Stream error:', error); logStream.end(); if (callback) { callback(error); @@ -486,7 +480,7 @@ async function dockerContainerLogsPolling(idOrName, lineCount, sinceTimestamp, c reject(error); }); } catch (error) { - console.error('Error during stream processing:', error); + log.error('Error during stream processing:', error); if (callback) { callback(new Error('An error occurred while processing the log stream')); } @@ -495,7 +489,7 @@ async function dockerContainerLogsPolling(idOrName, lineCount, sinceTimestamp, c }); }); } catch (error) { - console.error('Error in dockerContainerLogsPolling:', error); + log.error('Error in dockerContainerLogsPolling:', error); if (callback) { callback(error); } @@ -663,6 +657,8 @@ async function appDockerCreate(appSpecifications, appName, isComponent, fullAppS Tty: false, ExposedPorts: exposedPorts, HostConfig: { + CpuQuota: Math.round(appSpecifications.cpu * 100000), + CpuPeriod: 100000, NanoCPUs: Math.round(appSpecifications.cpu * 1e9), Memory: Math.round(appSpecifications.ram * 1024 * 1024), MemorySwap: Math.round((appSpecifications.ram + (config.fluxapps.defaultSwap * 1000)) * 1024 * 1024), // default 2GB swap diff --git a/services/serviceManager.js b/services/serviceManager.js index 11b837e7..30669071 100644 --- a/services/serviceManager.js +++ b/services/serviceManager.js @@ -215,8 +215,8 @@ async function startFluxFunctions() { appsService.checkApplicationsCpuUSage(); setInterval(() => { appsService.checkApplicationsCpuUSage(); - }, 60 * 60 * 1000); - }, 65 * 60 * 1000); + }, 15 * 60 * 1000); + }, 15 * 60 * 1000); setTimeout(() => { // appsService.checkForNonAllowedAppsOnLocalNetwork(); appsService.checkMyAppsAvailability(); // periodically checks diff --git a/services/syncthingService.js b/services/syncthingService.js index 77277e92..3150d601 100644 --- a/services/syncthingService.js +++ b/services/syncthingService.js @@ -51,39 +51,38 @@ const stc = new FluxController(); * @returns {Promise<(string | null)>} config gile (XML). */ async function getConfigFile() { - // const homedir = os.homedir(); - // const configDir = path.join(homedir, '.config'); - // const syncthingDir = path.join(configDir, 'syncthing'); - // const configFile = path.join(syncthingDir, 'config.xml'); - const configFile = '/dat/usr/lib/syncthing/config.xml'; + const homedir = os.homedir(); + const configDir = path.join(homedir, '.config'); + const syncthingDir = path.join(configDir, 'syncthing'); + const configFile = path.join(syncthingDir, 'config.xml'); - // const user = os.userInfo().username; - // const owner = `${user}:${user}`; + const user = os.userInfo().username; + const owner = `${user}:${user}`; // As syncthing is running as root, we need to change owenership to running user - // const { error: chownConfigDirError } = await serviceHelper.runCommand('chown', { - // runAsRoot: true, - // logError: false, - // params: [owner, configDir], - // }); + const { error: chownConfigDirError } = await serviceHelper.runCommand('chown', { + runAsRoot: true, + logError: false, + params: [owner, configDir], + }); - // if (chownConfigDirError) return null; + if (chownConfigDirError) return null; - // const { error: chownSyncthingError } = await serviceHelper.runCommand('chown', { - // runAsRoot: true, - // logError: false, - // params: [owner, syncthingDir], - // }); + const { error: chownSyncthingError } = await serviceHelper.runCommand('chown', { + runAsRoot: true, + logError: false, + params: [owner, syncthingDir], + }); - // if (chownSyncthingError) return null; + if (chownSyncthingError) return null; - // const { error: chmodError } = await serviceHelper.runCommand('chmod', { - // runAsRoot: true, - // logError: false, - // params: ['644', configFile], - // }); + const { error: chmodError } = await serviceHelper.runCommand('chmod', { + runAsRoot: true, + logError: false, + params: ['644', configFile], + }); - // if (chmodError) return null; + if (chmodError) return null; let result = null; // this should never reject as chown would error first but just in case @@ -2495,11 +2494,10 @@ async function runSyncthingSentinel() { log.error('Unable to get syncthing deviceId. Reconfiguring syncthing.'); await stopSyncthing(); await installSyncthingIdempotently(); - // await configureDirectories(); + await configureDirectories(); - // const homedir = os.homedir(); - // const syncthingHome = path.join(homedir, '.config/syncthing'); - const syncthingHome = '/dat/usr/lib/syncthing'; + const homedir = os.homedir(); + const syncthingHome = path.join(homedir, '.config/syncthing'); const logFile = path.join(syncthingHome, 'syncthing.log'); if (stc.aborted) return 0; @@ -2517,26 +2515,32 @@ async function runSyncthingSentinel() { // adding old spawn with shell in the interim. childProcess.spawn( - 'nohup', - [ - 'syncthing', - '--logfile', - logFile, - '--logflags=3', - '--log-max-old-files=2', - '--log-max-size=26214400', - '--allow-newer-config', - '--no-browser', - '--home', - syncthingHome, - ], - { - detached: true, - stdio: 'ignore', - env: { HOME: syncthingHome }, - }, + `sudo nohup syncthing --logfile ${logFile} --logflags=3 --log-max-old-files=2 --log-max-size=26214400 --allow-newer-config --no-browser --home ${syncthingHome} >/dev/null 2>&1