54 lines
2.4 KiB
JavaScript
54 lines
2.4 KiB
JavaScript
'use strict';
|
|
|
|
const crypto = require('node:crypto'),
|
|
path = require('node:path'),
|
|
safe = require('@cloudron/safetydance').default;
|
|
|
|
function getMountPoint(dataDir) {
|
|
const output = safe.child_process.execSync(`df --output=target "${dataDir}" | tail -1`, { encoding: 'utf8' });
|
|
if (!output) return dataDir;
|
|
const mountPoint = output.trim();
|
|
if (mountPoint === '/') return dataDir;
|
|
return mountPoint;
|
|
}
|
|
|
|
exports.up = async function(db) {
|
|
// use safe() here because this migration failed midway in 7.2.4
|
|
await safe(db.runSql('ALTER TABLE apps ADD storageVolumeId VARCHAR(128), ADD FOREIGN KEY(storageVolumeId) REFERENCES volumes(id)'));
|
|
await safe(db.runSql('ALTER TABLE apps ADD storageVolumePrefix VARCHAR(128)'));
|
|
await safe(db.runSql('ALTER TABLE apps ADD CONSTRAINT apps_storageVolume UNIQUE (storageVolumeId, storageVolumePrefix)'));
|
|
|
|
const apps = await db.runSql('SELECT * FROM apps WHERE dataDir IS NOT NULL');
|
|
|
|
for (const app of apps) {
|
|
const allVolumes = await db.runSql('SELECT * FROM volumes');
|
|
|
|
console.log(`data-dir (${app.id}): migrating data dir ${app.dataDir}`);
|
|
|
|
const mountPoint = getMountPoint(app.dataDir);
|
|
const prefix = path.relative(mountPoint, app.dataDir);
|
|
|
|
console.log(`data-dir (${app.id}): migrating to mountpoint ${mountPoint} and prefix ${prefix}`);
|
|
|
|
const volume = allVolumes.find(v => v.hostPath === mountPoint);
|
|
if (volume) {
|
|
console.log(`data-dir (${app.id}): using existing volume ${volume.id}`);
|
|
await db.runSql('UPDATE apps SET storageVolumeId=?, storageVolumePrefix=? WHERE id=?', [ volume.id, prefix, app.id ]);
|
|
continue;
|
|
}
|
|
|
|
const id = crypto.randomUUID().replace(/-/g, ''); // to make systemd mount file names more readable
|
|
const name = `appdata-${id}`;
|
|
const type = app.dataDir === mountPoint ? 'filesystem' : 'mountpoint';
|
|
|
|
console.log(`data-dir (${app.id}): creating new volume ${id}`);
|
|
await db.runSql('INSERT INTO volumes (id, name, hostPath, mountType, mountOptionsJson) VALUES (?, ?, ?, ?, ?)', [ id, name, mountPoint, type, JSON.stringify({}) ]);
|
|
await db.runSql('UPDATE apps SET storageVolumeId=?, storageVolumePrefix=? WHERE id=?', [ id, prefix, app.id ]);
|
|
}
|
|
|
|
await db.runSql('ALTER TABLE apps DROP COLUMN dataDir');
|
|
};
|
|
|
|
exports.down = async function(/*db*/) {
|
|
};
|