Merge remote-tracking branch 'upstream/plugin_dev' into plugin_dev

This commit is contained in:
He Chengyuan 2022-01-24 10:10:28 +08:00
commit f3de0f92e3
29 changed files with 927 additions and 376 deletions

View File

@ -25,7 +25,7 @@ LOCALTIDFILE = "tidfile.conf"
MSGSNDDIR = "/var/lib/kylin-system-updater/sendinfos/"
class UpdateMsgCollector():
def __init__(self, manager):
def __init__(self, manager=None):
self.UploadMessage = {}
self.PackageInfo = {}
self.waitSendList = []
@ -63,7 +63,6 @@ class UpdateMsgCollector():
# 获取本地tid
self.sender.GetLocalTid()
PackageInfo["tid"] = str(self.sender.localtid)
logging.info("Get local tid:(%s).",self.sender.localtid)
json_PackageInfo = self.convertor.dictConvertJson(PackageInfo)
@ -110,6 +109,7 @@ class FormatConvert():
def dictConvertJson(self, dict_msg):
#字典转换为json格式字符串
json_file = ''
try:
json_file = json.dumps(dict_msg)
except JSONDecodeError as e:
@ -118,6 +118,7 @@ class FormatConvert():
def JsonConvertDict(self, json_file):
# json格式字符串转换为字典
dict_file = {}
try:
dict_file = json.loads(json_file)
except JSONDecodeError as e:
@ -170,7 +171,8 @@ class MessageSend():
self.collector = UpdateMsgCollector()
else:
self.collector = DataCollector
self.ReadFromFile("/var/lib/kylin-system-updater/sendinfos/testMsg.json")
# self._ReadFromFile("/var/lib/kylin-system-updater/sendinfos/testMsg.json")
# self._TimedTransmission()
def MsgSendToServer(self, UploadMessage, PackageInfo, encodeMsg):
daqbus = dbus.SystemBus()
@ -180,6 +182,18 @@ class MessageSend():
except DBusException as e:
logging.error(str(e))
# 调用发送接口
# PackageInfo = ("{\"messageType\":\"testDataa\",\"packageName\":\"testPack1\",\"tid\":\"HSx9qTy1TK3J06DRq7pkeTXptNEbVrDqq08yre+OLtE=\"}")
# UploadMessage = ("{\"createTimeStamp\":\"2021-12-21 16:12:04.587\",\"myInt\":2}")
# encodeMsg = ("fvlIx/KXjDIe3cbc1GMrs1FPRvqVBCt0LnrI1DSKYPc48e0pHPrkIwrSWISjrdu2Q7SqvlmrN9O3aGDKHBAyOovEtUPKKC18adfBQ6vDalhmHkHbrRhFwRrhDJ07PzTl8Lkw+hfW6eSAJ11LWqe00cNRRKgttfBM9IsHPJ82310KEwD3gieMVRwq1Zb9Ztc3hjP7mY0IhntffhRKnzou32A+dh8YT3B0jqQkEuMA2bOftEmDslKrspYSdV13Dj1QlPixiM6eF3G4sLSvcNwSwTG43e5eeqoWrsF0SE4hJUrLS/stGgX+2BabwZ9aX1Bsi+SQB+ZQy2uq5WEZcJO83w==")
# print(PackageInfo)
# PackageInfo = self.collector.convertor.JsonConvertDict(PackageInfo)
# print(PackageInfo)
# PackageInfo = self.collector.convertor.dictConvertJson(PackageInfo)
# print(PackageInfo)
# UploadMessage = self.collector.convertor.JsonConvertDict(UploadMessage)
# print(UploadMessage)
# UploadMessage = self.collector.convertor.dictConvertJson(UploadMessage)
# print(UploadMessage)
try:
retval,retid = daqinterface.UploadMessage(PackageInfo, UploadMessage, encodeMsg)
except AttributeError:
@ -209,7 +223,7 @@ class MessageSend():
result = "The createTimeStamp field of UploadedMessage is abnormal"
logging.info("Sent Status: false - packageName: %s : result: %s.", PackageInfo['packageName'], result)
# 上传失败写入本地json
if retval != self.ERR_NO_LOACLTID:
if retval != self.ERR_NO_LOACLTID or retval == self.ERR_NO_LOACLTID:
self.WriteToJson(PackageInfo['messageType'], json_PackageInfo, json_UploadMessage, encodeMsg)
elif retval == 0:
result = "Send to server success"
@ -258,13 +272,65 @@ class MessageSend():
except Exception as e:
logging.error(str(e))
def ReadFromFile(self, json_path):
def _TimedTransmission(self, file_path = MSGSNDDIR):
classify_list = [name for name in os.listdir(file_path) if name.endswith(".json")]
for f in classify_list:
# 循环发送每一个文件
self._ReadFromFile(os.path.join(file_path, f))
def _ReadFromFile(self, json_path):
new_lines = []
# 从本地文件读取
if not os.path.exists(json_path):
return
# with open(json_path, "w") as f:
# while True:
# line =
with open(json_path, "r+") as f:
lines = f.readlines()
# file is empty and path is exit -> remove file
if len(lines) == 0 and os.path.exists(json_path):
os.remove(json_path)
return
#send installinfo or updateinfo
for line in lines:
(retval,retid) = self._file_send_server(line)
if retval != 0: # success
new_lines.append(line)
if os.path.exists(json_path):
os.remove(json_path)
if len(new_lines) != 0:
with open(json_path, "w+") as f:
for line in lines:
f.write(line)
def _file_send_server(self, json):
UploadMessage = {}
PackageInfo = {}
encodeMsg = ''
dict_msg = self.collector.convertor.JsonConvertDict(json)
if 'UploadMessage' in dict_msg.keys():
UploadMessage = dict_msg['UploadMessage']
UploadMessage = self.collector.convertor.dictConvertJson(UploadMessage)
if 'PackageInfo' in dict_msg.keys():
PackageInfo = dict_msg['PackageInfo']
PackageInfo = self.collector.convertor.dictConvertJson(PackageInfo)
if 'encodeMsg' in dict_msg.keys():
encodeMsg = str(dict_msg['encodeMsg'])
if len(UploadMessage) == 0 or len(PackageInfo) == 0 or encodeMsg == '':
logging.error("Msg error")
return 6, ''
daqbus = dbus.SystemBus()
try:
daqobj = daqbus.get_object('com.kylin.daq', '/com/kylin/daq')
daqinterface = dbus.Interface(daqobj, dbus_interface='com.kylin.daq.interface')
except DBusException as e:
logging.error(str(e))
try:
retval,retid = daqinterface.UploadMessage(PackageInfo, UploadMessage, encodeMsg)
except AttributeError:
logging.error("Call UploadMessage: Attribute Error.")
return (retval,retid)
class UniqueKey():
keyvalue = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FR\
@ -302,4 +368,4 @@ def get_east_8_time():
if __name__ == "__name__":
# 执行定时发送
ms = MessageSend()
ms.ReadFromFile("/var/lib/kylin-system-updater/sendinfos/testMsg.json")
ms._ReadFromFile("/var/lib/kylin-system-updater/sendinfos/testMsg.json")

View File

@ -164,7 +164,7 @@ class Sqlite3Server(object):
UpdateInfos.update({"errorCode":str(error_string+" "+error_desc)})
json_file = json.dumps(UpdateInfos.copy())
UpdateInfos.clear()
self.window_main.collector.UpdateMsg("UpdateInfos", json_file)
# self.window_main.collector.UpdateMsg("UpdateInfos", json_file)
#安装信息install-infos
InstallInfos.update({"packageName":str(pkgname)})
if pkgname in self.window_main.update_list.local_upgrade_data.versoin_pkgs['groups_upgrade'].keys():
@ -175,7 +175,7 @@ class Sqlite3Server(object):
InstallInfos.update({"status":status})
InstallInfos.update({"errorCode":str(error_string+" "+error_desc)})
json_file = json.dumps(InstallInfos.copy())
self.window_main.collector.UpdateMsg("InstallInfos", json_file)
# self.window_main.collector.UpdateMsg("InstallInfos", json_file)
elif pkg_list:
# 单包更新 # 获取单包数据插入数据库
pkgname = pkg_list.pop(0)
@ -213,7 +213,7 @@ class Sqlite3Server(object):
UpdateInfos.update({"errorCode":str(error_string+" "+error_desc)})
json_file = json.dumps(UpdateInfos.copy())
UpdateInfos.clear()
self.window_main.collector.UpdateMsg("UpdateInfos", json_file)
# self.window_main.collector.UpdateMsg("UpdateInfos", json_file)
#安装信息install-infos
InstallInfos.update({"packageName":str(pkgname)})
if pkgname in self.window_main.update_list.local_upgrade_data.versoin_pkgs['single_upgrade'].keys():
@ -224,7 +224,7 @@ class Sqlite3Server(object):
InstallInfos.update({"status":status})
InstallInfos.update({"errorCode":str(error_string+" "+error_desc)})
json_file = json.dumps(InstallInfos.copy())
self.window_main.collector.UpdateMsg("InstallInfos", json_file)
# self.window_main.collector.UpdateMsg("InstallInfos", json_file)
try:
self.insert_into_updateinfo(pkgname, pkgversion, pkgdescription, timestr, status, "1", errstr)
@ -257,7 +257,7 @@ class Sqlite3Server(object):
UpdateInfos.update({"errorCode":str(error_string+" "+error_desc)})
json_file = json.dumps(UpdateInfos.copy())
UpdateInfos.clear()
self.window_main.collector.UpdateMsg("UpdateInfos", json_file)
# self.window_main.collector.UpdateMsg("UpdateInfos", json_file)
#安装信息install-infos
InstallInfos.update({"packageName":str(pkg.name)})
if pkg.name in self.window_main.update_list.local_upgrade_data.versoin_pkgs['groups_upgrade'].keys():
@ -268,7 +268,7 @@ class Sqlite3Server(object):
InstallInfos.update({"status":status})
InstallInfos.update({"errorCode":str(error_string+" "+error_desc)})
json_file = json.dumps(InstallInfos.copy())
self.window_main.collector.UpdateMsg("InstallInfos", json_file)
# self.window_main.collector.UpdateMsg("InstallInfos", json_file)
try:
self.insert_into_updateinfo(str(i), pkgversion, pkgdescription, timestr, status, "1", errstr)
@ -289,7 +289,7 @@ class Sqlite3Server(object):
UpdateInfos.update({"errorCode":str(error_string+" "+error_desc)})
json_file = json.dumps(UpdateInfos.copy())
UpdateInfos.clear()
self.window_main.collector.UpdateMsg("UpdateInfos", json_file)
# self.window_main.collector.UpdateMsg("UpdateInfos", json_file)
#安装信息install-infos
InstallInfos.update({"packageName":str(i)})
if i in self.window_main.update_list.local_upgrade_data.versoin_pkgs['groups_upgrade'].keys():
@ -300,7 +300,7 @@ class Sqlite3Server(object):
InstallInfos.update({"status":status})
InstallInfos.update({"errorCode":str(error_string+" "+error_desc)})
json_file = json.dumps(InstallInfos.copy())
self.window_main.collector.UpdateMsg("InstallInfos", json_file)
# self.window_main.collector.UpdateMsg("InstallInfos", json_file)
try:
self.insert_into_updateinfo(str(i), pkgversion, pkgdescription, timestr, status, "1", errstr)
group_list = []
@ -328,7 +328,7 @@ class Sqlite3Server(object):
UpdateInfos.update({"errorCode":str(error_string+" "+error_desc)})
json_file = json.dumps(UpdateInfos.copy())
UpdateInfos.clear()
self.window_main.collector.UpdateMsg("UpdateInfos", json_file)
# self.window_main.collector.UpdateMsg("UpdateInfos", json_file)
#安装信息install-infos
InstallInfos.update({"packageName":str(pkg.name)})
if pkg.name in self.window_main.update_list.local_upgrade_data.versoin_pkgs['groups_upgrade'].keys():
@ -339,7 +339,7 @@ class Sqlite3Server(object):
InstallInfos.update({"status":status})
InstallInfos.update({"errorCode":str(error_string+" "+error_desc)})
json_file = json.dumps(InstallInfos.copy())
self.window_main.collector.UpdateMsg("InstallInfos", json_file)
# self.window_main.collector.UpdateMsg("InstallInfos", json_file)
try:
self.insert_into_updateinfo(str(i), pkgversion, pkgdescription, timestr, status, "1", errstr)
# 数据库文件被删除或者新增字段导致需要重新初始化数据库再写入

