Compare commits

...

6 Commits
8.3 ... 7.2

Author SHA1 Message Date
Girish Ramakrishnan
131f823e57 7.2.5 changes 2022-06-22 17:59:02 -07:00
Girish Ramakrishnan
24af101784 Fix issue where only 25 group members were returned
This is because GROUP_CONCAT defaults to 1024. uuid is 40 chars.
1024/40 = ~25

(cherry picked from commit 94a196bfa0)
2022-06-22 17:58:05 -07:00
Girish Ramakrishnan
c2fdb9ae3f Fix storage volume migration
Patch the migration so it runs again properly in 7.2.5

https://forum.cloudron.io/topic/7256/app-data-regression-in-v7-2-4
2022-06-22 17:15:54 -07:00
Johannes Zellner
21cf67639a Reload volumes in case one was created in the for loop
(cherry picked from commit e818e5f7d5)
2022-06-22 11:38:03 -07:00
Girish Ramakrishnan
52d2fe6909 data dir: allow sameness of old and new dir
this makes it easy to migrate to a new volume setup

(cherry picked from commit a32166bc9d)
2022-06-10 09:39:24 -07:00
Girish Ramakrishnan
61a1ac6983 7.2.4 changes 2022-06-10 09:33:12 -07:00
6 changed files with 49 additions and 12 deletions

10
CHANGES
View File

@@ -2498,3 +2498,13 @@
* Use volumes for app data instead of raw path
* initial xfs support
[7.2.4]
* volumes: Ensure long volume names do not overflow the table
* Move all appstore filter to the left
* app data: allow sameness of old and new dir
[7.2.5]
* Fix storage volume migration
* Fix issue where only 25 group members were returned
* Fix eventlog display

View File

@@ -13,14 +13,21 @@ function getMountPoint(dataDir) {
}
exports.up = async function(db) {
await db.runSql('ALTER TABLE apps ADD storageVolumeId VARCHAR(128), ADD FOREIGN KEY(storageVolumeId) REFERENCES volumes(id)');
await db.runSql('ALTER TABLE apps ADD storageVolumePrefix VARCHAR(128)');
await db.runSql('ALTER TABLE apps ADD CONSTRAINT apps_storageVolume UNIQUE (storageVolumeId, storageVolumePrefix)');
// 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');
const allVolumes = await db.runSql('SELECT * FROM volumes');
for (const app of apps) {
if (app.storageVolumeId) {
console.log(`data-dir (${app.id}): app was migrated in 7.2.4`);
continue;
}
const allVolumes = await db.runSql('SELECT * FROM volumes');
console.log(`data-dir (${app.id}): migrating data dir ${app.dataDir}`);
const mountPoint = getMountPoint(app.dataDir);
@@ -36,7 +43,7 @@ exports.up = async function(db) {
}
const id = uuid.v4().replace(/-/g, ''); // to make systemd mount file names more readable
const name = `app-${app.id}`;
const name = `appdata-${id}`;
const type = app.dataDir === mountPoint ? 'filesystem' : 'mountpoint';
console.log(`data-dir (${app.id}): creating new volume ${id}`);

View File

@@ -501,7 +501,7 @@ async function checkStorage(app, volumeId, prefix) {
const rel = path.relative(sourceDir, targetDir);
if (!rel.startsWith('../') && rel.split('/').length > 1) throw new BoxError(BoxError.BAD_FIELD, 'Only one level subdirectory moves are supported');
const [error] = await safe(shell.promises.sudo('checkStorage', [ CHECKVOLUME_CMD, targetDir ], {}));
const [error] = await safe(shell.promises.sudo('checkStorage', [ CHECKVOLUME_CMD, targetDir, sourceDir ], {}));
if (error && error.code === 2) throw new BoxError(BoxError.BAD_FIELD, `Target directory ${targetDir} is not empty`);
if (error && error.code === 3) throw new BoxError(BoxError.BAD_FIELD, `Target directory ${targetDir} does not support chown`);

View File

@@ -61,8 +61,9 @@ async function initialize() {
// note the pool also has an 'acquire' event but that is called whenever we do a getConnection()
connection.on('error', (error) => debug(`Connection ${connection.threadId} error: ${error.message} ${error.code}`));
connection.query('USE ' + gDatabase.name);
connection.query(`USE ${gDatabase.name}`);
connection.query('SET SESSION sql_mode = \'strict_all_tables\'');
connection.query('SET SESSION group_concat_max_len = 65536'); // GROUP_CONCAT has only 1024 default
});
}

View File

@@ -17,14 +17,24 @@ if [[ "$1" == "--check" ]]; then
exit 0
fi
volume_dir="$1"
target_dir="$1"
source_dir="$2"
readonly test_file="${volume_dir}/.chown-test"
source_stat=$(stat --format='%d,%i' "${source_dir}")
target_stat=$(stat --format='%d,%i' "${target_dir}")
mkdir -p "${volume_dir}"
# test sameness across bind mounts. if it's same, we can skip the emptiness check
if [[ "${source_stat}" == "${target_stat}" ]]; then
echo "Source dir and target dir are the same"
exit 0
fi
readonly test_file="${target_dir}/.chown-test"
mkdir -p "${target_dir}"
rm -f "${test_file}" # clean up any from previous run
if [[ -n $(ls -A "${volume_dir}") ]]; then
if [[ -n $(ls -A "${target_dir}") ]]; then
echo "volume dir is not empty"
exit 2
fi
@@ -35,5 +45,5 @@ if ! chown yellowtent:yellowtent "${test_file}"; then
exit 3
fi
rm -f "${test_file}"
rm -r "${volume_dir}" # will get recreated by the local storage addon
rm -r "${target_dir}" # will get recreated by the local storage addon

View File

@@ -26,6 +26,15 @@ if [[ "${BOX_ENV}" == "test" ]]; then
[[ "${target_dir}" != *"/.cloudron_test/"* ]] && exit 1
fi
source_stat=$(stat --format='%d,%i' "${source_dir}")
target_stat=$(stat --format='%d,%i' "${target_dir}")
# test sameness across bind mounts
if [[ "${source_stat}" == "${target_stat}" ]]; then
echo "Source dir and target dir are the same"
exit 0
fi
# copy and remove - this way if the copy fails, the original is intact
# the find logic is so that move to a one level subdir works (and we also move hidden files)
find "${source_dir}" -maxdepth 1 -mindepth 1 -not -wholename "${target_dir}" -exec cp -ar '{}' "${target_dir}" \;