Merge "Introduce multi-version auto downgrade for apps"

This commit is contained in:
Zuul 2024-04-18 17:53:43 +00:00 committed by Gerrit Code Review
commit 37beadd020
3 changed files with 43 additions and 10 deletions

View File

@ -125,7 +125,7 @@ def validate_metadata_file(path, metadata_file, upgrade_from_release=None):
if not error_message:
error_message = _("Invalid boolean value: {}"
.format(value))
raise exception.SysinvException(error_message)
raise exception.SysinvException(error_message)
def validate_dict(value, error_message=None):
"""Validate dictionary types"""
@ -381,6 +381,13 @@ def validate_metadata_file(path, metadata_file, upgrade_from_release=None):
for version in from_versions:
validate_string(version)
# Downgrades section validation
downgrades = validate_dict_field(doc, constants.APP_METADATA_DOWNGRADES)
if downgrades:
validate_boolstr_field(
downgrades,
constants.APP_METADATA_AUTO_DOWNGRADE)
# Kubernetes version section validation
k8s_version = validate_k8s_version(doc)
if k8s_version:

View File

@ -1988,6 +1988,9 @@ APP_METADATA_UPGRADES = 'upgrades'
APP_METADATA_UPDATE_FAILURE_SKIP_RECOVERY = 'update_failure_no_rollback'
APP_METADATA_AUTO_UPDATE = 'auto_update'
APP_METADATA_AUTO_UPDATE_DEFAULT_VALUE = True
APP_METADATA_DOWNGRADES = 'downgrades'
APP_METADATA_AUTO_DOWNGRADE = 'auto_downgrade'
APP_METADATA_AUTO_DOWNGRADE_DEFAULT_VALUE = True
APP_METADATA_FAILED_VERSIONS = 'failed_versions'
APP_METADATA_FROM_VERSIONS = 'from_versions'
APP_METADATA_SUPPORTED_K8S_VERSION = 'supported_k8s_version'

View File

@ -53,6 +53,7 @@ import xml.etree.ElementTree as ElementTree
from contextlib import contextmanager
from datetime import datetime
from datetime import timedelta
from distutils.util import strtobool
from distutils.version import LooseVersion
from copy import deepcopy
from urllib3.exceptions import MaxRetryError
@ -7805,6 +7806,11 @@ class ConductorManager(service.PeriodicService):
True,
k8s_upgrade_timing)
auto_downgrade = strtobool(app.app_metadata.get(constants.APP_METADATA_DOWNGRADES, {})
.get(constants.APP_METADATA_AUTO_DOWNGRADE,
str(constants.APP_METADATA_AUTO_DOWNGRADE_DEFAULT_VALUE)))
latest_downgrade_bundle = None
available_versions = set()
latest_version_bundle = None
if k8s_version is None:
@ -7813,15 +7819,8 @@ class ConductorManager(service.PeriodicService):
k8s_version = k8s_version.strip().lstrip('v')
for bundle_metadata in bundle_metadata_list:
if LooseVersion(bundle_metadata.version) <= LooseVersion(app.app_version):
LOG.debug("Bundle {} version {} lower than installed app version ({})"
.format(bundle_metadata.file_path,
bundle_metadata.version,
app.app_version))
elif not bundle_metadata.auto_update:
LOG.debug("Application auto update disabled for bundle {}"
.format(bundle_metadata.file_path))
elif LooseVersion(k8s_version) < LooseVersion(bundle_metadata.k8s_minimum_version):
available_versions.add(bundle_metadata.version)
if LooseVersion(k8s_version) < LooseVersion(bundle_metadata.k8s_minimum_version):
LOG.debug("Kubernetes version {} is lower than {} which is "
"the minimum required for bundle {}"
.format(k8s_version,
@ -7834,6 +7833,21 @@ class ConductorManager(service.PeriodicService):
.format(k8s_version,
bundle_metadata.k8s_maximum_version,
bundle_metadata.file_path))
elif LooseVersion(bundle_metadata.version) == LooseVersion(app.app_version):
LOG.debug("Bundle {} version and installed app version are the same ({})"
.format(bundle_metadata.file_path,
app.app_version))
elif LooseVersion(bundle_metadata.version) < LooseVersion(app.app_version):
LOG.debug("Bundle {} version {} is lower than installed app version ({})"
.format(bundle_metadata.file_path,
bundle_metadata.version,
app.app_version))
if (latest_downgrade_bundle is None or LooseVersion(bundle_metadata.version) >
LooseVersion(latest_downgrade_bundle.version)):
latest_downgrade_bundle = bundle_metadata
elif not bundle_metadata.auto_update:
LOG.debug("Application auto update disabled for bundle {}"
.format(bundle_metadata.file_path))
elif ((latest_version_bundle is None) or
(LooseVersion(bundle_metadata.version) >
LooseVersion(latest_version_bundle.version))):
@ -7841,6 +7855,15 @@ class ConductorManager(service.PeriodicService):
# of the current one is higher than the one previously set.
latest_version_bundle = bundle_metadata
# Downgrade if the installed app version is not available anymore and an older compatible
# bundle is available instead.
if (auto_downgrade and
app.app_version not in available_versions and
latest_downgrade_bundle is not None):
LOG.info("Application {} will be downgraded from version {} to {}"
.format(app.name, app.app_version, latest_downgrade_bundle.version))
return latest_downgrade_bundle
return latest_version_bundle
def _auto_update_app(self,