View File

@ -0,0 +1,130 @@
import os
from gettext import gettext as _
import apt
import logging
import fcntl
import apt_pkg
class LogInstallProgress(apt.progress.base.InstallProgress):
""" Install progress that writes to self.progress_log
(/var/run/unattended-upgrades.progress by default)
"""
def __init__(self,file):
# type: (str) -> None
apt.progress.base.InstallProgress.__init__(self)
self.output_logfd = None # type: int
self.filename=file
self.error_pkg=""
self.errormsg=""
def error(self,pkg, errormsg):
logging.info(("errormsg:%s"),errormsg)
self.error_pkg=self.filename
self.errormsg = errormsg
global error_status
global error_msg
error_status=1
error_msg=errormsg
def status_change(self, pkg, percent, status):
# type: (str, float, str) -> None
logging.info(("pkg:%s,percent:%s,status:%s"),pkg,percent,status)
with open(self.progress_log, "w") as f:
f.write(("%s")%percent)
f.write(_("当前进度: %s ,正在安装:%s,当前状态:%s") % (percent, pkg,status))
f.write(_("Progress: %s %% (%s)") % (percent, pkg))
def _fixup_fds(self):
# () -> None
required_fds = [0, 1, 2, # stdin, stdout, stderr
self.writefd,
self.write_stream.fileno(),
self.statusfd,
self.status_stream.fileno()
]
# ensure that our required fds close on exec
for fd in required_fds[3:]:
old_flags = fcntl.fcntl(fd, fcntl.F_GETFD)
fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC)
# close all fds
try:
# PEP-446 implemented in Python 3.4 made all descriptors
# CLOEXEC, but we need to be able to pass writefd to dpkg
# when we spawn it
os.set_inheritable(self.writefd, True)
except AttributeError: # if we don't have os.set_inheritable()
pass
proc_fd = "/proc/self/fd"
if os.path.exists(proc_fd):
error_count = 0
for fdname in os.listdir(proc_fd):
try:
fd = int(fdname)
except Exception:
print("ERROR: can not get fd for %s" % fdname)
if fd in required_fds:
continue
try:
os.close(fd)
# print("closed: ", fd)
except OSError as e:
# there will be one fd that can not be closed
# as its the fd from pythons internal diropen()
# so its ok to ignore one close error
error_count += 1
if error_count > 1:
print("ERROR: os.close(%s): %s" % (fd, e))
def _redirect_stdin(self):
# type: () -> None
REDIRECT_INPUT = os.devnull
fd = os.open(REDIRECT_INPUT, os.O_RDWR)
os.dup2(fd, 0)
def _redirect_output(self):
# type: () -> None
# do not create log in dry-run mode, just output to stdout/stderr
if not apt_pkg.config.find_b("Debug::pkgDPkgPM", False):
logfd = self._get_logfile_dpkg_fd()
os.dup2(logfd, 1)
os.dup2(logfd, 2)
def _get_logfile_dpkg_fd(self):
# type: () -> int
logfd = os.open(
"/var/log/kylin-system-updater/kylin-system-updater.log.1", os.O_RDWR | os.O_APPEND | os.O_CREAT, 0o640)
try:
import grp
adm_gid = grp.getgrnam("adm").gr_gid
os.fchown(logfd, 0, adm_gid)
except (KeyError, OSError):
pass
return logfd
def update_interface(self):
# type: () -> None
# call super class first
apt.progress.base.InstallProgress.update_interface(self)
def _log_in_dpkg_log(self, msg):
# type: (str) -> None
logfd = self._get_logfile_dpkg_fd()
os.write(logfd, msg.encode("utf-8"))
os.close(logfd)
def finish_update(self):
# type: () -> None
# logging.info("finished")
# if error_status == 1:
# os._exit(1)
pass
def fork(self):
# type: () -> int
pid = os.fork()
if pid == 0:
self._fixup_fds()
self._redirect_stdin()
self._redirect_output()
return pid

View File

@ -371,7 +371,23 @@ class OriginProperty():
except Exception as e:
logging.error(str(e))
class UnattendUpgradeFilter():
def __init__(self) -> None:
pass
def GetAllowOrigins(self):
# 获取源属性
self.origin_property = OriginProperty()
self.origin_property.get_allowed_sources()
self.origin_property.get_allowed_origin()
self.allowed_origins = get_allowed_origins(self.origin_property.allow_origin)
self.allowed_origins = deleteDuplicatedElementFromList(self.allowed_origins)
logging.info(_("Allowed origins: %s"),
self.allowed_origins)
return self.allowed_origins
def ver_in_allowed_origin(pkg, allow_origin):
# type: (apt.Package, List[str]) -> apt.package.Version

View File

@ -103,11 +103,11 @@ class UpdateList():
if not os.path.exists(OUTPUT_CONFIG_PATH):
os.makedirs(OUTPUT_CONFIG_PATH)
logging.info('making the configuration file is complete...')
logging.info('making the ConfigPath(%s) is complete...',OUTPUT_CONFIG_PATH)
else:
shutil.rmtree(OUTPUT_CONFIG_PATH)
os.makedirs(OUTPUT_CONFIG_PATH)
logging.info('Emptying the configuration file is complete...')
logging.info('Emptying the ConfigPath(%s) is complete...',OUTPUT_CONFIG_PATH)
except Exception as e:
logging.error(str(e))
@ -276,21 +276,31 @@ class UpdateList():
return [],[]
#输出白名单的配置
def _make_white_config(self,cache,upgrade_data):
def _make_autoupgrade_config(self,cache,upgrade_data,_adjust_pkgs):
try:
pkgs_install,pkgs_upgrade = self._make_pkgs_list(cache,upgrade_data.upgrade_groups_pkgs,upgrade_data.upgrade_groups,upgrade_data.single_pkgs)
split_adjust_pkgs = [i.split("=")[0] for i in _adjust_pkgs]
pkgs_upgrade_str = ''
if pkgs_upgrade or pkgs_install:
for pkg_str in pkgs_upgrade + pkgs_install:
pkgs_list = pkgs_upgrade + pkgs_install
if pkgs_list:
for pkg_str in pkgs_list:
#记录源过滤后调整的版本
if pkg_str in split_adjust_pkgs:
pkg_str = _adjust_pkgs[split_adjust_pkgs.index(pkg_str)]
else:
ver = getattr(cache[pkg_str].candidate, "version", '')
pkg_str = pkg_str + "=" + ver
pkgs_upgrade_str += (pkg_str + ',')
pkgs_upgrade_str=pkgs_upgrade_str[:-1]
self.parent.configs.setValue("AutoUpgrade","upgradelist",pkgs_upgrade_str,True)
logging.info("Generate Configfile to complete...")
logging.info("Generate AutoUpgrade Configfile to Complete and Upgradable Number:%d...",len(pkgs_list))
except Exception as e:
logging.error(e)
logging.error(e)
def _make_groups_upgrade(self,cache,group_list, pkgs_upgrade = []):
try:
@ -508,7 +518,7 @@ class UpdateList():
#分组的包的JSON
self._make_groups_upgrade(cache,group_important_list,[pkg.name for pkg in pkgs_upgrade])
self._make_white_config(cache,self.local_upgrade_data)
self._make_autoupgrade_config(cache,self.local_upgrade_data,self.local_upgrade_data.adjust_pkgs)
#是否存在可升级的组
if self.local_upgrade_data.upgrade_groups or self.local_upgrade_data.single_pkgs:
return True,header,desc

View File

@ -416,12 +416,12 @@ def get_ubuntu_flavor(cache=None):
return pkg.split('-', 1)[0]
def _load_meta_pkg_list():
# This could potentially introduce a circular dependency, but the config
# parser logic is simple, and doesn't rely on any UpdateManager code.
from DistUpgrade.DistUpgradeConfigParser import DistUpgradeConfig
parser = DistUpgradeConfig('/usr/share/ubuntu-release-upgrader')
return parser.getlist('Distro', 'MetaPkgs')
# def _load_meta_pkg_list():
# # This could potentially introduce a circular dependency, but the config
# # parser logic is simple, and doesn't rely on any UpdateManager code.
# from DistUpgrade.DistUpgradeConfigParser import DistUpgradeConfig
# parser = DistUpgradeConfig('/usr/share/ubuntu-release-upgrader')
# return parser.getlist('Distro', 'MetaPkgs')
def get_ubuntu_flavor_package(cache=None):
@ -431,10 +431,10 @@ def get_ubuntu_flavor_package(cache=None):
# Lastly, fallback to ubuntu-desktop again.
meta_pkgs = ['ubuntu-desktop']
try:
meta_pkgs.extend(sorted(_load_meta_pkg_list()))
except Exception as e:
print('Could not load list of meta packages:', e)
# try:
# meta_pkgs.extend(sorted(_load_meta_pkg_list()))
# except Exception as e:
# print('Could not load list of meta packages:', e)
if cache is None:
cache = apt.Cache()
@ -787,8 +787,8 @@ def unLockedEnableShutdown():
logging.error("unlock failed." + str(e))
pidfile.close()
pidfile = None
return False
return False
if __name__ == "__main__":
#print(mirror_from_sources_list())
#print(on_battery())

View File

