Merge branch 'backend_dev' into 'dev'

Backend dev

See merge request kylin-desktop/update-manager-group/kylin-system-updater!56
This commit is contained in:
Xueyi Luo 2021-11-16 06:44:13 +00:00
commit 3fd0f59629
11 changed files with 269 additions and 33 deletions

View File

@ -24,6 +24,29 @@
- 运行运行
### 配置文件
- 名称:`system-updater.conf`
- 路径:`/var/lib/kylin-system-updater`
- 配置项:
```shell
#自动更新使用
[AutoUpgrade]
#升级列表,自动更新使用
upgradelist =
#系统状态
[SystemStatus]
#标志是否异常强制关闭
isabnormalreboot = False
```
### 文档

View File

@ -1,5 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from math import log10
import os
import re
import json
@ -107,9 +108,24 @@ class Sqlite3Server(object):
# 写入数据到display表中
def insert_into_display(self, *args, **kwargs):
sql = "update display set " + args[0] + "='" + args[1] + "' where id = 1"
self.cursor.execute(sql)
self.connect.commit()
try:
sql = "update display set " + args[0] + "='" + args[1] + "' where id = 1"
self.cursor.execute(sql)
self.connect.commit()
except Exception as e:
logging.error("Insert error: %s.", str(e))
logging.info(_("Data insertion complete ."))
# 读出display表中数据
def select_from_display(self, *args, **kwargs):
try:
sql = "select "+args[0]+" from display"
self.cursor.execute(sql)
self.connect.commit()
return str(self.cursor.fetchone()[0])
except Exception as e:
logging.error("Insert error: %s.", str(e))
logging.info(_("Data insertion complete ."))
# 写入updateinfos表中
def insert_into_updateinfo(self, *args, **kwargs):
@ -125,7 +141,7 @@ class Sqlite3Server(object):
logging.info(_("Data insertion complete ."))
# 接收更新列表与信息,生成数据并插入数据库中
def insert_info(self, mode, pkg_list=[], pkg_group=[], success = False, error_string = '', error_desc = ''):
def insert_info(self, mode, pkg_list=[], pkg_group=[], adjust_pkg=[], success = False, error_string = '', error_desc = ''):
errstr = error_string + " " + error_desc
status = " "
time = datetime.datetime.now()
@ -151,13 +167,23 @@ class Sqlite3Server(object):
elif pkg_list:
# 单包更新 # 获取单包数据插入数据库
pkgname = pkg_list[0]
for adj in adjust_pkg:
if pkgname in adj:
# 该部分升级的单包为调整版本,与候选版本不一致
pkgname = adj
break
try:
pkg = self.window_main.cache[pkgname]
pkg = self.window_main.cache[pkgname.split("=")[0]]
for ver in pkg.versions:
if ver.version == pkgname.split("=")[1]:
pkg_inst_ver = ver
break
pkgname = pkgname.split("=")[0]
except Exception as e:
logging.error(_("%s could not be detected in the source because the source was changed or for other reasons."), \
str(pkgname))
pkgversion = str(pkg.candidate.version)
pkgdescription = str(pkg.candidate.raw_description)
pkgversion = str(pkg_inst_ver.source_version)
pkgdescription = str(pkg_inst_ver.description)
try:
self.insert_into_updateinfo(pkgname, pkgversion, pkgdescription, timestr, status, "1", errstr)
# FIXME: 发送插入数据库成功的信号local_upgrade_list

View File

@ -86,6 +86,9 @@ class UpdateList():
#清空上次输出的分组JSON文件
def _empty_output_dir(self):
try:
#清空 升级列表
self.parent.configs.setValue("AutoUpgrade","upgradelist",'',True)
if not os.path.exists(OUTPUT_CONFIG_PATH):
os.makedirs(OUTPUT_CONFIG_PATH)
logging.info('making the configuration file is complete...')
@ -451,6 +454,9 @@ class UpdateList():
success,group_important_list,self.local_upgrade_data.single_pkgs,header,desc = self._read_important_list(cache,pkgs_upgrade)
#清空输出的目录
self._empty_output_dir()
#important_list 为空时此次不需要升级
if success == True and not group_important_list and not self.local_upgrade_data.single_pkgs:
header = _("The software on this computer is up to date.")
@ -459,9 +465,6 @@ class UpdateList():
elif success == False:
return success,header,desc
#清空输出的目录
self._empty_output_dir()
#产生单包的JSON
self._make_single_upgrade(cache,self.local_upgrade_data.single_pkgs)

View File

