venv rebuild: various improvements in the migration code

This commit is contained in:
Alexandre Aubin 2022-08-07 22:24:50 +02:00 committed by ljf (zamentur)
parent 1d84e07988
commit 0a737c4e9b
2 changed files with 40 additions and 24 deletions

View file

@ -503,10 +503,12 @@
"migration_0023_not_enough_space": "Make sufficient space available in {path} to run the migration.",
"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_0024_rebuild_python_venv_broken_app": "To upgrade your app {app} to bullseye, you probably should force the upgrade of this app thanks to `yunohost app upgrade --force {app}`",
"migration_0024_rebuild_python_venv_disclaimer": "Python applications doesn't support upgrade to bullseye and need an extra steps to rebuild their virtual environement. By running this migration, YunoHost will try to rebuild automaticcaly your Python apps except for : {apps}. For those apps, you should force the upgrade manually by running `yunohost app upgrade -f APP`.",
"migration_0024_rebuild_python_venv_in_progress": "Rebuild the python virtualenv `{venv}`",
"migration_0024_rebuild_python_venv_failed": "Unable to rebuild the python virtual env {venv}, this app is probably broken. If your app is broken, you probably should force the upgrade of this app thanks to `yunohost app upgrade --force APP`",
"migration_0024_rebuild_python_venv_broken_app": "Skipping {app} because virtualenv can't easily be rebuilt for this app. Instead, you should fix the situation by forcing the upgrade of this app using `yunohost app upgrade --force {app}`.",
"migration_0024_rebuild_python_venv_disclaimer_base": "Following the upgrade to Debian Bullseye, some Python applications needs to be partially rebuilt to get converted to the new Python version shipped in Debian (in technical terms: what's called the 'virtualenv' needs to be recreated). In the meantime, those Python applications may not work. YunoHost can attempt to rebuild the virtualenv for some of those, as detailed below. For other apps, or if the rebuild attempt fails, you will need to manually force an upgrade for those apps.",
"migration_0024_rebuild_python_venv_disclaimer_rebuild": "Rebuilding the virtualenv will be attempted for the following apps (NB: the operation may take some time!): {rebuid_apps}",
"migration_0024_rebuild_python_venv_disclaimer_ignored": "Virtualenvs can't be rebuilt automatically for those apps. You need to force an upgrade for those, which can be done from the command line with: `yunohost app upgrade -f APP`: {ignored_apps}",
"migration_0024_rebuild_python_venv_in_progress": "Now attempting to rebuild python virtualenv for `{app}`",
"migration_0024_rebuild_python_venv_failed": "Failed to rebuild the python virtual env for {app}. The app may not work as long as this is not resolved. You should fix the situation by forcing the upgrade of this app using `yunohost app upgrade --force {app}`.",
"migration_description_0021_migrate_to_bullseye": "Upgrade the system to Debian Bullseye and YunoHost 11.x",
"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",

View file

@ -11,7 +11,14 @@ from moulinette.utils.filesystem import rm, read_file
logger = getActionLogger("yunohost.migration")
VENV_REQUIREMENTS_SUFFIX = ".requirements_backup_for_bullseye_upgrade.txt"
VENV_IGNORE = "ynh_migration_no_regen"
def extract_app_from_venv_path(venv_path):
venv_path = venv_path.replace("/var/www/", "")
venv_path = venv_path.replace("/opt/yunohost/", "")
venv_path = venv_path.replace("/opt/", "")
return venv_path.split("/")[0]
def _get_all_venvs(dir, level=0, maxlevel=3):
@ -29,8 +36,6 @@ def _get_all_venvs(dir, level=0, maxlevel=3):
for file in os.listdir(dir):
path = os.path.join(dir, file)
if os.path.isdir(path):
if os.path.isfile(os.path.join(path, VENV_IGNORE)):
continue
activatepath = os.path.join(path, "bin", "activate")
if os.path.isfile(activatepath):
content = read_file(activatepath)
@ -87,19 +92,31 @@ class MyMigration(Migration):
if not self.is_pending():
return None
apps = []
ignored_apps = []
rebuild_apps = []
venvs = _get_all_venvs("/opt/") + _get_all_venvs("/var/www/")
for venv in venvs:
if not os.path.isfile(venv + VENV_REQUIREMENTS_SUFFIX):
continue
# Search for ignore apps
for app in self.ignored_python_apps:
if app in venv:
apps.append(app)
app_corresponding_to_venv = extract_app_from_venv_path(venv)
return m18n.n("migration_0024_rebuild_python_venv_disclaimer",
apps=", ".join(apps))
# Search for ignore apps
if any(app_corresponding_to_venv.startswith(app) for app in self.ignored_python_apps):
ignored_apps.append(app_corresponding_to_venv)
else:
rebuild_apps.append(app_corresponding_to_venv)
msg = m18n.n("migration_0024_rebuild_python_venv_disclaimer_base",
if rebuild_apps:
msg += "\n\n" + m18n.n("migration_0024_rebuild_python_venv_disclaimer_rebuild",
rebuild_apps="\n - " + "\n - ".join(rebuild_apps))
if ignored_apps:
msg += "\n\n" + m18n.n("migration_0024_rebuild_python_venv_disclaimer_ignored",
ignored_apps="\n - " + "\n - ".join(ignored_apps))
return msg
def run(self):
@ -108,18 +125,15 @@ class MyMigration(Migration):
if not os.path.isfile(venv + VENV_REQUIREMENTS_SUFFIX):
continue
# Search for ignore apps
ignored_app = None
for app in self.ignored_python_apps:
if app in venv:
ignored_app = app
app_corresponding_to_venv = extract_app_from_venv_path(venv)
if ignored_app:
# Search for ignore apps
if any(app_corresponding_to_venv.startswith(app) for app in self.ignored_python_apps):
rm(venv + VENV_REQUIREMENTS_SUFFIX)
logger.info(m18n.n("migration_0024_rebuild_python_venv_broken_app", app=ignored_app))
logger.info(m18n.n("migration_0024_rebuild_python_venv_broken_app", app=app_corresponding_to_venv))
continue
logger.info(m18n.n("migration_0024_rebuild_python_venv_in_progress", venv=venv))
logger.info(m18n.n("migration_0024_rebuild_python_venv_in_progress", app=app_corresponding_to_venv))
# Recreate the venv
rm(venv, recursive=True)
@ -132,7 +146,7 @@ class MyMigration(Migration):
f"{venv}/bin/pip", "install", "-r",
venv + VENV_REQUIREMENTS_SUFFIX], callbacks)
if status != 0:
logger.warning(m18n.n("migration_0024_rebuild_python_venv",
venv=venv))
logger.error(m18n.n("migration_0024_rebuild_python_venv_failed",
app=app_corresponding_to_venv))
else:
rm(venv + VENV_REQUIREMENTS_SUFFIX)