@ -1,10 +1,11 @@
# UpdateManager.py
# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*-
import apt
import fcntl
import os
import subprocess
from apt import Cache
import apt_pkg
import sys
import time
import shutil
import dbus
import logging
@ -21,19 +22,18 @@ from .Core.Database import Sqlite3Server
from .Core.loop import mainloop
from .Core.DataAcquisition import UpdateMsgCollector
import time
from gettext import gettext as _
from SystemUpdater.backend import DownloadBackend as downb
import apt_pkg
from SystemUpdater.Core.UpdaterConfigParser import UpgradeConfig
from SystemUpdater.Core.utils import country_mirror, get_broken_details,get_lis_from_cache
import subprocess
from SystemUpdater.Core.utils import get_broken_details,get_lis_from_cache
from SystemUpdater.Core.DpkgInstallProgress import LogInstallProgress
class UpdateManager():
SELF_PKG_NAME = 'kylin-system-updater'
GROUPS_PKG_NAME = 'kylin-update-desktop-config'
INSTALL_ALONE_PROGRESS = "alone"
SOURCE_PARTS_PATH = "/etc/apt/"
SOURCE_FILE_NAME = "sources.list"
def __init__(self,options):
self.options = options
@ -58,6 +58,9 @@ class UpdateManager():
#数据采集器
self.collector = UpdateMsgCollector(self)
#后台aptdaemon的语言环境
self.aptdaemonLang = os.environ["LANGUAGE"]
#检查是否需要重新启动aptdeamon 目前需要重启的有限速功能
def restart_aptdeamon(self):
@ -82,7 +85,7 @@ class UpdateManager():
except Exception as e:
logging.error(e)
#进行升级的操作
#进行修复破损的包的操作 apt install -f
def start_fix_broken(self):
try:
fix_backend = get_backend(self, InstallBackend.ACTION_FIX_BROKEN)
@ -90,7 +93,7 @@ class UpdateManager():
except Exception as e:
logging.error(e)
#进行升级的操作
#进行 dpkg --configure
def start_fix_incomplete(self):
try:
fix_backend = get_backend(self, InstallBackend.ACTION_FIX_INCOMPLETE)
@ -117,6 +120,28 @@ class UpdateManager():
except Exception as e:
logging.error(str(e))
#读取source.list 内容
def _read_source_list(self):
try:
source_file_content = ''
source_file_path = os.path.join(self.SOURCE_PARTS_PATH,self.SOURCE_FILE_NAME)
with open(source_file_path) as source_file:
source_file_content = source_file.read()
return source_file_content
except Exception as e:
logging.error(str(e))
return ''
#判断是否为光盘源
def _is_disc_source(self):
logging.info("Check: Whether to use CD-ROM source updates Successfully...")
source_file_content = self._read_source_list()
if "deb file:" in source_file_content:
logging.info("Current use of CD-ROM source without network check...")
return True
else:
return False
#进行更新的操作
def start_update(self):
_success = True
@ -127,12 +152,23 @@ class UpdateManager():
#每次更新之前 重新读取配置文件 刷新参数
self.configs.reReadConfigFiles()
#进行检查网络
self.dbusController.UpdateDetectStatusChanged(5,_("Checking network connection"))
_success,header,desc = self.dbusController.check_connectivity()
if _success == False:
self.dbusController.DistUpdateDetectFinished(_success,[],header,desc)
return
#光盘源的话
if self._is_disc_source() == True:
logging.info("Turn off NetworkCheck and CloseFiter and UpdateSource...")
#关闭网络检查
self.options.no_check_network = True
#当判断为光盘源时 关闭源过滤
self.options.close_filter = True
#关闭 更新源模板
self.options.no_update_source = True
if self.options.no_check_network is False:
#进行检查网络
self.dbusController.UpdateDetectStatusChanged(5,_("Checking network connection"))
_success,header,desc = self.dbusController.check_connectivity()
if _success == False:
self.dbusController.DistUpdateDetectFinished(_success,[],header,desc)
return
#从服务器端更新摸板
if self.options.no_update_source is False:
@ -239,8 +275,6 @@ class UpdateManager():
upgrade_list = self.update_list.local_upgrade_data.upgrade_groups + self.update_list.local_upgrade_data.single_pkgs
#发送更新升级列表完成的标志
self.dbusController.DistUpdateDetectFinished(_success,upgrade_list,header,desc)
#检查安装完成之后需要重启吗
self.is_reboot_required()
#清空cache
if self.cache != None and self.cache.get_changes():
self.cache.clear()
@ -290,9 +324,10 @@ class UpdateManager():
self._check_cache_broken(self.cache)
#检查自己是否需要升级更新
_success,header,desc = self._check_self_upgrade(self.cache)
if _success == False:
return _success,header,desc
if self.options.no_check_selfupgrade is False:
_success,header,desc = self._check_self_upgrade(self.cache)
if _success == False:
return _success,header,desc
#检查更新分组配置表
_success,header,desc = self._check_group_config(self.cache)
@ -399,11 +434,6 @@ class UpdateManager():
return _success,header,desc
def is_reboot_required(self):
"""If a reboot is required to get all changes into effect."""
return os.path.exists(os.path.join(apt_pkg.config.find_dir("Dir"),
"var/run/reboot-required"))
def _check_cache_broken(self,cache):
with cache.actiongroup():
if cache.get_changes():
@ -433,9 +463,7 @@ class UpdateManager():
def _setup_dbus(self):
# check if there is another g-a-i already and if not setup one
# listening on dbus
bus = dbus.SystemBus()
try:
bus_name = dbus.service.BusName(UPDATER_DBUS_SERVICE,
bus,
@ -447,15 +475,32 @@ class UpdateManager():
logging.critical("Another daemon is already running")
sys.exit(1)
logging.warning("Replacing already running daemon")
retry_reboot_times = 0
the_other_guy = bus.get_object(UPDATER_DBUS_SERVICE,
UPDATER_DBUS_PATH)
the_other_guy.Quit(dbus_interface=UPDATER_DBUS_INTERFACE,
timeout=300)
time.sleep(1)
bus_name = dbus.service.BusName(UPDATER_DBUS_SERVICE,
bus,
do_not_queue=True)
return UpdateManagerDbusController(self, bus_name)
while True:
retry_reboot_times = retry_reboot_times + 1
#当重试次数超过5次时退出程序
if retry_reboot_times > 5:
logging.critical("Reboot backend is Failed...")
sys.exit(1)
try:
bus_name = dbus.service.BusName(UPDATER_DBUS_SERVICE,
bus,
do_not_queue=True)
logging.warning("Replacing already running daemon to Success...")
return UpdateManagerDbusController(self, bus_name)
except dbus.exceptions.NameExistsException:
the_other_guy = bus.get_object(UPDATER_DBUS_SERVICE,
UPDATER_DBUS_PATH)
the_other_guy.Quit(dbus_interface=UPDATER_DBUS_INTERFACE,
timeout=300)
logging.error("Dbus has not withdrawn and retry reboot times:%d...",retry_reboot_times)
time.sleep(1)
# 是否查找本地依赖
def _attempt_depends(self,deb_cache, deb_path,_check_local_dep,_auto_satisfy, _install):
@ -491,7 +536,7 @@ class UpdateManager():
_local_satisfy = True
elif not _auto_satisfy:
_local_satisfy = False
error_string = str(debname.split("_")[0])+" dependency is not satisfied. "
error_string = str(debname.split("_")[0])+_("dependency is not satisfied")
error_desc = ",".join(_install)
logging.error(error_string+ error_desc)
else:
@ -509,14 +554,14 @@ class UpdateManager():
elif not _check_local_dep and _auto_satisfy:
_local_satisfy = True
if _install:
error_string = str(debname.split("_")[0])+" dependency is not satisfied, will download. "
error_string = str(debname.split("_")[0])+_("dependency is not satisfied will download")
error_desc = ",".join(_install)
logging.error(error_string+error_desc)
return _local_satisfy,error_string,error_desc
elif not _check_local_dep and not _auto_satisfy:
_local_satisfy = False
if _install:
error_string = str(debname.split("_")[0])+" dependency is not satisfied. "
error_string = str(debname.split("_")[0])+_("dependency is not satisfied")
error_desc = ",".join(_install)
logging.error(error_string+error_desc)
return _local_satisfy,error_string,error_desc
@ -531,6 +576,7 @@ class UpdateManager():
depends_list = []
depends_pkg = []
satisfy_list = []
noSatisfyList = []
depends_count = 0
_status = False
error_string = ''
@ -542,7 +588,11 @@ class UpdateManager():
if _check_local_dep: #查找本地
# 需要查找本地依赖
if len(self.noSatisfyList) > 0:
noSatisfyList = [ str(nS[self.noSatisfyList.index(nS)][0]+'_'+nS[self.noSatisfyList.index(nS)][1]) for nS in self.noSatisfyList]
for nS in self.noSatisfyList:
if len(nS[0]) == 1:
noSatisfyList.append(str(nS[0][0]))
else :
noSatisfyList.append(str(nS[0][0]))
if len(_install) > 0:
for pkg in deb_cache:
if pkg.marked_install and pkg.name != str(debname.split("_")[0]):
@ -553,18 +603,22 @@ class UpdateManager():
depends_list = [debfile for debfile in os.listdir(absolute_path) if debfile.endswith(".deb")]
for depends in depends_pkg:
for debfile in depends_list:
if "%3a" in debfile:
debfile=debfile.replace("%3a",":")
if depends.name in debfile and depends.candidate.version in debfile:
depends_count += 1
satisfy_list.append(debfile)
for depends in noSatisfyList:
for debfile in depends_list:
if "%3a" in debfile:
debfile=debfile.replace("%3a",":")
if depends.split('_')[0] == debfile.split('_')[0] and depends.split('_')[1] == debfile.split('_')[1] and debfile not in satisfy_list:
depends_count += 1
satisfy_list.append(debfile)
if depends_count < len(noSatisfyList):
#本地依赖不满足
_status = False
error_string = str(debname.split("_")[0])+" dependency is not satisfied. "+",".join(noSatisfyList)
error_string = str(debname.split("_")[0])+_("dependency is not satisfied")+", ".join(noSatisfyList)
logging.error(error_string)
header = error_string
return False,header, desc
@ -584,7 +638,7 @@ class UpdateManager():
elif not _check_local_dep:
_status = False
if _install:
error_string = str(debname.split("_")[0])+" dependency is not satisfied. "+",".join(_install)
error_string = str(debname.split("_")[0])+_("dependency is not satisfied")+":".join(_install)
logging.error(error_string)
header = error_string
return False,header, desc
@ -626,7 +680,10 @@ class UpdateManager():
# 需要降级
try:
pkg = deb_cache[debname.split('_')[0]]
if pkg.is_installed and pkg.installed.source_version > debname.split('_')[1]:
# 判断":"在版本号中的情况
if "%3a" in debname:
debname=debname.replace("%3a",":")
if pkg.is_installed and (pkg.installed.source_version > debname.split('_')[1]):
logging.info("Downgrade deb %s, from %s to %s.",\
debname.split('_')[0], pkg.installed.source_version,debname.split('_')[1])
self._need_downgrade = True
@ -657,139 +714,38 @@ class UpdateManager():
def _gen_noSatisfyList(self, depends, deb_cache):
_noSatisfyList = []
_group_satify = False
providers = []
for or_group in depends:
for deb in or_group:
debname,ver,oper = deb
if ":" in debname:
debname=debname.split(":")[0]
try:
pkg = deb_cache[debname]
if not pkg.installed or not apt_pkg.check_dep(pkg.installed.source_version, oper, ver):
_noSatisfyList.append(or_group)
if debname not in deb_cache:
if deb_cache.is_virtual_package(debname):
logging.warning("The cache has no package named '%s', this is a virtual package...", debname)
providers = deb_cache.get_providing_packages(debname)
# hear!
if len(providers) != 1:
logging.error("Can not found depend %s.", debname)
continue
depname = providers[0].name
pkg = deb_cache[depname]
cand = deb_cache._depcache.get_candidate_ver(pkg._pkg)
if not cand:
_group_satify = False
if not apt_pkg.check_dep(cand.ver_str, oper, ver):
_group_satify = False
else:
_group_satify = True
else:
pkg = deb_cache[debname]
if pkg.installed and apt_pkg.check_dep(pkg.installed.source_version, oper, ver) and _group_satify == False:
_group_satify = True
except Exception as e:
logging.error(str(e))
if _group_satify == False and or_group not in _noSatisfyList:
_noSatisfyList.append(or_group)
_group_satify = False
return _noSatisfyList
class LogInstallProgress(apt.progress.base.InstallProgress):
""" Install progress that writes to self.progress_log
(/var/run/unattended-upgrades.progress by default)
"""
def __init__(self,file):
# type: (str) -> None
apt.progress.base.InstallProgress.__init__(self)
self.output_logfd = None # type: int
self.filename=file
self.error_pkg=""
self.errormsg=""
def error(self,pkg, errormsg):
logging.info(("errormsg:%s"),errormsg)
self.error_pkg=self.filename
self.errormsg = errormsg
global error_status
global error_msg
error_status=1
error_msg=errormsg
def status_change(self, pkg, percent, status):
# type: (str, float, str) -> None
logging.info(("pkg:%s,percent:%s,status:%s"),pkg,percent,status)
with open(self.progress_log, "w") as f:
f.write(("%s")%percent)
f.write(_("当前进度: %s ,正在安装:%s,当前状态:%s") % (percent, pkg,status))
f.write(_("Progress: %s %% (%s)") % (percent, pkg))
def _fixup_fds(self):
# () -> None
required_fds = [0, 1, 2, # stdin, stdout, stderr
self.writefd,
self.write_stream.fileno(),
self.statusfd,
self.status_stream.fileno()
]
# ensure that our required fds close on exec
for fd in required_fds[3:]:
old_flags = fcntl.fcntl(fd, fcntl.F_GETFD)
fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC)
# close all fds
try:
# PEP-446 implemented in Python 3.4 made all descriptors
# CLOEXEC, but we need to be able to pass writefd to dpkg
# when we spawn it
os.set_inheritable(self.writefd, True)
except AttributeError: # if we don't have os.set_inheritable()
pass
proc_fd = "/proc/self/fd"
if os.path.exists(proc_fd):
error_count = 0
for fdname in os.listdir(proc_fd):
try:
fd = int(fdname)
except Exception:
print("ERROR: can not get fd for %s" % fdname)
if fd in required_fds:
continue
try:
os.close(fd)
# print("closed: ", fd)
except OSError as e:
# there will be one fd that can not be closed
# as its the fd from pythons internal diropen()
# so its ok to ignore one close error
error_count += 1
if error_count > 1:
print("ERROR: os.close(%s): %s" % (fd, e))
def _redirect_stdin(self):
# type: () -> None
REDIRECT_INPUT = os.devnull
fd = os.open(REDIRECT_INPUT, os.O_RDWR)
os.dup2(fd, 0)
def _redirect_output(self):
# type: () -> None
# do not create log in dry-run mode, just output to stdout/stderr
if not apt_pkg.config.find_b("Debug::pkgDPkgPM", False):
logfd = self._get_logfile_dpkg_fd()
os.dup2(logfd, 1)
os.dup2(logfd, 2)
def _get_logfile_dpkg_fd(self):
# type: () -> int
logfd = os.open(
"/var/log/kylin-system-updater/kylin-system-updater.log.1", os.O_RDWR | os.O_APPEND | os.O_CREAT, 0o640)
try:
import grp
adm_gid = grp.getgrnam("adm").gr_gid
os.fchown(logfd, 0, adm_gid)
except (KeyError, OSError):
pass
return logfd
def update_interface(self):
# type: () -> None
# call super class first
apt.progress.base.InstallProgress.update_interface(self)
def _log_in_dpkg_log(self, msg):
# type: (str) -> None
logfd = self._get_logfile_dpkg_fd()
os.write(logfd, msg.encode("utf-8"))
os.close(logfd)
def finish_update(self):
# type: () -> None
# logging.info("finished")
# if error_status == 1:
# os._exit(1)
pass
def fork(self):
# type: () -> int
pid = os.fork()
if pid == 0:
self._fixup_fds()
self._redirect_stdin()
self._redirect_output()
return pid