@ -3,8 +3,6 @@
import os
import sys
import apt
from apt import cache
import shutil
import dbus
import logging
@ -25,7 +23,6 @@ import time
from gettext import gettext as _
from SystemUpdater.backend import DownloadBackend as downb
from SystemUpdater.Core.Database import MODE_UPGRADE_SINGLE
from aptdaemon.enums import get_status_string_from_enum
import apt_pkg
from SystemUpdater.Core.UpdaterConfigParser import UpgradeConfig
@ -40,7 +37,7 @@ class UpdateManager():
self.update_list = None
#表示aptdeamon是否处于工作状态
self.is_working = False
self.is_working = InstallBackend.ACTION_DEFUALT_STATUS
#建立dbus
self.dbusController = self._setup_dbus()
@ -68,6 +65,14 @@ class UpdateManager():
except KeyboardInterrupt:
self.dbusController.Quit(None)
#进行清空所有下载的文件
def start_clean(self):
try:
clean_backend = get_backend(self, InstallBackend.ACTION_CLEAN)
clean_backend.start()
except Exception as e:
logging.error(e)
#进行升级的操作
def start_fix_broken(self):
try:
@ -75,6 +80,14 @@ class UpdateManager():
fix_backend.start()
except Exception as e:
logging.error(e)
#进行升级的操作
def start_fix_incomplete(self):
try:
fix_backend = get_backend(self, InstallBackend.ACTION_FIX_INCOMPLETE)
fix_backend.start()
except Exception as e:
logging.error(e)
#download only
def download_backend(self, pkgs):

View File

