加入强制降级系统软件包版本的模式

This commit is contained in:
wangsong 2022-06-22 02:16:00 +08:00
parent 4d4111b6b0
commit 9c0507adcd
4 changed files with 110 additions and 78 deletions

View File

@ -276,7 +276,7 @@ class UpdateList():
except Exception as e:
logging.error(e)
def _split_package_id(package):
def _split_package_id(self,package):
"""Return the name, the version number and the release of the
specified package."""
if "=" in package:
@ -290,68 +290,56 @@ class UpdateList():
version = release = None
return name, version, release
def _mark_packages_for_downgrade(self, packages, resolver):
"""Mark packages for downgrade."""
for pkg_name, pkg_ver, pkg_rel in [self._split_package_id(pkg)
for pkg in packages]:
try:
pkg = self.cache[pkg_name]
except KeyError:
pass
# raise TransactionFailed(ERROR_NO_PACKAGE,
# _("Package %s isn't available"),
# pkg_name)
if not pkg.is_installed:
pass
# raise TransactionFailed(ERROR_PACKAGE_NOT_INSTALLED,
# _("Package %s isn't installed"),
# pkg_name)
auto = pkg.is_auto_installed
if pkg_ver:
if pkg.installed and pkg.installed.version < pkg_ver:
pass
# FIXME: We need a new error enum
# raise TransactionFailed(ERROR_NO_PACKAGE,
# _("The former version %s of %s "
# "is already installed"),
# pkg.installed.version, pkg.name)
elif pkg.installed and pkg.installed.version == pkg_ver:
pass
# raise TransactionFailed(ERROR_PACKAGE_ALREADY_INSTALLED,
# _("The version %s of %s "
# "is already installed"),
# pkg.installed.version, pkg.name)
try:
pkg.candidate = pkg.versions[pkg_ver]
except KeyError:
pass
# raise TransactionFailed(ERROR_NO_PACKAGE,
# _("The version %s of %s isn't "
# "available"), pkg_ver, pkg_name)
else:
pass
# raise TransactionFailed(ERROR_NO_PACKAGE,
# _("You need to specify a version to "
# "downgrade %s to"),
# pkg_name)
# pkg.mark_install(False, False, True)
# pkg.mark_auto(auto)
# resolver.clear(pkg)
# resolver.protect(pkg)
def _make_downgrade(self,cache,data):
downgrade_pkgs = data["force_downgrade"]
def _make_downgrade(self,cache,downgrade_pkgs):
output_downgrade = []
adjust_pkgs = []
for pkg_name, pkg_ver, pkg_rel in [self._split_package_id(pkg)
for pkg in downgrade_pkgs]:
try:
pkg = cache[pkg_name]
except KeyError:
logging.warning("Package %s isn't available",pkg_name)
continue
if not pkg.is_installed:
logging.warning("Package %s isn't installed",pkg_name)
pass
if pkg_ver:
if pkg.installed and pkg.installed.version < pkg_ver:
logging.warning("The former version %s of %s is already installed",pkg.installed.version, pkg.name)
continue
elif pkg.installed and pkg.installed.version == pkg_ver:
logging.warning("The version %s of %s is already installed",pkg.installed.version, pkg.name)
continue
try:
pkg.candidate = pkg.versions[pkg_ver]
except KeyError:
logging.warning("The version %s of %s isn't available",pkg_ver, pkg_name)
continue
output_downgrade.append(pkg_name)
adjust_pkgs.append(pkg_name+'='+pkg_ver)
return output_downgrade,adjust_pkgs
def _get_downgrade_list(self,cache,data):
downgrade_pkgs = []
try:
downgrade_raw = data['force_downgrade']
except Exception as e:
downgrade_raw = []
for pkg_name, pkg_ver, pkg_rel in [self._split_package_id(pkg)
for pkg in downgrade_raw]:
if pkg_name in cache:
downgrade_pkgs.append(pkg_name)
else:
logging.warning("Package %s isn't available",pkg_name)
continue
return downgrade_raw,downgrade_pkgs
def _make_groups_upgrade(self,cache,group_list, pkgs_upgrade = []):
try:
@ -385,17 +373,34 @@ class UpdateList():
if not group_name in group_list:
continue
upgrade_pkgs_list = data['upgrade_list']
#检查包是否在cache中 以及是否已经安装 没有安装的话才添加到列表
new_install_list = self._check_pkg_in_cache(cache,data['install_list'])
downgrade_raw,downgrade_pkgs = self._get_downgrade_list(cache,data)
#被降级的软件包优先级最高
for pkg in downgrade_pkgs:
if pkg in upgrade_pkgs_list:
upgrade_pkgs_list.remove(pkg)
if pkg in new_install_list:
new_install_list.remove(pkg)
if pkg in self.upgrade_meta.single_pkgs:
self.upgrade_meta.single_pkgs.remove(pkg)
#进行交集 升级列表
new_upgrade_list = list(set(pkgs_upgrade) & set(upgrade_pkgs_list))
#进行源过滤
new_install_list,new_upgrade_list,adjust_pkgs = self._make_fiter_origin([cache[pkg] for pkg in new_install_list + new_upgrade_list],False)
self.upgrade_meta.adjust_pkgs.extend(adjust_pkgs)
#在总升级列表中移除这些包
for pkg in new_upgrade_list:
pkgs_upgrade.remove(pkg)
downgrade_pkg,adjust_pkgs = self._make_downgrade(cache,downgrade_raw)
self.upgrade_meta.adjust_pkgs.extend(adjust_pkgs)
new_upgrade_list.extend(downgrade_pkg)
#单包的优先级最高 从组中剔除此包
for pkg in self.upgrade_meta.single_pkgs:
if pkg in new_install_list:
@ -404,9 +409,7 @@ class UpdateList():
#判断当前是否可升级或者新装的包
if len(new_install_list) == 0 and len(new_upgrade_list) == 0:
continue
#在总升级列表中移除这些包
for pkg in new_upgrade_list:
pkgs_upgrade.remove(pkg)
#3、生成升级的包列表JSON
upgrade_pkgs_json = self._make_pkg_info_json(cache,new_upgrade_list)
#2、生成安装的软件列表