View File

@ -4,14 +4,14 @@ import dbus
import dbus.service
import logging
import apt_pkg
import subprocess#snap
from gettext import gettext as _
from .backend import InstallBackend
from .Core.loop import mainloop
from .Core.utils import humanize_size
from SystemUpdater.Core.utils import (
unLockedEnableShutdown,
)
from SystemUpdater.Core.utils import unLockedEnableShutdown
import locale
UPDATER_DBUS_INTERFACE = 'com.kylin.systemupgrade.interface'
UPDATER_DBUS_PATH = '/com/kylin/systemupgrade'
@ -42,8 +42,6 @@ COLORMETHOR_PREFIX = FRONT_COLOR_SEQ % CYAN
class UpdateManagerDbusController(dbus.service.Object):
""" this is a helper to provide the UpdateManagerIFace """
UPDATER_DBUS_INTERFACE = 'com.kylin.systemupgrade.interface'
def __init__(self, parent, bus_name,
object_path=UPDATER_DBUS_PATH):
dbus.service.Object.__init__(self, bus_name, object_path)
@ -61,7 +59,7 @@ class UpdateManagerDbusController(dbus.service.Object):
# logging.info("Start to update Source Template...")
obj = self.bus.get_object('com.kylin.software.properties', '/com/kylin/software/properties')
interface = dbus.Interface(obj, dbus_interface='com.kylin.software.properties.interface')
retval = interface.updateSourceTemplate(timeout=5)
retval = interface.updateSourceTemplate(timeout=20)
except Exception as e:
header = _("Unable to access the source management server")
desc = str(e)
@ -77,6 +75,16 @@ class UpdateManagerDbusController(dbus.service.Object):
# logging.info("Update sourceTemplate successed...")
return retval,header,desc
def is_reboot_required(self):
"""If a reboot is required to get all changes into effect."""
return os.path.exists(os.path.join(apt_pkg.config.find_dir("Dir"),
"var/run/reboot-required"))
def is_logout_required(self):
"""If a logout is required to get all changes into effect."""
return os.path.exists(os.path.join(apt_pkg.config.find_dir("Dir"),
"var/run/logout-required"))
#重启aptdeamon后台服务
def make_aptdeamon_restart(self):
header = ''
@ -149,17 +157,13 @@ class UpdateManagerDbusController(dbus.service.Object):
@dbus.service.method(UPDATER_DBUS_INTERFACE,in_signature='s',out_signature='i')
def GetBackendStatus(self,user_lang):
try:
# if user_lang not in os.environ["LANG"]:
# 如果系统不是中文也不是英文 就默认中文
# if user_lang != "en" and user_lang != "zh_CN:en":
# logging.error("%s",user_lang)
# user_lang = "zh_CN:en"
# logging.warning("The system language is switched %s to %s",os.environ["LANGUAGE"],user_lang)
# os.environ["LANGUAGE"] = user_lang
(lang, encoding) = locale._parse_localename(str(user_lang))
#处于更新和升级中的话 不进行更新
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' GetBackendStatus ...')
if lang != os.environ["LANGUAGE"]:
logging.warning("The system language is switched %s to %s",os.environ["LANGUAGE"],lang)
os.environ["LANGUAGE"] = lang
return self.parent.is_working
except Exception:
return False
@ -338,12 +342,12 @@ class UpdateManagerDbusController(dbus.service.Object):
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='ss', sender_keyword='sender')
def InsertInstallState(self, item, value, sender=None):
try:
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' InsertInstallState, options%svalue%s' % (item, value))
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' InsertInstallState, options:%svalue:%s' % (item, value))
self.parent.sqlite3_server.insert_into_display(item, value)
logging.info("Database inserted successfullyoptions%svalue%s" % (item, value))
logging.info("Database inserted successfullyoptions:%svalue:%s" % (item, value))
return True
except Exception as e:
logging.error("Database insert failedoptions%svalue%s" % (item, value))
logging.error("Database insert failedoptions:%svalue:%s" % (item, value))
return False
# # download certain package and its dependencies
@ -431,6 +435,61 @@ class UpdateManagerDbusController(dbus.service.Object):
except Exception as e:
logging.error(str(e))
# dbus接口安装本地snap包
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='s', out_signature='b', sender_keyword='sender')
def InstallSnap(self, path, sender=None):
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+" Install Snap Packages(%s)...",path)
try:
status= subprocess.getstatusoutput("snap install " +path+" --dangerous")
except Exception as e:
logging.error("Install Snap Packages occur error:%s",str(e))
msg = {"statue": "Fail", "errorcode": str(0), "error_message": _("Command execution error")}
kwarg = {"error_message": str(msg)}
self.KumSnapSignal("snap_error", kwarg)
return False
#安装成功
if status[0]==0:
logging.info("Install Snap Packages(%s) is success",path)
msg = {"statue": "Success", "errorcode": str(0), "error_message": ""}
kwarg = {"action": str(msg)}
self.KumSnapSignal("snap_finish", kwarg)
return True
else:
#失败之后的处理
logging.info("Install Snap Packages(%s) is Failed",path)
if "supported architectures" in status[1]:
logging.error("Supported architectures does not match")
msg = {"statue": "Fail", "errorcode": str(0), "error_message": _("Unsupported architecture")}
else:
logging.error("Other Error...")
msg = {"statue": "Fail", "errorcode": str(0), "error_message": _("Other Error")}
kwarg = {"error_message": str(msg)}
self.KumSnapSignal("snap_error", kwarg)
return False
# 监控是否需要重启的操作
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='s', out_signature='b')
def CheckRebootRequired(self, model):
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' CheckRebootRequired is be %s',str(model))
try:
#更新完成之后检查是否需要重启
if self.is_reboot_required() == True:
self.RebootLogoutRequired("reboot")
logging.info("System need to Reboot...")
elif self.is_logout_required() == True:
self.RebootLogoutRequired("logout")
logging.info("System need to Logout...")
else:
logging.info("System not need to Reboot or Logout...")
except Exception as e:
logging.error(str(e))
return False
return True
#更新进度信息 0~100 进度信息 101为非预期的信号
@dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='is')
def UpdateDetectStatusChanged(self,progress,status):
@ -471,7 +530,7 @@ class UpdateManagerDbusController(dbus.service.Object):
#查询解决依赖 信号
@dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='bbasasasss')
def UpdateDependResloveStatus(self, resolver_status, remove_status,remove_pkgs,pkg_raw_description,delete_desc,error_string='',error_desc=''):
logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" UpdateDependResloveStatus:resolver_status = %r , resolver_status = %r , remove_pkgs = %a,pkg_raw_description = %s ,delete_desc = %s,error_string = %s , error_desc = %s ",\
logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" UpdateDependResloveStatus:resolver_status = %r , remove_status = %r , remove_pkgs = %a,pkg_raw_description = %s ,delete_desc = %s,error_string = %s , error_desc = %s ",\
resolver_status,remove_status,remove_pkgs,pkg_raw_description,delete_desc,error_string,error_desc)
#查询dist-upgrade解决依赖
@ -517,49 +576,17 @@ class UpdateManagerDbusController(dbus.service.Object):
success,error_string,error_desc)
#安装进度信息 0~100 进度信息 101为非预期的信号
@dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='bss')
@dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='iss')
def InstalldebStatusChanged(self,progress,status,current_details):
logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" InstalldebStatusChanged progress = %d , status = %s ,current_details = %s",\
progress,status,current_details)
# dbus接口安装本地snap包
@dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='s', out_signature='b', sender_keyword='sender')
def InstallSnap(self, path, sender=None):
logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+" InstallSnap Install Path = %s...",path)
try:
status= subprocess.getstatusoutput("snap install " +path+" --dangerous")
except Exception as e:
logging.error("Install Snap Packages occur error:%s",str(e))
msg = {"statue": "Fail", "errorcode": str(0), "error_message": _("Command execution error")}
kwarg = {"error_message": str(msg)}
self.KumSnapSignal("snap_error", kwarg)
return False
#安装成功
if status[0]==0:
logging.info("Install Snap Packages(%s) is success",path)
msg = {"statue": "Success", "errorcode": str(0), "error_message": ""}
kwarg = {"action": str(msg)}
self.KumSnapSignal("snap_finish", kwarg)
return True
else:
#失败之后的处理
logging.info("Install Snap Packages(%s) is Failed",path)
if "supported architectures" in status[1]:
logging.error("Supported architectures does not match")
msg = {"statue": "Fail", "errorcode": str(0), "error_message": _("Unsupported architecture")}
else:
logging.error("Other Error...")
msg = {"statue": "Fail", "errorcode": str(0), "error_message": _("Other Error")}
kwarg = {"error_message": str(msg)}
self.KumSnapSignal("snap_error", kwarg)
return False
# dbus 信号用于发送本地安装snap包的结果
@dbus.service.signal(UPDATER_DBUS_INTERFACE, signature='sa{sv}')
def KumSnapSignal(self, type_msg, msg):
logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" KumSnapSignal type_msg = %s,msg = %s",type_msg,str(msg))
#重启和注销请求信号
@dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='s')
def RebootLogoutRequired(self,required_status=''):
logging.info(COLORLOG_PREFIX + "Emitting"+ COLORLOG_SUFFIX + " RebootLogoutRequired required_status = %s",required_status)

View File