@ -6,14 +6,13 @@ import logging
import threading
from gettext import gettext as _
from .Core.AlertWatcher import AlertWatcher
# from .Core.roam import NetworkManagerHelper
from .backend import InstallBackend
from .Core.loop import mainloop
from .Core.utils import humanize_size
from SystemUpdater.Core.utils import (
unLockedEnableShutdown,
)
from SystemUpdater.Core.Database import MODE_UPGRADE_PARTIAL,MODE_UPGRADE_ALL,MODE_UPGRADE_SYSTEM,MODE_UPGRADE_SINGLE
from SystemUpdater.Core.Database import MODE_UPGRADE_PARTIAL,MODE_UPGRADE_ALL,MODE_UPGRADE_SYSTEM
UPDATER_DBUS_INTERFACE = 'com.kylin.systemupgrade.interface'
UPDATER_DBUS_PATH = '/com/kylin/systemupgrade'
@ -125,12 +124,37 @@ class UpdateManagerDbusController(dbus.service.Object):
mainloop.quit()
logging.debug("Exit")
#更新的dbus
#Remove all downloaded files.
@dbus.service.method(UPDATER_DBUS_INTERFACE,out_signature='b')
def Clean(self):
try:
#处于更新和升级中的话 不进行更新
if self.parent.is_working != InstallBackend.ACTION_DEFUALT_STATUS:
logging.warning('Clean In the process of updating or Upgrading...')
return False,'In the process of updating or Upgrading...'
else:
self.parent.start_clean()
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' Clean ...')
return True
except Exception:
return False
#获取后端现在的状态
@dbus.service.method(UPDATER_DBUS_INTERFACE,out_signature='i')
def GetBackendStatus(self):
try:
#处于更新和升级中的话 不进行更新
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' GetBackendStatus ...')
return self.parent.is_working
except Exception:
return False
#更新的dbus apt install -f
@dbus.service.method(UPDATER_DBUS_INTERFACE,out_signature='b')
def FixBrokenDepends(self):
try:
#处于更新和升级中的话 不进行更新
if self.parent.is_working:
if self.parent.is_working != InstallBackend.ACTION_DEFUALT_STATUS:
logging.warning('FixBrokenDepends In the process of updating or Upgrading...')
return False,'In the process of updating or Upgrading...'
else:
@ -140,12 +164,27 @@ class UpdateManagerDbusController(dbus.service.Object):
except Exception:
return False
#dpkg configure -a
@dbus.service.method(UPDATER_DBUS_INTERFACE,out_signature='b')
def FixIncompleteInstall(self):
try:
#处于更新和升级中的话 不进行更新
if self.parent.is_working != InstallBackend.ACTION_DEFUALT_STATUS:
logging.warning('FixIncompleteInstall In the process of updating or Upgrading...')
return False,'In the process of updating or Upgrading...'
else:
self.parent.start_fix_incomplete()
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' FixIncompleteInstall ...')
return True
except Exception:
return False
#更新的dbus
@dbus.service.method(UPDATER_DBUS_INTERFACE,out_signature='b')
def UpdateDetect(self):
try:
#处于更新和升级中的话 不进行更新
if self.parent.is_working:
if self.parent.is_working != InstallBackend.ACTION_DEFUALT_STATUS:
logging.warning('UpdateDetect In the process of updating or Upgrading...')
return False,'In the process of updating or Upgrading...'
else:
@ -164,7 +203,7 @@ class UpdateManagerDbusController(dbus.service.Object):
logging.warning('Perform \"UpdateDetect\" first')
return False,'Perform \"UpdateDetect\" first'
#处于更新和升级中的话 不进行升级
if self.parent.is_working:
if self.parent.is_working != InstallBackend.ACTION_DEFUALT_STATUS:
logging.warning('DistUpgradeAll In the process of updating or Upgrading...')
return False,'In the process of updating or Upgrading...'
else:
@ -183,7 +222,7 @@ class UpdateManagerDbusController(dbus.service.Object):
logging.warning('Perform \"UpdateDetect\" first')
return False,'Perform \"UpdateDetect\" first'
#处于更新和升级中的话 不进行升级
if self.parent.is_working:
if self.parent.is_working != InstallBackend.ACTION_DEFUALT_STATUS:
logging.warning('DistUpgradePartial In the process of updating or Upgrading...')
return False,'In the process of updating or Upgrading...'
else:
@ -210,7 +249,7 @@ class UpdateManagerDbusController(dbus.service.Object):
purge_list = [str(pkg) for pkg in _purge_list]
#处于更新和升级中的话 不进行升级
if self.parent.is_working:
if self.parent.is_working != InstallBackend.ACTION_DEFUALT_STATUS:
logging.warning('PurgePackages In the process of updating or Upgrading...')
return False,'In the process of updating or Upgrading...'
else:
@ -243,7 +282,7 @@ class UpdateManagerDbusController(dbus.service.Object):
try:
is_install = bool(_is_install)
#处于更新和升级中的话 不进行升级
if self.parent.is_working:
if self.parent.is_working != InstallBackend.ACTION_DEFUALT_STATUS:
logging.warning('DistUpgradeSystem In the process of updating or Upgrading...')
return False,'In the process of updating or Upgrading...'
else:
@ -294,9 +333,31 @@ class UpdateManagerDbusController(dbus.service.Object):
self.parent.start_download(pkgs)
times -= 1
return True
# 是否允许关机前更新
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='ss', out_signature='bs')
def UnattendedUpgradeValue(self, operation, value="false"):
if operation.lower() != "get" and operation.lower() != "set":
return False, 'Please input [\"set\", \"value\"] to set. \nor [\"get\"] to get whether updates are allowed before shutdown.'
if operation == "set":
try:
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' UnattendedUpgradeValue is going to %s [allow_unattended_upgrades_shutdown] value to %s.'%(operation,value))
self.parent.sqlite3_server.insert_into_display("allow_unattended_upgrades_shutdown", value.lower())
except Exception as e:
logging.error(str(e))
return False,str(e)
else:
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' UnattendedUpgradeValue is going to %s [allow_unattended_upgrades_shutdown] value.'%(operation))
try:
value = self.parent.sqlite3_server.select_from_display("allow_unattended_upgrades_shutdown")
logging.info("[allow_unattended_upgrades_shutdown] value is %s."%(value))
except Exception as e:
logging.error(str(e))
return False,str(e)
return True,"success"
# # dbus接口改变apt下载速度
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='sb')
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='sb', out_signature='s')
def SetDownloadspeedMax(self, speed, set):
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' SetDownloadspeedMax, speed:%s, set:%r.'%(speed, set))
self.parent.is_restart_aptdeamon = True

View File