View File

@ -36,6 +36,7 @@ class UpdateManager():
BACKEND_PKG_NAME = 'kylin-system-updater'
FRONTEND_PKG_NAME = "kylin-update-frontend"
GROUPS_PKG_NAME = 'kylin-update-desktop-config'
SOURCES_UPDATE_NAME = "kylin-software-properties"
APTD_PKG_NAME = "aptdaemon"
RUN_UNATTENDED_UPGRADE = '/var/run/unattended-upgrades.pid'
RETRY_LIMIT_NUM = 2

View File

@ -158,13 +158,13 @@ class InstallBackendAptdaemon(InstallBackend):
raise
@inline_callbacks
def commit(self,model,pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_purge = []):
def commit(self,model,pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_downgrade = []):
"""Commit a list of package adds and removes"""
try:
reinstall = downgrade = []
reinstall = purge = []
trans = yield self.client.commit_packages(
pkgs_install, reinstall, pkgs_remove, purge = pkgs_purge, upgrade = pkgs_upgrade,
downgrade = downgrade,download = model, defer=True)
pkgs_install, reinstall, pkgs_remove, purge = purge, upgrade = pkgs_upgrade,
downgrade = pkgs_downgrade,download = model, defer=True)
self.window_main.dbusController.transaction = trans
yield self._show_transaction(trans, self.action,

View File

@ -148,8 +148,9 @@ class InstallBackend():
#拿到升级列表
self.now_upgrade.make_upgrade_content(partial_upgrade_list)
pkgs_install,pkgs_upgrade,pkgs_remove = self._get_mark_from_cache(self.cache,self.upgrade_data.adjust_pkgs,self.action_mode)
logging.info("INSTALL install:%d , upgrade:%d remove:%d",len(pkgs_install),len(pkgs_upgrade),len(pkgs_remove))
pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_downgrade = self._get_mark_from_cache(self.cache,self.upgrade_data.adjust_pkgs,self.action_mode)
logging.info("INSTALL install:%d , upgrade:%d remove:%d pkgs_downgrade:%d",len(pkgs_install),\
len(pkgs_upgrade),len(pkgs_remove),len(pkgs_downgrade))
#当下载数量大于200个包时 就认为属于大版本升级 开启重试机制
if len(pkgs_install) + len(pkgs_upgrade) > 100:
@ -157,7 +158,7 @@ class InstallBackend():
self.now_upgrade.version_upgrade = True
#检查是否存在可升级的包
if len(pkgs_install) == 0 and len(pkgs_upgrade) == 0 and len(pkgs_remove) == 0:
if len(pkgs_install) == 0 and len(pkgs_upgrade) == 0 and len(pkgs_remove) == 0 and len(pkgs_downgrade) == 0:
raise UpdateBaseError(ERROR_NOT_UPGRADE_PACKAGES)
# if self.action_mode == self.MODE_INSTALL_SINGLE:
@ -172,10 +173,10 @@ class InstallBackend():
self.window_main.collector.Upgrade_Process_Msg(self.action, {"appname":ul})
if self.action == self.ACTION_INSTALL:
self.commit(self.action,pkgs_install, pkgs_upgrade, pkgs_remove)
self.commit(self.action,pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_downgrade)
elif self.action == self.ACTION_DOWNLOADONLY:
self._update_to_config(self.now_upgrade,pkgs_install,pkgs_upgrade,pkgs_remove)
self.commit(self.action,pkgs_install, pkgs_upgrade, pkgs_remove)
self.commit(self.action,pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_downgrade)
elif self.action == self.ACTION_INSTALL_SHUTDOWN:
self.now_upgrade,pkgs_install,pkgs_upgrade,pkgs_remove = self._config_to_upgrade()
@ -202,8 +203,8 @@ class InstallBackend():
#获取要升级和安装的包列表
pkgs_install,pkgs_upgrade = self._make_pkgs_list(self.cache,self.upgrade_data.groups_pkgs,self.now_upgrade.upgrade_groups,self.now_upgrade.single_pkgs)
#计算解决依赖关系
delete_pkgs,delete_desc = self._make_problem_resolver(self.cache,pkgs_install,pkgs_upgrade)
pkgs_install,pkgs_upgrade,pkgs_remove = self._get_mark_from_cache(self.cache,self.upgrade_data.adjust_pkgs,self.action_mode)
delete_pkgs,delete_desc = self._make_problem_resolver(self.cache,pkgs_install,pkgs_upgrade,self.upgrade_data.adjust_pkgs)
pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_downgrade = self._get_mark_from_cache(self.cache,self.upgrade_data.adjust_pkgs,self.action_mode)
if len(pkgs_remove) != len(delete_pkgs):
logging.warning("Simulation of the deletion package list:%s",str(delete_pkgs))
@ -220,13 +221,14 @@ class InstallBackend():
except Exception as e:
logging.error(str(e))
raise UpdateBaseError(ERROR_RESOLVER_FAILED,desc= str(e))
pkgs_install,pkgs_upgrade,pkgs_remove = self._get_mark_from_cache(self.cache,self.upgrade_data.adjust_pkgs,self.action_mode)
pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_downgrade = self._get_mark_from_cache(self.cache,self.upgrade_data.adjust_pkgs,self.action_mode)
self.window_main.collector.Generate_Msg(self.now_upgrade.upgrade_groups+self.now_upgrade.single_pkgs, self.action_mode)
for ul in self.window_main.collector.upgrade_list:
self.window_main.collector.Upgrade_Process_Msg(self.action, {"appname":ul})
logging.info("RESOLVER install:%d , upgrade:%d remove:%d",len(pkgs_install),len(pkgs_upgrade),len(pkgs_remove))
logging.info("RESOLVER install:%d , upgrade:%d remove:%d pkgs_downgrade:%d",len(pkgs_install),len(pkgs_upgrade),\
len(pkgs_remove),len(pkgs_downgrade))
is_remove_pkgs = len(pkgs_remove) != 0
#添加关于删除包的描述信息
@ -292,7 +294,7 @@ class InstallBackend():
"""Remove all downloaded files.t"""
raise NotImplementedError
def commit(self,model,pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_purge = []):
def commit(self,model,pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_downgrade = []):
"""Commit the cache changes """
raise NotImplementedError
@ -317,6 +319,7 @@ class InstallBackend():
pkgs_install = []
pkgs_upgrade = []
pkgs_remove = []
pkgs_downgrade = []
#全盘升级不做任何的调整
if upgrade_mode == self.MODE_INSTALL_SYSTEM or upgrade_mode == self.MODE_INSTALL_SINGLE:
@ -342,9 +345,11 @@ class InstallBackend():
pkgs_upgrade.append(pkg.name)
elif pkg.marked_delete:
pkgs_remove.append(pkg.name)
elif pkg.marked_downgrade:
pkgs_downgrade.append(pkg.name+'='+pkg.candidate.source_version)
except KeyError:
pass
return pkgs_install,pkgs_upgrade,pkgs_remove
return pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_downgrade
#获取当前升级的升级列表
def _make_groups_list(self,upgrade_data,_upgrade_mode,partial_upgrade_list):
@ -417,13 +422,26 @@ class InstallBackend():
pass
return all_deps
def _split_package_id(self,package):
"""Return the name, the version number and the release of the
specified package."""
if "=" in package:
name, version = package.split("=", 1)
release = None
elif "/" in package:
name, release = package.split("/", 1)
version = None
else:
name = package
version = release = None
return name, version, release
#将获取本次升级的包 进行计算依赖关系 解决依赖问题
def _make_problem_resolver(self,cache,pkgs_install = [],pkgs_upgrade = []):
def _make_problem_resolver(self,cache,pkgs_install = [],pkgs_upgrade = [],adjust_pkgs = []):
last_broken_count = 0
#计算出来的需要删除的包列表
delete_pkgs = []
delete_desc = []
fresh_cache = Cache()
try:
logging.info("ProblemResolver install:%d , upgrade:%d",len(pkgs_install),len(pkgs_upgrade))
logging.info("Start calculating dependencies...")
@ -433,12 +451,21 @@ class InstallBackend():
if cache.get_changes():
cache.clear()
resolver = apt.cache.ProblemResolver(cache)
#调整候选版本强制更改版本
for pkg_name, pkg_ver, pkg_rel in [self._split_package_id(pkg)
for pkg in adjust_pkgs]:
try:
pkg = cache[pkg_name]
pkg.candidate = pkg.versions[pkg_ver]
except KeyError:
logging.warning("The version %s of %s isn't available",pkg_ver, pkg_name)
continue
#标记计算所有需要安装的
for pkg in pkgs_upgrade + pkgs_install:
pkg_cache = cache[pkg]
#将第二个参数调整为False 当为True时就不能检查缺少依赖的包 默认自动移除掉了
#将第二个参数调整为False 当为True时就不能检查缺少依赖的包 默认自动移除掉了
pkg_cache.mark_install(False, False, True)
#将可自动升级的标记为自动安装
@ -452,6 +479,7 @@ class InstallBackend():
if cache._depcache.broken_count != last_broken_count and \
self.window_main.configs_cover.getWithDefault("ConfigPkgStatus", "check_resover_remove", False) == True:
last_broken_count = cache._depcache.broken_count
fresh_cache = Cache()
tmp_pkgs,tmp_desc = self._emulate_calcul_delete(pkg,fresh_cache)
delete_pkgs.extend(tmp_pkgs)
delete_desc.extend(tmp_desc)