From 4e2e54676a1c23475903823ad621f765d36c3b3a Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 4 Jun 2021 17:23:09 +0200 Subject: [PATCH] Yolo postgresql 11 -> 13 cluster migration --- locales/en.json | 4 + .../0023_postgresql_11_to_13.py | 82 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 src/yunohost/data_migrations/0023_postgresql_11_to_13.py diff --git a/locales/en.json b/locales/en.json index 922ece34a..1ab813bc4 100644 --- a/locales/en.json +++ b/locales/en.json @@ -427,6 +427,7 @@ "migration_description_0019_extend_permissions_features": "Extend/rework the app permission management system", "migration_description_0020_ssh_sftp_permissions": "Add SSH and SFTP permissions support", "migration_description_0022_php73_to_php74_pools": "Migrate php7.3-fpm 'pool' conf files to php7.4", + "migration_description_0023_postgresql_11_to_13": "Migrate databases from PostgreSQL 11 to 13", "migration_ldap_backup_before_migration": "Creating a backup of LDAP database and apps settings prior to the actual migration.", "migration_ldap_can_not_backup_before_migration": "The backup of the system could not be completed before the migration failed. Error: {error:s}", "migration_ldap_migration_failed_trying_to_rollback": "Could not migrate... trying to roll back the system.", @@ -453,6 +454,9 @@ "migration_0018_failed_to_reset_legacy_rules": "Failed to reset legacy iptables rules: {error}", "migration_0019_add_new_attributes_in_ldap": "Add new attributes for permissions in LDAP database", "migration_0019_slapd_config_will_be_overwritten": "It looks like you manually edited the slapd configuration. For this critical migration, YunoHost needs to force the update of the slapd configuration. The original files will be backuped in {conf_backup_folder}.", + "migration_0023_postgresql_11_not_installed": "PostgreSQL was not installed on your system. Nothing to do.", + "migration_0023_postgresql_13_not_installed": "PostgreSQL 11 is installed, but not postgresql 13!? Something weird might have happened on your system :(...", + "migration_0023_not_enough_space": "Make sufficient space available in {path} to run the migration.", "migrations_already_ran": "Those migrations are already done: {ids}", "migrations_cant_reach_migration_file": "Could not access migrations files at the path '%s'", "migrations_dependencies_not_satisfied": "Run these migrations: '{dependencies_id}', before migration {id}.", diff --git a/src/yunohost/data_migrations/0023_postgresql_11_to_13.py b/src/yunohost/data_migrations/0023_postgresql_11_to_13.py new file mode 100644 index 000000000..30527f0c8 --- /dev/null +++ b/src/yunohost/data_migrations/0023_postgresql_11_to_13.py @@ -0,0 +1,82 @@ +import subprocess + +from moulinette import m18n +from yunohost.utils.error import YunohostError, YunohostValidationError +from moulinette.utils.log import getActionLogger + +from yunohost.tools import Migration +from yunohost.utils.filesystem import free_space_in_directory, space_used_by_directory + +logger = getActionLogger("yunohost.migration") + + +class MyMigration(Migration): + + "Migrate DBs from Postgresql 11 to 13 after migrating to Bullseye" + + dependencies = ["migrate_to_bullseye"] + + def run(self): + + if not self.package_is_installed("postgresql-11"): + logger.warning(m18n.n("migration_0023_postgresql_11_not_installed")) + return + + if not self.package_is_installed("postgresql-13"): + raise YunohostValidationError("migration_0023_postgresql_13_not_installed") + + # Make sure there's a 11 cluster + try: + self.runcmd("pg_lsclusters | grep -q '^11 '") + except Exception: + logger.warning( + "It looks like there's not active 11 cluster, so probably don't need to run this migration" + ) + return + + if not space_used_by_directory( + "/var/lib/postgresql/11" + ) > free_space_in_directory("/var/lib/postgresql"): + raise YunohostValidationError( + "migration_0023_not_enough_space", path="/var/lib/postgresql/" + ) + + self.runcmd("systemctl stop postgresql") + self.runcmd( + "LC_ALL=C pg_dropcluster --stop 13 main || true" + ) # We do not trigger an exception if the command fails because that probably means cluster 13 doesn't exists, which is fine because it's created during the pg_upgradecluster) + self.runcmd("LC_ALL=C pg_upgradecluster -m upgrade 11 main") + self.runcmd("LC_ALL=C pg_dropcluster --stop 11 main") + self.runcmd("systemctl start postgresql") + + def package_is_installed(self, package_name): + + (returncode, out, err) = self.runcmd( + "dpkg --list | grep '^ii ' | grep -q -w {}".format(package_name), + raise_on_errors=False, + ) + return returncode == 0 + + def runcmd(self, cmd, raise_on_errors=True): + + logger.debug("Running command: " + cmd) + + p = subprocess.Popen( + cmd, + shell=True, + executable="/bin/bash", + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + + out, err = p.communicate() + returncode = p.returncode + if raise_on_errors and returncode != 0: + raise YunohostError( + "Failed to run command '{}'.\nreturncode: {}\nstdout:\n{}\nstderr:\n{}\n".format( + cmd, returncode, out, err + ) + ) + + out = out.strip().split("\n") + return (returncode, out, err)