@ -53,7 +53,7 @@ class InstallBackendAptdaemon(InstallBackend):
"""
logging.info("Checking for inactivity...")
if self.window_main.is_working == False:
if self.window_main.is_working == self.ACTION_DEFUALT_STATUS:
logging.info("Installing to exit and timeout check quit...")
return False
#进度不同时 更新时间戳
@ -161,6 +161,44 @@ class InstallBackendAptdaemon(InstallBackend):
authorized=True, success=False,
error_string='', error_desc='')
raise
@inline_callbacks
def fix_incomplete(self):
"""修复未完成的安装 """
try:
trans = yield self.client.fix_incomplete_install(defer=True)
self.window_main.dbusController.transaction = trans
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_FIX_INCOMPLETE,
_("fix incomplete install"), False)
except errors.NotAuthorizedError:
self._action_done(self.ACTION_FIX_INCOMPLETE,
authorized=False, success=False,
error_string='', error_desc='')
except Exception:
self._action_done(self.ACTION_FIX_INCOMPLETE,
authorized=True, success=False,
error_string='', error_desc='')
raise
@inline_callbacks
def clean(self):
"""清空所有下载的文件 """
try:
trans = yield self.client.clean(defer=True)
self.window_main.dbusController.transaction = trans
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_CLEAN,
_("Remove all downloaded files."), False)
except errors.NotAuthorizedError:
self._action_done(self.ACTION_CLEAN,
authorized=False, success=False,
error_string='', error_desc='')
except Exception:
self._action_done(self.ACTION_CLEAN,
authorized=True, success=False,
error_string='', error_desc='')
raise
@inline_callbacks
def download_deb(self, pkg_lists):
@ -229,9 +267,10 @@ class InstallBackendAptdaemon(InstallBackend):
#此处发不发信号一样 频率很低
self.window_main.dbusController.UpdateDloadAndInstStaChanged(upgrade_content,progress,status,details)
elif action == self.ACTION_FIX_BROKEN:
self.window_main.dbusController.FixBrokenStatusChanged(progress,status)
# elif action == self.ACTION_FIX_BROKEN:
# self.window_main.dbusController.FixBrokenStatusChanged(progress,status)
else:
logging.info("Other Action:progress = %d , status = %s ,details = %s",progress,status,details)
def _on_details_changed(self, trans, details):
self.details = details

View File

@ -38,6 +38,7 @@ class NowUpgradePara:
self.single_pkgs = single_pkgs
class InstallBackend():
ACTION_DEFUALT_STATUS = -1
ACTION_UPDATE = 0
ACTION_INSTALL = 1
ACTION_INSTALL_DEB = 2
@ -45,6 +46,8 @@ class InstallBackend():
ACTION_DOWNLOADONLY = 4
ACTION_FIX_BROKEN = 5
ACTION_REMOVE_PACKAGES = 6
ACTION_FIX_INCOMPLETE = 7
ACTION_CLEAN = 8
def __init__(self, window_main, action):
self.window_main = window_main
@ -60,7 +63,7 @@ class InstallBackend():
def start(self,_upgrade_mode = MODE_DEFAULT_STATUS,partial_upgrade_list = []):
#对所有的操作进行枷锁 当执行完毕后返回到_action_done 进行解锁,除了计算依赖模式 不进入_action_done 单独解锁
self.window_main.is_working = True
self.window_main.is_working = self.action
#安装升级包 首先必须调用ACTION_CHECK_RESOLVER 计算依赖解决方便 标记cache 进行升级
if self.action == self.ACTION_INSTALL:
@ -83,7 +86,7 @@ class InstallBackend():
#检查磁盘的状态
_success,desc = check_free_space(self.cache)
if _success == False and desc != None:
if _success == False:
header = _("Disk space is insufficient, please clean the disk and then upgrade")
self._action_done(self.action,True,False,header,desc)
return
@ -135,7 +138,7 @@ class InstallBackend():
else:
raw_description.append(getattr(pkg_obj.candidate, "summary", ''))
#解锁忙碌
self.window_main.is_working = False
self.window_main.is_working = self.ACTION_DEFUALT_STATUS
if _upgrade_mode != MODE_UPGRADE_SYSTEM:
self.window_main.dbusController.UpdateDependResloveStatus(_success,is_remove_pkgs,pkgs_remove,raw_description,delete_desc,header,desc)
else:
@ -143,9 +146,15 @@ class InstallBackend():
#修复未满足的依赖关系 与apt-get -f install匹配
elif self.action == self.ACTION_FIX_BROKEN:
self.fix_broken()
# 修复不完整的安装dpkg configure -a
elif self.action == self.ACTION_FIX_INCOMPLETE:
self.fix_incomplete()
#卸载包
elif self.action == self.ACTION_REMOVE_PACKAGES:
self.purge_packages(partial_upgrade_list)
#清空所有下载的文件
elif self.action == self.ACTION_CLEAN:
self.clean()
#更新cache
elif self.action == self.ACTION_UPDATE:
self.update()
@ -168,6 +177,10 @@ class InstallBackend():
"""Run a update to refresh the package list"""
raise NotImplementedError
def clean(self):
"""Remove all downloaded files.t"""
raise NotImplementedError
def commit(self, pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_purge = []):
"""Commit the cache changes """
raise NotImplementedError
@ -180,6 +193,10 @@ class InstallBackend():
"""fix_broken_depends"""
raise NotImplementedError
def fix_incomplete(self):
"""fix_incomplete_install"""
raise NotImplementedError
def purge_packages(self,pkgs_purge):
"""purge_packages"""
raise NotImplementedError
@ -421,7 +438,7 @@ class InstallBackend():
#调用aptdeamon结束之后处理的地方 不管是出错还是正常都在此处理
def _action_done(self, action, authorized, success, error_string,error_desc):
self.window_main.is_working = False
self.window_main.is_working = self.ACTION_DEFUALT_STATUS
#升级完成后走的分支
if action == self.ACTION_INSTALL:
@ -438,6 +455,7 @@ class InstallBackend():
self.now_upgrade.upgrade_mode,
self.now_upgrade.single_pkgs,
self.now_upgrade.upgrade_groups,
self.upgrade_data.adjust_pkgs,
success,
error_string, error_desc)
if success:
@ -453,6 +471,9 @@ class InstallBackend():
#只有安装配置文件包 才会走到此处
self.window_main.start_available()
return
#当更新过程中安装配置包时 失败时发送错误信号
elif success == False and self.now_upgrade.upgrade_mode == MODE_UPGRADE_SINGLE:
self.window_main.dbusController.UpdateDetectFinished(success,upgrade_content,error_string,error_desc)
if error_string != '' or error_desc != '':
logging.info(error_string + error_desc)
@ -469,10 +490,16 @@ class InstallBackend():
elif action == self.ACTION_FIX_BROKEN:
logging.warning("fix broken packages is complete...")
self.window_main.start_available()
elif action == self.ACTION_FIX_INCOMPLETE:
if success:
logging.info("fix incomplete install success.")
else:
logging.warning("fix incomplete install failed.")
elif action == self.ACTION_INSTALL_DEB:
pass
# unLockedEnableShutdown()
# try aptdaemon
if os.path.exists("/usr/sbin/aptd") \

Binary file not shown.

View File

@ -31,6 +31,8 @@
| InsertInstallState | ss | b | 向display表插入数据 |
| GtDownloadspeedLimitValue | 无 | b | 获取当前限速 |
| SetDownloadspeedMax | sb | b | 设置限速 |
| GetBackendStatus | 无 | i | 控制获取后端状态 |
| UnattendedUpgradeValue | ss | bs | 获取是否允许关机前更新 |
#### Method分析
#### UpdateDetect
@ -75,6 +77,37 @@
#### GetBackendStatus
- `介绍:` 获取后端的状态,现在正在处理那些任务
- `出参`: `i:`当前任务ID整型数字
- `示例:`
```python
ACTION_DEFUALT_STATUS = -1 #默认状态空闲状态
ACTION_UPDATE = 0 #处于更新cache状态
ACTION_INSTALL = 1 #处于升级安装包括部分升级、全部升级、q状态
ACTION_INSTALL_DEB = 2 #处于安装deb的状态
ACTION_CHECK_RESOLVER = 3 #处于计算依赖过程
ACTION_DOWNLOADONLY = 4 #单独下载软件包过程
ACTION_FIX_BROKEN = 5 #修复依赖的过程
ACTION_REMOVE_PACKAGES = 6 #卸载包的状态中
```
#### UnattendedUpgradeValue
- `介绍:` 设置或获取是否允许关机前更新
- `入参`: `s:`operation("get"/"set")`s:`value将要设置的值
- `示例:`
```sh
operation = "set", value = "false"
```
#### Signal列表

10
debian/changelog vendored
View File

@ -1,3 +1,13 @@
kylin-system-updater (1.2.7.2kord) v101; urgency=medium
* BUG:
* 需求号: 9002
* 需求:1.升级依赖修复机制减小第三方软件对系统更新的影响2.更新源锁定功能,屏蔽第三方软件源对系统更新的影响
* 其他改动说明:升级插件UI修复;添加修复功能;修复安装时preinst报错的问题
* 影响域: 系统升级
-- luoxueyi <luoxueyi@kylinos.cn> Mon, 15 Nov 2021 11:04:56 +0800
kylin-system-updater (1.2.7.1kord) v101; urgency=medium
* BUG:

View File

@ -8,5 +8,6 @@ backend/SystemUpdater/*.py /usr/share/kylin-system-updater/SystemUpdater/
backend/SystemUpdater/backend/*.py /usr/share/kylin-system-updater/SystemUpdater/backend/
backend/SystemUpdater/Core/*.py /usr/share/kylin-system-updater/SystemUpdater/Core/
backend/build/mo/* /usr/share/locale/
backend/data/system-updater.conf /var/lib/kylin-system-updater/
plugin/translations/* /usr/share/Upgrade/translations/
plugin/libupgrade.so /usr/lib/