yunohost/src/migrations/0023_postgresql_11_to_13.py

85 lines
2.8 KiB
Python

import subprocess
import time
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")
time.sleep(3)
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)
time.sleep(3)
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(b"\n")
return (returncode, out, err)