@ -1,5 +1,16 @@
#!/usr/bin/env python
import aptdaemon.client as client
import aptdaemon.errors as errors
import aptdaemon.enums as enums
from aptdaemon.enums import (
EXIT_SUCCESS,
EXIT_FAILED,
EXIT_CANCELLED,
get_error_description_from_enum,
get_error_string_from_enum,
get_status_string_from_enum
)
from defer import inline_callbacks
from SystemUpdater.backend import InstallBackend
import logging
@ -7,6 +18,8 @@ from gettext import gettext as _
from SystemUpdater.Core.utils import humanize_size
import dbus,time
from gi.repository import GLib
import os
from importlib import reload
# 超时检测 秒单位
UPDATER_IDLE_CHECK_INTERVAL = 10
@ -22,23 +35,13 @@ class InstallBackendAptdaemon(InstallBackend):
def __init__(self, window_main, action):
InstallBackend.__init__(self, window_main, action)
self.window_main = window_main
from aptdaemon import client
from aptdaemon import errors
from aptdaemon.enums import (EXIT_SUCCESS,
EXIT_FAILED,
EXIT_CANCELLED,
get_error_description_from_enum,
get_error_string_from_enum,
get_status_string_from_enum
)
self.errors = errors
self.EXIT_SUCCESS = EXIT_SUCCESS
self.EXIT_FAILED = EXIT_FAILED
self.EXIT_CANCELLED = EXIT_CANCELLED
self.get_error_description_from_enum = get_error_description_from_enum
self.get_error_string_from_enum = get_error_string_from_enum
self.get_status_string_from_enum = get_status_string_from_enum
#切换aptdaemon的语言 重新导入模块就可以进行切换
if os.environ["LANGUAGE"] != self.window_main.aptdaemonLang:
logging.warning("Aptdeamon language is switched %s to %s",self.window_main.aptdaemonLang,os.environ["LANGUAGE"])
self.window_main.aptdaemonLang = os.environ["LANGUAGE"]
reload(client)
reload(errors)
reload(enums)
#客户端连接aptdeamon的dbus接口
self.client = client.AptClient()
@ -116,7 +119,7 @@ class InstallBackendAptdaemon(InstallBackend):
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_UPDATE,
_("Checking for updates…"), False)
except self.errors.NotAuthorizedError:
except errors.NotAuthorizedError:
self._action_done(self.ACTION_UPDATE,
authorized=False, success=False,
error_string='', error_desc='')
@ -138,11 +141,11 @@ class InstallBackendAptdaemon(InstallBackend):
yield self._show_transaction(trans, self.ACTION_INSTALL,
_("Installing updates…"), True)
except self.errors.NotAuthorizedError:
except errors.NotAuthorizedError:
self._action_done(self.ACTION_INSTALL,
authorized=False, success=False,
error_string='', error_desc='')
except self.errors.TransactionFailed as e:
except errors.TransactionFailed as e:
self.trans_failed_msg = str(e)
except dbus.DBusException as e:
if e.get_dbus_name() != "org.freedesktop.DBus.Error.NoReply":
@ -164,7 +167,7 @@ class InstallBackendAptdaemon(InstallBackend):
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_INSTALL_DEB,
_("Installing deb packages…"), False)
except self.errors.NotAuthorizedError:
except errors.NotAuthorizedError:
self._action_done(self.ACTION_INSTALL_DEB,
authorized=False, success=False,
error_string='', error_desc='')
@ -184,7 +187,7 @@ class InstallBackendAptdaemon(InstallBackend):
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_FIX_BROKEN,
_("Installing deb packages…"), False)
except self.errors.NotAuthorizedError:
except errors.NotAuthorizedError:
self._action_done(self.ACTION_FIX_BROKEN,
authorized=False, success=False,
error_string='', error_desc='')
@ -203,7 +206,7 @@ class InstallBackendAptdaemon(InstallBackend):
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_FIX_INCOMPLETE,
_("fix incomplete install"), False)
except self.errors.NotAuthorizedError:
except errors.NotAuthorizedError:
self._action_done(self.ACTION_FIX_INCOMPLETE,
authorized=False, success=False,
error_string='', error_desc='')
@ -222,7 +225,7 @@ class InstallBackendAptdaemon(InstallBackend):
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_CLEAN,
_("Remove all downloaded files."), False)
except self.errors.NotAuthorizedError:
except errors.NotAuthorizedError:
self._action_done(self.ACTION_CLEAN,
authorized=False, success=False,
error_string='', error_desc='')
@ -241,7 +244,7 @@ class InstallBackendAptdaemon(InstallBackend):
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_DOWNLOADONLY,
_("Downloading deb packages…"), False)
except self.errors.NotAuthorizedError:
except errors.NotAuthorizedError:
self._action_done(self.ACTION_DOWNLOADONLY,
authorized=False, success=False,
error_string='', error_desc='')
@ -260,15 +263,15 @@ class InstallBackendAptdaemon(InstallBackend):
# 注册回调函数 接收更新的状态
yield self._show_transaction(trans, self.ACTION_REMOVE_PACKAGES,
_("Installing deb packages…"), False)
except self.errors.NotAuthorizedError:
except errors.NotAuthorizedError:
self._action_done(self.ACTION_REMOVE_PACKAGES,
authorized=False, success=False,
error_string='', error_desc='')
except Exception as e:
logging.error(str(e))
# self._action_done(self.ACTION_REMOVE_PACKAGES,
# is_cancelled=False, success=False,
# error_string='', error_desc='')
self._action_done(self.ACTION_REMOVE_PACKAGES,
is_cancelled=False, success=False,
error_string=str(e), error_desc='')
#进度回调
def _on_progress_changed(self, trans,progress,action):
@ -290,7 +293,7 @@ class InstallBackendAptdaemon(InstallBackend):
#同步状态回调
def _on_status_changed(self, trans, status,action):
#转化词条
self.trans_status = self.get_status_string_from_enum(status)
self.trans_status = get_status_string_from_enum(status)
self._dist_status_changed(action,self.now_upgrade.upgrade_groups+self.now_upgrade.single_pkgs,\
self.trans_progress,self.trans_status,self.details)
@ -360,7 +363,7 @@ class InstallBackendAptdaemon(InstallBackend):
#增加记录当产生错误的时候 详细信息
def _on_error_changed(self, trans,error_code, error_details):
# error_string = self.get_error_string_from_enum(error_code)
# error_string = get_error_string_from_enum(error_code)
self.trans_error_details = str(error_details)
logging.error(str(error_details))
@ -377,7 +380,7 @@ class InstallBackendAptdaemon(InstallBackend):
trans.connect("progress-details-changed", self._on_progress_download_changed)
trans.connect("status-details-changed", self._on_details_changed)
trans.connect("error", self._on_error_changed)
# yield trans.set_debconf_frontend("ukui")
# yield trans.set_locale(os.environ["LANGUAGE"] + ".UTF-8")
yield trans.run()
def _on_finished(self, trans, status, action):
@ -386,29 +389,29 @@ class InstallBackendAptdaemon(InstallBackend):
#退出
self.on_install_stage = False
if status == self.EXIT_FAILED:
error_string = self.get_error_string_from_enum(trans.error.code)
error_desc = self.get_error_description_from_enum(trans.error.code)
if status == EXIT_FAILED:
error_string = get_error_string_from_enum(trans.error.code)
error_desc = get_error_description_from_enum(trans.error.code)
if self.trans_failed_msg:
error_desc = error_desc + "\n" + self.trans_failed_msg
#取消下载
elif status == self.EXIT_CANCELLED:
elif status == EXIT_CANCELLED:
error_string = _("Failed to fetch")
error_desc = _("_Cancel Upgrade")
elif status == self.EXIT_SUCCESS and action == self.ACTION_INSTALL:
elif status == EXIT_SUCCESS and action == self.ACTION_INSTALL:
error_string = _("System upgrade is complete.")
elif status == self.EXIT_SUCCESS and action == self.ACTION_REMOVE_PACKAGES:
elif status == EXIT_SUCCESS and action == self.ACTION_REMOVE_PACKAGES:
error_string = _("Uninstallation completed")
is_success = (status == self.EXIT_SUCCESS)
is_success = (status == EXIT_SUCCESS)
try:
self._action_done(action,
is_cancelled=(status == self.EXIT_CANCELLED), success=is_success,
is_cancelled=(status == EXIT_CANCELLED), success=is_success,
error_string=error_string, error_desc=error_desc)
except TypeError:
# this module used to be be lazily imported and in older code
# trans_failed= is not accepted
# TODO: this workaround can be dropped in Ubuntu 20.10
self._action_done(action,
is_cancelled=(status == self.EXIT_CANCELLED), success=is_success,
is_cancelled=(status == EXIT_CANCELLED), success=is_success,
error_string=error_string, error_desc=error_desc)

View File

@ -7,7 +7,7 @@ import logging
import os
from gettext import gettext as _
import apt_pkg
import apt
from SystemUpdater.Core.utils import (
unLockedEnableShutdown,
check_free_space,
@ -95,7 +95,7 @@ class InstallBackend():
if len(pkgs_install) == 0 and len(pkgs_upgrade) == 0 and len(pkgs_remove) == 0:
#FIXME: 没有需要升级和安装的包 检查升级包是否不存在本次升级
header = _("There are no packages that need to be upgraded and installed")
header = _("Resolve the dependency exception,there is no package that needs to be upgrade,please check the package status.")
desc = _("Check if the upgrade package does not exist for this upgrade")
self._action_done(self.action,True,False,header,desc)
return
@ -330,14 +330,19 @@ class InstallBackend():
with cache.actiongroup():
if cache.get_changes():
cache.clear()
Fix = apt_pkg.ProblemResolver(cache._depcache)
resolver = apt.cache.ProblemResolver(cache)
#计算出来的需要删除的包列表
all_delete_pkgs = []
all_delete_desc = []
#标记计算所有需要升级的包
for pkg in pkgs_upgrade:
cache[pkg].mark_upgrade()
#mark_install (auto_fix: bool = True, auto_inst: bool = True, from_user: bool = True)
cache[pkg].mark_install(True, False, True)
resolver.clear(cache[pkg])
resolver.protect(cache[pkg])
deleted_pkgs = self._make_delete_pkgs(cache,all_delete_pkgs)
for d_pkg in deleted_pkgs:
delete_desc = str(d_pkg) + _(" Will be deleted Due to Upgrade ") + str(pkg)
@ -346,14 +351,17 @@ class InstallBackend():
#标记计算所有需要安装的
for pkg in pkgs_install:
cache[pkg].mark_install()
cache[pkg].mark_install(True, False,True)
resolver.clear(cache[pkg])
resolver.protect(cache[pkg])
deleted_pkgs = self._make_delete_pkgs(cache,all_delete_pkgs)
for d_pkg in deleted_pkgs:
delete_desc = str(d_pkg) + _(" Will be deleted Due to Install ") + str(pkg)
all_delete_desc.append(delete_desc)
logging.warning(delete_desc)
#会安装新包和卸载包
Fix.resolve()
resolver.resolve()
#不会安装和卸载 只升级
return _success,all_delete_pkgs,all_delete_desc,header,desc
except Exception as e:
@ -430,6 +438,9 @@ class InstallBackend():
self.cache.clear()
self.window_main.dbusController.UpdateInstallFinished(success,upgrade_content,error_string,error_desc)
if success:
self.window_main.dbusController.CheckRebootRequired("self")
elif action == self.ACTION_UPDATE:
if success == False and 'The following signatures' in self.trans_error_details:

View File

@ -26,3 +26,6 @@ Kylin-system-updater::ImportantListDir "/var/lib/kylin-software-properties/templ
Dir::Bin::Methods::ftp "ftp";
DPkg::Options{
"--force-confnew";
};

View File

@ -0,0 +1,26 @@
#!/bin/sh
# a) it breaks if its not available
# b) the string we have here does not need it (because it has no vars)
eval_gettext() {
if [ -x /usr/bin/gettext ]; then
echo $(gettext "$1")
else
echo "$1"
fi
}
export TEXTDOMAIN=update-notifier
export TEXTDOMAINDIR=/usr/share/locale
case "$DPKG_MAINTSCRIPT_PACKAGE::$DPKG_MAINTSCRIPT_NAME" in
linux-image-extra*::postrm)
exit 0;;
esac
if [ "$0" = "/etc/kernel/postinst.d/update-notifier" ]; then
DPKG_MAINTSCRIPT_PACKAGE=linux-base
fi
# Wake the applet up
echo "*** $(eval_gettext "System logout required") ***" > /var/run/logout-required
echo "$DPKG_MAINTSCRIPT_PACKAGE" >> /var/run/logout-required.pkgs

View File

@ -0,0 +1,26 @@
#!/bin/sh
# a) it breaks if its not available
# b) the string we have here does not need it (because it has no vars)
eval_gettext() {
if [ -x /usr/bin/gettext ]; then
echo $(gettext "$1")
else
echo "$1"
fi
}
export TEXTDOMAIN=update-notifier
export TEXTDOMAINDIR=/usr/share/locale
case "$DPKG_MAINTSCRIPT_PACKAGE::$DPKG_MAINTSCRIPT_NAME" in
linux-image-extra*::postrm)
exit 0;;
esac
if [ "$0" = "/etc/kernel/postinst.d/update-notifier" ]; then
DPKG_MAINTSCRIPT_PACKAGE=linux-base
fi
# Wake the applet up
echo "*** $(eval_gettext "System restart required") ***" > /var/run/reboot-required
echo "$DPKG_MAINTSCRIPT_PACKAGE" >> /var/run/reboot-required.pkgs

View File

