diff --git a/src/apptask.js b/src/apptask.js index f3c10df16..b27b09566 100644 --- a/src/apptask.js +++ b/src/apptask.js @@ -38,8 +38,7 @@ const apps = require('./apps.js'), shell = require('./shell.js')('apptask'), _ = require('./underscore.js'); -const MV_VOLUME_CMD = path.join(__dirname, 'scripts/mvvolume.sh'), - LOGROTATE_CONFIG_EJS = fs.readFileSync(__dirname + '/logrotate.ejs', { encoding: 'utf8' }), +const LOGROTATE_CONFIG_EJS = fs.readFileSync(__dirname + '/logrotate.ejs', { encoding: 'utf8' }), CONFIGURE_LOGROTATE_CMD = path.join(__dirname, 'scripts/configurelogrotate.sh'); function makeTaskError(error, app) { @@ -209,25 +208,6 @@ async function downloadIcon(app) { await updateApp(app, { appStoreIcon }); } -async function moveDataDir(app, targetVolumeId, targetVolumePrefix) { - assert.strictEqual(typeof app, 'object'); - assert.ok(app.manifest.addons.localstorage, 'should have local storage addon'); - assert(targetVolumeId === null || typeof targetVolumeId === 'string'); - assert(targetVolumePrefix === null || typeof targetVolumePrefix === 'string'); - - const resolvedSourceDir = await apps.getStorageDir(app); - const resolvedTargetDir = await apps.getStorageDir(Object.assign({}, app, { storageVolumeId: targetVolumeId, storageVolumePrefix: targetVolumePrefix })); - - debug(`moveDataDir: migrating data from ${resolvedSourceDir} to ${resolvedTargetDir}`); - - if (resolvedSourceDir !== resolvedTargetDir) { - const [error] = await safe(shell.promises.sudo([ MV_VOLUME_CMD, resolvedSourceDir, resolvedTargetDir ], {})); - if (error) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error migrating data directory: ${error.message}`); - } - - await updateApp(app, { storageVolumeId: targetVolumeId, storageVolumePrefix: targetVolumePrefix }); -} - async function downloadImage(manifest) { assert.strictEqual(typeof manifest, 'object'); @@ -531,13 +511,10 @@ async function migrateDataDirCommand(app, args, progressCallback) { await progressCallback({ percent: 10, message: 'Deleting old containers' }); await deleteContainers(app, { managedOnly: true }); - // re-setup addon since this creates the localStorage destination - await progressCallback({ percent: 50, message: 'Setting up addons' }); - await services.setupAddons(Object.assign({}, app, { storageVolumeId: newStorageVolumeId, storageVolumePrefix: newStorageVolumePrefix }), _.pick(app.manifest.addons, 'localstorage')); - if (app.manifest.addons?.localstorage) { - await progressCallback({ percent: 60, message: 'Moving data dir' }); - await moveDataDir(app, newStorageVolumeId, newStorageVolumePrefix); + await progressCallback({ percent: 40, message: 'Moving data dir' }); + await services.moveDataDir(app, newStorageVolumeId, newStorageVolumePrefix); + await updateApp(app, { storageVolumeId: newStorageVolumeId, storageVolumePrefix: newStorageVolumePrefix }); } await progressCallback({ percent: 90, message: 'Creating container' }); diff --git a/src/scripts/mvvolume.sh b/src/scripts/mvvolume.sh index e6a31254b..27c4961d8 100755 --- a/src/scripts/mvvolume.sh +++ b/src/scripts/mvvolume.sh @@ -26,6 +26,8 @@ if [[ "${BOX_ENV}" == "test" ]]; then [[ "${target_dir}" != *"/.cloudron_test/"* ]] && exit 1 fi +mkdir -p "${target_dir}" + source_stat=$(stat --format='%d,%i' "${source_dir}") target_stat=$(stat --format='%d,%i' "${target_dir}") diff --git a/src/services.js b/src/services.js index 44ae76ebc..36fb8d70e 100644 --- a/src/services.js +++ b/src/services.js @@ -16,6 +16,8 @@ exports = module.exports = { startServices, + moveDataDir, // localstorage specific command + setupAddons, teardownAddons, backupAddons, @@ -76,6 +78,7 @@ const RESTART_SERVICE_CMD = path.join(__dirname, 'scripts/restartservice.sh'); const CLEARVOLUME_CMD = path.join(__dirname, 'scripts/clearvolume.sh'); const RMVOLUME_CMD = path.join(__dirname, 'scripts/rmvolume.sh'); const SETUPVOLUME_CMD = path.join(__dirname, 'scripts/setupvolume.sh'); +const MV_VOLUME_CMD = path.join(__dirname, 'scripts/mvvolume.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 @@ -2207,3 +2210,20 @@ async function checkAddonsSupport(addons) { return null; } + +async function moveDataDir(app, targetVolumeId, targetVolumePrefix) { + assert.strictEqual(typeof app, 'object'); + assert.ok(app.manifest.addons.localstorage, 'should have local storage addon'); + assert(targetVolumeId === null || typeof targetVolumeId === 'string'); + assert(targetVolumePrefix === null || typeof targetVolumePrefix === 'string'); + + const resolvedSourceDir = await apps.getStorageDir(app); + const resolvedTargetDir = await apps.getStorageDir(Object.assign({}, app, { storageVolumeId: targetVolumeId, storageVolumePrefix: targetVolumePrefix })); + + debug(`moveDataDir: migrating data from ${resolvedSourceDir} to ${resolvedTargetDir}`); + + if (resolvedSourceDir !== resolvedTargetDir) { + const [error] = await safe(shell.promises.sudo([ MV_VOLUME_CMD, resolvedSourceDir, resolvedTargetDir ], {})); + if (error) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error migrating data directory: ${error.message}`); + } +}