From 774f14327cabb24d438bd2f56abf9d76bad97dba Mon Sep 17 00:00:00 2001 From: Girish Ramakrishnan Date: Sat, 30 Mar 2024 18:31:57 +0100 Subject: [PATCH] addons: optional start mongodb based on AVX --- CHANGES | 5 +++++ scripts/cloudron-setup | 3 ++- src/apps.js | 3 ++- src/services.js | 31 +++++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 87987baa4..adaacbd9a 100644 --- a/CHANGES +++ b/CHANGES @@ -2765,3 +2765,8 @@ * backups: deleted apps must also be displayed in contents * filemanager: make uploads cancellable * Fix crash on systemds with no swap + +[8.0.0] +* mongodb: optionally start mongodb based on AVX support +* dashboard: font and color improvements + diff --git a/scripts/cloudron-setup b/scripts/cloudron-setup index 86b5cb193..a7846c160 100755 --- a/scripts/cloudron-setup +++ b/scripts/cloudron-setup @@ -206,7 +206,8 @@ else version="${requestedVersion}" fi -if vergte "${version}" "7.5.99"; then +# 7.6 dropped support for CPUs lacking AVX but this came back in 8.0 +if vergte "${version}" "7.5.99" && vergte "7.8.0" "${version}"; then if ! grep -q avx /proc/cpuinfo; then echo "Cloudron version ${version} requires AVX support in the CPU. No avx found in /proc/cpuinfo" exit 1 diff --git a/src/apps.js b/src/apps.js index 9321b0d79..f29e56bad 100644 --- a/src/apps.js +++ b/src/apps.js @@ -2482,7 +2482,8 @@ async function checkManifest(manifest) { return new BoxError(BoxError.BAD_FIELD, 'App version requires a new platform version'); } - return null; + const error = await services.checkAddonsSupport(manifest.addons || {}); + return error; } async function createExec(app, options) { diff --git a/src/services.js b/src/services.js index 35cd8e46c..323d098ca 100644 --- a/src/services.js +++ b/src/services.js @@ -21,6 +21,7 @@ exports = module.exports = { backupAddons, restoreAddons, clearAddons, + checkAddonsSupport, getEnvironment, getContainerNamesSync, @@ -75,6 +76,7 @@ const MKDIRVOLUME_CMD = path.join(__dirname, 'scripts/mkdirvolume.sh'); // setup can be called multiple times for the same app (configure crash restart) and existing data must not be lost // teardown is destructive. app data stored with the addon is lost +// addons have 1-1 mapping with the manifest const ADDONS = { turn: { setup: setupTurn, @@ -1492,6 +1494,12 @@ async function restorePostgreSql(app, options) { await pipeFileToRequest(dumpPath('postgresql', app.id), `http://${result.ip}:3000/databases/${database}/restore?access_token=${result.token}&username=${username}`); } +async function hasAVX() { + // mongodb 5 and above requires AVX + const [error] = await safe(shell.exec('grep -q avx /proc/cpuinfo', {})); + return !error; +} + async function startMongodb(existingInfra) { assert.strictEqual(typeof existingInfra, 'object'); @@ -1533,6 +1541,11 @@ async function startMongodb(existingInfra) { await docker.stopContainer('mongodb'); await docker.deleteContainer('mongodb'); + if (!await hasAVX()) { + debug('startMongodb: not starting mongodb because CPU does not have AVX'); + return; + } + debug('startMongodb: starting mongodb container'); await shell.exec('startMongodb', runCmd, { shell: '/bin/bash' }); @@ -1548,6 +1561,8 @@ async function setupMongoDb(app, options) { debug('Setting up mongodb'); + if (!await hasAVX()) throw new BoxError(BoxError.ADDONS_ERROR, 'Error setting up mongodb. CPU has no AVX support'); + const existingPassword = await addonConfigs.getByName(app.id, 'mongodb', '%MONGODB_PASSWORD'); let database = await addonConfigs.getByName(app.id, 'mongodb', '%MONGODB_DATABASE'); database = database || hat(8 * 8); // 16 bytes. keep this short, so as to not overflow the 127 byte index length in MongoDB < 4.4 @@ -1589,6 +1604,8 @@ async function clearMongodb(app, options) { assert.strictEqual(typeof app, 'object'); assert.strictEqual(typeof options, 'object'); + if (!await hasAVX()) throw new BoxError(BoxError.ADDONS_ERROR, 'Error clearing mongodb. CPU has no AVX support'); + const result = await getContainerDetails('mongodb', 'CLOUDRON_MONGODB_TOKEN'); const database = await addonConfigs.getByName(app.id, 'mongodb', '%MONGODB_DATABASE'); @@ -1605,6 +1622,8 @@ async function teardownMongoDb(app, options) { assert.strictEqual(typeof app, 'object'); assert.strictEqual(typeof options, 'object'); + if (!await hasAVX()) throw new BoxError(BoxError.ADDONS_ERROR, 'Error tearing down mongodb. CPU has no AVX support'); + const result = await getContainerDetails('mongodb', 'CLOUDRON_MONGODB_TOKEN'); const database = await addonConfigs.getByName(app.id, 'mongodb', '%MONGODB_DATABASE'); @@ -1625,6 +1644,8 @@ async function backupMongoDb(app, options) { debug('Backing up mongodb'); + if (!await hasAVX()) throw new BoxError(BoxError.ADDONS_ERROR, 'Error backing up mongodb. CPU has no AVX support'); + const result = await getContainerDetails('mongodb', 'CLOUDRON_MONGODB_TOKEN'); const database = await addonConfigs.getByName(app.id, 'mongodb', '%MONGODB_DATABASE'); @@ -1639,6 +1660,8 @@ async function restoreMongoDb(app, options) { debug('restoreMongoDb'); + if (!await hasAVX()) throw new BoxError(BoxError.ADDONS_ERROR, 'Error restoring mongodb. CPU has no AVX support'); + const result = await getContainerDetails('mongodb', 'CLOUDRON_MONGODB_TOKEN'); const database = await addonConfigs.getByName(app.id, 'mongodb', '%MONGODB_DATABASE'); @@ -2058,3 +2081,11 @@ async function getDynamicEnvironmentOidc(app, options) { return tmp; } + +async function checkAddonsSupport(addons) { + assert.strictEqual(typeof addons, 'object'); + + if (addons.mongodb && !await hasAVX()) return new BoxError(BoxError.BAD_FIELD, 'Addon MongoDB requires AVX support'); + + return null; +}