@ -40,7 +40,7 @@
| PurgePackages | as | b | 卸载软件包 | |
| InstalldebFile | ssbb | b | 安装本地deb包 | |
| DataBackendCollect | ss | b | | |
| | | | | |
| CheckRebootRequired | s | b | 检查是否需要重启的方法,以及弹窗提示 | |
### Method分析
#### UpdateDetect
@ -182,6 +182,14 @@
#### CheckRebootRequired
- `介绍:` 检查是否需要重启的方法,以及弹窗提示
- `入参`: `s:`标识那个应用调的此接口如自动更新可填入字符串“autoyupgrade”
- `出参:`True or False 执行的结果
### Signal列表
@ -200,7 +208,7 @@
| FixBrokenStatusChanged | iiisss | 修复依赖的状态信号 |
| PurgePackagesFinished | iss | 卸载完成信号 |
| PurgePkgStatusChanged | bss | 卸载进度信息以及状态信息 |
| | | |
| RebootLogoutRequired | s | 请求重启或者注销的信号 |
| | | |
@ -271,7 +279,7 @@
- `介绍:` 升级安装完成的信号
- `出参`: `b:`升级是否成功, `b:`是否需要重启,`as:`可升级的组列表,`s:`产生错误的结果,`s:`产生错误的原因
- `出参`: `b:`升级是否成功,`as:`可升级的组列表,`s:`产生错误的结果,`s:`产生错误的原因
- `示例:`
@ -367,13 +375,30 @@
InstalldebFinished success = True , error_string = , error_desc =
#安装失败 缺少依赖的
InstalldebFinished success = False , error_string = bandit dependency is not satisfied. , error_desc = python3-bandit
InstalldebFinished success = False , error_string = bandit dependency is not satisfied , error_desc = python3-bandit
#安装失败 选择从网络拉依赖 网络断开 报网络错误
InstalldebFinished success = False , error_string = 下载软件包文件失败 , error_desc = 检查您的网络连接。
```
#### RebootLogoutRequired
- `介绍:`请求重启和注销的信号
- `出参`: `s:` "reboot" 表示重启 "logout"表示注销
- `示例:`
```sh
Emitting RebootLogoutRequired required_status = reboot
```

View File

@ -42,17 +42,25 @@ if __name__ == "__main__":
help=_("Do not check for updates source when updating"))
parser.add_option ("--no-update", action="store_true",
dest="no_update", default=False,
help=_("Do not check for updates when starting"))
help="Do not check for updates when starting")
parser.add_option("-c", "--close-filter",
default=False,
action="store_true", dest="close_filter",
help=_("Quit and close allowed_origin"))
help=_("Quit and close allowed origin"))
parser.add_option("--no-check-network",
default=False,
action="store_true", dest="no_check_network",
help=_("Quit and close check network"))
parser.add_option("--no-check-selfupgrade",
default=False,
action="store_true", dest="no_check_selfupgrade",
help=_("no check self(kylin-system-updater) upgrade"))
(options, args) = parser.parse_args()
if os.getuid() != 0:
print(_("You need to be root to run this application"))
sys.exit(1)
# set debconf to NON_INTERACTIVE
@ -60,6 +68,16 @@ if __name__ == "__main__":
os.environ["TERM"] = "xterm"
os.environ["PATH"] = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
#当不存在语言变量时 默认显示中文
if not "LANGUAGE" in os.environ:
os.environ["LANGUAGE"] = "zh_CN"
#做一些规范处理
if os.environ["LANGUAGE"] == "en":
os.environ["LANGUAGE"] = "en_US"
if os.environ["LANGUAGE"] == "zh_CN:en":
os.environ["LANGUAGE"] = "zh_CN"
# ensure that we are not killed when the terminal goes away e.g. on
# shutdown
signal.signal(signal.SIGHUP, signal.SIG_IGN)
@ -69,22 +87,12 @@ if __name__ == "__main__":
logging.basicConfig(format=FORMAT,level=logging.DEBUG,datefmt='%m-%d,%H:%M:%S')
else:
logging.basicConfig(format=FORMAT,level=logging.DEBUG,datefmt='%m-%d,%H:%M:%S',filename = logfile(),filemode = 'a')
#目前 多用户的语言切换还未做好 不启用
# if sys.getfilesystemencoding() == "ascii" and not "LANG" in os.environ:
# logging.info('start setting environ["LANG"] ...')
# os.environ["LANG"] = "C.UTF-8"
# os.execv(sys.argv[0], sys.argv)
# if not "LANGUAGE" in os.environ:
# os.environ["LANGUAGE"] = "zh_CN.UTF-8"
# logging.info('kylin-system-updater(lang:%s) starting ...',os.environ["LANGUAGE"])
logging.info('kylin-system-updater starting ...')
logging.info('kylin-system-updater(lang:%s) starting ...',os.environ["LANGUAGE"])
app = UpdateManager(options)
#当出现安装过程中异常的重启时 直接开机直接进行修复操作
#当出现安装过程中异常的重启时 开机直接进行修复操作
if app.configs.getWithDefault("SystemStatus", "isabnormalreboot", False) == True:
app.start_update()

View File

@ -2569,8 +2569,8 @@ msgstr "获取推送出现异常,请稍后再试"
msgid "You need to be root to run this application"
msgstr "你需要root权限运行"
msgid "There are no packages that need to be upgraded and installed"
msgstr "没有需要升级和安装的包"
msgid "Resolve the dependency exception,there is no package that needs to be upgrade,please check the package status."
msgstr "解决依赖关系存在异常,没有需要升级的软件,请检查软件包状态。"
msgid "Check if the upgrade package does not exist for this upgrade"
msgstr "检查升级包是否不存在本次升级"
@ -2593,6 +2593,12 @@ msgstr "架构不符合"
msgid "Other Error"
msgstr "其他错误"
msgid "dependency is not satisfied"
msgstr "依赖关系不满足"
msgid "dependency is not satisfied will download"
msgstr "依赖关系不满足"
msgid "Disk space is insufficient, please clean the disk and then upgrade"
msgstr "磁盘空间不足,请清理磁盘后进行升级更新"

View File

@ -5,7 +5,7 @@ domain=kylin-system-updater
formats = bztar
[nosetests]
match=^test
match=test
[install]
skip-build=0

144
debian/changelog vendored
View File

@ -1,10 +1,148 @@
kylin-system-updater (1.3.1kord) v101; urgency=medium
* BUG: wu
kylin-system-updater (1.4.6.1kord) v101; urgency=medium
* BUG: 无
* 需求号: 无
* 其他改动说明: 增加重启弹窗
* 其他改动影响域:系统更新
-- luoxueyi <luoxueyi@kylinos.cn> Tue, 18 Jan 2022 21:45:30 +0800
kylin-system-updater (1.4.6kord) v101; urgency=medium
* BUG: #102463: 【自动更新】自动更新时源优先级策略未生效,实际获取所有源中最高版本而非按照设置的优先级顺序获取包,导致包版本下载错误
* 需求号: 无
* 其他改动说明: 无
* 其他改动影响域:系统更新
-- luoxueyi <luoxueyi@kylinos.cn> Tue, 18 Jan 2022 21:45:30 +0800
kylin-system-updater (1.4.5kord) v101; urgency=medium
* BUG: #102442 【系统更新】【PTOF】系统更新过程重启控制面板页面展示内容为上次更新时间并持续停留在此页面此时不能获取更新列表进行更新操作
* 需求号: 无
* 其他改动说明: 无
* 其他改动影响域:系统更新
-- luoxueyi <luoxueyi@kylinos.cn> Fri, 14 Jan 2022 20:38:07 +0800
kylin-system-updater (1.4.4kord) v101; urgency=medium
* BUG: 无
* 需求号: 无
* 其他改动说明: 增加自适应更新的安装重启提示
* 其他改动影响域:系统更新
-- luoxueyi <luoxueyi@kylinos.cn> Wed, 12 Jan 2022 21:34:56 +0800
kylin-system-updater (1.4.3kord) v101; urgency=medium
* BUG: #94805 【更新升级-需求-9002】【系统更新】更新页面上方文字与图标未对齐
#101985【更新】系统字号为15点击查看历史设备左上角“历史更新”字样未随系统字号改变而改变
#101669【自适应更新】【自动更新】自动更新过滤掉了非正式源只能获取archive正式源的包其余源的更新内容不能获取到
#102069【安装器】无法安装360助手等三方软件且报错不满足依赖使用dpkg命令可以成功安装且不需要安装其他依赖
* 需求号: 无
* 其他改动说明: 无
* 其他改动影响域:系统更新
-- luoxueyi <luoxueyi@kylinos.cn> Mon, 10 Jan 2022 18:11:55 +0800
kylin-system-updater (1.4.1.5kord) v101; urgency=medium
* BUG: #94805 【更新升级-需求-9002】【系统更新】更新页面上方文字与图标未对齐
#101985【更新】系统字号为15点击查看历史设备左上角“历史更新”字样未随系统字号改变而改变
#101333【控制面板】【更新】系统语言为英文系统字号为15系统主题为默认升级页面自动下载与安装更新悬浮框背景为黑色
#101669【自适应更新】【自动更新】自动更新过滤掉了非正式源只能获取archive正式源的包其余源的更新内容不能获取到
#102069【安装器】无法安装360助手等三方软件且报错不满足依赖使用dpkg命令可以成功安装且不需要安装其他依赖
* 需求号: 无
* 其他改动说明: 无
* 其他改动影响域:系统更新
-- luoxueyi <luoxueyi@kylinos.cn> Mon, 10 Jan 2022 18:11:55 +0800
kylin-system-updater (1.4.1.1kord) v101; urgency=medium
* BUG: #101309【控制面板】【更新】更新页面图标和检查更新时的动画丢失
#89824【更新升级-需求-9002】【系统更新】单个待更新包选择全部更新拒绝安装后不应该提示"部分更新失败";且更新失败后应该出现检测更新的按钮
#100839【控制面板|更新】最大字号,一个账户系统语言为英文,一个为中文,英文账户的控制面板-更新界面显示不全
* 需求号: 无
* 其他改动说明: 无
* 其他改动影响域:系统更新插件
-- luoxueyi <luoxueyi@kylinos.cn> Fri, 24 Dec 2021 10:36:19 +0800
kylin-system-updater (1.4.0kord) v101; urgency=medium
* BUG: #99496【系统更新】【英文】【UI布局】更新界面提示信息较长时页面格式变成左右拖动框与其他界面格式不符
#98774【用例104332】【升级】更新历史窗口左侧名称显示不全
#97888【离线更新】【PTOF】控制面板识别不到光盘源中的包
#97116【控制面板|更新】更新界面检测按钮显示不全
#95290【系统更新】系统语言为英文时打开控制面板-更新升级页面再切换到字体页面将字号切换到15号返回升级页面details显示不全
#94804【更新升级-需求-9002】【系统更新】应用后的更新按钮内“更新”字样未居中
#93555【系统更新】【SP2 UI走查】更新-页面未按最新设计稿实现
#85618【内测】【摸底测试】【更新升级】上次更新提示词错误
#85312【内测】【摸底测试】【更新升级】更新失败提示字不合理
#85269【内测】【控制面板|更新】英文模式下检查更新文字显示不全
* 需求号: 无
* 其他改动说明: 修改frame边际保证在显示器不同缩放情况下仍然能够正常显示
* 其他改动影响域:系统更新插件
-- hechengyuan <hechengyuan@kylinos.cn> Fri, 24 Dec 2021 10:36:19 +0800
kylin-system-updater (1.3.5kord) v101; urgency=medium
* BUG: #100356【试用模式】点击设置的更新控制面板闪退安装完系统后打开不会闪退
#93390 【控制面板|更新】打开控制面板切换深色主题,不关闭控制面板的前提下更新部分文字未反白
#91169 【更新升级-需求-9002】【系统更新】开启通知可更新应用后不弹窗通知可更新
#99894 【安装器】安装失败-不满足依赖的提示未汉化
#97120 【控制面板|更新】软件源更新失败提示语未汉化
#99500 【系统更新】【英文】【UI布局】更新界面update settings与下方标题未对齐
#99498 【系统更新】【英文】【UI布局】更新界面自动更新的第二行介绍显示不全
* 需求号: 无
* 其他改动说明: 修改部分英文表述和中文翻译
* 其他改动影响域:系统更新插件
-- hechengyuan <hechengyuan@kylinos.cn> Fri, 24 Dec 2021 10:36:19 +0800
kylin-system-updater (1.3.4kord) v101; urgency=medium
* BUG: #100356【试用模式】点击设置的更新控制面板闪退安装完系统后打开不会闪退
#93390 【控制面板|更新】打开控制面板切换深色主题,不关闭控制面板的前提下更新部分文字未反白
#91169 【更新升级-需求-9002】【系统更新】开启通知可更新应用后不弹窗通知可更新
#99894 【安装器】安装失败-不满足依赖的提示未汉化
#97120 【控制面板|更新】软件源更新失败提示语未汉化
#99500 【系统更新】【英文】【UI布局】更新界面update settings与下方标题未对齐
#99498 【系统更新】【英文】【UI布局】更新界面自动更新的第二行介绍显示不全
* 需求号: 无
* 其他改动说明: 无
* 其他改动影响域:系统更新插件
-- hechengyuan <hechengyuan@kylinos.cn> Fri, 24 Dec 2021 10:36:19 +0800
kylin-system-updater (1.3.2.1kord) v101; urgency=medium
* BUG: 无
* 需求号: 无
* 其他改动说明: 增加运行依赖python3-distro-info
* 其他改动影响域:系统更新插件
-- luoxueyi <luoxueyi@kylinos.cn> Fri, 24 Dec 2021 10:36:19 +0800
kylin-system-updater (1.3.2kord) v101; urgency=medium
* BUG: 无
* 需求号: 无
* 其他改动说明: 修改与旧版本控制面板的冲突
* 其他改动影响域:系统更新插件
-- luoxueyi <luoxueyi@kylinos.cn> Thu, 23 Dec 2021 16:44:11 +0800
kylin-system-updater (1.3.1kord) v101; urgency=medium
* BUG: 无
* 需求号: 无
* 其他改动说明: 修复点击全部升级后执行更新检测的问题
* 其他改动影响域:系统更新全部升级
-- luoxueyi <luoxueyi@kylinos.cn> Tue, 21 Dec 2021 17:07:57 +0800
kylin-system-updater (1.3.0kord) v101; urgency=medium

1
debian/control vendored
View File

@ -71,6 +71,7 @@ Depends: ${python3:Depends},
python3-gi (>= 3.8),
python3-yaml,
aptdaemon,
python3-distro-info,
ukui-control-center (>= 3.1.1+1103)
gettext
Breaks:

View File

@ -3,6 +3,8 @@ backend/data/kylin-system-updater.db /usr/share/kylin-system-updater/
backend/data/30kylin-system-updater /etc/apt/apt.conf.d/
backend/data/com.kylin.systemupgrade.conf /etc/dbus-1/system.d/
backend/data/kylin-system-updater.service /usr/lib/systemd/system/
backend/data/kylin-logout-required /usr/share/kylin-system-updater/
backend/data/kylin-reboot-required /usr/share/kylin-system-updater/
backend/kylin-system-updater /usr/share/kylin-system-updater/
backend/SystemUpdater/*.py /usr/share/kylin-system-updater/SystemUpdater/
backend/SystemUpdater/backend/*.py /usr/share/kylin-system-updater/SystemUpdater/backend/
@ -23,8 +25,9 @@ unattended-upgrades/*.timer /lib/systemd/system/
unattended-upgrades/unattended-upgrades-daily /usr/bin/
unattended-upgrades/notify /usr/bin/
unattended-upgrades/*.desktop /etc/xdg/autostart/
unattended-upgrades/unattended-upgrade /usr/bin
unattended-upgrades/unattended-upgrade-shutdown /usr/bin
unattended-upgrades/kylin-unattended-upgrade /usr/bin
unattended-upgrades/kylin-unattended-upgrade-shutdown /usr/bin
unattended-upgrades/unattended-upgrades-daily /usr/bin
unattended-upgrades/50unattended-upgrades /etc/apt/apt.conf.d/
unattended-upgrades/kylin-unattended-upgrades /etc/apt/apt.conf.d/
unattended-upgrades/logrotate.d/* /etc/logrotate.d/
unattended-upgrades/kylin-unattended-upgrades-logind-maxdelay.conf /usr/lib/systemd/logind.conf.d/

5
debian/postinst vendored
View File

@ -17,7 +17,8 @@ fi
mkdir -p /var/lib/unattended-upgrades
chmod +x /usr/bin/unattended-upgrades-daily
chmod +x /usr/bin/unattended-upgrade
chmod +x /usr/bin/kylin-unattended-upgrade
chmod +x /usr/bin/kylin-unattended-upgrade-shutdown
systemctl enable unattended-upgrades-download.timer
systemctl enable unattended-upgrades-install.timer
systemctl enable unattended-upgrades.service
systemctl enable kylin-unattended-upgrades.service

View File

@ -4,4 +4,4 @@ kylin-update-desktop-kernel-3a4000
kylin-update-desktop-ukui
kylin-update-desktop-support
linux-meta
kylin-update-desktop-system

View File

@ -92,6 +92,9 @@ import fcntl
import time
import subprocess
SYSTEM_UPDATER_CORE_LIB_PATH="/usr/share/kylin-system-updater/SystemUpdater/Core"
sys.path.append(SYSTEM_UPDATER_CORE_LIB_PATH)
from OriginFilter import UnattendUpgradeFilter
CONFIG_FILE_ROOT_PATH="/var/lib/unattended-upgrades"
UNATTENDED_UPGRADE_CONFIG_FILE_PATH="/var/lib/unattended-upgrades/unattended-upgrade.conf"
WHITE_LIST_FILE_PATH="/var/lib/kylin-system-updater/system-updater.conf"
@ -185,6 +188,12 @@ def unLockedEnableShutdown():
pidfile = None
return False
def get_white_list_with_version(srclist,list,namelist):
for name_with_version in srclist:
nvlist = name_with_version.split("=")
list.append(nvlist)
namelist.append(nvlist[0])
#global timeStamp
def get_timestamp():
@ -364,6 +373,9 @@ class KylinSystemUpdater:
ret = self.update_interface.UnattendedUpgradeValue('get','')
return ret[0]
def CheckRebootRequired(self,msg):
ret = self.update_interface.CheckRebootRequired(msg)
def ConnectToSignals(self):
def update_detect_finished_handler(success,updatelist,error_status,error_cause):
if success:
@ -457,7 +469,7 @@ PkgFilePin = namedtuple('PkgFilePin', ['id', 'priority'])
class UnattendedUpgradesCache(apt.Cache):
def __init__(self, rootdir, whitelist):
def __init__(self, rootdir, whitelist,blacklist):
self._cached_candidate_pkgnames = set() # type: Set[str]
@ -465,15 +477,25 @@ class UnattendedUpgradesCache(apt.Cache):
logging.info(_("Allowed origins are: %s"),
", ".join(self.allowed_origins))
self.blacklist = apt_pkg.config.value_list(
self.blacklist = blacklist
'''
apt_pkg.config.value_list(
"Unattended-Upgrade::Package-Blacklist")
'''
logging.info(_("Initial blacklist: %s"), " ".join(self.blacklist))
self.whitelist = whitelist
self.whitelist_with_version = whitelist
self.whitelist = []
self.get_white_list()
# self.whitelist_with_version = []
# self.get_white_list_with_version()
# self.whitelist = apt_pkg.config.value_list(
# "Unattended-Upgrade::Package-Whitelist")
self.strict_whitelist = apt_pkg.config.find_b(
self.strict_whitelist = False
'''
apt_pkg.config.find_b(
"Unattended-Upgrade::Package-Whitelist-Strict", False)
'''
logging.info(_("Initial whitelist (%s): %s"),
"strict" if self.strict_whitelist else "not strict",
" ".join(self.whitelist))
@ -494,6 +516,10 @@ class UnattendedUpgradesCache(apt.Cache):
logging.debug("Using %s regexp to find running kernel packages",
self.running_kernel_pkgs_regexp.pattern)
def get_white_list(self):
for name_with_version in self.whitelist_with_version:
self.whitelist.append(name_with_version[0])
def find_better_version(self, pkg):
# type (apt.Package) -> apt.package.Version
if pkg.is_installed and pkg.versions[0] > pkg.installed:
@ -699,8 +725,12 @@ class UnattendedUpgradesCache(apt.Cache):
return
else:
function = apt.package.Package.mark_install
marking_succeeded = self.call_checked(function, pkg, **kwargs)
if not marking_succeeded:
logging.error("%s mark failed"%pkg.name)
if (not marking_succeeded
or not check_changes_for_sanity(self, desired_pkg=pkg)) \
and allow_marking_fallback():
@ -719,7 +749,7 @@ class UnattendedUpgradesCache(apt.Cache):
pass
self.call_checked(function, pkg, **kwargs)
for marked_pkg in self.get_changes():
if marked_pkg.name in self._cached_candidate_pkgnames:
continue
@ -745,7 +775,7 @@ class UnattendedUpgradesCache(apt.Cache):
new_pkg_adjusted = True
if new_pkg_adjusted:
self.call_adjusted(function, pkg, **kwargs)
def mark_upgrade_adjusted(self, pkg, **kwargs):
self.call_adjusted(apt.package.Package.mark_upgrade, pkg, **kwargs)
@ -1107,10 +1137,13 @@ def get_allowed_origins_legacy():
def get_allowed_origins():
# type: () -> List[str]
uuf = UnattendUpgradeFilter()
allowed_origins = uuf.GetAllowOrigins()
""" return a list of allowed origins from apt.conf
This will take substitutions (like distro_id) into account.
"""
'''
allowed_origins = get_allowed_origins_legacy()
key = "Unattended-Upgrade::Origins-Pattern"
try:
@ -1119,6 +1152,8 @@ def get_allowed_origins():
except ValueError:
logging.error(_("Unable to parse %s." % key))
raise
'''
#logging.info("allowed origins are:%s"%"\n".join(allowed_origins))
return allowed_origins
@ -1158,6 +1193,8 @@ def match_whitelist_string(whitelist, origin):
match = fnmatch.fnmatch(origin.site, value)
elif what in ("n", "codename",):
match = fnmatch.fnmatch(origin.codename, value)
elif what in ("uri"):
pass
else:
raise UnknownMatcherError(
"Unknown whitelist entry for matcher %s (token %s)" % (
@ -1317,7 +1354,7 @@ def is_in_allowed_origin(ver, allowed_origins):
def ver_in_allowed_origin(pkg, allowed_origins):
# type: (apt.Package, List[str]) -> apt.package.Version
for ver in pkg.versions:
if is_in_allowed_origin(ver, allowed_origins):
if is_in_allowed_origin(ver, allowed_origins):
# leave as soon as we have the highest new candidate
return ver
raise NoAllowedOriginError()
@ -1354,12 +1391,14 @@ def is_pkg_change_allowed(pkg, blacklist, whitelist, strict_whitelist):
# whitelist, most people will want the relaxed whitelist
# that whitelists a package but pulls in the package
# dependencies
if strict_whitelist and \
not is_pkgname_in_whitelist(pkg.name, whitelist):
logging.debug("pkg %s package is not whitelisted" %
pkg.name)
return False
if pkg._pkg.selected_state == apt_pkg.SELSTATE_HOLD:
logging.debug("pkg %s is on hold" % pkg.name)
return False
@ -1416,8 +1455,8 @@ def check_changes_for_sanity(cache, desired_pkg=None):
if sanity_check_result is None:
return True
else:
logging.debug("sanity check failed for: %s : %s"
% (str({str(p.candidate) for p in cache.get_changes()}),
logging.debug("sanity check failed for: %s:%s : %s"
% (desired_pkg.name,str({str(p.candidate) for p in cache.get_changes()}),
sanity_check_result))
return False
@ -1429,17 +1468,22 @@ def sanity_problem(cache, desired_pkg):
# If there are no packages to be installed they were kept back
if cache.install_count == 0:
return ("no package is selected to be upgraded or installed")
changes = cache.get_changes()
for pkg in changes:
if pkg.marked_delete:
return ("pkg %s is marked to be deleted" % pkg.name)
if pkg.marked_install or pkg.marked_upgrade:
# apt will never fallback from a trusted to a untrusted
# origin so its good enough if we have a single trusted one
if not any([o.trusted for o in pkg.candidate.origins]):
return ("pkg %s is not from a trusted origin" % pkg.name)
if not is_in_allowed_origin(pkg.candidate, cache.allowed_origins):
return ("pkg %s is not in an allowed origin" % pkg.name)
if not is_pkg_change_allowed(pkg,
cache.blacklist,
cache.whitelist,
@ -1447,13 +1491,16 @@ def sanity_problem(cache, desired_pkg):
return ("pkg %s is blacklisted or is not whitelisted"
% pkg.name)
# check if the package is unsafe to upgrade unattended
'''
ignore_require_restart = apt_pkg.config.find_b(
"Unattended-Upgrade::IgnoreAppsRequireRestart", False)
upgrade_requires = pkg.candidate.record.get("Upgrade-Requires")
if pkg.marked_upgrade and ignore_require_restart is False \
and upgrade_requires == "app-restart":
return ("pkg %s requires app-restart, it is not safe to "
"upgrade it unattended")
'''
# check that the package we want to upgrade is in the change set
if desired_pkg and desired_pkg not in changes:
return ("pkg %s to be marked for upgrade/install is not marked "
@ -2022,17 +2069,24 @@ def try_to_upgrade(pkg, # type: apt.Package
):
# type: (...) -> None
try:
try:
# try to adjust pkg itself first, if that throws an exception it
# can't be upgraded on its own
cache.adjust_candidate(pkg)
'''
if not pkg.is_upgradable and not apt_pkg.config.find_b(
"Unattended-Upgrade::Allow-downgrade", False):
return
return
'''
except NoAllowedOriginError:
return
cache._cached_candidate_pkgnames.add(pkg.name)
cache.mark_upgrade_adjusted(pkg, from_user=not pkg.is_auto_installed)
if not pkg.installed:
cache.mark_install_adjusted(pkg,from_user=True)
else:
cache.mark_upgrade_adjusted(pkg, from_user=not pkg.is_auto_installed)
if check_changes_for_sanity(cache, pkg):
# add to packages to upgrade
pkgs_to_upgrade.append(pkg)
@ -2056,29 +2110,41 @@ def candidate_version_changed(pkg, # type: apt.Package
def calculate_upgradable_pkgs(cache, # type: UnattendedUpgradesCache
options, # type: Options
):
whitelist):
# type: (...) -> List[apt.Package]
pkgs_to_upgrade = [] # type: List[apt.Package]
# now do the actual upgrade
for pkg in cache:
for pkgname in whitelist:
try:
pkg = cache[pkgname]
except Exception as e:
logging.error("error checking pkg:%s"%e)
continue
#for pkg in cache:
# if pkg.name not in cache.whitelist:
# logging.debug("%s not in whitelist skipping..."%(pkg.name))
# continue
if options.debug and pkg.is_upgradable \
or candidate_version_changed(pkg):
logging.debug("Checking: %s (%s)" % (
pkg.name, getattr(pkg.candidate, "origins", [])))
if (pkg.is_upgradable or candidate_version_changed(pkg)):#is_pkgname_in_whitelist(pkg.name, cache.whitelist)):
if (pkg.is_upgradable or candidate_version_changed(pkg) or not pkg.is_installed):#is_pkgname_in_whitelist(pkg.name, cache.whitelist)):
try:
ver_in_allowed_origin(pkg, cache.allowed_origins)
except NoAllowedOriginError:
continue
try_to_upgrade(pkg,
pkgs_to_upgrade,
cache)
logging.debug("Checking: %s (%s)" % (
pkg.name, getattr(pkg.candidate, "origins", [])))
#pkgs_to_upgrade.append(pkg)
if cache.get_changes():
cache.clear()
@ -2308,11 +2374,11 @@ def main(options, rootdir="/"):
pass
# lock for the shutdown check
shutdown_lock = apt_pkg.get_lock(LOCK_FILE)
if shutdown_lock < 0:
logging.error("Lock file is already taken, exiting")
WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","idle")
return 1
# shutdown_lock = apt_pkg.get_lock(LOCK_FILE)
# if shutdown_lock < 0:
# logging.error("Lock file is already taken, exiting")
# WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","idle")
# return 1
try:
res = run(options, rootdir, mem_log, logfile_dpkg,
@ -2327,10 +2393,12 @@ def main(options, rootdir="/"):
# there is some meaningful result which is worth an email
log_content = get_dpkg_log_content(logfile_dpkg,
install_start_time)
'''
send_summary_mail(res.pkgs, res.success, res.result_str,
res.pkgs_kept_back, res.pkgs_removed,
res.pkgs_kept_installed, mem_log,
log_content)
'''
if res.update_stamp:
# write timestamp file
write_stamp_file()
@ -2369,8 +2437,15 @@ def mark_pkgs_to_upgrade(cache, pkgs_to_upgrade):
cache.mark_upgrade_adjusted(pkg,
from_user=not pkg.is_auto_installed)
elif not pkg.is_installed:
cache.mark_install_adjusted(pkg, from_user=False)
cache.mark_install_adjusted(pkg, from_user=True)
def adjust_candidate_with_version(cache,pkgnamelist,versionlist):
for pkgname in pkgnamelist:
pkg = cache[pkgname]
for v in pkg.versions:
if is_in_allowed_origin(v,cache.allowed_origins):
if str(v) in versionlist:
pkg.candidate = v
def run(options, # type: Options
rootdir, # type: str
@ -2389,6 +2464,7 @@ def run(options, # type: Options
return UnattendedUpgradesResult(False)
# check to see if want to auto-upgrade the devel release
'''
if apt_pkg.config.find("Unattended-Upgrade::DevRelease") == "auto":
try:
if DISTRO_ID.lower() == 'ubuntu':
@ -2422,7 +2498,7 @@ def run(options, # type: Options
syslog.syslog(_("Not running on the development release."))
logging.info(_("Not running on the development release."))
return UnattendedUpgradesResult(True)
'''
logging.info(_("Starting unattended upgrades script"))
kylin_system_updater = KylinSystemUpdater()
if KylinSystemUpdater.GetUnattendedUpgradeValue:
@ -2465,10 +2541,16 @@ def run(options, # type: Options
config_manager = ConfigFileManager(CONFIG_FILE_ROOT_PATH)
white_list = config_manager.ReadListFromFile(WHITE_LIST_FILE_PATH,'AutoUpgrade','upgradelist')
global wl
wl = white_list
logging.debug("white list from kylin system updater:%s"%("\n".join(white_list)))
white_list_with_version =[]
namelist = []
blacklist = []
get_white_list_with_version(white_list,white_list_with_version,namelist)
# get a cache
try:
cache = UnattendedUpgradesCache(rootdir=rootdir,whitelist=white_list)
cache = UnattendedUpgradesCache(rootdir=rootdir,whitelist=white_list_with_version,blacklist=blacklist)
#cache.whitelist=white_list
except SystemError as error:
print(_("Apt returned an error, exiting"))
@ -2500,16 +2582,17 @@ def run(options, # type: Options
auto_removable = get_auto_removable(cache)
# find out about the packages that are upgradable (in an allowed_origin)
pkgs_to_upgrade = calculate_upgradable_pkgs(cache, options)
pkgs_to_upgrade = calculate_upgradable_pkgs(cache, options,namelist)
pkgs_to_upgrade.sort(key=lambda p: p.name)
pkgs = [pkg.name for pkg in pkgs_to_upgrade]
logging.debug("pkgs that look like they should be upgraded: %s"
logging.debug("pkgs that look like they should be upgraded or installed: %s"
% "\n".join(pkgs))
# FIXME: make this into a ContextManager
# stop being nice
os.nice(old_priority - os.nice(0))
adjust_candidate_with_version(cache,namelist,white_list)
# download what looks good
mark_pkgs_to_upgrade(cache, pkgs)
@ -2812,6 +2895,8 @@ def run(options, # type: Options
logfile_dpkg)
unLockedEnableShutdown()
subprocess.Popen('dbus-send --system --type=signal / com.kylin.install.notification.InstallFinish',shell=True)
if pkg_install_success:
kylin_system_updater.CheckRebootRequired("unattended-upgrades")
# Was the overall run succesful: only if everything installed
# fine and nothing was held back because of a conffile prompt.
successful_run = (kernel_pkgs_remove_success and pkg_install_success
@ -2848,7 +2933,7 @@ def run(options, # type: Options
successful_run = successful_run and pkg_remove_success
# the user wants *only new* auto-removals to be removed
elif apt_pkg.config.find_b(
"Unattended-Upgrade::Remove-New-Unused-Dependencies", True):
"Unattended-Upgrade::Remove-New-Unused-Dependencies", False):
# calculate the new auto-removals
new_pending_autoremovals = get_auto_removable(cache)
auto_removals = new_pending_autoremovals - previous_autoremovals
@ -2891,9 +2976,16 @@ class Options:
self.verbose = False
self.minimal_upgrade_steps = False
shutdown_lock = -1
if __name__ == "__main__":
WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","idle")
# lock for the shutdown check
shutdown_lock = apt_pkg.get_lock(LOCK_FILE)
if shutdown_lock < 0:
logging.error("Lock file is already taken, exiting")
#WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","idle")
sys.exit(0)
localesApp = "unattended-upgrades"
localesDir = "/usr/share/locale"
gettext.bindtextdomain(localesApp, localesDir)
@ -2958,7 +3050,7 @@ if __name__ == "__main__":
signal.signal(signal.SIGHUP, signal.SIG_IGN)
# setup signal handler for graceful stopping
signal.signal(signal.SIGTERM, signal_handler_term)
signal.signal(signal.SIGTERM, signal_handler)
signal.signal(signal.SIGINT,signal_handler_int)

View File

@ -325,7 +325,7 @@ class UnattendedUpgradesShutdown():
env["UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN"] = "1"
logging.debug("starting unattended-upgrades in shutdown mode")
self.on_shutdown_mode_uu_proc = subprocess.Popen(
["unattended-upgrade","--install-only"], env=env)
["kylin-unattended-upgrade","--install-only"], env=env)
log_msg(_("Running unattended-upgrades in shutdown mode"))
# run u-u, but switch to stopping when receiving stop signal
# because it means shutdown progressed despite holding the lock

View File

@ -0,0 +1,3 @@
[Login]
# delay
InhibitDelayMaxSec=1800

View File

@ -5,7 +5,7 @@ RequiresMountsFor=/run /var/log /var/run /var/lib /boot
Documentation=man:unattended-upgrade(8)
[Service]
ExecStart=/usr/bin/unattended-upgrade-shutdown --wait-for-signal
ExecStart=/usr/bin/kylin-unattended-upgrade-shutdown --wait-for-signal
KillMode=process
TimeoutStopSec=1800

View File

@ -114,8 +114,8 @@ if [ "$1" = "download" ] || [ -z "$1" ] ; then
# download all upgradeable packages (if it is requested)
DOWNLOAD_STAMP=/var/lib/apt/periodic/kylin-auto-download-stamp
if which unattended-upgrade >/dev/null 2>&1 && check_stamp $DOWNLOAD_STAMP $KylinAutodownloadInterval; then
if unattended-upgrade --download-only; then
if which kylin-unattended-upgrade >/dev/null 2>&1 && check_stamp $DOWNLOAD_STAMP $KylinAutodownloadInterval; then
if kylin-unattended-upgrade --download-only; then
update_stamp $DOWNLOAD_STAMP
debug_echo "kylin-autoupdate-download (success)"
else
@ -129,8 +129,8 @@ fi
if [ "$1" = "install" ] || [ -z "$1" ] ; then
# auto upgrade all upgradeable packages
INSTALL_STAMP=/var/lib/apt/periodic/kylin-auto-install-stamp
if which unattended-upgrade >/dev/null 2>&1 && check_stamp $INSTALL_STAMP $KylinAutoInstallInterval; then
if unattended-upgrade --install-only; then
if which kylin-unattended-upgrade >/dev/null 2>&1 && check_stamp $INSTALL_STAMP $KylinAutoInstallInterval; then
if kylin-unattended-upgrade --install-only; then
update_stamp $INSTALL_STAMP
debug_echo "kylin-autoupdate-install (success)"
else