From 7c7431325340bef4accff540756c4fecebb87bd6 Mon Sep 17 00:00:00 2001 From: wangsong Date: Mon, 29 May 2023 14:47:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E4=B8=BB=E7=BA=BF=E5=8F=98?= =?UTF-8?q?=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/SystemUpdater/Core/DataAcquisition.py | 25 +- backend/SystemUpdater/Core/DataMigration.py | 6 +- backend/SystemUpdater/Core/Database.py | 402 ++++++++- .../SystemUpdater/Core/JsonConfigParser.py | 61 ++ .../SystemUpdater/Core/LocalUpgradeData.py | 278 ++++++ backend/SystemUpdater/Core/PluginManager.py | 402 +++++++++ backend/SystemUpdater/Core/UpdateList.py | 287 ++---- .../SystemUpdater/Core/UpdaterConfigParser.py | 11 +- backend/SystemUpdater/Core/enums.py | 77 +- backend/SystemUpdater/Core/utils.py | 65 +- backend/SystemUpdater/UpdateManager.py | 271 +++--- backend/SystemUpdater/UpdateManagerDbus.py | 60 +- backend/SystemUpdater/UpgradeStrategies.py | 2 +- .../SystemUpdater/UpgradeStrategiesDbus.py | 24 +- .../backend/InstallBackendAptdaemon.py | 236 +++-- backend/SystemUpdater/backend/__init__.py | 843 +++++++++--------- .../data/cn.kylinos.KylinSystemUpdater.policy | 48 +- .../data/com.kylin.UpgradeStrategies.service | 2 +- backend/data/kylin-system-updater.db | Bin 40960 -> 40960 bytes backend/data/system-updater-defaults.conf | 1 + backend/data/unattended-upgrades-policy.conf | 11 +- backend/data/unattended-upgrades-timestamp | 6 +- backend/kylin-system-updater | 13 +- backend/po/bo_CN.po | 226 +++++ backend/po/zh_CN.po | 16 +- backend/po/zh_HK.po | 2 +- backend/po/zh_TW.po | 2 +- backend/report-updater-bug | 2 + debian/changelog | 9 + unattended-upgrades/kylin-unattended-upgrade | 565 +++++++----- .../kylin-unattended-upgrade-shutdown | 475 ++++++---- 31 files changed, 3089 insertions(+), 1339 deletions(-) create mode 100755 backend/SystemUpdater/Core/JsonConfigParser.py create mode 100644 backend/SystemUpdater/Core/LocalUpgradeData.py create mode 100644 backend/SystemUpdater/Core/PluginManager.py create mode 100644 backend/po/bo_CN.po diff --git a/backend/SystemUpdater/Core/DataAcquisition.py b/backend/SystemUpdater/Core/DataAcquisition.py index 33b0d20..b8736a0 100644 --- a/backend/SystemUpdater/Core/DataAcquisition.py +++ b/backend/SystemUpdater/Core/DataAcquisition.py @@ -16,6 +16,7 @@ import tarfile import requests import datetime import threading +import subprocess from email import message from datetime import datetime @@ -32,6 +33,7 @@ from SystemUpdater.Core.UpdaterConfigParser import UpgradeConfig LOCALTIDDIR = "/var/lib/kylin-system-updater/" LOCALTIDFILE = "tidfile.conf" MSGSNDDIR = "/var/lib/kylin-system-updater/sendinfos/" +SERVERID = "/var/lib/kylin-software-properties/config/serverID.conf" SOURCE_PKGNAME = { 'Kylin System Updater': 'kylin-system-updater', @@ -126,6 +128,17 @@ class UpdateMsgCollector(): UploadMessage['UUID'] = str(local_uuid) else: UploadMessage['UUID'] = str(uuid.uuid1()) + serverid_configs = UpgradeConfig(datadir = "/var/lib/kylin-software-properties/config/", name = "serverID.conf") + tans_id = serverid_configs.getWithDefault("ID", "pushID", " ") + UploadMessage['transactionID'] = tans_id + + snobj = dbus.SystemBus().get_object('org.freedesktop.activation', '/org/freedesktop/activation') + sninterface = dbus.Interface(snobj, dbus_interface='org.freedesktop.activation.interface') + retval,retid = sninterface.serial_number() + if(retid==0): + UploadMessage['serialNumber'] = str(retval) + else: + UploadMessage['serialNumber'] = '' except Exception as e: logging.error(str(e)) @@ -186,7 +199,6 @@ class UpdateMsgCollector(): try: self.upgrade_list = upgrade_list self.upgrade_mode = mode - self.uuid = str(uuid.uuid1()) self.UpdateInfos.update({"upgradeMode":self.mode_map.get(self.upgrade_mode, "default-mode")}) except DBusException as e: logging.error(e) @@ -196,6 +208,11 @@ class UpdateMsgCollector(): tmp_dict = {} tmp_dict.update(dict_msg) try: + self.Init_UUID() + if 'error_string' in tmp_dict.keys() and 'error_desc' in tmp_dict.keys(): + if tmp_dict['error_string'] == "下载失败" and tmp_dict['error_desc'] == "取消升级": + tmp_dict.update({"error_string":str(tmp_dict['error_string']+","+tmp_dict['error_desc'])}) + tmp_dict.update({"error_desc":str(tmp_dict['error_string']+","+tmp_dict['error_desc'])}) self.UpdateInfos.update({"step":self.action_map.get(action, "")}) if self.upgrade_mode == self.MODE_INSTALL_SYSTEM: self.UpdateInfos.update({"appname":"Upgrade System"}) @@ -222,10 +239,16 @@ class UpdateMsgCollector(): self.background_version.update({pkg.name:"Unknown"}) self.background_list.append(pkg.name) + def Init_UUID(self): + if self.uuid == "": + self.uuid = str(uuid.uuid1()) + def Msg_Clean(self): self.UploadMessage = {} self.PackageInfo = {} self.UpdateInfos = {} + self.uuid = "" + class FormatConvert(): def __init__(self, DataCollector): #秘钥 diff --git a/backend/SystemUpdater/Core/DataMigration.py b/backend/SystemUpdater/Core/DataMigration.py index e6bb6fa..e7ba57c 100755 --- a/backend/SystemUpdater/Core/DataMigration.py +++ b/backend/SystemUpdater/Core/DataMigration.py @@ -315,7 +315,7 @@ def CopyData(): if (_is_first_migration(new_db, new_db_cursor)): # 数据迁移 dateMigration(new_db=new_db, new_db_cursor=new_db_cursor) - sql_commnd = "UPDATE display SET firstmigration='no';" + sql_commnd = "UPDATE display SET firstmigration='false';" new_db_cursor.execute(sql_commnd) new_db.commit() else: @@ -324,11 +324,11 @@ def CopyData(): # 新增 firstmigration 字段 sql_commnd = "alter table display add column firstmigration text;" new_db_cursor.execute(sql_commnd) - sql_commnd = "UPDATE display SET firstmigration='yes';" + sql_commnd = "UPDATE display SET firstmigration='true';" new_db_cursor.execute(sql_commnd) #数据迁移 dateMigration(new_db=new_db, new_db_cursor=new_db_cursor) - sql_commnd = "UPDATE display SET firstmigration='no';" + sql_commnd = "UPDATE display SET firstmigration='false';" new_db_cursor.execute(sql_commnd) new_db.commit() diff --git a/backend/SystemUpdater/Core/Database.py b/backend/SystemUpdater/Core/Database.py index 6b8715e..f9c3d7f 100644 --- a/backend/SystemUpdater/Core/Database.py +++ b/backend/SystemUpdater/Core/Database.py @@ -9,6 +9,7 @@ import shutil import sqlite3 import logging import datetime +from operator import itemgetter from gettext import gettext as _ from sys import exec_prefix from SystemUpdater.Core.DataAcquisition import PHPSeverSend @@ -20,11 +21,14 @@ from ..backend import InstallBackend DB_FILE = os.path.join("/var/cache/kylin-system-updater/kylin-system-updater.db") # UMDB_FILE = os.path.join("/var/cache/kylin-system-updater/kylin-system-updater.db") +DB_UPDATER = "/var/cache/kylin-update-manager/kylin-update-manager.db" +DB_UPGRADE = "/var/cache/kylin-system-updater/kylin-system-updater.db" +VER_DB = "/usr/share/kylin-system-updater/kylin-system-updater.db" INSTALLED_LIST = [{"item": "errorcode", "type": "int", "default": "0"}] DISPALY_LIST = [] class Sqlite3Server(object): - def __init__(self, updateManager): + def __init__(self, updateManager, _no_DataMigration=False): self.connect = None self.window_main = updateManager self.config_path = get_config_patch() @@ -33,8 +37,31 @@ class Sqlite3Server(object): # uncoverable配置文件 self.ucconfigs = UpgradeConfig(datadir = "/etc/kylin-version", name = "kylin-system-version.conf") self._system_version_config() + #判断数据迁移 + if not _no_DataMigration: + if (not os.path.exists(DB_UPDATER)): + logging.debug("Can not found database: %s, should ignore.",DB_UPDATER) + self.__need_DataMigration(mark_FirstMigration = True) + else: + self.__need_DataMigration(mark_FirstMigration = False) + self.current_purge_pkgs = [] + self.init_metadata() - # 初始化连接数据库,修改为使用时连接 + def init_metadata(self): + self.deb_metadata = {} + self.deb_metadata.update({"current_install_debfile":""}) + self.deb_metadata.update({"absolute_path":""}) + self.deb_metadata.update({"debname":""}) + self.deb_metadata.update({"deblist":[]}) + self.deb_metadata.update({"action":''}) + self.deb_metadata.update({"mode":''}) + self.deb_metadata.update({"source":''}) + self.deb_metadata.update({"sender":''}) + self.deb_metadata.update({"caller":''}) + self.deb_metadata.update({"old_version":''}) + self.deb_metadata.update({"new_version":''}) + + # Initialize the connection database and modify it to connect when using def init_sqlit(self): try: logging.info(_("Initialize database files ...")) @@ -48,7 +75,6 @@ class Sqlite3Server(object): #connect连接数据库 def connect_database(self): try: - logging.debug("Connect database ...") self.connect = sqlite3.connect(DB_FILE, check_same_thread=False) self.cursor = self.connect.cursor() except Exception as e: @@ -57,10 +83,9 @@ class Sqlite3Server(object): #disconnect连接数据库 def disconnect_database(self): try: - logging.debug("Disconnect database ...") if self.connect != None: self.connect.close() - if self.connect != None: + if self.cursor != None: del self.cursor except Exception as e: logging.error("Failed to disconnect database: %s", str(e)) @@ -194,12 +219,49 @@ class Sqlite3Server(object): logging.info(_("Database: Insert To updateinfos Complete...")) self.disconnect_database() + #get display data + def gen_display_mate(self)->dict: + mateData = {} + self.connect_database() + try: + sql = "pragma table_info({})".format("display") + self.cursor.execute(sql) + keys=[key[1] for key in self.cursor.fetchall()] + sql = "select * from display where id=1;" + self.cursor.execute(sql) + values = self.cursor.fetchone() + mateData = dict(zip(keys, values)) + # + # self.connect.row_factory = self.dictFactory + # values = self.cursor.execute("select * from display where id=1;").fetchall() + except Exception as e: + logging.error("select error: %s.", str(e)) + self.disconnect_database() + return mateData + + def dictFactory(self,cursor,row): + """将sql查询结果整理成字典形式""" + d={} + for index,col in enumerate(cursor.description): + d[col[0]]=row[index] + return d + + def __need_DataMigration(self, mark_FirstMigration = False): + # mateData = self.gen_display_mate() + # if "firstmigration" in mateData.keys() and mateData["firstmigration"] == "true": + dm = DataMigration() + if (mark_FirstMigration): + dm.MarkFirstMigration() + else: + dm.CopyData() + # 接收更新列表与信息,生成数据并插入数据库中 def insert_info(self, mode, pkg_list=[], pkg_group=[], adjust_pkg=[], success = False, error_string = '', error_desc = ''): errstr = error_string + " " + error_desc status = " " status_cn = " " appname_cn = "" + errorcode = "10000" UpdateInfos = {} InstallInfos = {} time = datetime.datetime.now() @@ -215,9 +277,11 @@ class Sqlite3Server(object): if success: status = 'success' status_cn = '成功' + errorcode = "10000000" else: status = 'failed' status_cn = '失败' + errorcode = "10000100" changeLog = "" try: @@ -233,17 +297,21 @@ class Sqlite3Server(object): UpdateInfos.update({"appname":str(pkgname)}) UpdateInfos.update({"source":"Kylin System Updater"}) UpdateInfos.update({"status":status}) - UpdateInfos.update({"errorCode":str(error_string+" "+error_desc)}) + UpdateInfos.update({"errorCode":str(errorcode)}) + UpdateInfos.update({"error_string":str(error_string)}) + UpdateInfos.update({"error_desc":str(error_desc)}) self.window_main.collector.Upgrade_Process_Msg("finish-update", UpdateInfos.copy()) #安装信息install-infos InstallInfos.update({"appname":str(pkgname)}) - if pkgname in self.window_main.update_list.upgrade_meta.versoin_pkgs['groups_upgrade'].keys(): - InstallInfos.update({"old_version":str(self.window_main.update_list.upgrade_meta.versoin_pkgs['groups_upgrade'][pkgname])}) + if pkgname in self.window_main.main_meta.versoin_pkgs['groups_upgrade'].keys(): + InstallInfos.update({"old_version":str(self.window_main.main_meta.versoin_pkgs['groups_upgrade'][pkgname])}) else: InstallInfos.update({"old_version":'UnKnown'}) InstallInfos.update({"new_version":str(pkgversion)}) InstallInfos.update({"status":status}) - InstallInfos.update({"errorCode":str(error_string+" "+error_desc)}) + InstallInfos.update({"errorCode":str(errorcode)}) + InstallInfos.update({"error_string":str(error_string)}) + InstallInfos.update({"error_desc":str(error_desc)}) self.window_main.collector.Upgrade_Process_Msg("finish-install", InstallInfos.copy()) # 系统升级完成 ..判断版本号 if status == "success" and "kylin-update-desktop-system" in pkgname: @@ -256,7 +324,7 @@ class Sqlite3Server(object): self._removal_of_marker() #FIXME: 临时方案 PHP - PHPSeverSend(_appname=pkgname, _appversion=pkgversion, _statue=status, _errorcode="10000100", _errorstring=errstr) + PHPSeverSend(_appname=pkgname, _appversion=pkgversion, _statue=status, _errorcode=str(errorcode), _errorstring=errstr) file_path = os.path.join(get_config_patch(), str(pkgname) + ".yaml") with open(file_path, "r") as stream: try: @@ -299,22 +367,26 @@ class Sqlite3Server(object): UpdateInfos.update({"appname":str(pkgname)}) UpdateInfos.update({"source":"Kylin System Updater"}) UpdateInfos.update({"status":status}) - UpdateInfos.update({"errorCode":str(error_string+" "+error_desc)}) + UpdateInfos.update({"errorCode":str(errorcode)}) + UpdateInfos.update({"error_string":str(error_string)}) + UpdateInfos.update({"error_desc":str(error_desc)}) self.window_main.collector.Upgrade_Process_Msg("finish-update", UpdateInfos.copy()) #安装信息install-infos InstallInfos.update({"appname":str(pkgname)}) - if pkgname in self.window_main.update_list.upgrade_meta.versoin_pkgs['single_upgrade'].keys(): - InstallInfos.update({"old_version":str(self.window_main.update_list.upgrade_meta.versoin_pkgs['single_upgrade'][pkgname])}) + if pkgname in self.window_main.main_meta.versoin_pkgs['single_upgrade'].keys(): + InstallInfos.update({"old_version":str(self.window_main.main_meta.versoin_pkgs['single_upgrade'][pkgname])}) else: InstallInfos.update({"old_version":'UnKnown'}) InstallInfos.update({"new_version":str(pkgversion)}) InstallInfos.update({"status":status}) - InstallInfos.update({"errorCode":str(error_string+" "+error_desc)}) + InstallInfos.update({"errorCode":str(errorcode)}) + InstallInfos.update({"error_string":str(error_string)}) + InstallInfos.update({"error_desc":str(error_desc)}) self.window_main.collector.Upgrade_Process_Msg("finish-install", InstallInfos.copy()) # 软件商店获取中文名 appname_cn = self.get_cn_appname(str(pkgname)) #FIXME: 临时方案 PHP - PHPSeverSend(_appname=pkgname, _appversion=pkgversion, _statue=status, _errorcode="10000100", _errorstring=errstr) + PHPSeverSend(_appname=pkgname, _appversion=pkgversion, _statue=status, _errorcode=str(errorcode), _errorstring=errstr) try: self.insert_into_updateinfo(pkgname, pkgversion, pkgdescription, timestr, status, "1", errstr, appname_cn, status_cn, changeLog) # FIXME: 发送插入数据库成功的信号local_upgrade_list @@ -344,17 +416,21 @@ class Sqlite3Server(object): UpdateInfos.update({"appname":str(pkg.name)}) UpdateInfos.update({"source":"Kylin System Updater"}) UpdateInfos.update({"status":status}) - UpdateInfos.update({"errorCode":str(error_string+" "+error_desc)}) + UpdateInfos.update({"errorCode":str(errorcode)}) + UpdateInfos.update({"error_string":str(error_string)}) + UpdateInfos.update({"error_desc":str(error_desc)}) self.window_main.collector.Upgrade_Process_Msg("finish-update", UpdateInfos.copy()) #安装信息install-infos InstallInfos.update({"appname":str(pkg.name)}) - if pkg.name in self.window_main.update_list.upgrade_meta.versoin_pkgs['groups_upgrade'].keys(): - InstallInfos.update({"old_version":str(self.window_main.update_list.upgrade_meta.versoin_pkgs['groups_upgrade'][pkg.name])}) + if pkg.name in self.window_main.main_meta.versoin_pkgs['groups_upgrade'].keys(): + InstallInfos.update({"old_version":str(self.window_main.main_meta.versoin_pkgs['groups_upgrade'][pkg.name])}) else: InstallInfos.update({"old_version":'UnKnown'}) InstallInfos.update({"new_version":str(pkgversion)}) InstallInfos.update({"status":status}) - InstallInfos.update({"errorCode":str(error_string+" "+error_desc)}) + InstallInfos.update({"errorCode":str(errorcode)}) + InstallInfos.update({"error_string":str(error_string)}) + InstallInfos.update({"error_desc":str(error_desc)}) self.window_main.collector.Upgrade_Process_Msg("finish-install", InstallInfos.copy()) try: @@ -368,7 +444,7 @@ class Sqlite3Server(object): self.insert_into_updateinfo(str(i), pkgversion, pkgdescription, timestr, status, "1", errstr, appname_cn, status_cn, changeLog) self.window_main.dbusController.UpdateSqlitSingle(str(i), timestr) #FIXME: 临时方案 PHP - PHPSeverSend(_appname=pkg.name, _appversion=pkgversion, _statue=status, _errorcode="10000100", _errorstring=errstr) + PHPSeverSend(_appname=pkg.name, _appversion=pkgversion, _statue=status, _errorcode=str(errorcode), _errorstring=errstr) # insert group deb next for i in pkg_group: # FIXME: 获取组信息 @@ -377,17 +453,21 @@ class Sqlite3Server(object): UpdateInfos.update({"appname":str(i)}) UpdateInfos.update({"source":"Kylin System Updater"}) UpdateInfos.update({"status":status}) - UpdateInfos.update({"errorCode":str(error_string+" "+error_desc)}) + UpdateInfos.update({"errorCode":str(errorcode)}) + UpdateInfos.update({"error_string":str(error_string)}) + UpdateInfos.update({"error_desc":str(error_desc)}) self.window_main.collector.Upgrade_Process_Msg("finish-update", UpdateInfos.copy()) #安装信息install-infos InstallInfos.update({"appname":str(i)}) - if i in self.window_main.update_list.upgrade_meta.versoin_pkgs['groups_upgrade'].keys(): - InstallInfos.update({"old_version":str(self.window_main.update_list.upgrade_meta.versoin_pkgs['groups_upgrade'][i])}) + if i in self.window_main.main_meta.versoin_pkgs['groups_upgrade'].keys(): + InstallInfos.update({"old_version":str(self.window_main.main_meta.versoin_pkgs['groups_upgrade'][i])}) else: InstallInfos.update({"old_version":'UnKnown'}) InstallInfos.update({"new_version":str(pkgversion)}) InstallInfos.update({"status":status}) - InstallInfos.update({"errorCode":str(error_string+" "+error_desc)}) + InstallInfos.update({"errorCode":str(errorcode)}) + InstallInfos.update({"error_string":str(error_string)}) + InstallInfos.update({"error_desc":str(error_desc)}) json_file = json.dumps(InstallInfos.copy()) try: self.window_main.collector.UpdateMsg("InstallInfos", json_file) @@ -395,7 +475,7 @@ class Sqlite3Server(object): pass #FIXME: 临时方案 PHP - PHPSeverSend(_appname=i, _appversion=pkgversion, _statue=status, _errorcode="10000100", _errorstring=errstr) + PHPSeverSend(_appname=i, _appversion=pkgversion, _statue=status, _errorcode=str(errorcode), _errorstring=errstr) file_path = os.path.join(get_config_patch(), str(i) + ".yaml") with open(file_path, "r") as stream: try: @@ -435,6 +515,7 @@ class Sqlite3Server(object): logging.warning("Cache is None.") except Exception as e: logging.error("record update error: %s.",str(e)) + self.window_main.collector.Msg_Clean() # 获取group信息 def GetGroupmsg(self, appname): @@ -508,7 +589,7 @@ class Sqlite3Server(object): sql = "select init_version from display where id=1" self.cursor.execute(sql) _is_init_verison = self.cursor.fetchone()[0] - if _is_init_verison == "yes": + if _is_init_verison == "yes" or _is_init_verison == "true": update_version, os_version = self.get_default_version() logging.info("Need to refresh version ...") self._refresh_system_version(update_version, os_version) @@ -517,7 +598,6 @@ class Sqlite3Server(object): self.connect.commit() except Exception as e: logging.error(str(e)) - self.disconnect_database() self.disconnect_database() def _refresh_system_version(self, update_version='', os_version = '', pseudo_version = False): @@ -526,8 +606,6 @@ class Sqlite3Server(object): update_version = str(update_version).split('=')[-1] if "=" in os_version: os_version = str(os_version).split('=')[-1] - os_version = os_version.strip() - update_version = update_version.strip() #刷新系统版本号:os_version if update_version == '': @@ -538,7 +616,7 @@ class Sqlite3Server(object): for line in lines: if "KYLIN_RELEASE_ID" in line: os_version = line.split('=')[1] - os_version = os_version.strip() + os_version = os_version.strip().strip('"') if not pseudo_version: if len(os_version) != 0: self.ucconfigs.setValue("SYSTEM","os_version",str(os_version),True) @@ -579,7 +657,7 @@ class Sqlite3Server(object): for line in lines: if "KYLIN_RELEASE_ID" in line: os_version = line.split('=')[1] - os_version = eval(os_version.strip()) + os_version = os_version.strip().strip('"') if update_version == "" and os_version != "": update_version = os_version elif update_version != "" and os_version == "": @@ -675,6 +753,268 @@ class Sqlite3Server(object): except Exception as e: logging.error(e) return False +class DataMigration(): + def __init__(self): + pass + + #connect连接数据库 + def connect_database(self): + try: + self.connect = sqlite3.connect(DB_FILE, check_same_thread=False) + self.cursor = self.connect.cursor() + except Exception as e: + logging.error("Failed to connect database: %s", str(e)) + + #disconnect连接数据库 + def disconnect_database(self): + try: + if self.connect != None: + self.connect.close() + if self.connect != None: + del self.cursor + except Exception as e: + logging.error("Failed to disconnect database: %s", str(e)) + + def MarkFirstMigration(self): + if (os.path.exists(DB_UPGRADE)): + try: + new_db = sqlite3.connect(DB_UPGRADE, check_same_thread=False) + new_db_cursor = new_db.cursor() + + if (self._has_first_migration(new_db, new_db_cursor)): # 存在 firstmigration + if (self._is_first_migration(new_db, new_db_cursor)): + sql_commnd = "UPDATE display SET firstmigration='false';" + new_db_cursor.execute(sql_commnd) + new_db.commit() + else:# 不存在firstmigration + # 新增 firstmigration 字段 + sql_commnd = "alter table display add column firstmigration text;" + new_db_cursor.execute(sql_commnd) + sql_commnd = "UPDATE display SET firstmigration='false';" + new_db_cursor.execute(sql_commnd) + new_db.commit() + except Exception as e: + logging.error("Failed to disconnect database: %s", str(e)) + else : + logging.info("Not found kylin-system-updater.db, ensure that \'kylin-system-updater\' is successfully installed ... ") + + def CopyData(self): + # 判断数据库是否存在 + if (os.path.exists(VER_DB) and os.path.exists(DB_UPGRADE)): + try: + new_db = sqlite3.connect(DB_UPGRADE, check_same_thread=False) + new_db_cursor = new_db.cursor() + ver_db = sqlite3.connect(VER_DB, check_same_thread=False) + ver_db_cursor = ver_db.cursor() + + if (self._has_first_migration(new_db, new_db_cursor)): # 存在 firstmigration + if (self._is_first_migration(new_db, new_db_cursor)): + # 数据迁移 + if (self.dateMigration(new_db=new_db, new_db_cursor=new_db_cursor)): + sql_commnd = "UPDATE display SET firstmigration='false';" + new_db_cursor.execute(sql_commnd) + new_db.commit() + else: + logging.info("No data migration is required ...") + else:# 不存在firstmigration + # 新增 firstmigration 字段 + sql_commnd = "alter table display add column firstmigration text;" + new_db_cursor.execute(sql_commnd) + sql_commnd = "UPDATE display SET firstmigration='yes';" + new_db_cursor.execute(sql_commnd) + #数据迁移 + if (self.dateMigration(new_db=new_db, new_db_cursor=new_db_cursor)): + sql_commnd = "UPDATE display SET firstmigration='false';" + new_db_cursor.execute(sql_commnd) + new_db.commit() + except Exception as e: + logging.error("Failed to disconnect database: %s", str(e)) + else : + logging.info("Not found kylin-system-updater.db, ensure that \'kylin-system-updater\' is successfully installed ... ") + + def _has_first_migration(self, new_db, new_db_cursor)->bool: + try: + sql_commnd = "select * from sqlite_master where type='table' and name='display';" + new_db_cursor.execute(sql_commnd) + retval = new_db_cursor.fetchone() + for rv in retval: + if "firstmigration" in str(rv): + return True + except Exception as e: + logging.error("Failed to get field firstMigration: %s", str(e)) + return False + + def _is_first_migration(self, new_db, new_db_cursor): + try: + sql_commnd = "select firstmigration from display;" + new_db_cursor.execute(sql_commnd) + retval = new_db_cursor.fetchone() + if "true" in retval or "yes" in retval: + return True + except Exception as e: + logging.error("Failed to select firstMigration: %s", str(e)) + return False + + def _is_display_exist_fields(self, field, db, db_cursor): + try: + sql_commnd = "select * from sqlite_master where type='table' and name='display';" + db_cursor.execute(sql_commnd) + retval = db_cursor.fetchone() + for rv in retval: + if field in str(rv): + return True + except Exception as e: + logging.error("Failed to select %s: %s", field, str(e)) + return False + + def _add_display_fields(self, fields_default): + try: + if "=" not in fields_default: + print("format: field=value") + return False + field, value = fields_default.split('=') + print(_("Loading Sqlite3Server...")) + db = sqlite3.connect(DB_UPGRADE, check_same_thread=False) + db_cursor = db.cursor() + if self._is_display_exist_fields(field, db, db_cursor): + print("field %s is exist."%field) + return False + # 字段不存在,新增字段 + sql_commnd = "alter table display add column "+field+" TEXT;" + db_cursor.execute(sql_commnd) + sql_commnd = "UPDATE display SET "+field+"='"+value+"'" + db_cursor.execute(sql_commnd) + db.commit() + except Exception as e: + print(e) + return False + print("Succeeded in adding field: '%s' "%field) + return True + + def dateMigration(self,new_db,new_db_cursor,old_db=None,old_db_cursor=None)->bool: + try: + if old_db==None and old_db_cursor==None: + old_db = sqlite3.connect(DB_UPDATER, check_same_thread=False) + old_db_cursor = old_db.cursor() + except Exception as e: + logging.error("Failed to dateMigration: %s", str(e)) + return False + + sql_commnd = "" + update_record_dict = {} + tmp_update_record_dict = [] + # step 2: 获取更新数据 + try: + sql_commnd = "SELECT * FROM installed" + old_db_cursor.execute(sql_commnd) + update_record = old_db_cursor.fetchall() + # sql_commnd = "SELECT * FROM updateinfos" + # new_db_cursor.execute(sql_commnd) + # new_update_record = new_db_cursor.fetchall() + + for ur in update_record: + id,appname,version,time,description,icon,statue,keyword,errorcode = ur + if errorcode in range(200): + errorcode = 'null' + update_record_dict.clear() + update_record_dict.update({"appname":appname}) + update_record_dict.update({"version":version}) + update_record_dict.update({"time":time}) + update_record_dict.update({"description":description}) + update_record_dict.update({"icon":icon}) + update_record_dict.update({"statue":statue}) + update_record_dict.update({"keyword":'1'}) + update_record_dict.update({"errorcode":errorcode}) + tmp_update_record_dict.append(update_record_dict.copy()) + # 按时间排序 + tmp_update_record_dict = sorted(tmp_update_record_dict, key=itemgetter('time')) + except Exception as e: + logging.error("Failed to generate update records: %s", str(e)) + return False + logging.info("Generate update records complete.") + # step 3: insert新生成的记录 + try: + # 创建临时表 + sql_commnd = "create table IF NOT EXISTS tmp('id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,\ + 'appname' TEXT,\ + 'version' TEXT,\ + 'description' TEXT,\ + 'date' TEXT,\ + 'status' TEXT,\ + 'keyword' TEXT,\ + 'errorcode' TEXT,\ + 'appname_cn' TEXT,\ + 'status_cn' TEXT,\ + 'changelog' TEXT) " + new_db_cursor.execute(sql_commnd) + # 更新数据 + for urd in tmp_update_record_dict: + new_db_cursor.execute( + "insert into tmp (appname, version, description, date, status, keyword, errorcode) values(?," + "?,?,?,?,?,?)", + (urd['appname'], urd['version'], urd['description'], urd['time'], urd['statue'], urd['keyword'], urd['errorcode'])) + new_db.commit() + + # 删除updateinfos + sql_commnd = "drop table updateinfos" + new_db_cursor.execute(sql_commnd) + new_db.commit() + # 修改表名 + sql_commnd = "alter table tmp rename to updateinfos" + new_db_cursor.execute(sql_commnd) + new_db.commit() + except Exception as e: + logging.error("Failed to transfer data: %s", str(e)) + return False + + old_cfg_dict = {} + new_cfg_dict = {} + # step 4: 更新配置转移 + try: + sql_commnd = "SELECT * FROM display where id=1" + old_db_cursor.execute(sql_commnd) + old_cfg = old_db_cursor.fetchone() + for od in old_db_cursor.description: + old_cfg_dict.update({str(od[0]):old_cfg[old_db_cursor.description.index(od)]}) + if old_db != None: + old_db.close() + if old_db_cursor != None: + del old_db_cursor + new_db_cursor.execute(sql_commnd) + new_cfg = new_db_cursor.fetchone() + for od in new_db_cursor.description: + new_cfg_dict.update({str(od[0]):new_cfg[new_db_cursor.description.index(od)]}) + + sql_commnd = "UPDATE display set check_time='"+old_cfg_dict['check_time']+"' Where id=1" + new_db_cursor.execute(sql_commnd) + new_db.commit() + sql_commnd = "UPDATE display set update_time='"+old_cfg_dict['update_time']+"' Where id=1" + new_db_cursor.execute(sql_commnd) + new_db.commit() + sql_commnd = "UPDATE display set auto_check='"+old_cfg_dict['auto_check']+"' Where id=1" + new_db_cursor.execute(sql_commnd) + new_db.commit() + sql_commnd = "UPDATE display set system_version='"+old_cfg_dict['system_version']+"' Where id=1" + new_db_cursor.execute(sql_commnd) + new_db.commit() + if old_cfg_dict['auto_backup'] != None: + sql_commnd = "UPDATE display set auto_backup='"+old_cfg_dict['auto_backup']+"' Where id=1" + new_db_cursor.execute(sql_commnd) + new_db.commit() + if 'download_limit' in old_cfg_dict.keys() and old_cfg_dict['download_limit'] != None: + sql_commnd = "UPDATE display set download_limit='"+old_cfg_dict['download_limit']+"' Where id=1" + new_db_cursor.execute(sql_commnd) + new_db.commit() + if 'download_limit_value' in old_cfg_dict.keys() and old_cfg_dict['download_limit_value'] != None: + sql_commnd = "UPDATE display set download_limit_value='"+old_cfg_dict['download_limit_value']+"' Where id=1" + new_db_cursor.execute(sql_commnd) + new_db.commit() + + except Exception as e: + print(e) + print("更新配置文件错误") + return + logging.info("The data migration is complete.") return True def listtojsonstr(lists): diff --git a/backend/SystemUpdater/Core/JsonConfigParser.py b/backend/SystemUpdater/Core/JsonConfigParser.py new file mode 100755 index 0000000..082bceb --- /dev/null +++ b/backend/SystemUpdater/Core/JsonConfigParser.py @@ -0,0 +1,61 @@ +#!/usr/bin/python3 +# DistUpgradeConfigParser.py +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + +import json +import logging + +class Singleton(object): + def __init__(self, cls): + self._cls = cls + self._instance = {} + def __call__(self): + if self._cls not in self._instance: + self._instance[self._cls] = self._cls() + return self._instance[self._cls] + +@Singleton +class JsonConfig(): + NOW_UPDATE_CONFIG = '/usr/share/kylin-update-desktop-config/config/kylin-update-desktop-system.json' + + def __init__(self): + self._configDate = None + self.read() + + def read(self): + try: + with open(self.NOW_UPDATE_CONFIG,'r') as f: + logging.info("Reading json configuration file...") + + self._configDate = json.load(f) + except Exception as exc: + logging.warning("Reading json configuration file,check json format...") + logging.warning(exc) + self._configDate = None + + def getWithDefault(self,key1=None,key2=None,key3=None,key4=None,default=None): + try: + if self._configDate == None: + logging.warning("Reading json configuration file,check json format...") + return default + + if key4 != None: + return self._configDate[key1][key2][key3][key4] + elif key3 != None: + return self._configDate[key1][key2][key3] + elif key2 != None: + return self._configDate[key1][key2] + elif key1 != None: + return self._configDate[key1] + else: + return self._configDate + except Exception as e: + logging.warning(str(e)) + return default + + +if __name__ == "__main__": + # c = UpgradeConfig("/home/x/share/kylin-system-updater/backend/data/") + # print(c.setValue("SystemStatus", "abnormal_reboot", str(False)),True) + # print(c.getWithDefault("SystemStatus", "abnormal_reboot", False)) + pass diff --git a/backend/SystemUpdater/Core/LocalUpgradeData.py b/backend/SystemUpdater/Core/LocalUpgradeData.py new file mode 100644 index 0000000..e6493e2 --- /dev/null +++ b/backend/SystemUpdater/Core/LocalUpgradeData.py @@ -0,0 +1,278 @@ +#!/usr/bin/python3 + +import os +import logging + +class LocalUpgradeDataList: + """ + Represent the (potentially partial) results of an unattended-upgrades + run + """ + def __init__(self): + #可升级的组列表 + self._push_groups = [] + self._push_steps = [] + self._push_singles = [] + + self._pkgs_data = {} + + #加版本号的升级包 + self.versoin_pkgs = {'single_upgrade':{}, 'groups_upgrade':{}} + + self._problem_resolver = {} + self.steps_queue = [] + self.last_task = '' + + self.resolver_name = "total_pkgs" + + if "en_US" in os.environ["LANG"]: + self.lang = "en_US" + else: + self.lang = "zh_CN" + + def refresh(self): + self._push_groups = [] + self._push_steps = [] + self._push_singles = [] + + self._pkgs_data = {} + + #加版本号的升级包 + self.versoin_pkgs = {'single_upgrade':{}, 'groups_upgrade':{}} + + self._problem_resolver = {} + + self.steps_queue = [] + self.last_task = '' + + if "en_US" in os.environ["LANG"]: + self.lang = "en_US" + else: + self.lang = "zh_CN" + + #单包推送 + def add_singles(self,pkgs): + self._push_singles = pkgs + def get_singles(self): + return self._push_singles + + #分步推送 添加分步数据 + def add_steps(self,groups,data): + self._push_steps.append(groups) + self._pkgs_data.update(data) + + def get_steps(self): + return self._push_steps + + #组推送 + def add_groups(self,groups,data): + self._push_groups.append(groups) + self._pkgs_data.update(data) + def get_groups(self): + return self._push_groups + + #获取所以推送的升级 + def get_push(self): + return self._push_groups + self._push_singles + + def is_steps(self,content): + for cont in content: + if cont in self._push_singles: + return False + + if self._push_steps == []: + return False + else: + return True + + def check_steps_reboot(self,content): + return self._pkgs_data.get(content,{}).get('need_reboot',False) + + def get_pkgs_total(self,cache): + pkgs_install = [] + pkgs_upgrade = [] + + #单包的升级方式 + for pkg in self._push_singles: + if cache[pkg].is_installed: + pkgs_upgrade.append(pkg) + else: + pkgs_install.append(pkg) + + #遍历升级组列表 + for group_name in self._push_groups: + pkgs_install += self._pkgs_data.get(group_name,{}).get('install_list',[]) + pkgs_upgrade += self._pkgs_data.get(group_name,{}).get('upgrade_list',[]) + + return pkgs_install,pkgs_upgrade + + def get_steps_pkgs(self,step_name): + pkgs_install = [] + pkgs_upgrade = [] + + pkgs_install += self._pkgs_data.get(step_name,{}).get('install_list',[]) + pkgs_upgrade += self._pkgs_data.get(step_name,{}).get('upgrade_list',[]) + + return pkgs_install,pkgs_upgrade + + def get_push_pkgs(self,content): + pkgs_install = [] + pkgs_upgrade = [] + + if content == []: + for group_name in self._push_groups: + pkgs_install += self._pkgs_data.get(group_name,{}).get('pkgs_install',[]) + pkgs_upgrade += self._pkgs_data.get(group_name,{}).get('pkgs_upgrade',[]) + + if self._push_singles != []: + pkgs_upgrade += self._push_singles + else: + for cont in content: + if cont in self._push_groups: + pkgs_install += self._pkgs_data.get(cont,{}).get('pkgs_install',[]) + pkgs_upgrade += self._pkgs_data.get(cont,{}).get('pkgs_upgrade',[]) + + if cont in self._push_singles: + pkgs_upgrade.append(cont) + + return pkgs_install,pkgs_upgrade + + #将要升级的内容 + def _make_upgrade_content(self,content): + if content == []: + return self._push_groups + self._push_singles + else: + return content + + def resolver_groups(self,pkgs_install,pkgs_upgrade,pkgs_remove): + put_data = {self.resolver_name:{'install_pkgs':pkgs_install,'upgrade_pkgs':pkgs_upgrade,'reomve_pkgs':pkgs_remove}} + self._problem_resolver.update(put_data) + + def resolver_steps(self,step_name,pkgs_install,pkgs_upgrade,pkgs_remove): + put_data = {step_name:{'install_pkgs':pkgs_install,'upgrade_pkgs':pkgs_upgrade,'reomve_pkgs':pkgs_remove}} + self._problem_resolver.update(put_data) + + def classify_content(self,content): + if content == []: + return self._push_singles.copy(),self._push_groups.copy() + else: + for cont in content: + if cont in self._push_singles.copy(): + return content,[] + elif cont in self._push_groups.copy(): + return [],content + else: + return [],[] + + def get_resolver_upgrade(self): + pkgs_install = [] + pkgs_upgrade = [] + pkgs_remove = [] + pkgs_install = self._problem_resolver.get(self.resolver_name,{}).get('install_pkgs',[]) + pkgs_upgrade = self._problem_resolver.get(self.resolver_name,{}).get('upgrade_pkgs',[]) + pkgs_remove = self._problem_resolver.get(self.resolver_name,{}).get('reomve_pkgs',[]) + + return pkgs_install,pkgs_upgrade,pkgs_remove + + def get_progress(self,content): + #为了 解决获取包列表和获取进度传输的数据不能协同的问题 + if content == self.resolver_name: + for groups in self._push_groups: + content = groups + break + begin = self._pkgs_data.get(content,{}).get('progress_begin',0) + end = self._pkgs_data.get(content,{}).get('progress_end',0) + + return begin,end + + def pop(self,content): + for cont in content: + if cont in self._push_singles: + self._push_singles.remove(cont) + if cont in self._push_groups: + self._push_groups.remove(cont) + + def get_resolver_steps(self,content): + pkgs_install = [] + pkgs_upgrade = [] + pkgs_remove = [] + pkgs_install = self._problem_resolver.get(content,{}).get('install_pkgs',[]) + pkgs_upgrade = self._problem_resolver.get(content,{}).get('upgrade_pkgs',[]) + pkgs_remove = self._problem_resolver.get(content,{}).get('reomve_pkgs',[]) + + return pkgs_install,pkgs_upgrade,pkgs_remove + + #升级完成后从升级列表删除 + def reset_push_content(self,content): + for cont in content: + if cont in self._push_singles: + self._push_singles.remove(cont) + if cont in self._push_groups: + self._push_groups.remove(cont) + + def get_post_notify(self): + notify = self._pkgs_data.get(self.last_task,{}).get("users_notify",{}).get("post_install_notify",None) + if notify == None: + return '' + + return notify.get(self.lang,'') + + def get_mid_notify(self,content): + notify = self._pkgs_data.get(content,{}).get("users_notify",{}).get("mid_install_notify",None) + if notify == None: + return '' + + return notify.get(self.lang,'') + + def get_pre_script(self,content): + script_list = [] + + if content == self.resolver_name: + for groups in self._push_groups: + content = groups + break + + script = self._pkgs_data.get(content,{}).get("script",None) + if script == None: + return script_list + + for scr in ["pre_update_status_check","pre_update_script"]: + run_path = script.get(scr,[]) + + if isinstance(run_path,list) == True: + for sc in run_path: + if sc != '': + script_list.append(sc) + elif isinstance(run_path,str) == True: + if run_path != '': + script_list.append(run_path) + else: + pass + + return script_list + + def get_post_script(self,content): + script_list = [] + if content == self.resolver_name: + for groups in self._push_groups: + content = groups + break + + script = self._pkgs_data.get(content,{}).get("script",None) + if script == None: + return script_list + + for scr in ["post_update_status_check","post_update_script"]: + run_path = script.get(scr,[]) + + if isinstance(run_path,list) == True: + for sc in run_path: + if sc != '': + script_list.append(sc) + elif isinstance(run_path,str) == True: + if run_path != '': + script_list.append(run_path) + else: + pass + + return script_list \ No newline at end of file diff --git a/backend/SystemUpdater/Core/PluginManager.py b/backend/SystemUpdater/Core/PluginManager.py new file mode 100644 index 0000000..19eda71 --- /dev/null +++ b/backend/SystemUpdater/Core/PluginManager.py @@ -0,0 +1,402 @@ +#!/usr/bin/python3 +# -*- coding: UTF-8 -*- +# 脚本插件化执行管理 +# TODO: + # 使能/失能 --配置文件--ok + # 错误码 --脚本/本程序--wait/add + # 进度同步 --线程获取--add + # 输出规范 --脚本/本程序(重定向日志文件、输出格式)--ok/ok + # 元数据类型 --描述信息、翻译(配置文件)--ok + # 运行等级 --(root/user)--wait + +import subprocess +import os +from sre_compile import isstring +import threading +import yaml +import logging +from gi.repository import GObject + +class pluginState(): + PLUGIN_SUCCESS = 0 + PLUGINERR_PLUGIN_NOT_EXIST = PLUGIN_SUCCESS - 1 + PLUGINERR_PLUGIN_NOT_COMPLETED = PLUGINERR_PLUGIN_NOT_EXIST - 1 + PLUGINERR_NO_AVAILABLE_YAML = PLUGINERR_PLUGIN_NOT_COMPLETED - 1 + PLUGINERR_NOT_LOAD_ALL = PLUGINERR_NO_AVAILABLE_YAML - 1 + PLUGINERR_PLUGIN_NOT_IN_LIST = PLUGINERR_NOT_LOAD_ALL - 1 + PLUGINERR_PLUGIN_NOT_ENABLED = PLUGINERR_PLUGIN_NOT_IN_LIST - 1 + PLUGINERR_PLUGIN_CONFIG_FAILED = PLUGINERR_PLUGIN_NOT_ENABLED - 1 + PLUGINERR_LOG_PATH_NOT_EXIT = PLUGINERR_PLUGIN_CONFIG_FAILED - 1 + PLUGINERR_CONFIG_NOT_COMPLETED = PLUGINERR_LOG_PATH_NOT_EXIT - 1 + PLUGINERR_CMD_IS_NONE = PLUGINERR_CONFIG_NOT_COMPLETED - 1 + PLUGINERR_LANGUAGE_NOT_SUPPORT = PLUGINERR_CMD_IS_NONE - 1 + + _numToInfo = { + PLUGIN_SUCCESS: 'success', + PLUGINERR_PLUGIN_NOT_EXIST: 'plugin path not exist', + PLUGINERR_PLUGIN_NOT_COMPLETED: 'plugin folder not completed', + PLUGINERR_NO_AVAILABLE_YAML: 'there is no available yaml', + PLUGINERR_NOT_LOAD_ALL: 'not run load_all', + PLUGINERR_PLUGIN_NOT_IN_LIST: 'plugin not in loaded plugin list', + PLUGINERR_PLUGIN_NOT_ENABLED: 'plugin not enabled', + PLUGINERR_PLUGIN_CONFIG_FAILED: 'plugin config failed', + PLUGINERR_LOG_PATH_NOT_EXIT: 'log path not exists', + PLUGINERR_CONFIG_NOT_COMPLETED: 'config not completed', + PLUGINERR_CMD_IS_NONE: 'cmd is none', + PLUGINERR_LANGUAGE_NOT_SUPPORT: 'not support this language', + } + _infoToNum = { + 'success': PLUGIN_SUCCESS, + 'plugin path not exist': PLUGINERR_PLUGIN_NOT_EXIST, + 'plugin folder not completed': PLUGINERR_PLUGIN_NOT_COMPLETED, + 'there is no available yaml': PLUGINERR_NO_AVAILABLE_YAML, + 'not run load_all': PLUGINERR_NOT_LOAD_ALL, + 'plugin not in loaded plugin list': PLUGINERR_PLUGIN_NOT_IN_LIST, + 'plugin not enabled': PLUGINERR_PLUGIN_NOT_ENABLED, + 'plugin config failed': PLUGINERR_PLUGIN_CONFIG_FAILED, + 'log path not exists': PLUGINERR_LOG_PATH_NOT_EXIT, + 'config not completed': PLUGINERR_CONFIG_NOT_COMPLETED, + 'cmd is none': PLUGINERR_CMD_IS_NONE, + 'not support this language': PLUGINERR_LANGUAGE_NOT_SUPPORT, + } + + +PLUGIN_MANAGER_PATH = "./" # 可修改 + +# 目录结构 FILE PATH +CFG_FILE = "conf.yaml" +CFG_EX_DIR = "conf.d/" +CFG_PATH = PLUGIN_MANAGER_PATH + CFG_FILE +CFG_EX_PATH = PLUGIN_MANAGER_PATH + CFG_EX_DIR +MOD_DIR = "modules/" +MOD_PATH = PLUGIN_MANAGER_PATH + MOD_DIR +MOD_AVAILABLE = "modules-available/" +MOD_ENABLED = "modules-enabled/" +MOD_AVAILABLE_PATH = MOD_PATH + MOD_AVAILABLE +MOD_ENABLED_PATH = MOD_PATH + MOD_ENABLED +PLUGIN_DIR = "script/" +PLUGIN_PATH = PLUGIN_MANAGER_PATH + PLUGIN_DIR + +# 配置 日志路径 +LOG_DIR_ROOT = '/var/log/kylin-system-updater/' +# 默认插件日志路径 +PLUGIN_LOG_DIR = '/var/log/kylin-system-updater/plugin/' + +# PLUGIN.YAML +PLUGIN_CONF_KEY_NAME = 'name' +PLUGIN_CONF_KEY_DESC = 'desc' +PLUGIN_CONF_KEY_EXEC = 'exec' +PLUGIN_CONF_KEY_LOGLEVEL = 'loglevel' +PLUGIN_CONF_KEY_RUNLEVEL = 'runlevel' +PLUGIN_CONF_KEY_LIST = [PLUGIN_CONF_KEY_NAME,PLUGIN_CONF_KEY_DESC,PLUGIN_CONF_KEY_EXEC,PLUGIN_CONF_KEY_LOGLEVEL,PLUGIN_CONF_KEY_RUNLEVEL] + +# CONF.YAML AND CONF.D +MANAGER_CONF_KEY_LOGDIR = "logdir" +MANAGER_CONF_KEY_LIST = [MANAGER_CONF_KEY_LOGDIR, ] + + +FORMAT = "%(asctime)s [%(levelname)s]: %(message)s" +RUNLEVEL_LIST = ['ROOT', 'USER'] +LOGLEVEL_LIST = ['DEBUG', 'INFO', 'NOTIFY', 'WARNING', 'ERROR', 'CRITICAL'] + +class LOADSTATE(): + PLGNAME = 0x01 + EXECCMD = 0x02 + STATESUM = PLGNAME + EXECCMD + + +LANG_KEY_ZH_CN = 'zh_CN' +LANG_KEY_EN = 'en' +class LANGLIST(): + LANG_EN = 0 + LANG_ZH_CN = 1 + + +class pluginClass(pluginState): + + def __init__(self): + # 必须配置项 + self.pluginName = None + self.execCmd = None + # 可选配置项 + self.descList = [] # en / zh + self.logLevel = LOGLEVEL_LIST.index('DEBUG') + self.runLevel = RUNLEVEL_LIST.index('ROOT') + self.enabled = False + # 合成变量 + self.cmd = None + self.logDir = PLUGIN_LOG_DIR # 插件日志路径 + self.logPath = os.path.join(self.logDir, "default.log") # 插件日志文件 + self.fifoName = "default-fifo" # 插件进度文件 + # self.fifoPath = PLUGIN_PATH + self.fifoName + self.fifoPath = "/var/log/kylin-system-updater"+self.fifoName + # 记录变量 + self.running = False # 是否在运行 + self.process = 0 # 执行进度 + self.loadState = 0 # 插件配置完成 + logging.info("init finished.") + + ###################### 内部函数 ###################### + # 1-配置指定字段 + # 2-更新进度 (1/0.5s) + # 3- + ###################### + def _config_key(self, cfg, key): + if cfg == None or key == None or key not in cfg: + logging.warning("[PLUGIN]: key[%s] not in yaml.", key) + + if key == PLUGIN_CONF_KEY_NAME: + if isstring(cfg[key]): + self.pluginName = cfg[key] + self.fifoName = cfg[key] + "-fifo" + self.loadState += LOADSTATE.PLGNAME + else: + logging.error("[PLUGIN]: name[%s] not string.", cfg[key]) + + elif key == PLUGIN_CONF_KEY_DESC: + langList = cfg[key] + descDict = {} + if langList == None or len(langList) == 0: + return + for i in range(len(langList)): + descDict = langList[i] + if LANG_KEY_EN in descDict: + self.descList.insert(LANGLIST.LANG_EN, descDict.pop(LANG_KEY_EN)) + continue + elif LANG_KEY_ZH_CN in descDict: + self.descList.insert(LANGLIST.LANG_ZH_CN, descDict.pop(LANG_KEY_ZH_CN)) + continue + + elif key == PLUGIN_CONF_KEY_EXEC: + if isstring(cfg[key]): + self.execCmd = cfg[key] + self.loadState += LOADSTATE.EXECCMD + else: + logging.error("[PLUGIN]: execCmd[%s] not string.", cfg[key]) + + elif key == PLUGIN_CONF_KEY_LOGLEVEL: + loglevel = cfg[key].upper() + if loglevel in LOGLEVEL_LIST: + self.logLevel = LOGLEVEL_LIST.index(loglevel) + + elif key == PLUGIN_CONF_KEY_RUNLEVEL: + runlevel = cfg[key].upper() + if runlevel in RUNLEVEL_LIST: + self.runLevel = RUNLEVEL_LIST.index(runlevel) + else: + logging.warning("[PLUGIN]: key[%s] not need config.", key) + + def _update_process(self): + if not self.running: + logging.info("[PLUGIN]: plugin [%s] is not running.", self.pluginName) + return + + if os.path.exists(self.fifoPath): + try: + fd = open(self.fifoPath, 'r', 1) + process = fd.readline() + self.process = int(process.strip("\n")) + except Exception as e: + logging.info("[PLUGIN]: get process err[%s].",e) + else: + logging.info("[PLUGIN]: fifo[%s] not exists.", self.fifoPath) + + if self.process >= 100 or self.process < 0: + return + + tmptimer = threading.Timer(0.5, function=self._update_process) + tmptimer.start() + + ###################### 外部函数 ###################### + # 1-读取配置文件,并配置该插件 + # 2-使能插件 + # 3-失能插件 + # 4-获取插件名称 + # 5-获取进度 + # 6-注册进度跟新回调 + # 7-执行插件 + # 8-获取描述信息 + # 9-设置脚本日志路径 + + # TODO: + # 重配置该插件 + ###################### + + # 配置该插件 + def plg_config(self, filePath): + if not os.path.exists(filePath): + logging.error("[PLUGIN]: [%s] not exist.", filePath) + return self.PLUGINERR_PLUGIN_CONFIG_FAILED + + def plg_enable(self): + self.enabled = True + def plg_disable(self): + self.enabled = False + + def plg_get_name(self): + return self.pluginName + + def plg_get_process(self): + return self.process + + def plg_get_desc(self): + # 获得语言变量 + #TODO: 例如:中文繁体,如果不存在的话,显示中文简体 + lang=os.getenv("LANG") + if LANG_KEY_EN in lang: + if len(self.descList) > LANGLIST.LANG_EN: + return self.descList[LANGLIST.LANG_EN] + else: + logging.error("[PLUGIN]: There is not a desc of the language[%s].", lang) + elif LANG_KEY_ZH_CN in lang: + if len(self.descList) > LANGLIST.LANG_ZH_CN: + return self.descList[LANGLIST.LANG_ZH_CN] + else: + logging.error("[PLUGIN]: There is not a desc of the language[%s].", lang) + else: + logging.error("[PLUGIN]: There is not a desc of the language[%s].", lang) + return + + # 添加 update cmd + # 设置脚本日志路径 + def plg_set_logDir(self, logPath): + if not os.path.exists(logPath): + try: + os.makedirs(logPath, mode=0o755) + except Exception as e: + logging.error("[PLUGIN]: create plugin log dir failed.[%s]", e) + return self.PLUGINERR_LOG_PATH_NOT_EXIT + self.logDir = logPath + if self.pluginName != None: + self.logPath = os.path.join(self.logDir, self.pluginName + ".log") + self.cmd = "bash " + self.execCmd + " fifoname=" + self.fifoName + " logpath=" + self.logPath + " loglevel=" + str(self.logLevel) + " modename=" + self.pluginName + + def plg_run(self): + if not self.enabled: + logging.error("[PLUGIN]: [%s] not enabled.", self.pluginName) + return self.PLUGINERR_PLUGIN_NOT_ENABLED + + self.running = True + tmptimer = threading.Timer(0.5, function=self._update_process) + tmptimer.start() + + if self.cmd == None: + logging.error("[PLUGIN]: cmd is None.") + return self.PLUGINERR_CMD_IS_NONE, self._numToInfo(self.PLUGINERR_CMD_IS_NONE), self._numToInfo(self.PLUGINERR_CMD_IS_NONE) + + logging.debug("[PLUGIN]: cmd[%s].",self.cmd) + try: + ret = subprocess.run(self.cmd, shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE) + except Exception as e: + logging.error("[PLUGIN]: subprocess run err[%s].", e) + + self.running = False + logging.debug("[PLUGIN]: [%s] run finished ret[%d].",self.pluginName, ret.returncode) + return ret.returncode, ret.stdout.decode(), ret.stderr.decode() + + def plg_reconfig(self): + pass + + + +class pluginManagerClass(pluginState): + def __init__(self): + # 变量初始化 + self.plgClassList = [] # 插件句柄 + self.loaded = False + + self.managerLogDir = LOG_DIR_ROOT # 管理器日志路径 + # 日志配置初始化,试用updater的logger + # if not os.path.exists(self.managerLogDir): + # os.mkdir(self.managerLogDir, mode=0o755) + # logfile = os.path.join(self.managerLogDir, 'PluginManager.log.' + str(self.classNum)) + # logging.basicConfig(format=FORMAT, level='DEBUG', datefmt='%m-%d,%H:%M:%S', filename=logfile, filemode='a') + # self.pluginLogDir = PLUGIN_LOG_DIR # 插件日志路径 + + # 将单个插件句柄添加到全局记录, 并使能 + def _add_single_plugin(self, filePath, enable): + if not os.path.exists(filePath): + logging.debug("[PLUGIN]: [%s] not exist.", filePath) + return + + singlePlgClass = pluginClass() + singlePlgClass.plg_config(filePath) + self.plgClassList.append(singlePlgClass) + if enable: + singlePlgClass.plg_enable() + singlePlgClass.plg_set_logDir(self.pluginLogDir) + + def _remove_single_plugin(self, pluginClass): + if pluginClass in self.plgClassList: + logging.debug("[PLUGIN]: remove [%s].", pluginClass.plg_get_name()) + pluginClass.remove(pluginClass) + pluginClass.plg_disable() + + + # 加载所有插件,读取所有配置 + # 第一个执行 + # 返回插件句柄列表 + # TODO:加载指定插件, 读取指定配置 + def reload_plugin(self, pluginName): + pass + + # 通过句柄获取插件名称 + def get_plugin_name(self, pluginClass): + if not self.loaded: + logging.error("[PLUGIN]: please run load_all first.") + return self.PLUGINERR_NOT_LOAD_ALL + if pluginClass not in self.plgClassList: + logging.error("[PLUGIN]: there is no this plugin in pluginList.") + return self.PLUGINERR_PLUGIN_NOT_IN_LIST + + return pluginClass.plg_get_name() + + # 运行指定插件 + # pluginName, pluginClass 都指定时,以名称为准 + def run_plugin(self, pluginName = None): + self.running = True + + if pluginName == None or not os.path.isfile(pluginName): + logging.error("[PLUGIN]: [%s] Cann't found.",pluginName) + return True + cmd = "bash " + pluginName + try: + ret = subprocess.run(cmd, shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE) + logging.info("[PLUGIN]: script[%s].",pluginName) + except Exception as e: + logging.error("[PLUGIN]: subprocess run err[%s].", e) + return True + + self.running = False + + if ret.returncode != 0: + logging.error("[PLUGIN]: code:%d, out:%s, err:%s",ret.returncode, ret.stdout.decode(), ret.stderr.decode()) + logging.debug("[PLUGIN]: run finished returncode[%d], out[%s], err[%s]",ret.returncode, ret.stdout.decode(), ret.stderr.decode()) + return (ret.returncode==0) + + def connect_signal(self, plgclass, signal, handler): + if plgclass not in self.plgClassList: + logging.error("[PLUGIN]: there is no this plugin in pluginList.") + return self.PLUGINERR_PLUGIN_NOT_IN_LIST + return plgclass.connect(signal, handler) + + +def plugin_process_handler(obj, process): + logging.info("[PLUGIN]: ******* process [%d].", process) + +# if __name__ == "__main__": + +# pMClass = pluginManagerClass() +# plgList = pMClass.load_all("./") + +# for everyPlg in iter(plgList): +# name = pMClass.get_plugin_name(everyPlg) +# print("name:", name) +# desc = pMClass.get_desc(everyPlg) +# print("desc:", desc) +# pMClass.connect_signal(everyPlg, "processChanged", plugin_process_handler) + +# ret = pMClass.run_plugin(name) + +# exit(0) + diff --git a/backend/SystemUpdater/Core/UpdateList.py b/backend/SystemUpdater/Core/UpdateList.py index cf5c987..eb0642d 100644 --- a/backend/SystemUpdater/Core/UpdateList.py +++ b/backend/SystemUpdater/Core/UpdateList.py @@ -7,42 +7,19 @@ import json import yaml import shutil from gi.repository import Gio -from .OriginFilter import UpdateListFilterCache from .errors import * from .enums import * from SystemUpdater.Core.utils import get_config_patch -class LocalUpgradeDataList: - """ - Represent the (potentially partial) results of an unattended-upgrades - run - """ - def __init__(self, - groups_pkgs={}, - upgrade_groups=[], - single_pkgs=[], - adjust_pkgs=[], - ): - #可升级的组列表 - self.upgrade_groups = upgrade_groups - #组列表中包含的包 - self.groups_pkgs = groups_pkgs - #推送的可升级的单包 - self.single_pkgs = single_pkgs - #调整版本列表 源过滤 - self.adjust_pkgs = adjust_pkgs - #加版本号的升级包 - self.versoin_pkgs = {'single_upgrade':{}, 'groups_upgrade':{}} - class UpdateList(): - OUTPUT_CONFIG_PATH = '/var/lib/kylin-system-updater/json/' + OUTPUT_JSON_PATH = '/var/lib/kylin-system-updater/json/' IMPORTANT_LIST_PATH = '/var/lib/kylin-software-properties/template/important.list' def __init__(self,parent): self.parent = parent #所有的组升级安装列表 - self.upgrade_meta = LocalUpgradeDataList({},[],[],[]) + self.update_meta = self.parent.main_meta if 'XDG_CURRENT_DESKTOP' in os.environ: self.current_desktop = os.environ.get('XDG_CURRENT_DESKTOP') @@ -56,32 +33,22 @@ class UpdateList(): self.application_dirs = [os.path.join(base, 'applications') for base in data_dirs.split(':')] - - self.config_path = get_config_patch() - - if self.parent.install_mode.check_filter() == True: - #开启原过滤 - self.fu = UpdateListFilterCache(self.parent) - else: - self.fu = None - logging.info("Close to Allowed origin fiter...") - #清空上次输出的分组JSON文件 - def _empty_output_dir(self): + def _empty_output_dir(self,path): #清空 升级列表 - if not os.path.exists(self.OUTPUT_CONFIG_PATH): - os.makedirs(self.OUTPUT_CONFIG_PATH) - logging.info('making the ConfigPath(%s) is complete...',self.OUTPUT_CONFIG_PATH) + if not os.path.exists(path): + os.makedirs(path) + logging.info('making the ConfigPath(%s) is complete...',path) else: - shutil.rmtree(self.OUTPUT_CONFIG_PATH) - os.makedirs(self.OUTPUT_CONFIG_PATH) - logging.info('Emptying the ConfigPath(%s) is complete...',self.OUTPUT_CONFIG_PATH) + shutil.rmtree(path) + os.makedirs(path) + logging.info('Emptying the ConfigPath(%s) is complete...',path) #读取推送列表,判断分组和单包推送,再进行源过滤 def _make_important_list(self,cache,pkgs_upgrade,important_list = []): upgradeable_pkgs = [] - tmp = [] + # tmp = [] upgradeable_groups = [] logging.info("The Server Push List: %a",important_list) @@ -94,17 +61,12 @@ class UpdateList(): if pkg_obj.is_installed: if pkg_name in pkgs_upgrade: pkgs_upgrade.remove(pkg_name) - tmp.append(pkg_obj) + upgradeable_pkgs.append(pkg_obj.name) else: - tmp.append(pkg_obj) + upgradeable_pkgs.append(pkg_obj.name) else: upgradeable_groups.append(pkg_name) - if tmp != []: - install_list,upgrade_list,adjust_pkgs = self._make_fiter_origin(tmp,True) - self.upgrade_meta.adjust_pkgs.extend(adjust_pkgs) - upgradeable_pkgs = install_list + upgrade_list - logging.info("Push Single Packages: %a, Push Groups:%a",upgradeable_pkgs,upgradeable_groups) return upgradeable_groups,upgradeable_pkgs @@ -144,12 +106,12 @@ class UpdateList(): pass return new_pkgs_list - def _make_group_output_json(self,data,data_yaml,upgrade_pkgs_json,install_pkgs_json): + def _make_group_output_json(self,data,data_yaml,upgrade_pkgs_json,install_pkgs_json,output_path): groups_base_info = {} output_json = {} #FIXME: 确定输出文件的文件名 以及放置位置 - output_config_name = self.OUTPUT_CONFIG_PATH + data['package'] + '.json' + output_config_name = output_path + data['package'] + '.json' #4、添加一些基础信息 groups_base_info.update({"package":data['package']}) @@ -172,57 +134,12 @@ class UpdateList(): with open(output_config_name, 'w', encoding='utf-8') as f: json.dump(output_json, f, ensure_ascii=False, indent=4) logging.info("Generate Jsonfile(%s) to complete... ",output_config_name) - - #进行源过滤,is_adjust 是否调整cache中的候选版本,单包推送会调整保持控制面板显示正确的版本 - def _make_fiter_origin(self,pkgs_list,adjust_versions): - install_pkgs = [] - upgrade_pkgs = [] - adjust_pkgs = [] - - #是否进行源过滤的选项 - if self.fu != None: - try: - after_pkgs_list,adjust_pkgs = self.fu.check_in_allowed_origin(pkgs_list,adjust_versions) - except Exception as e: - after_pkgs_list = pkgs_list - logging.error("Check Allowed origin is occur error:" + str(e)) - else: - after_pkgs_list = pkgs_list - adjust_pkgs = [] - - for pkg_obj in after_pkgs_list: - if pkg_obj.is_installed: - upgrade_pkgs.append(pkg_obj.name) - else: - install_pkgs.append(pkg_obj.name) - - return install_pkgs,upgrade_pkgs,adjust_pkgs - - #从本地中获取本次升级需要升级的包 部分升级和全部升级使用 全盘升级不适用 - def _make_pkgs_list(self,cache,groups_pkgs,groups_list,pkg_list): - pkgs_install = [] - pkgs_upgrade = [] - - #单包的升级方式 - for pkg in pkg_list: - if cache[pkg].is_installed: - pkgs_upgrade.append(pkg) - else: - pkgs_install.append(pkg) - - #遍历升级组列表 - for group_name in groups_list: - pkgs_install += groups_pkgs.get(group_name,[]).get('pkgs_install',[]) - pkgs_upgrade += groups_pkgs.get(group_name,[]).get('pkgs_upgrade',[]) - - return pkgs_install,pkgs_upgrade #输出白名单的配置 - def _make_autoupgrade_config(self,cache,upgrade_data,_adjust_pkgs): - pkgs_install,pkgs_upgrade = self._make_pkgs_list(cache,upgrade_data.groups_pkgs,upgrade_data.upgrade_groups,upgrade_data.single_pkgs) - split_adjust_pkgs = [i.split("=")[0] for i in _adjust_pkgs] + def _make_autoupgrade_config(self,cache,output_path,config_path): + pkgs_install,pkgs_upgrade = self.update_meta.get_pkgs_total(cache) - output_config_name = self.OUTPUT_CONFIG_PATH + 'auto-upgrade-list.json' + output_config_name = output_path + 'auto-upgrade-list.json' output_json = {} install_info = {} for pkg in pkgs_install: @@ -230,11 +147,7 @@ class UpdateList(): pkgs_json = {} pkgs_json.update({"cur_version":getattr(pkg_cache.installed, "version", '')}) - if pkg in split_adjust_pkgs: - version_adjust = _adjust_pkgs[split_adjust_pkgs.index(pkg)].split("=")[1] - pkgs_json.update({"new_version":version_adjust}) - else: - pkgs_json.update({"new_version":getattr(pkg_cache.candidate, "version", '')}) + pkgs_json.update({"new_version":getattr(pkg_cache.candidate, "version", '')}) install_info.update({pkg:pkgs_json}) upgrade_json = {} @@ -243,18 +156,14 @@ class UpdateList(): pkgs_json = {} pkgs_json.update({"cur_version":getattr(pkg_cache.installed, "version", '')}) - if pkg in split_adjust_pkgs: - version_adjust = _adjust_pkgs[split_adjust_pkgs.index(pkg)].split("=")[1] - pkgs_json.update({"new_version":version_adjust}) - else: - pkgs_json.update({"new_version":getattr(pkg_cache.candidate, "version", '')}) + pkgs_json.update({"new_version":getattr(pkg_cache.candidate, "version", '')}) upgrade_json.update({pkg:pkgs_json}) group_json = {} - for ug in self.upgrade_meta.groups_pkgs: + for ug in self.update_meta.get_groups(): pkgs_json = {} - with open(self.config_path + str(ug) + ".yaml", "r") as stream: + with open(config_path + str(ug) + ".yaml", "r") as stream: try: data_yaml = yaml.safe_load(stream) pkgs_json.update({"cur_version":""}) @@ -265,16 +174,12 @@ class UpdateList(): group_json.update({ug:pkgs_json}) single_json = {} - for us in self.upgrade_meta.single_pkgs: + for us in self.update_meta.get_singles(): pkg_cache = cache[us] pkgs_json = {} pkgs_json.update({"cur_version":getattr(pkg_cache.installed, "version", '')}) - if pkg in split_adjust_pkgs: - version_adjust = _adjust_pkgs[split_adjust_pkgs.index(pkg)].split("=")[1] - pkgs_json.update({"new_version":version_adjust}) - else: - pkgs_json.update({"new_version":getattr(pkg_cache.candidate, "version", '')}) + pkgs_json.update({"new_version":getattr(pkg_cache.candidate, "version", '')}) pkgs_json.update({"changelog":""}) single_json.update({us:pkgs_json}) @@ -356,57 +261,36 @@ class UpdateList(): def _make_groups_pkgs(self,cache,data,pkgs_upgrade = []): upgrade_pkgs_list = data['upgrade_list'] - #检查包是否在cache中 以及是否已经安装 没有安装的话才添加到列表 new_install_list = self._check_pkg_in_cache(cache,data['install_list']) - - downgrade_raw,downgrade_pkgs = self._get_downgrade_list(cache,data) - #被降级的软件包优先级最高 - for pkg in downgrade_pkgs: - if pkg in upgrade_pkgs_list: - upgrade_pkgs_list.remove(pkg) - if pkg in new_install_list: - new_install_list.remove(pkg) - if pkg in self.upgrade_meta.single_pkgs: - self.upgrade_meta.single_pkgs.remove(pkg) #进行交集 升级列表 new_upgrade_list = list(set(pkgs_upgrade) & set(upgrade_pkgs_list)) - #进行源过滤 - new_install_list,new_upgrade_list,adjust_pkgs = self._make_fiter_origin([cache[pkg] for pkg in new_install_list + new_upgrade_list],False) - self.upgrade_meta.adjust_pkgs.extend(adjust_pkgs) - #在总升级列表中移除这些包 for pkg in new_upgrade_list: pkgs_upgrade.remove(pkg) - downgrade_pkg,adjust_pkgs = self._make_downgrade(cache,downgrade_raw) - self.upgrade_meta.adjust_pkgs.extend(adjust_pkgs) - new_upgrade_list.extend(downgrade_pkg) - #单包的优先级最高 从组中剔除此包 - for pkg in self.upgrade_meta.single_pkgs: + for pkg in self.update_meta.get_singles(): if pkg in new_install_list: new_install_list.remove(pkg) return new_install_list,new_upgrade_list - - def _make_groups_upgrade(self,cache,group_list,is_openkylin,pkgs_install,pkgs_upgrade): + def _make_groups_upgrade(self,cache,group_list,is_openkylin,pkgs_install,pkgs_upgrade,output_path,config_path): upgrade_list = [] install_list = [] - if os.path.isdir(self.config_path) == False: - logging.warning("configPath(%s) is not exists...",self.config_path) + if os.path.isdir(config_path) == False: + logging.warning("configPath(%s) is not exists...",config_path) return - files = os.listdir(self.config_path) #获得文件夹中所有文件的名称列表 + files = os.listdir(config_path) #获得文件夹中所有文件的名称列表 for ifile in files: - #判是否是目录以及是否以JSON结尾 if ifile.endswith('.json'): #读取组JSON文件 - with open(self.config_path+ifile,'r') as f: + with open(config_path+ifile,'r') as f: try: data = json.load(f) except Exception as exc: @@ -415,7 +299,7 @@ class UpdateList(): group_name = data['package'] #读取组的yaml 文件的changelog的信息 - with open(self.config_path + group_name + ".yaml", "r") as stream: + with open(config_path + group_name + ".yaml", "r") as stream: try: data_yaml = yaml.safe_load(stream) except Exception as exc: @@ -425,7 +309,7 @@ class UpdateList(): #过滤没有推送的配置文件 if not group_name in group_list: continue - + if is_openkylin == True: install_list,upgrade_list = pkgs_install,pkgs_upgrade else: @@ -440,45 +324,53 @@ class UpdateList(): #2、生成安装的软件列表 install_pkgs_json = self._make_pkg_info_json(cache,install_list) #输出JSON配置文件 - self._make_group_output_json(data,data_yaml,upgrade_pkgs_json,install_pkgs_json) + self._make_group_output_json(data,data_yaml,upgrade_pkgs_json,install_pkgs_json,output_path) #保存分组版本号,好像没有 - self.upgrade_meta.versoin_pkgs['groups_upgrade'].update({group_name:''}) + self.update_meta.versoin_pkgs['groups_upgrade'].update({group_name:''}) - #添加到字典维护的升级列表 - self.upgrade_meta.upgrade_groups.append(group_name) - self.upgrade_meta.groups_pkgs.update({group_name:{"pkgs_upgrade":upgrade_list,"pkgs_install":install_list}}) + update_script = data.setdefault("script",{}) + + steps_begin = 50 + step_update = data.setdefault("step_update",{}) + if step_update != {}: + for step_name in step_update: + step_data = step_update.get(step_name,{}) + if step_data == {}: + continue + step_install = list(set(step_data.setdefault("install_list",[])) & set(install_list)) + step_upgrade = list(set(step_data.setdefault("upgrade_list",[])) & set(upgrade_list)) + need_reboot = step_data.setdefault("need_reboot",False) + if step_install == [] and step_upgrade == []: + continue + step_data["install_list"] = step_install + step_data["upgrade_list"] = step_upgrade + + #进度算法 + value = int((len(step_install) + len(step_upgrade))/(len(install_list) + len(upgrade_list)) * 50) + if need_reboot == True: + step_data.update({"progress_begin":steps_begin}) + step_data.update({"progress_end":100}) + else: + progress_end = steps_begin + value + step_data.update({"progress_begin":steps_begin}) + step_data.update({"progress_end":progress_end}) + steps_begin = progress_end + + logging.info("Steps(%s) upgrade:%d install:%d",step_name,len(step_upgrade),len(step_install)) + self.update_meta.add_steps(step_name,{step_name:step_data}) + + #需要重启的话 后面的阶段将不再考虑 + if need_reboot == True: + break + + put_data = {group_name:{"progress_begin":steps_begin,"progress_end":100,"pkgs_upgrade":upgrade_list,"pkgs_install":install_list,"script":update_script}} + + self.update_meta.add_groups(group_name,put_data) logging.info("Group(%s) upgrade:%d install:%d",group_name,len(upgrade_list),len(install_list)) else: pass - def _make_openkylin_output_json(self,upgrade_pkgs_json,install_pkgs_json): - groups_base_info = {} - output_json = {} - - #FIXME: 确定输出文件的文件名 以及放置位置 - output_config_name = self.OUTPUT_CONFIG_PATH + "kylin-update-desktop-system.json" - - #4、添加一些基础信息 - groups_base_info.update({"package":"kylin-update-desktop-system"}) - groups_base_info.update({"new_version":"33797.0001"}) - groups_base_info.update({"name":{"zh_CN": "系统更新","en_US": "Kylin OS"}}) - groups_base_info.update({"description":{"zh_CN": "Openkylin-系统更新包","en_US": "Openkylin-System Update Package"}}) - groups_base_info.update({"icon":" "}) - - #添加读yaml文件 - groups_base_info.update({"changelog":"Openkylin-系统更新包\n"}) - - #5、添加升级的内容 - output_json.update(groups_base_info) - output_json.update({"upgrade_list":upgrade_pkgs_json}) - output_json.update({"install_list":install_pkgs_json}) - - #6 产生JSON文件 - with open(output_config_name, 'w', encoding='utf-8') as f: - json.dump(output_json, f, ensure_ascii=False, indent=4) - logging.info("Generate Jsonfile(%s) to complete... ",output_config_name) - def _rate_application_for_package(self, application, pkg): score = 0 desktop_file = os.path.basename(application.get_filename()) @@ -533,12 +425,12 @@ class UpdateList(): else: return None - def _make_single_upgrade(self,cache,pkg_list): + def _make_single_upgrade(self,cache,pkg_list,output_path): for pkg in pkg_list: zh_name = '' base_info = {} output_json = {} - output_config_name = self.OUTPUT_CONFIG_PATH + pkg + '.json' + output_config_name = output_path + pkg + '.json' pkg_cache = cache[pkg] @@ -576,7 +468,7 @@ class UpdateList(): logging.info("Generate Jsonfile(%s) to complete... ",output_config_name) #6、保存单包版本号 - self.upgrade_meta.versoin_pkgs['single_upgrade'].update({pkg_cache.name:getattr(pkg_cache.installed, "version", '')}) + self.update_meta.versoin_pkgs['single_upgrade'].update({pkg_cache.name:getattr(pkg_cache.installed, "version", '')}) def _make_distupgrade(self,cache): pkgs_upgrade = [] @@ -597,37 +489,36 @@ class UpdateList(): return pkgs_install,pkgs_upgrade def update_kylin(self,cache,important_data,is_openkylin = False): - pkgs_install = [] - pkgs_upgrade = [] + system_install = [] + system_upgrade = [] #查找所有可升级的包 if is_openkylin == True: - pkgs_install,pkgs_upgrade = self._make_distupgrade(cache) + system_install,system_upgrade = self._make_distupgrade(cache) else: for pkg in cache: if pkg.is_upgradable and pkg.is_installed: - pkgs_upgrade.append(pkg.name) + system_upgrade.append(pkg.name) - logging.info("System all upgradeable packages:upgrade:%d install:%d ",len(pkgs_upgrade),len(pkgs_install)) + logging.info("System all upgradeable packages:upgrade:%d install:%d ",len(system_upgrade),len(system_install)) - group_important_list,self.upgrade_meta.single_pkgs = self._make_important_list(cache,pkgs_upgrade,important_data) + group_list,single_pkgs = self._make_important_list(cache,system_upgrade,important_data) #清空输出的目录 - self._empty_output_dir() + self._empty_output_dir(self.OUTPUT_JSON_PATH) - #important_list 为空时此次不需要升级 - if not group_important_list and not self.upgrade_meta.single_pkgs: - self.parent.dbusController.UpdateDetectFinished(True,[],'','') + if not group_list and not single_pkgs: return + self.update_meta.add_singles(single_pkgs) + #产生单包的JSON - self._make_single_upgrade(cache,self.upgrade_meta.single_pkgs) + self._make_single_upgrade(cache,single_pkgs,self.OUTPUT_JSON_PATH) #分组的包的JSON - self._make_groups_upgrade(cache,group_important_list,is_openkylin,pkgs_install,pkgs_upgrade) + self._make_groups_upgrade(cache,group_list,is_openkylin,\ + system_install,system_upgrade,self.OUTPUT_JSON_PATH,get_config_patch()) - self._make_autoupgrade_config(cache,self.upgrade_meta,self.upgrade_meta.adjust_pkgs) - - self.parent.dbusController.UpdateDetectFinished(True,self.upgrade_meta.upgrade_groups + self.upgrade_meta.single_pkgs,'','') - return + self._make_autoupgrade_config(cache,self.OUTPUT_JSON_PATH,get_config_patch()) + return \ No newline at end of file diff --git a/backend/SystemUpdater/Core/UpdaterConfigParser.py b/backend/SystemUpdater/Core/UpdaterConfigParser.py index bfef7bd..f79ec64 100755 --- a/backend/SystemUpdater/Core/UpdaterConfigParser.py +++ b/backend/SystemUpdater/Core/UpdaterConfigParser.py @@ -1,4 +1,5 @@ #!/usr/bin/python3 +# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- # DistUpgradeConfigParser.py # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA @@ -20,20 +21,20 @@ class UpgradeConfig(SafeConfigParser): self.config_files.append(os.path.join(datadir, defaults_dir)) # our config file self.config_files += [maincfg] - self.read(self.config_files) + self.read(self.config_files, encoding='iso-8859-1') logging.info("Initialize Upgrade ConfigFile(%s) to success",str(self.config_files)) def optionxform(self, optionstr): return optionstr - def reReadConfigFiles(self): - self.read(self.config_files) + def reRead(self): + self.read(self.config_files, encoding='iso-8859-1') def setValue(self, section, option, value=None,is_write = True): if option != 'upgradelist': logging.info("SetValue Section:%s Option:%s Value:%s",section, option, value) try: - self.reReadConfigFiles() + self.reRead() self.set(section, option,value) except Exception as e: @@ -48,7 +49,7 @@ class UpgradeConfig(SafeConfigParser): def getWithDefault(self, section, option, default,re_read=False): try: if re_read == True: - self.reReadConfigFiles() + self.reRead() if type(default) == bool: return self.getboolean(section, option) diff --git a/backend/SystemUpdater/Core/enums.py b/backend/SystemUpdater/Core/enums.py index 5e5aa5f..38da3a1 100644 --- a/backend/SystemUpdater/Core/enums.py +++ b/backend/SystemUpdater/Core/enums.py @@ -9,17 +9,25 @@ __all__ = ( "ERROR_REMOVE_ESSENTIAL_PACKAGES","ERROR_NOT_DISK_SPACE","ERROR_NOT_CONFIGPKG_DEPENDENCIES","ERROR_NOT_SELFPKG_DEPENDENCIES", "ERROR_NOT_FIX_SYSTEM","ERROR_READ_LOCAL_DEB","ERROR_LOCAL_DEB_FORMAT","ERROR_INSTALL_DEB_BASE","ERROR_LOAD_CONFIG_FAILED", "ERROR_UPDATE_KEY_SIGNATURES","ERROR_UPDATE_NET_AUTHENTICATION","ERROR_UPDATE_NOTREAD_SOURCES","PRIORITY_UPGRADE_SUCCCESSED", - "ERROR_UPDATE_INVALID_TIME", + "ERROR_UPDATE_INVALID_TIME","ERROR_UPDATE_SOURCE_TIMEOUT","ERROR_PROGRAM_EXCEPTION","ERROR_RUN_SCRIPTS_FAILED", - "get_error_description_from_enum", "get_error_string_from_enum", "get_source_name_from_enum", "get_caller_from_enum") + "get_error_description_from_enum", "get_error_string_from_enum", "get_source_name_from_enum", "get_caller_from_enum", + "get_error_code_from_enum","get_policykit_authority_action_enum" + ) import gettext gettext.bindtextdomain('kylin-system-updater', '/usr/share/locale') gettext.textdomain('kylin-system-updater') _ = gettext.gettext +from aptdaemon.enums import ( + ERROR_REPO_DOWNLOAD_FAILED + ) + PRIORITY_UPGRADE_SUCCCESSED = "priority-upgrade-successed" +ERROR_PROGRAM_EXCEPTION = "error_program_exception" + #apt update阶段出现的错误解析 ERROR_UPDATE_DEFAULT_FAILED = "error-update-default-failed" ERROR_UPDATE_KEY_SIGNATURES = "The following signatures" @@ -28,6 +36,7 @@ ERROR_UPDATE_NOTREAD_SOURCES = "The list of sources could not be read" ERROR_UPDATE_INVALID_TIME = "(invalid for another" ERROR_UPDATE_SOURCE_FAILED = "error-update-source-failed" +ERROR_UPDATE_SOURCE_TIMEOUT = "error-update-source-timeout" ERROR_NETWORK_FAILED = "error-network-failed" ERROR_NOT_GROUPS_CONFIG = "error-not-groups-config" ERROR_NOT_CONFIGPKG_DEPENDENCIES = "error-not-configpkg-dependencies" @@ -44,6 +53,7 @@ ERROR_READ_IMPORTANTLIST_FAILED = "error-read-importantlist-failed" ERROR_RESOLVER_FAILED = "error-resolver-failed" ERROR_NOT_UPGRADE_PACKAGES = "error-not-upgrade-packages" ERROR_REMOVE_ESSENTIAL_PACKAGES = "error-remove-essential-packages" +ERROR_RUN_SCRIPTS_FAILED = "error-run-scripts-failed" ERROR_NOT_DISK_SPACE = "error-not-disk-space" ERROR_READ_LOCAL_DEB = "error-read-local-deb" ERROR_LOCAL_DEB_FORMAT = "error-local-deb-format" @@ -55,6 +65,7 @@ _STRINGS_ERROR = { #update ERROR_UPDATE_DEFAULT_FAILED: _("Check for update exceptions!"), ERROR_UPDATE_SOURCE_FAILED: _("Check for update exceptions!"), + ERROR_UPDATE_SOURCE_TIMEOUT: _("Check for update exceptions!"), ERROR_NETWORK_FAILED: _("Network anomaly, can't check for updates!"), ERROR_UPDATE_KEY_SIGNATURES: _("Check for update exceptions!"), ERROR_READ_IMPORTANTLIST_FAILED: _("Check for update exceptions!"), @@ -62,6 +73,7 @@ _STRINGS_ERROR = { ERROR_NOT_INIT_PACKAGESINFIO: _("Check for update exceptions!"), ERROR_NOT_FIX_SYSTEM: _("Check for update exceptions!"), ERROR_LOAD_CONFIG_FAILED: _("Check for update exceptions!"), + ERROR_PROGRAM_EXCEPTION: _("Check for update exceptions!"), #优先升级 ERROR_NOT_GROUPS_CONFIG: _("Upgrade configuration acquisition exception."), @@ -72,14 +84,17 @@ _STRINGS_ERROR = { ERROR_RESOLVER_FAILED: _("Could not calculate the upgrade"), ERROR_NOT_UPGRADE_PACKAGES: _("There is an exception in the update package."), ERROR_REMOVE_ESSENTIAL_PACKAGES: _("There is an exception in the update package."), + ERROR_RUN_SCRIPTS_FAILED: _("There is an exception in the update package."), ERROR_NOT_DISK_SPACE: _("Disk space is insufficient, please clean the disk and then upgrade"), ERROR_READ_LOCAL_DEB:_(" "), ERROR_LOCAL_DEB_FORMAT:_(" "), ERROR_INSTALL_DEB_BASE:_(" ")} _DESCS_ERROR = { + ERROR_PROGRAM_EXCEPTION: _("Program exception, please contact the administrator to solve."), #update - ERROR_UPDATE_SOURCE_FAILED: _("Unable to access the source management server"), + ERROR_UPDATE_SOURCE_FAILED: _("Unable to access the source management server, please try again later"), + ERROR_UPDATE_SOURCE_TIMEOUT: _("Access to the source management server timed out, please try again later"), ERROR_NETWORK_FAILED: _("Please check your network connection and retry."), ERROR_UPDATE_KEY_SIGNATURES: _("Check your source public key signature"), ERROR_UPDATE_NOTREAD_SOURCES: _("Please check your source list and retry."), @@ -102,12 +117,45 @@ _DESCS_ERROR = { ERROR_RESOLVER_FAILED: _("nothing"), ERROR_NOT_UPGRADE_PACKAGES: _("This update cannot detect the upgradeable package."), ERROR_REMOVE_ESSENTIAL_PACKAGES: _("You request the removal of a system-essential package."), + ERROR_RUN_SCRIPTS_FAILED:_("Exceptions to running the check script."), ERROR_NOT_DISK_SPACE: _("test"), ERROR_READ_LOCAL_DEB:_("Deb format exception, read local deb file error."), ERROR_LOCAL_DEB_FORMAT:_("Deb format exception, failed to parse package file."), ERROR_INSTALL_DEB_BASE:_("Install deb error.") } +_CODE_ERROR = { + ERROR_PROGRAM_EXCEPTION: "#0000", + #update + ERROR_UPDATE_SOURCE_FAILED: "#0100", + ERROR_UPDATE_SOURCE_TIMEOUT: "#0101", + ERROR_NETWORK_FAILED: "#0102", + ERROR_UPDATE_KEY_SIGNATURES: "#0103", + ERROR_UPDATE_NOTREAD_SOURCES: "#0104", + ERROR_UPDATE_INVALID_TIME: "#0105", + ERROR_UPDATE_NET_AUTHENTICATION: "#0106", + ERROR_NOT_GROUPS_CONFIG: "#0107", + ERROR_NOT_INIT_PACKAGESINFIO: "#0108", + ERROR_SOFTWARE_INDEX_RROKEN: "#0109", + ERROR_READ_IMPORTANTLIST_FAILED: "#0110", + ERROR_NOT_CONFIGPKG_DEPENDENCIES: "#0111", + ERROR_NOT_SELFPKG_DEPENDENCIES: "#0112", + ERROR_LOAD_CONFIG_FAILED: "#0113", + ERROR_NOT_FIX_SYSTEM: "#0114", + ERROR_REPO_DOWNLOAD_FAILED: "#0115", + + #install + ERROR_RESOLVER_FAILED: "#0200", + ERROR_NOT_UPGRADE_PACKAGES: "#0201", + ERROR_REMOVE_ESSENTIAL_PACKAGES: "#0202", + ERROR_RUN_SCRIPTS_FAILED: "#0203", + ERROR_NOT_DISK_SPACE: "#0204", + ERROR_READ_LOCAL_DEB: "#0205", + ERROR_LOCAL_DEB_FORMAT: "#0206", + ERROR_INSTALL_DEB_BASE: "#0207" + } + + #UPGRADE MONITOR STATUS MONIT_DETECT = "step-updatedetect" MONIT_DEPRESOLUT = "step-depresolution" @@ -130,6 +178,13 @@ CALLER = { 'kylin-software-center':"Kylin Software Center", } +PolicyKit_Authority_Action = { + 'kylin-installer':"cn.kylin.installer.action", + 'kylin-uninstaller':"cn.kylin.uninstaller.action", + 'kylin-software-center':"cn.kylin.software.center.action", + 'kylin-system-updater':"cn.kylinos.KylinSystemUpdater.action", +} + def get_error_description_from_enum(enum): """Get a long description of an error. @@ -141,6 +196,16 @@ def get_error_description_from_enum(enum): except KeyError: return None +def get_error_code_from_enum(enum): + """Get a long description of an error. + + :param enum: The transaction error enum, e.g. :data:`ERROR_NO_LOCK`. + :returns: The description string. + """ + try: + return _CODE_ERROR[enum] + except KeyError: + return enum def get_error_string_from_enum(enum): """Get a short description of an error. @@ -166,4 +231,10 @@ def get_caller_from_enum(enum): except KeyError: return _("Kylin System Updater") +def get_policykit_authority_action_enum(enum): + try: + return PolicyKit_Authority_Action[enum] + except KeyError: + return "cn.kylinos.KylinSystemUpdater.action" #默认配置 + # vim:ts=4:sw=4:et diff --git a/backend/SystemUpdater/Core/utils.py b/backend/SystemUpdater/Core/utils.py index 2717de1..6069635 100644 --- a/backend/SystemUpdater/Core/utils.py +++ b/backend/SystemUpdater/Core/utils.py @@ -57,6 +57,7 @@ import psutil import ctypes from ctypes import * import struct +from SystemUpdater.Core.enums import get_policykit_authority_action_enum # 禁止关机锁文件路径 VERIFY_SO = "libkylin_signtool.so" @@ -731,18 +732,6 @@ def deb_verify(deb_path, _isinstall = False): _deb_path = str(deb_path) try: # # 加载验证签名库 , 验签接口暂时无法调用 - # args = ["dpkg-architecture", "-qDEB_TARGET_MULTIARCH"] - # ret = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True) - # verifyso_path = os.path.join("/usr/lib/",str(ret.stdout).strip(),VERIFY_SO) - # logging.info("Load verify interface:%s.",verifyso_path) - # verifyso = ctypes.CDLL(verifyso_path) - # #环境初始化 - # ret = verifyso.SOF_Initialize(ctx_obj) - # if (ret) : - # logging.info("SOF_InitializeEx error!") - # return 2 - # if os.path.isfile(_deb_path): - # ret = verifyso.BJCA_dodebverify(None, bytes(_deb_path, encoding='utf8'), _isinstall) if not os.path.isfile("/usr/bin/kylinsigntool"): logging.error("SOF_InitializeEx error!") return 1 @@ -750,42 +739,46 @@ def deb_verify(deb_path, _isinstall = False): ret = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True) if "Signature Verified failed" in str(ret.stdout).strip() or "签名验证失败" in str(ret.stdout).strip(): logging.info("Signature Verified failed!") - return 2 elif "Signature Verified Ok" in str(ret.stdout).strip() or "签名验证成功" in str(ret.stdout).strip(): logging.info("Signature Verified Ok!") return 0 + else: + logging.error("Signature Verified failed:%s.",ret) + return 2 except Exception as e: logging.error(e) return 3 -def PolicyKit_Authority(details = '', sender = None): +def PolicyKit_Authority(details = '', sender = None, InstPolicy = False, source=''): _allow_kylinsign = False _verify_kylinsign = False try: - #获取未知来源应用安装策略Unknown sources apply installation policies - inst_policies_path = "/etc/dpkg/dpkg.cfg" - if os.path.isfile(inst_policies_path): - with open(inst_policies_path, "r") as f: - lines = f.readlines() - for line in lines: - if "allow-kylinsign" in line: - _allow_kylinsign = True - if "verify-kylinsign" in line: - _verify_kylinsign = True - if _allow_kylinsign == True and _verify_kylinsign == False: #策略: 阻止 - logging.debug("unknown sources apply installation policies: deter") - return False,_("The package is unsigned, refuses to install.") - elif _allow_kylinsign == True and _verify_kylinsign == True: #策略: 警告 - logging.debug("unknown sources apply installation policies: warning") - elif _allow_kylinsign == False and _verify_kylinsign == False: #策略: 关闭 - logging.debug("unknown sources apply installation policies: close") - else: - logging.warning("Unknown sources apply installation policies get failed.") - + if InstPolicy: + #获取未知来源应用安装策略Unknown sources apply installation policies + inst_policies_path = "/etc/dpkg/dpkg.cfg" + if os.path.isfile(inst_policies_path): + with open(inst_policies_path, "r") as f: + lines = f.readlines() + for line in lines: + if "allow-kylinsign" in line: + _allow_kylinsign = True + if "verify-kylinsign" in line: + _verify_kylinsign = True + if _allow_kylinsign == True and _verify_kylinsign == False: #策略: 阻止 + logging.debug("unknown sources apply installation policies: deter") + return False,_("The package is unsigned, refuses to install.") + elif _allow_kylinsign == True and _verify_kylinsign == True: #策略: 警告 + logging.debug("unknown sources apply installation policies: warning") + elif _allow_kylinsign == False and _verify_kylinsign == False: #策略: 关闭 + logging.debug("unknown sources apply installation policies: close") + else: + logging.warning("Unknown sources apply installation policies get failed.") + #用户鉴权 + logging.debug("Authentication via PolicyKit .") details = {'polkit.message':details} cancel_id = '' - action = "cn.kylinos.KylinSystemUpdater.action" + action = get_policykit_authority_action_enum(source) kit = dbus.SystemBus().get_object('org.freedesktop.PolicyKit1', '/org/freedesktop/PolicyKit1/Authority') kit = dbus.Interface(kit, 'org.freedesktop.PolicyKit1.Authority') (granted, notused , details) = kit.CheckAuthorization( @@ -800,7 +793,7 @@ def PolicyKit_Authority(details = '', sender = None): except Exception as e: logging.error(e) return False,str(e) - + if __name__ == "__main__": #print(mirror_from_sources_list()) #print(on_battery()) diff --git a/backend/SystemUpdater/UpdateManager.py b/backend/SystemUpdater/UpdateManager.py index 35987db..30e9bc2 100644 --- a/backend/SystemUpdater/UpdateManager.py +++ b/backend/SystemUpdater/UpdateManager.py @@ -22,12 +22,15 @@ from .Core.enums import * from .Core.MyCache import MyCache from .UpdateManagerDbus import UpdateManagerDbusController,UpdateManagerDbusControllerUtils,UPDATER_DBUS_INTERFACE,UPDATER_DBUS_PATH,UPDATER_DBUS_SERVICE from .Core.UpdateList import UpdateList +from .Core.PluginManager import * from .backend import InstallBackend,get_backend from .Core.Database import Sqlite3Server from .Core.loop import mainloop from .Core.DataAcquisition import UpdateMsgCollector +from SystemUpdater.Core.LocalUpgradeData import LocalUpgradeDataList from SystemUpdater.Core.UpdaterConfigParser import UpgradeConfig +from SystemUpdater.Core.JsonConfigParser import JsonConfig as json_config from SystemUpdater.Core.utils import kill_process from SystemUpdater.Core.DpkgInstallProgress import LogInstallProgress from SystemUpdater.Core.utils import deb_verify,PolicyKit_Authority,get_proc_from_dbus_name,whether_to_quit_uu,get_dist @@ -61,52 +64,18 @@ class UpdateManager(): self.collector = UpdateMsgCollector(self) #连接数据库 self.sqlite3_server = Sqlite3Server(self) + self.pm_class = pluginManagerClass() self.simulate_mode = SimulateTerminal() self.install_mode = UpdateInstallMode(self) self.apt_p2p_config = AptP2pConfigManager() - self._reload_options_config() + self.main_meta = LocalUpgradeDataList() + json_config() self._refresh_cache_only() except Exception as e: logging.error(e) traceback.print_exc() - def _reload_options_config(self): - #添加默认保留旧配置 - apt_pkg.config["DPkg::Options::"] = "--force-confold" - options_new = list(set(apt_pkg.config.value_list("DPkg::Options"))) - for option in ("--force-confnew","--force-confdef"): - if option in options_new: - options_new.remove(option) - #清除所有配置重新加载 - apt_pkg.config.clear("DPkg::Options") - for option in options_new: - apt_pkg.config["DPkg::Options::"] = option - #去除安装推荐和建议的软件包 - if apt_pkg.config.find_b("APT::Install-Recommends",False) == True: - apt_pkg.config.clear("APT::Install-Recommends") - if apt_pkg.config.find_b("APT::Install-Suggests",False) == True: - apt_pkg.config.clear("APT::Install-Suggests") - - def check_frontend_pkg(self): - #控制面板前端包的检查升级 - if self.FRONTEND_PKG_NAME in self.cache: - self_pkg = self.cache[self.FRONTEND_PKG_NAME] - - if not self_pkg.is_installed: - logging.info("Check: Frontend(%s) start new installing...",self.FRONTEND_PKG_NAME) - self_pkg.mark_install() - self.start_install(InstallBackend.MODE_INSTALL_SINGLE,True) - else: - #没有在cache中就认为不需要升级 - logging.error("Check: Frontend(%s) The upgrade package is not in Cache...",self.FRONTEND_PKG_NAME) - - #检查是否需要重新启动aptdeamon 目前需要重启的有限速功能 - def check_conifg_aptdeamon(self): - if self.init_config_aptdeamon == True: - self.init_config_aptdeamon = False - self.dbusController.set_aptdeamon_environ("init","config") - def run(self): """Start the daemon and listen for calls.""" logging.info("Waiting for calls...") @@ -131,30 +100,39 @@ class UpdateManager(): fix_backend.start() #进行升级的操作 - def start_install(self,upgrade_mode,not_resolver = False,upgrade_content = []): + def start_install(self,upgrade_mode = InstallBackend.MODE_DEFAULT_STATUS,not_resolver = False,push_content = []): try: if self.install_mode.shutdown_mode() == True and upgrade_mode != InstallBackend.MODE_INSTALL_SINGLE: + #部分升级的方式 计算的时候 补上上次更新的内容一起计算 if upgrade_mode == InstallBackend.MODE_INSTALL_PARTIAL: - upgrade_content += self.install_mode.tmp_content + push_content += self.install_mode.tmp_content if not_resolver == True: - kill_process(self.RUN_UNATTENDED_UPGRADE) - #未下载的阶段 + # if whether_to_quit_uu(): + # kill_process(self.RUN_UNATTENDED_UPGRADE) + + self.check_config_aptdeamon() install_backend = get_backend(self, InstallBackend.ACTION_DOWNLOADONLY,upgrade_mode) - install_backend.start(upgrade_content) + install_backend.start(push_content) else: resolver_backend = get_backend(self, InstallBackend.ACTION_CHECK_RESOLVER,upgrade_mode) - resolver_backend.start(upgrade_content) + resolver_backend.start_resolver(push_content) else: + if self.main_meta.is_steps(push_content) == True and \ + upgrade_mode != InstallBackend.MODE_INSTALL_SYSTEM: + upgrade_mode = InstallBackend.MODE_INSTALL_STEP + if not_resolver == True: - if whether_to_quit_uu(): - kill_process(self.RUN_UNATTENDED_UPGRADE) + # if whether_to_quit_uu(): + # kill_process(self.RUN_UNATTENDED_UPGRADE) + + self.check_config_aptdeamon() install_backend = get_backend(self, InstallBackend.ACTION_INSTALL,upgrade_mode) - install_backend.start(upgrade_content) + install_backend.start(push_content) else: resolver_backend = get_backend(self, InstallBackend.ACTION_CHECK_RESOLVER,upgrade_mode) - resolver_backend.start(upgrade_content) + resolver_backend.start_resolver(push_content) except Exception as e: logging.error(e) @@ -162,12 +140,8 @@ class UpdateManager(): def start_update(self,update_mode = InstallBackend.MODE_UPDATE_ALL): try: #更新前的准备 - self.configs_cover.reReadConfigFiles() - self.retry_limit = self.RETRY_LIMIT_NUM + # self.install_mode.reset_shutdown_mode() - self.install_mode.reset_shutdown_mode() - - #检查 光盘源 self.install_mode.check_source() if self.install_mode.check_network() == True: @@ -185,12 +159,16 @@ class UpdateManager(): self.start_update_backend(update_mode = update_mode) except UpdateBaseError as excep: + self.dbusController.InstallDetectStatus(False,get_error_code_from_enum(excep.code)) self.dbusController.UpdateDetectFinished(False,[''],excep.header,excep.desc) except UpdateProgressExit: pass except Exception as e: logging.error(e) traceback.print_exc() + self.dbusController.InstallDetectStatus(False,get_error_code_from_enum(ERROR_PROGRAM_EXCEPTION)) + self.dbusController.UpdateDetectFinished(False,[''],get_error_string_from_enum(ERROR_PROGRAM_EXCEPTION),\ + get_error_description_from_enum(ERROR_PROGRAM_EXCEPTION)) def start_update_backend(self,update_mode = InstallBackend.MODE_UPDATE_ALL): #调用aptdeamon进行update @@ -199,39 +177,47 @@ class UpdateManager(): def start_available(self): try: + self.configs_cover.reRead() + + self.retry_limit = self.RETRY_LIMIT_NUM + + json_config().read() + self.refresh_cache() + self.main_meta.refresh() + self.update_list = UpdateList(self) - #1、 检查出现安装过程异常重启 出现的话 进行异常修复 if self.configs_uncover.getWithDefault("SystemStatus", "abnormal_reboot", False) == True: self.configs_uncover.setValue("SystemStatus","abnormal_reboot",str(False),True) logging.warning("start fix Abnormal Reboot broken pkgs...") self.start_fix_broken() return - #检查当前系统的状态 是否存在系统为破损状态 导致出现异常 self._check_system_broken(self.cache) + + self._check_config_upgrade(self.cache) - #检查优先自我升级 self._check_self_upgrade(self.cache) self.update_list.update_kylin(self.cache,self.install_mode.get_important_data(),self.install_mode.is_openkylin_desktop()) - if self.cache != None and self.cache.get_changes(): - self.cache.clear() + self.dbusController.UpdateDetectFinished(True,self.main_meta.get_push(),'','') except UpdateBaseError as excep: + self.dbusController.InstallDetectStatus(False,get_error_code_from_enum(excep.code)) self.dbusController.UpdateDetectFinished(False,[''],excep.header,excep.desc) except UpdateProgressExit as excep: pass except Exception as e: logging.error(e) traceback.print_exc() + self.dbusController.UpdateDetectFinished(False,[''],get_error_string_from_enum(ERROR_PROGRAM_EXCEPTION),\ + get_error_description_from_enum(ERROR_PROGRAM_EXCEPTION)) def refresh_cache(self): try: - #第一次进入 之后update不进入 if self.cache is None: self.cache = MyCache(None) else: @@ -245,45 +231,18 @@ class UpdateManager(): raise UpdateBaseError(ERROR_NOT_INIT_PACKAGESINFIO) def _refresh_cache_only(self): - #第一次进入 之后update不进入 + self._reload_options_config() + if self.cache is None: self.cache = MyCache(None) else: self.cache.open(None) self.cache._initDepCache() - def _check_self_upgrade(self,cache): + def _check_config_upgrade(self,cache): need_upgrade = False self_upgrade = [] - important_list = self.install_mode.get_important_data() - for pkg_name in [self.BACKEND_PKG_NAME,self.APTD_PKG_NAME,self.FRONTEND_PKG_NAME]: - if pkg_name in cache: - self_pkg = cache[pkg_name] - if self_pkg.is_installed: - if self_pkg.is_upgradable: - logging.info("Check: (%s) will upgrading From %s to %s...",pkg_name,\ - self_pkg.installed.source_version,self_pkg.candidate.source_version) - if pkg_name in important_list: - try: - logging.info("Check: (%s) start upgrading From %s to %s...",pkg_name,\ - self_pkg.installed.source_version,self_pkg.candidate.source_version) - self_pkg.mark_install(True,False,True) - self_upgrade.append(pkg_name) - need_upgrade = True - except SystemError: - self.simulate_mode.thread_install([pkg_name]) - logging.error("Check: mark %s to upgrade Failed...",pkg_name) - raise UpdateBaseError(ERROR_NOT_SELFPKG_DEPENDENCIES) - else: - logging.info("Check: (%s:%s) No need to upgrade and duo to not pust...",pkg_name,self_pkg.installed.source_version) - else: - logging.info("Check: (%s:%s) No need to upgrade...",pkg_name,self_pkg.installed.source_version) - else: - logging.info("Check: (%s) Not to be installed...",pkg_name) - else: - logging.error("Check: (%s) The upgrade package is not in Cache...",pkg_name) - #config包 for pkg_name in [self.GROUPS_PKG_NAME]: if pkg_name in cache: @@ -318,16 +277,54 @@ class UpdateManager(): if need_upgrade == True: self.dbusController.UpdateDetectStatusChanged(95,_("Priority Upgrade Package being updated")) - self.start_install(InstallBackend.MODE_INSTALL_SINGLE,True,upgrade_content=self_upgrade) + self.start_install(InstallBackend.MODE_INSTALL_SINGLE,True,push_content=self_upgrade) + raise UpdateProgressExit() + + def _check_self_upgrade(self,cache): + need_upgrade = False + self_upgrade = [] + + channel_config = json_config().getWithDefault("update_channel_upgrade",default = None) + if channel_config == None: + logging.warning("Json: update_channel_upgrade item is None...") + upgrade_list = [self.BACKEND_PKG_NAME,self.APTD_PKG_NAME,self.FRONTEND_PKG_NAME] + else: + upgrade_list = channel_config.get("upgrade_list",[self.BACKEND_PKG_NAME,self.APTD_PKG_NAME,self.FRONTEND_PKG_NAME]) + + for pkg_name in upgrade_list: + if pkg_name in cache: + self_pkg = cache[pkg_name] + if self_pkg.is_installed: + if self_pkg.is_upgradable: + logging.info("Check: (%s) will upgrading From %s to %s...",pkg_name,\ + self_pkg.installed.source_version,self_pkg.candidate.source_version) + try: + logging.info("Check: (%s) start upgrading From %s to %s...",pkg_name,\ + self_pkg.installed.source_version,self_pkg.candidate.source_version) + self_pkg.mark_install(True,False,True) + self_upgrade.append(pkg_name) + need_upgrade = True + except SystemError: + self.simulate_mode.thread_install([pkg_name]) + logging.error("Check: mark %s to upgrade Failed...",pkg_name) + raise UpdateBaseError(ERROR_NOT_SELFPKG_DEPENDENCIES) + else: + logging.info("Check: (%s:%s) No need to upgrade...",pkg_name,self_pkg.installed.source_version) + else: + logging.info("Check: (%s) Not to be installed...",pkg_name) + else: + logging.error("Check: (%s) The upgrade package is not in Cache...",pkg_name) + + if need_upgrade == True: + self.dbusController.UpdateDetectStatusChanged(95,_("Priority Upgrade Package being updated")) + self.start_install(InstallBackend.MODE_INSTALL_SINGLE,True,push_content=self_upgrade) raise UpdateProgressExit() def _check_system_broken(self,cache): if cache.get_changes(): cache.clear() - #获取出现破损状态包的数量 if cache._depcache.broken_count or cache._depcache.del_count > 0 or \ cache._depcache.inst_count > 0: - #线程获取详细的卸载软件包情况 self.simulate_mode.start_caculate(["apt-get", "install","-f","--simulate"],thread=True) else: logging.info("Check: System Apt Cache for Broken Successfully...") @@ -423,7 +420,14 @@ class UpdateManager(): def start_back_upgrade(self, pkglist): try: install_backend = get_backend(self, InstallBackend.ACTION_BACKGROUND_UPGRADE) - install_backend.start_alone(partial_upgrade_list = pkglist) + install_backend.start_alone(push_content = pkglist) + except Exception as e: + logging.error(str(e)) + + def start_deb_resolver(self, pkglist = []): + try: + install_backend = get_backend(self, InstallBackend.ACTION_INSTALL_DEB_RESOLVER) + install_backend.start_alone(push_content = pkglist) except Exception as e: logging.error(str(e)) @@ -434,6 +438,10 @@ class UpdateManager(): header = '' desc = '' absolute_path, debname = os.path.split(deb_path) + self.sqlite3_server.deb_metadata.update({"current_install_debfile":deb_path}) + self.sqlite3_server.deb_metadata.update({"absolute_path":absolute_path}) + self.sqlite3_server.deb_metadata.update({"source":source}) + self.deb_obj = {} UpdateMsg = {} try: @@ -445,10 +453,9 @@ class UpdateManager(): sender_name = get_proc_from_dbus_name(sender) caller = get_caller_from_enum(sender_name) caller_trans = get_source_name_from_enum(sender_name) - if source == "kylin-software-center": - logging.info("caller : %s.",source) - else: - (status,error_string) = PolicyKit_Authority(caller_trans+_(" requires authentication to install software packages."),sender) + if deb_verify(deb_path) != 0: #验签失败,提权 + (status,error_string) = PolicyKit_Authority(caller_trans+_(" requires authentication to install software packages."), + sender,InstPolicy=True,source=source) if not status: self.dbusController.InstalldebFinished(False,error_string,'') return @@ -458,6 +465,8 @@ class UpdateManager(): UpdateMsg.update({"source":str(self.deb_obj.get("source","kylin-system-updater"))}) deb_cache, ins, _isinstall = self._suit_install_mode(deb_path) UpdateMsg.update({"appname":str(self.debName)}) + self.sqlite3_server.deb_metadata.update({"debname":str(self.debName)}) + self.sqlite3_server.deb_metadata['deblist'].append(str(self.debName)) UpdateMsg.update({"new_version":str(self.debVersion)}) if self._is_broken > 0 or not self.cacheSatisfy or self._need_downgrade: # 走 dpkg 安装流程,说明本地apt环境已经损坏,or dep not satisfied or need downgrade @@ -480,7 +489,8 @@ class UpdateManager(): dep_satisfy, header, desc = self._attempt_depends(deb_cache, deb_path, _check_local_dep,_auto_satisfy, ins) if dep_satisfy: install_backend = get_backend(self, InstallBackend.ACTION_INSTALL_DEB) - install_backend.start_alone(partial_upgrade_list = deb_path, _is_install = _auto_satisfy, caller=caller_trans) + logging.info("source name: %s.", source) + install_backend.start_alone(push_content=deb_path,_is_install=_auto_satisfy,caller=source) else: self.dbusController.InstalldebFinished(False, header, desc) except UpdateBaseError as excep: @@ -508,12 +518,14 @@ class UpdateManager(): _success,header,desc = self._dpkg_purge_pkgs(pkgs_list) if _success == True: logging.info(header) + # self.dbusController.PurgePackagesFinished(_success,'',desc," ".join(pkgs_list)) self.dbusController.PurgePackagesFinished(_success,'',desc) else: + # self.dbusController.PurgePackagesFinished(_success,header,desc," ".join(pkgs_list)) self.dbusController.PurgePackagesFinished(_success,header,desc) else: purge_backend = get_backend(self, InstallBackend.ACTION_REMOVE_PACKAGES) - purge_backend.start(partial_upgrade_list = pkgs_list) + purge_backend.start(push_content = pkgs_list) deb_cache.close() except Exception as e: @@ -530,6 +542,26 @@ class UpdateManager(): success = p.returncode == 0 return success,p.stdout,'' + def _reload_options_config(self): + apt_pkg.config["DPkg::Options::"] = "--force-confold" + options_new = list(set(apt_pkg.config.value_list("DPkg::Options"))) + for option in ("--force-confnew","--force-confdef"): + if option in options_new: + options_new.remove(option) + apt_pkg.config.clear("DPkg::Options") + for option in options_new: + apt_pkg.config["DPkg::Options::"] = option + if apt_pkg.config.find_b("APT::Install-Recommends",False) == True: + apt_pkg.config.clear("APT::Install-Recommends") + if apt_pkg.config.find_b("APT::Install-Suggests",False) == True: + apt_pkg.config.clear("APT::Install-Suggests") + + def check_config_aptdeamon(self): + #检查是否需要重新启动aptdeamon 目前需要重启的有限速功能 + if self.init_config_aptdeamon == True: + self.init_config_aptdeamon = False + self.dbusController.set_aptdeamon_environ("init","config") + # 是否查找本地依赖 def _attempt_depends(self,deb_cache, deb_path,_check_local_dep,_auto_satisfy, _install): depends_list = [] @@ -637,11 +669,9 @@ class UpdateManager(): satisfy_list.append(debfile) for depends in noSatisfyList: for debfile in depends_list: - if "_" not in debfile and len(debfile.split['_'])!=3: - break if "%3a" in debfile: debfile=debfile.replace("%3a",":") - if depends == debfile.split('_')[0]and debfile not in satisfy_list: + 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) or depends_count < len(depends_pkg): @@ -687,7 +717,7 @@ class UpdateManager(): def _suit_install_mode(self, deb_path): self._is_broken = False self.cacheSatisfy = False - _is_install = False + _is_install=False absolute_path, debname = os.path.split(deb_path) # 检查本地破损 try: @@ -737,11 +767,11 @@ class UpdateManager(): else: self.cacheSatisfy = False logging.info("Cache satisfy is %r.",self.cacheSatisfy) - return deb_cache, install, _is_install + return deb_cache,install,_is_install def _gen_noSatisfyList(self, depends, deb_cache): _noSatisfyList = [] - _group_satify = False + _group_satify=False providers = [] for or_group in depends: for deb_info in or_group: @@ -950,7 +980,6 @@ class UpdateInstallMode(): def is_openkylin_desktop(self): return self.dist == self.OPENKYLIN_DISTTRIBUTOR - # return True def check_network(self): if self.parent.options.no_check_network is False and self.is_disc == False: @@ -971,14 +1000,12 @@ class UpdateInstallMode(): data = f.read() important_list = data.split() else: - important_list = [self.SYSTEM_UPDATE_GROUPS,self.parent.BACKEND_PKG_NAME,self.parent.APTD_PKG_NAME,self.parent.FRONTEND_PKG_NAME] - return important_list + important_list = [self.SYSTEM_UPDATE_GROUPS] + + #去除重复内容 + important_list = list(set(important_list)) - def check_filter(self): - if self.parent.options.close_filter == False and self.is_disc == False and self.is_openkylin_desktop() == False: - return True - else: - return False + return important_list def _plymouth_splash(self): if os.path.exists("/bin/plymouth"): @@ -987,6 +1014,17 @@ class UpdateInstallMode(): subprocess.Popen(["/bin/plymouth", "show-splash","--wait"]) subprocess.call(["/bin/plymouth","system-update","--progress=0"]) + def _set_inhibit_delay(self,delay_time): + try: + #首先设置systemd默认延长时间为1800 + obj = self.bus.get_object('org.freedesktop.login1', '/org/freedesktop/login1') + getter_interface = dbus.Interface( + self.logind_proxy, + dbus_interface='org.freedesktop.login1.Manager') + ret = getter_interface.SetExtraInhibitShutdownDelaySec(delay_time) + except Exception as e: + logging.error(e) + def _inhibit_sleep(self): """ Send a dbus signal to logind to not suspend the system, it will be @@ -996,11 +1034,7 @@ class UpdateInstallMode(): from gi.repository import Gio, GLib connection = Gio.bus_get_sync(Gio.BusType.SYSTEM) - #首先设置systemd默认延长时间为1800 - getter_interface = dbus.Interface( - self.logind_proxy, - dbus_interface='org.freedesktop.login1.Manager') - ret = getter_interface.SetInhibitDelayMaxSec(1800) + self._set_inhibit_delay(1800) var, fdlist = connection.call_with_unix_fd_list_sync( 'org.freedesktop.login1', '/org/freedesktop/login1', @@ -1011,11 +1045,10 @@ class UpdateInstallMode(): 'delay')), None, 0, -1, None, None) inhibitor = Gio.UnixInputStream(fd=fdlist.steal_fds()[var[0]]) - return inhibitor except Exception as e: logging.error(e) - return False + return None def _prompt_in_boot(self): #关机安装完成之后开机时进行提醒 diff --git a/backend/SystemUpdater/UpdateManagerDbus.py b/backend/SystemUpdater/UpdateManagerDbus.py index beba797..d1d63be 100755 --- a/backend/SystemUpdater/UpdateManagerDbus.py +++ b/backend/SystemUpdater/UpdateManagerDbus.py @@ -75,6 +75,7 @@ class UpdateManagerDbusController(dbus.service.Object): def _update_important_reply(self,retval): if bool(retval) == False: + self.InstallDetectStatus(False,enums.get_error_code_from_enum(enums.ERROR_UPDATE_SOURCE_FAILED)) self.UpdateDetectFinished(False,[''],enums.get_error_string_from_enum(enums.ERROR_UPDATE_SOURCE_FAILED),\ enums.get_error_description_from_enum(enums.ERROR_UPDATE_SOURCE_FAILED)) else: @@ -82,8 +83,9 @@ class UpdateManagerDbusController(dbus.service.Object): def _update_important_error(self,retval): logging.error(str(retval)) - self.UpdateDetectFinished(False,[''],enums.get_error_string_from_enum(enums.ERROR_UPDATE_SOURCE_FAILED),\ - enums.get_error_description_from_enum(enums.ERROR_UPDATE_SOURCE_FAILED)) + self.InstallDetectStatus(False,enums.get_error_code_from_enum(enums.ERROR_UPDATE_SOURCE_TIMEOUT)) + self.UpdateDetectFinished(False,[''],enums.get_error_string_from_enum(enums.ERROR_UPDATE_SOURCE_TIMEOUT),\ + enums.get_error_description_from_enum(enums.ERROR_UPDATE_SOURCE_TIMEOUT)) #更新important.list的本次升级的列表 def on_update_important_list(self): @@ -108,7 +110,7 @@ class UpdateManagerDbusController(dbus.service.Object): obj = self.bus.get_object('org.debian.apt', '/org/debian/apt') interface = dbus.Interface(obj, dbus_interface='org.debian.apt') logging.info("Now start to restart Aptdeamon...") - interface.Quit() + interface.Quit(timeout=0.5) except Exception as e: logging.error(str(e)) @@ -131,14 +133,30 @@ class UpdateManagerDbusController(dbus.service.Object): try: self.UpdateDetectStatusChanged(5,_("Checking network connection")) obj = self.bus.get_object("org.freedesktop.NetworkManager","/org/freedesktop/NetworkManager") - interface = dbus.Interface(obj, "org.freedesktop.NetworkManager") - retval = interface.CheckConnectivity(timeout=0.5) + interface = dbus.Interface(obj, "org.freedesktop.DBus.Properties") + retval = interface.Get("org.freedesktop.NetworkManager","Connectivity",timeout=0.5) except Exception: retval = 4 #1 表示没有网卡可以使用 if retval == 1: raise UpdateBaseError(enums.ERROR_NETWORK_FAILED) + def check_connectivity_pro(self): + try: + obj = self.bus.get_object("org.freedesktop.NetworkManager","/org/freedesktop/NetworkManager") + interface = dbus.Interface(obj, "org.freedesktop.NetworkManager") + retval = interface.CheckConnectivity(timeout=15) + except Exception as e: + logging.error("Network status is Exception:" + str(e)) + return False + + if retval == 4: + logging.info("Network status is Success...") + return True + else: + logging.info("Network status(%d) is Exception...",retval) + return False + def _check_prohibit_user(self, sender_name): prohibit_list = ["dbus-send","gdbus"] if sender_name in prohibit_list: @@ -191,15 +209,15 @@ class UpdateManagerDbusController(dbus.service.Object): try: if self.parent.configs_cover.has_section(str(section)) and self.parent.configs_cover.has_option(str(section),str(option)): value = str(self.parent.configs_cover.get(str(section), str(option))) - logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+" GetConfigValue section:%s option:%s value:%s ...",section,option,value) + # logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+" GetConfigValue section:%s option:%s value:%s ...",section,option,value) return True,value if self.parent.configs_uncover.has_section(str(section)) and self.parent.configs_uncover.has_option(str(section),str(option)): value = str(self.parent.configs_uncover.get(str(section), str(option))) - logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+" GetConfigValue section:%s option:%s value:%s ...",section,option,value) + # logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+" GetConfigValue section:%s option:%s value:%s ...",section,option,value) return True,value elif self.parent.sqlite3_server.ucconfigs.has_section(str(section)) and self.parent.sqlite3_server.ucconfigs.has_option(str(section),str(option)): value = str(self.parent.sqlite3_server.ucconfigs.get(str(section), str(option))) - logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+" GetConfigValue section:%s option:%s value:%s ...",section,option,value) + # logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+" GetConfigValue section:%s option:%s value:%s ...",section,option,value) return True,value else: logging.warning("Warning: Can't found section:%s option:%s ... ",section, option) @@ -321,16 +339,11 @@ class UpdateManagerDbusController(dbus.service.Object): partial_upgrade_list = [str(i) for i in _partial_upgrade_list] logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' DistUpgradePartial sender:%s and not_resolver:%r, partial_upgrade_list:%s. ',sender_name,not_resolver,",".join(partial_upgrade_list)) self._check_prohibit_user(sender_name) - local_upgrade_groups = self.parent.update_list.upgrade_meta.upgrade_groups - local_single_pkgs = self.parent.update_list.upgrade_meta.single_pkgs - - new_upgrade_list = list(set(partial_upgrade_list) & set(local_upgrade_groups + local_single_pkgs)) - - if new_upgrade_list: + + if partial_upgrade_list: self.parent.start_install(InstallBackend.MODE_INSTALL_PARTIAL,not_resolver,partial_upgrade_list) return self.RETURN_SUCCESS_CODE,self.RETURN_SUCCESS_DESC else: - logging.warning('input upgrade list(%s) not in local upgrade_list(%s)',partial_upgrade_list,local_upgrade_groups+local_single_pkgs) return self.RETURN_BUSY_STATE,self.RETURN_BUSY_DESC except Exception as e: logging.info(str(e)) @@ -407,25 +420,28 @@ class UpdateManagerDbusController(dbus.service.Object): purge_list = [str(pkg) for pkg in _purge_list] sender_name = get_proc_from_dbus_name(sender) logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' DistPurgePackages Sender:%s and purge list is:%s...',sender_name, purge_list) - (status, details) = PolicyKit_Authority(get_source_name_from_enum(sender_name)+_(" requires authentication to uninstall software packages."), sender) + (status, details) = PolicyKit_Authority(get_source_name_from_enum(sender_name)+_(" requires authentication to uninstall software packages."), + sender,source=sender_name) if not status: self.PurgePackagesFinished(False,details,'') return self.RETURN_UNKNOWN_CODE,details #目前只有360使用这个环境变量 当其他包也使用时 可以将这个权限放开 - if "360epp" in purge_list: + if True: #需要对aptdeamon加这两个环境变量 才可以提示弹窗 self.set_aptdeamon_environ("XAUTHORITY","/home/"+str(cur_user)+"/.Xauthority") self.set_aptdeamon_environ("DISPLAY",":0") # 处于更新和升级中的话 不进行升级 if self.parent.now_working != InstallBackend.ACTION_DEFUALT_STATUS: + # self.PurgePackagesFinished(False,_("Other tasks are being updated and upgraded, please uninstall them later."),''," ".join(purge_list)) self.PurgePackagesFinished(False,_("Other tasks are being updated and upgraded, please uninstall them later."),'') logging.warning('PurgePackages In the process of updating or Upgrading...') return self.RETURN_BUSY_STATE,self.RETURN_BUSY_DESC else: self._check_prohibit_user(sender_name) + self.parent.sqlite3_server.current_purge_pkgs = purge_list self.parent.start_purge_pkgs(purge_list) return self.RETURN_SUCCESS_CODE,self.RETURN_SUCCESS_DESC except Exception as e: @@ -840,6 +856,16 @@ class UpdateManagerDbusController(dbus.service.Object): logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" UpdateInstallFinished success = %r , upgrade_group = %a, error_string = %s , error_desc = %s ",\ success,upgrade_group, error_string,error_desc) + #分步更新安装完成后的弹窗 + @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='bs') + def PopupStepsInstalled(self, need_reboot,details_desc=''): + logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" PopupStepsInstalled success = %r ,details_desc = %s ",need_reboot,details_desc) + + #分步更新安装中的提示 + @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='bs') + def NotifyStepsInstalled(self, reservations,details_desc=''): + logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" NotifyStepsInstalled reservations = %r ,details_desc = %s ",reservations,details_desc) + #升级完成的信号 @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='basss') def UpdateDownloadFinished(self, success, upgrade_group,error_string='',error_desc=''): diff --git a/backend/SystemUpdater/UpgradeStrategies.py b/backend/SystemUpdater/UpgradeStrategies.py index 78902f9..18ae58b 100644 --- a/backend/SystemUpdater/UpgradeStrategies.py +++ b/backend/SystemUpdater/UpgradeStrategies.py @@ -28,7 +28,7 @@ class UpgradeStrategies(): self.dbusController = self._setup_dbus() #config self.uuconfigs = UpgradeConfig(datadir = "/var/lib/unattended-upgrades/", name = "unattended-upgrades-policy.conf") - self.sqlite3_server = Sqlite3Server(self) + self.sqlite3_server = Sqlite3Server(self, _no_DataMigration=True) #策略配置接口的超时退出机制 self.strategy_timestamp = 0 GLib.timeout_add_seconds(STRATEGY_IDLE_INTERVAL, diff --git a/backend/SystemUpdater/UpgradeStrategiesDbus.py b/backend/SystemUpdater/UpgradeStrategiesDbus.py index dec8a97..cc89358 100644 --- a/backend/SystemUpdater/UpgradeStrategiesDbus.py +++ b/backend/SystemUpdater/UpgradeStrategiesDbus.py @@ -148,9 +148,9 @@ class UpgradeStrategiesDbusController(dbus.service.Object): logging.info("Apt-p2p service has been disabled and not need to redisabled...") return self.RETURN_SUCCESS_CODE,self.RETURN_SUCCESS_DESC else: - logging.waring("error: input value _status=%s",status) + logging.warning("error: input value _status=%s",status) else: - logging.waring("apt-p2p function is not install...") + logging.warning("apt-p2p function is not install...") ## dbus接口: 开启或关闭预下载功能 @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='bs', out_signature='b',sender_keyword='sender') @@ -360,16 +360,16 @@ class UpgradeStrategiesDbusController(dbus.service.Object): return False,str(e) return True,"success" - # 设置自动更新时间 - @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='s', out_signature='bs',sender_keyword='sender') - def SetAutoUpgradePeriod(self, period, sender = None): - sender_name = get_proc_from_dbus_name(sender) - logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' SetAutoUpgradePeriod will be set value %s, SetAutoUpgradePeriod sender: %s.'%(period, sender_name)) - try: - self.parent.sqlite3_server.insert_into_display("update_period", period.lower()) - except Exception as e: - logging.error(str(e)) - return True,"success" + # # 设置自动更新时间 + # @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='s', out_signature='bs',sender_keyword='sender') + # def SetAutoUpgradePeriod(self, period, sender = None): + # sender_name = get_proc_from_dbus_name(sender) + # logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' SetAutoUpgradePeriod will be set value %s, SetAutoUpgradePeriod sender: %s.'%(period, sender_name)) + # try: + # self.parent.sqlite3_server.insert_into_display("update_period", period.lower()) + # except Exception as e: + # logging.error(str(e)) + # return True,"success" # 获取数据库值 @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='bss', out_signature='s') diff --git a/backend/SystemUpdater/backend/InstallBackendAptdaemon.py b/backend/SystemUpdater/backend/InstallBackendAptdaemon.py index 9fbe894..a20bd7c 100644 --- a/backend/SystemUpdater/backend/InstallBackendAptdaemon.py +++ b/backend/SystemUpdater/backend/InstallBackendAptdaemon.py @@ -45,11 +45,16 @@ class InstallBackendAptdaemon(InstallBackend): #客户端连接aptdeamon的dbus接口 self.client = client.AptClient() self.trans_failed_msg = None + + self.steps_progress_begin = 0 + self.steps_progress_end = 0 + + self.need_retry = False #是否在安装状态 判断依据进度>50 - self.on_install_stage = False + self.on_installing = False if self.action == self.ACTION_INSTALL_SHUTDOWN: - self.on_install_stage = True + self.on_installing = True if self.action == self.ACTION_UPDATE: #更新的超时检查机制 超时时取消下载 @@ -74,7 +79,7 @@ class InstallBackendAptdaemon(InstallBackend): if self.aptd_base.progress >= 90 or self.simulation_progress > 80: return False else: - self._dist_status_changed(self.action,[],self.simulation_progress,self.aptd_base.status,self.aptd_base.details) + self._dist_status_changed(self.action,self.simulation_progress,self.aptd_base.status,self.aptd_base.details) return True def _check_install_inactivity(self): @@ -83,6 +88,11 @@ class InstallBackendAptdaemon(InstallBackend): """ logging.info("Checking for inactivity in Installing Time:%d...",self.install_timestamp) + #需要重试下载的话 退出上一个定时器 + if self.need_retry == True: + logging.info("Need retry:Installing to exit and timeout check quit...") + return False + if self.window_main.now_working != self.ACTION_INSTALL and self.window_main.now_working != self.ACTION_INSTALL_SHUTDOWN: logging.info("Installing to exit and timeout check quit...") return False @@ -93,7 +103,7 @@ class InstallBackendAptdaemon(InstallBackend): self.install_timestamp = INSTALL_IDLE_TIMEOUT #只有安装的时候启用 下载时候不使用 - if (self.install_timestamp <= 0 and self.on_install_stage == True): + if (self.install_timestamp <= 0 and self.on_installing == True): logging.error("Quitting due to inactivity(%s)",self.aptd_base.details) if self.action == self.ACTION_INSTALL_SHUTDOWN: #关机安装模式 解除禁止关机锁 @@ -108,7 +118,7 @@ class InstallBackendAptdaemon(InstallBackend): error_string=_("Could not install the upgrades"), error_desc=_("Installtion timeout to exit Due to inactivity") + self.aptd_base.details) - # self.window_main.dbusController.Quit(None) + # self.dbus_send.Quit(None) return False else: self.install_timestamp = self.install_timestamp - 1 @@ -133,7 +143,7 @@ class InstallBackendAptdaemon(InstallBackend): and self.aptd_base.cancelable == True: logging.error("Quitting due to inactivity") - self.window_main.dbusController.transaction.cancel() + self.dbus_send.transaction.cancel() return False return True @@ -143,7 +153,7 @@ class InstallBackendAptdaemon(InstallBackend): """刷新包cache""" try: trans = yield self.client.update_cache(defer=True) - self.window_main.dbusController.transaction = trans + self.dbus_send.transaction = trans # 注册回调函数 接收更新的状态 yield self._show_transaction(trans, self.ACTION_UPDATE, _("Checking for updates…"), False) @@ -165,7 +175,7 @@ class InstallBackendAptdaemon(InstallBackend): trans = yield self.client.commit_packages( pkgs_install, reinstall, pkgs_remove, purge = purge, upgrade = pkgs_upgrade, downgrade = pkgs_downgrade,defer=True) - self.window_main.dbusController.transaction = trans + self.dbus_send.transaction = trans yield self._show_transaction(trans, self.action, _("Installing updates…"), True) @@ -195,7 +205,7 @@ class InstallBackendAptdaemon(InstallBackend): trans = yield self.client.commit_only( pkgs_install, reinstall, pkgs_remove, purge = purge, upgrade = pkgs_upgrade, downgrade = pkgs_downgrade,download = model, defer=True) - self.window_main.dbusController.transaction = trans + self.dbus_send.transaction = trans yield self._show_transaction(trans, self.action, _("Installing updates…"), True) @@ -217,6 +227,43 @@ class InstallBackendAptdaemon(InstallBackend): error_string='', error_desc='') raise + @inline_callbacks + def commit_steps(self,model,pkgs_install, pkgs_upgrade, pkgs_remove,begin=0,end=100,last_steps=False): + """Commit a list of package adds and removes""" + try: + reinstall = purge = downgrade = [] + trans = yield self.client.commit_only( + pkgs_install, reinstall, pkgs_remove, purge = purge, upgrade = pkgs_upgrade, + downgrade = downgrade,download = model, defer=True) + self.dbus_send.transaction = trans + + self.steps_progress_begin = begin + self.steps_progress_end = end + if last_steps == True: + yield self._show_transaction(trans, self.action, + _("Installing updates…"), True) + else: + yield self._show_transaction_steps(trans, self.action, + _("Installing updates…"), True) + + except errors.NotAuthorizedError: + self._action_done(self.action, + authorized=False, success=False, + error_string='', error_desc='') + 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": + raise + self._action_done(self.action, + authorized=False, success=False, + error_string='', error_desc='') + except Exception: + self._action_done(self.action, + is_cancelled=False, success=False, + error_string='', error_desc='') + raise + @inline_callbacks def install_deb(self,install_path,install_force): """安装deb包 """ @@ -232,7 +279,7 @@ class InstallBackendAptdaemon(InstallBackend): except Exception as e: self._action_done(self.ACTION_INSTALL_DEB, is_cancelled=False, success=False, - error_string=str(e), error_desc='') + error_string=str(e), error_desc='', error_code=e.code) # raise @inline_callbacks @@ -240,7 +287,7 @@ class InstallBackendAptdaemon(InstallBackend): """安装deb包 """ try: trans = yield self.client.fix_broken_depends(defer=True) - self.window_main.dbusController.transaction = trans + self.dbus_send.transaction = trans # 注册回调函数 接收更新的状态 yield self._show_transaction(trans, self.ACTION_FIX_BROKEN, _("Installing deb packages…"), False) @@ -259,7 +306,7 @@ class InstallBackendAptdaemon(InstallBackend): """修复未完成的安装 """ try: trans = yield self.client.fix_incomplete_install(defer=True) - self.window_main.dbusController.transaction = trans + self.dbus_send.transaction = trans # 注册回调函数 接收更新的状态 yield self._show_transaction(trans, self.ACTION_FIX_INCOMPLETE, _("fix incomplete install"), False) @@ -278,7 +325,7 @@ class InstallBackendAptdaemon(InstallBackend): """清空所有下载的文件 """ try: trans = yield self.client.clean(defer=True) - self.window_main.dbusController.transaction = trans + self.dbus_send.transaction = trans # 注册回调函数 接收更新的状态 yield self._show_transaction(trans, self.ACTION_CLEAN, _("Remove all downloaded files."), False) @@ -298,7 +345,7 @@ class InstallBackendAptdaemon(InstallBackend): try: # trans = yield self.client.remove_packages(package_names = pkgs_purge,defer=True) trans = yield self.client.commit_packages([],[],[],pkgs_purge,[],[],defer=True) - self.window_main.dbusController.transaction = trans + self.dbus_send.transaction = trans # 注册回调函数 接收更新的状态 yield self._show_transaction(trans, self.ACTION_REMOVE_PACKAGES, _("Installing deb packages…"), False) @@ -308,25 +355,25 @@ class InstallBackendAptdaemon(InstallBackend): 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=str(e), error_desc='') #进度回调 def _on_progress_changed(self, trans,progress,action): #不要101这种未知状态 if progress == 101: return - - #过滤掉不是线性的进度 - if progress > self.aptd_base.progress: - self.aptd_base.progress = progress - else: - return - self.aptd_base.progress = progress - self._dist_status_changed(action,self.now_upgrade.upgrade_content,self.aptd_base.progress,self.aptd_base.status,self.aptd_base.details) + if self.action_mode == self.MODE_INSTALL_STEP: + progress = int(self.steps_progress_begin + (progress / 100) * + (self.steps_progress_end - self.steps_progress_begin)) + else: + #过滤掉不是线性的进度 + if progress > self.aptd_base.progress: + self.aptd_base.progress = progress + else: + return + self.aptd_base.progress = progress + self._dist_status_changed(action,self.aptd_base.progress,self.aptd_base.status,self.aptd_base.details) #同步状态回调 def _on_status_changed(self, trans, status,action): @@ -338,66 +385,63 @@ class InstallBackendAptdaemon(InstallBackend): if self.aptd_base.status == None: return - self._dist_status_changed(action,self.now_upgrade.upgrade_content,\ - self.aptd_base.progress,self.aptd_base.status,self.aptd_base.details) + self._dist_status_changed(action,self.aptd_base.progress,self.aptd_base.status,self.aptd_base.details) #分发进度状态和细节信息 - def _dist_status_changed(self,action,upgrade_content = [],progress = 0,status = '',details = ''): + def _dist_status_changed(self,action,progress = 0,status = '',details = ''): + if action == self.ACTION_UPDATE: # 更新进度100后推迟发出100%的信号 -- 等待源过滤完成 if progress == 11: progress = 15 if progress != 100: - self.window_main.dbusController.UpdateDetectStatusChanged(progress,status) + self.dbus_send.UpdateDetectStatusChanged(progress,status) elif action == self.ACTION_INSTALL: - #50%时候 属于下载状态切换到安装状态的过程 下面的代码只执行一次 - if progress >= 50 and progress < 90 and self.on_install_stage == False: - logging.info("The process is now in the installtion phase") - self.on_install_stage = True - self.safe_manager.shutdown_safe() - self._start_install_lock(_("Kylin System Updater")) - - #只处理从下载切换到安装时出现的网络问题 - #当网络波动时下载某些软件包失败时属于异常状态进行重试时 不发送后续进度 等待重试正常是 进行下载安装 - if self.now_upgrade.version_upgrade == True and progress >= 48 and self.on_install_stage != True and 'Failed to fetch' in self.aptd_base.error_details: + if self.meta_upgrade.version_upgrade == True and progress >= 48 and 'Failed to fetch' in self.aptd_base.error_details: logging.warning("Arise Failed to fetch and Need retry Upgrade...") - self.now_upgrade.need_retry = True + self.need_retry = True return + #50%时候 属于下载状态切换到安装状态的过程 下面的代码只执行一次 + #在安装的阶段的时候就进入安装阶段 禁止关机操作 + #提前进度安装状态 + if progress >= 49 and progress < 90 and self.on_installing == False: + self.on_installing = True + self.entering_installed() + #在下载阶段发送取消信号 - if self.on_install_stage == False: - self.window_main.dbusController.Cancelable(self.aptd_base.cancelable) - - self.window_main.dbusController.UpdateDloadAndInstStaChanged(upgrade_content,progress,status,details) - elif action == self.ACTION_INSTALL_SHUTDOWN: - # 写入进度 到plymouth - self._progress_to_plymouth(progress) - self.window_main.dbusController.UpdateDloadAndInstStaChanged(upgrade_content,progress,status,details) + if self.on_installing == False: + self.dbus_send.Cancelable(self.aptd_base.cancelable) + + self.dbus_send.UpdateDloadAndInstStaChanged(self.meta_upgrade.get_content(),progress,status,details) elif action == self.ACTION_DOWNLOADONLY: #只处理从下载切换到安装时出现的网络问题 #当网络波动时下载某些软件包失败时属于异常状态进行重试时 不发送后续进度 等待重试正常是 进行下载安装 - if self.now_upgrade.version_upgrade == True and progress >= 48 and 'Failed to fetch' in self.aptd_base.error_details: + if self.meta_upgrade.version_upgrade == True and 'Failed to fetch' in self.aptd_base.error_details: logging.warning("Arise Failed to fetch and Need retry Upgrade...") - self.now_upgrade.need_retry = True + self.need_retry = True return - self.window_main.dbusController.Cancelable(self.aptd_base.cancelable) - self.window_main.dbusController.UpdateDloadAndInstStaChanged(upgrade_content,progress,status,details) + self.dbus_send.Cancelable(self.aptd_base.cancelable) + self.dbus_send.UpdateDloadAndInstStaChanged(self.meta_upgrade.get_content(),progress,status,details) + elif action == self.ACTION_INSTALL_SHUTDOWN: + # 写入进度 到plymouth + self._progress_to_plymouth(progress) + self.dbus_send.UpdateDloadAndInstStaChanged(self.meta_upgrade.get_content(),progress,status,details) elif action == self.ACTION_FIX_BROKEN: - self.window_main.dbusController.FixBrokenStatusChanged(False,True,progress,status,'','') + self.dbus_send.FixBrokenStatusChanged(False,True,progress,status,'','') elif action == self.ACTION_REMOVE_PACKAGES: - self.window_main.dbusController.PurgePkgStatusChanged(progress,status,details) + self.dbus_send.PurgePkgStatusChanged(progress,status,details) elif action == self.ACTION_INSTALL_DEB or action == self.ACTION_BACKGROUND_UPGRADE: - self.window_main.dbusController.InstalldebStatusChanged(progress,status,details) + self.dbus_send.InstalldebStatusChanged(progress,status,details) else: logging.info("Other Action:progress = %d , status = %s ,details = %s",progress,status,details) def _on_details_changed(self, trans, details,action): self.aptd_base.details = details - self._dist_status_changed(action,self.now_upgrade.upgrade_groups+self.now_upgrade.single_pkgs,\ - self.aptd_base.progress,self.aptd_base.status,self.aptd_base.details) + self._dist_status_changed(action,self.aptd_base.progress,self.aptd_base.status,self.aptd_base.details) def _on_download_changed(self, trans, details): logging.info(details) @@ -405,8 +449,7 @@ class InstallBackendAptdaemon(InstallBackend): # eta 剩余时间不正确,取消掉 def _on_progress_download_changed(self,trans,current_items, total_items, currenty_bytes, total_bytes, current_cps, eta): if self.action == self.ACTION_INSTALL or self.action == self.ACTION_DOWNLOADONLY or self.action == self.ACTION_BACKGROUND_UPGRADE: - self.window_main.dbusController.UpdateDownloadInfo(\ - self.now_upgrade.upgrade_groups+self.now_upgrade.single_pkgs,\ + self.dbus_send.UpdateDownloadInfo(self.meta_upgrade.get_content(),\ current_items, total_items, \ currenty_bytes, total_bytes, \ current_cps) @@ -425,27 +468,25 @@ class InstallBackendAptdaemon(InstallBackend): if self.action != self.ACTION_UPDATE: logging.info("\033[1;32m" + "Emitting" + "\033[0m" +" Cancelable: %r",Cancelable) - self.window_main.dbusController.Cancelable(Cancelable) + self.dbus_send.Cancelable(Cancelable) #增加取消信号的频发机制 self.aptd_base.cancelable = Cancelable def _on_config_file_conflict(self, transaction, old, new): logging.info("Config file conflict oldconf = %s , newconf = %s...",str(old),str(new)) logging.info("Default To Replace Old Configfile...") - #默认替换旧的配置文件 + transaction.resolve_config_file_conflict(old, "keep") - # transaction.resolve_config_file_conflict(old, "keep") #增加记录当产生错误的时候 详细信息 def _on_error_changed(self, trans,error_code, error_details): - # error_string = get_error_string_from_enum(error_code) self.aptd_base.error_details = str(error_details) logging.error(str(error_details)) @inline_callbacks - def _show_transaction(self, trans, action, header, show_details): - #更新和升级最后完成和失败都会走此在此进行完成之后的处理 - trans.connect("finished", self._on_finished, action) + def _show_transaction_steps(self, trans, action, header, show_details): + + trans.connect("finished", self._on_finished_steps, action) #升级和更新的状态信息和进度 trans.connect("status-changed", self._on_status_changed,action) trans.connect("progress-changed", self._on_progress_changed,action) @@ -458,18 +499,47 @@ class InstallBackendAptdaemon(InstallBackend): trans.connect("config-file-conflict", self._on_config_file_conflict) - # yield trans.set_debconf_frontend("ukui") - # yield trans.set_locale(os.environ["LANGUAGE"] + ".UTF-8") yield trans.run() + @inline_callbacks + def _show_transaction(self, trans, action, header, show_details): + if action == self.ACTION_INSTALL_DEB: + trans.connect("finished", self._on_finished_special, action) + else: + trans.connect("finished", self._on_finished, action) + #升级和更新的状态信息和进度 + trans.connect("status-changed", self._on_status_changed,action) + trans.connect("progress-changed", self._on_progress_changed,action) + #取消升级 + trans.connect("cancellable-changed", self._on_cancellable_changed) + #下载的进度信息 + trans.connect("progress-details-changed", self._on_progress_download_changed) + trans.connect("status-details-changed", self._on_details_changed,action) + trans.connect("error", self._on_error_changed) + + trans.connect("config-file-conflict", self._on_config_file_conflict) + + yield trans.run() + + def _on_finished_steps(self, trans, status, action): + try: + if status == EXIT_SUCCESS: + self._steps_done() + else: + self._on_finished(trans, status, action) + except Exception as e: + logging.error(e) + traceback.print_exc() + def _on_finished(self, trans, status, action): try: error_string = '' error_desc = '' - #退出 - self.on_install_stage = False + error_code = '' + if status == EXIT_FAILED: # self.log_audit(str(trans.error.code)) + error_code = trans.error.code 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: @@ -479,14 +549,36 @@ class InstallBackendAptdaemon(InstallBackend): error_string = _("Failed to fetch") error_desc = _("_Cancel Upgrade") elif status == EXIT_SUCCESS and action == self.ACTION_INSTALL: - error_string = _("System upgrade is complete.") + pass elif status == EXIT_SUCCESS and action == self.ACTION_REMOVE_PACKAGES: error_string = _("Uninstallation completed") is_success = (status == EXIT_SUCCESS) + self._action_done(action, is_cancelled=(status == EXIT_CANCELLED), success=is_success, - error_string=error_string, error_desc=error_desc) + error_string=error_string, error_desc=error_desc,error_code=error_code) + except Exception as e: + logging.error(e) + traceback.print_exc() + + def _on_finished_special(self, trans, status, action): + try: + error_string = '' + error_desc = '' + error_code = '' + + if status == EXIT_FAILED and action == self.ACTION_INSTALL_DEB: + error_code = trans.error.code + error_string = get_error_string_from_enum(trans.error.code) + error_desc = get_error_description_from_enum(trans.error.code) + if str(error_code) == 'error-dep-resolution-failed': + status,detailed_information,err_info = self.window_main.start_deb_resolver(self.window_main.sqlite3_server.deb_metadata['deblist']) + + is_success = ((status == EXIT_SUCCESS) or (status == 0)) + self._action_done(action, + is_cancelled=(status == EXIT_CANCELLED), success=is_success, + error_string=error_string, error_desc=error_desc,error_code=error_code) except Exception as e: logging.error(e) traceback.print_exc() diff --git a/backend/SystemUpdater/backend/__init__.py b/backend/SystemUpdater/backend/__init__.py index 763f4f6..cb55007 100644 --- a/backend/SystemUpdater/backend/__init__.py +++ b/backend/SystemUpdater/backend/__init__.py @@ -19,62 +19,26 @@ from gettext import gettext as _ from SystemUpdater.Core.errors import * from SystemUpdater.Core.enums import * from SystemUpdater.Core.DataAcquisition import get_east_8_time -from SystemUpdater.Core.UpdateList import LocalUpgradeDataList from SystemUpdater.Core.DistUpgradeCache import NotEnoughFreeSpaceError from SystemUpdater.Core.utils import get_config_patch +from SystemUpdater.Core.JsonConfigParser import JsonConfig as json_config +from aptdaemon.enums import ERROR_PACKAGE_DOWNLOAD_FAILED class NowUpgradeMeta: """ Represent the (potentially partial) results of an unattended-upgrades run """ - def __init__(self, - parent, - upgrade_groups = [], - single_pkgs = [], - version_upgrade = False, - need_retry = False, - ): - self.parent = parent + def __init__(self,_upgrade_groups = [],_single_pkgs = []): + self.push_content = [] #组列表中包含的包 - self.upgrade_groups = upgrade_groups + self.upgrade_groups = _upgrade_groups #推送的可升级的单包 - self.single_pkgs = single_pkgs - self.version_upgrade = version_upgrade - self.need_retry = need_retry - self.upgrade_content = self.upgrade_groups + self.single_pkgs - - #获取当前升级的升级列表 - def _make_groups_list(self,upgrade_data,_upgrade_mode,partial_upgrade_list): - groups_list = [] - pkg_list = [] - - #部分升级 - if _upgrade_mode == self.parent.MODE_INSTALL_PARTIAL: - for elem in partial_upgrade_list: - #组升级方式 - if elem in upgrade_data.upgrade_groups: - groups_list.append(elem) - #单包升级方式 - elif elem in upgrade_data.single_pkgs: - pkg_list.append(elem) - else: - logging.warning("this package(%s) not in selected list",elem) - - #全部升级列表 - elif _upgrade_mode == self.parent.MODE_INSTALL_ALL: - groups_list = upgrade_data.upgrade_groups - pkg_list = upgrade_data.single_pkgs - - return groups_list,pkg_list - - def make_upgrade_content(self,content): - if self.parent.action_mode != self.parent.MODE_INSTALL_SINGLE: - self.upgrade_groups,self.single_pkgs = self._make_groups_list(self.parent.upgrade_data,self.parent.action_mode,content) - self.upgrade_content = self.upgrade_groups + self.single_pkgs - else: - self.single_pkgs = content - self.upgrade_content = self.upgrade_groups + self.single_pkgs + self.single_pkgs = _single_pkgs + self.version_upgrade = True + + def get_content(self): + return self.single_pkgs + self.upgrade_groups class UpdateEssentialItem(): def __init__(self,parent): @@ -134,7 +98,7 @@ class AptdBaseInformation: self.error_details = error_details class InstallBackend(): - INSTALL_OUTPUT_JSON = "/var/lib/kylin-system-updater/json/showdown_install.json" + INSTALL_OUTPUT_JSON = "/var/lib/kylin-system-updater/json/requires_upgrade_meta.json" ACTION_DEFUALT_STATUS = -1 ACTION_UPDATE = 0 @@ -149,20 +113,16 @@ class InstallBackend(): ACTION_INSTALL_SHUTDOWN = 9 ACTION_BACKGROUND_UPGRADE = 10 ACTION_CHECK_BROKEN = 11 + ACTION_INSTALL_DEB_RESOLVER = 12 MODE_DEFAULT_STATUS = -1 - #1、ACTION_INSTALL 安装的子类 - #部分升级 MODE_INSTALL_PARTIAL = 0 - #全部升级 MODE_INSTALL_ALL = 1 - #系统全盘升级 MODE_INSTALL_SYSTEM = 2 - #后端内部安装包使用 目前 更新配置包和升级本身使用 MODE_INSTALL_SINGLE = 3 + MODE_INSTALL_STEP = 4 - #2、更新的子类 MODE_UPDATE_CACHE = 0 MODE_UPDATE_ALL = 1 @@ -175,123 +135,76 @@ class InstallBackend(): self.window_main.now_working = action self.aptd_base = AptdBaseInformation() + self.collector = window_main.collector - self.inhibit_shutdown = InhibitShutdownLock() + self.backend_data = window_main.main_meta + self.dbus_send = window_main.dbusController + self.database = window_main.sqlite3_server + self.meta_upgrade = NowUpgradeMeta() - self.update_essential = UpdateEssentialItem(self) - - if self.action == self.ACTION_INSTALL: + if self.action != self.ACTION_UPDATE: self.safe_manager = UpdateSafeManager() - - #更新的时候此对象还未生成 - if self.window_main.update_list != None: - self.upgrade_data = window_main.update_list.upgrade_meta - else: - self.upgrade_data = LocalUpgradeDataList() - - #要拿到升级列表必须调用_make_upgrade_list - self.now_upgrade = NowUpgradeMeta(parent=self) - - def start(self,partial_upgrade_list = []): + self.update_essential = UpdateEssentialItem(self) + self.inhibit_shutdown = InhibitShutdownLock() + self.scripts = window_main.pm_class + + def start(self,push_content = []): try: #安装升级包 首先必须调用ACTION_CHECK_RESOLVER 计算依赖解决方便 标记cache 进行升级 if self.action == self.ACTION_INSTALL or self.action == self.ACTION_DOWNLOADONLY: - #拿到升级列表 - self.now_upgrade.make_upgrade_content(partial_upgrade_list) + self.meta_upgrade.push_content = push_content + if self.action_mode == self.MODE_INSTALL_SINGLE: + pkgs_install,pkgs_upgrade,pkgs_remove = self.get_mark_from_cache(self.cache) - pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_downgrade = self._get_mark_from_cache(self.cache,self.upgrade_data.adjust_pkgs,self.action_mode) - logging.info("INSTALL install:%d , upgrade:%d remove:%d pkgs_downgrade:%d",len(pkgs_install),\ - len(pkgs_upgrade),len(pkgs_remove),len(pkgs_downgrade)) + self.meta_upgrade.single_pkgs = push_content + elif self.action_mode == self.MODE_INSTALL_STEP: + self.meta_upgrade.single_pkgs,self.meta_upgrade.upgrade_groups = self.backend_data.classify_content(push_content) - #当下载数量大于200个包时 就认为属于大版本升级 开启重试机制 - if len(pkgs_install) + len(pkgs_upgrade) > 100: - logging.info("Open a major version upgrade and Retry mechanism on...") - self.now_upgrade.version_upgrade = True - - #检查是否存在可升级的包 - if len(pkgs_install) == 0 and len(pkgs_upgrade) == 0 and len(pkgs_remove) == 0 and len(pkgs_downgrade) == 0: - pkgs_install,pkgs_upgrade = self._make_pkgs_list(self.cache,self.upgrade_data.groups_pkgs,self.now_upgrade.upgrade_groups,self.now_upgrade.single_pkgs) - logging.warning("There is an exception in the update package install = %r upgrade = %r",pkgs_install,pkgs_upgrade) + pkgs_install,pkgs_upgrade,pkgs_remove = self.backend_data.get_resolver_upgrade() + elif self.action_mode == self.MODE_INSTALL_SYSTEM: + self.meta_upgrade.upgrade_groups = ["dist-upgrade"] + pkgs_install,pkgs_upgrade,pkgs_remove = self.backend_data.get_resolver_upgrade() + else: + #单独下载和下载安装同时走此分支 + self.meta_upgrade.single_pkgs,self.meta_upgrade.upgrade_groups = self.backend_data.classify_content(push_content) + pkgs_install,pkgs_upgrade,pkgs_remove = self.backend_data.get_resolver_upgrade() - # if self.action_mode == self.MODE_INSTALL_SINGLE: - # logging.warning("MODE_INSTALL_SINGLE install:%s , upgrade:%s remove:%s",str(pkgs_install),str(pkgs_upgrade),str(pkgs_remove)) + logging.info("INSTALL install:%d , upgrade:%d remove:%d",len(pkgs_install),len(pkgs_upgrade),len(pkgs_remove)) self.update_essential.check_essential(pkgs_remove) - - #检查磁盘的状态 - self.check_free_space(self.cache) - for ul in self.window_main.collector.upgrade_list: - self.window_main.collector.Upgrade_Process_Msg(self.action, {"appname":ul}) + for ul in self.collector.upgrade_list: + self.collector.Upgrade_Process_Msg(self.action, {"appname":ul}) - if self.action == self.ACTION_INSTALL: - self.commit(self.action,pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_downgrade) - elif self.action == self.ACTION_DOWNLOADONLY: - self._update_to_config(self.now_upgrade,pkgs_install,pkgs_upgrade,pkgs_remove) - self.commit_only(self.action,pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_downgrade) - + if self.action_mode != self.MODE_INSTALL_SINGLE: + self._update_to_config(self.meta_upgrade,pkgs_install,pkgs_upgrade,pkgs_remove) + + if len(pkgs_install) + len(pkgs_upgrade) > 100: + logging.info("Open a major version upgrade and Retry mechanism on...") + self.meta_upgrade.version_upgrade = True + + if self.action == self.ACTION_DOWNLOADONLY: + self.commit_only(self.action,pkgs_install, pkgs_upgrade, pkgs_remove) + return + + if self.action_mode != self.MODE_INSTALL_STEP and self.action_mode != self.MODE_INSTALL_SINGLE: + #更新前执行脚本的操作 + for groups in self.meta_upgrade.upgrade_groups: + if self.run_steps_script(50,'',groups) == False: + raise UpdateBaseError(ERROR_RUN_SCRIPTS_FAILED) + + if self.action_mode == self.MODE_INSTALL_STEP: + logging.info("Will be enter to step install model...") + self.commit_steps(self.ACTION_DOWNLOADONLY,pkgs_install, pkgs_upgrade, pkgs_remove,0,50) + else: + self.commit(self.action,pkgs_install, pkgs_upgrade, pkgs_remove) elif self.action == self.ACTION_INSTALL_SHUTDOWN: - self.now_upgrade,pkgs_install,pkgs_upgrade,pkgs_remove = self._config_to_upgrade() + self.meta_upgrade,pkgs_install,pkgs_upgrade,pkgs_remove = self._config_to_upgrade() logging.info("ACTION_INSTALL_SHUTDOWN install:%d , upgrade:%d remove:%d",len(pkgs_install),len(pkgs_upgrade),len(pkgs_remove)) # self._start_install_lock() self.commit(self.action,pkgs_install, pkgs_upgrade, pkgs_remove) - #计算依赖解决方案 - elif self.action == self.ACTION_CHECK_RESOLVER: - #被删除包的描述 - raw_description = [] - - #判断是否配置aptdaemon的限速 - self.window_main.check_conifg_aptdeamon() - - if self.action_mode != self.MODE_INSTALL_SYSTEM: - #获取要升级的组列表 - self.now_upgrade.make_upgrade_content(partial_upgrade_list) - #获取要升级和安装的包列表 - pkgs_install,pkgs_upgrade = self._make_pkgs_list(self.cache,self.upgrade_data.groups_pkgs,self.now_upgrade.upgrade_groups,self.now_upgrade.single_pkgs) - #计算解决依赖关系 - self._make_problem_resolver(self.cache,pkgs_install,pkgs_upgrade,self.upgrade_data.adjust_pkgs) - pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_downgrade = self._get_mark_from_cache(self.cache,self.upgrade_data.adjust_pkgs,self.action_mode) - else: - # 使用全盘升级 全盘使用dist-upgrade - if self.cache.get_changes(): - self.cache.clear() - self.cache._depcache.upgrade(True) - pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_downgrade = self._get_mark_from_cache(self.cache,self.upgrade_data.adjust_pkgs,self.action_mode) - - logging.warning("ProblemResolver of the deletion package list:%s",str(pkgs_remove)) - self.update_essential.check_white(pkgs_remove) - logging.info("RESOLVER install:%d , upgrade:%d remove:%d pkgs_downgrade:%d",len(pkgs_install),len(pkgs_upgrade),\ - len(pkgs_remove),len(pkgs_downgrade)) - is_remove_pkgs = len(pkgs_remove) != 0 - - # 数据上报 - self.window_main.collector.Generate_Msg(self.now_upgrade.upgrade_groups+self.now_upgrade.single_pkgs, self.action_mode) - errorCode = "" - if is_remove_pkgs: - errorCode = _("Need remove pkgs: ")+", ".join(pkgs_remove) - for ul in self.window_main.collector.upgrade_list: - self.window_main.collector.Upgrade_Process_Msg(self.action, {"appname":ul, "status":is_remove_pkgs, "errorCode":errorCode}) - - #补充删除包的描述信息,删除描述 - delete_desc = [] - for pkg in pkgs_remove: - pkg_obj = self.cache[pkg] - raw_description.append(getattr(pkg_obj.candidate, "summary", '')) - delete_desc.append('') - - if self.action_mode != self.MODE_INSTALL_SYSTEM: - self.window_main.dbusController.UpdateDependResloveStatus(True,is_remove_pkgs,pkgs_remove,raw_description,delete_desc,'','') - else: - self.window_main.dbusController.DistupgradeDependResloveStatus(True,is_remove_pkgs,pkgs_remove,raw_description,delete_desc,'','') - - self._action_done(self.action,False,True,'','') - - if is_remove_pkgs: - threading_emulate = threading.Thread(target=self._emulate_calcul_delete,args=((pkgs_upgrade + pkgs_install),)) - threading_emulate.start() - #修复未满足的依赖关系 与apt-get -f install匹配 elif self.action == self.ACTION_CHECK_BROKEN: try: @@ -317,7 +230,7 @@ class InstallBackend(): pkg_obj = self.cache[pkg] raw_description.append(getattr(pkg_obj.candidate, "summary", '')) - self.window_main.dbusController.UpdateFixBrokenStatus(True,True,pkgs_remove,raw_description,delete_desc,'','') + self.dbus_send.UpdateFixBrokenStatus(True,True,pkgs_remove,raw_description,delete_desc,'','') self._action_done(self.action,False,True,'','') elif self.action == self.ACTION_FIX_BROKEN: @@ -331,13 +244,13 @@ class InstallBackend(): #卸载包 elif self.action == self.ACTION_REMOVE_PACKAGES: self._start_install_lock(_("Kylin System Updater")) - self.purge_packages(partial_upgrade_list) + self.purge_packages(push_content) elif self.action == self.ACTION_CLEAN: self.clean() #更新cache elif self.action == self.ACTION_UPDATE: #检查依赖之前 判断是否需要重启aptdeamon 目前为了生效限速功能 - self.window_main.check_conifg_aptdeamon() + self.window_main.check_config_aptdeamon() self.update() except UpdateBaseError as excep: self._action_done(self.action,True,False,excep.header,excep.desc,excep.code) @@ -347,31 +260,141 @@ class InstallBackend(): logging.error(e) traceback.print_exc() - def start_alone(self,partial_upgrade_list = [],_is_install = False, caller=''): + def start_resolver(self,push_content): + try: + #被删除包的描述 + raw_description = [] + total_remove = [] + + if self.action_mode != self.MODE_INSTALL_SYSTEM: + all_install,all_upgrade = self.backend_data.get_push_pkgs(push_content) + logging.info("ALLs install:%d , upgrade:%d",len(all_install),len(all_upgrade)) + + self._make_problem_resolver(self.cache,all_install,all_upgrade) + pkgs_install,pkgs_upgrade,pkgs_remove = self.get_mark_from_cache(self.cache) + total_remove += pkgs_remove + + self.backend_data.resolver_groups(pkgs_install,pkgs_upgrade,pkgs_remove) + self.check_free_space(self.cache) + + #分步更新处理过程 + if self.action_mode == self.MODE_INSTALL_STEP: + steps_reboot = False + for step_name in self.backend_data.get_steps(): + step_install,step_upgrade = self.backend_data.get_steps_pkgs(step_name) + logging.info("Steps(%s): install:%d , upgrade:%d",step_name,len(step_install),len(step_upgrade)) + self._make_problem_resolver(self.cache,step_install,step_upgrade) + + step_install,step_upgrade,step_remove = self.get_mark_from_cache(self.cache) + logging.info("RESOLVER(%s):Steps install:%d , upgrade:%d remove:%d ",step_name,len(step_install),\ + len(step_upgrade),len(step_remove)) + + if len(step_install) == 0 and len(step_upgrade) == 0 and len(step_remove) == 0: + logging.warning("Steps(%s) This update cannot detect the upgradeable package.",step_name) + + self.backend_data.resolver_steps(step_name,step_install,step_upgrade,step_remove) + + total_remove += step_remove + + self.backend_data.steps_queue.insert(0,step_name) + + steps_reboot = self.backend_data.check_steps_reboot(step_name) + if steps_reboot == True: + break + + if steps_reboot == False: + self.backend_data.steps_queue.insert(0,self.backend_data.resolver_name) + else: + # 使用全盘升级 类似 apt dist-upgrade + if self.cache.get_changes(): + self.cache.clear() + self.cache._depcache.upgrade(True) + pkgs_install,pkgs_upgrade,pkgs_remove = self.get_mark_from_cache(self.cache) + self.backend_data.resolver_groups(pkgs_install,pkgs_upgrade,pkgs_remove) + + self.check_free_space(self.cache) + + total_remove += pkgs_remove + + #可能存在重复,去除 + total_remove = list(set(total_remove)) + + logging.warning("ProblemResolver of the deletion package list:%s",str(total_remove)) + self.update_essential.check_white(total_remove) + + logging.info("RESOLVER:ALL install:%d , upgrade:%d remove:%d ",len(pkgs_install),len(pkgs_upgrade),\ + len(total_remove)) + + is_remove_pkgs = len(total_remove) != 0 + + # 数据上报 + self.collector.Generate_Msg(self.meta_upgrade.get_content(), self.action_mode) + errorCode = "" + if is_remove_pkgs: + errorCode = _("Need remove pkgs: ")+", ".join(total_remove) + for ul in self.collector.upgrade_list: + self.collector.Upgrade_Process_Msg(self.action, {"appname":ul, "status":is_remove_pkgs, "errorCode":errorCode}) + + #补充删除包的描述信息,删除描述 + delete_desc = [] + for pkg in total_remove: + pkg_obj = self.cache[pkg] + raw_description.append(getattr(pkg_obj.candidate, "summary", '')) + delete_desc.append('') + + if self.action_mode != self.MODE_INSTALL_SYSTEM: + self.dbus_send.UpdateDependResloveStatus(True,is_remove_pkgs,total_remove,raw_description,delete_desc,'','') + else: + self.dbus_send.DistupgradeDependResloveStatus(True,is_remove_pkgs,total_remove,raw_description,delete_desc,'','') + + self._action_done(self.action,False,True,'','') + + if is_remove_pkgs: + threading_emulate = threading.Thread(target=self._emulate_calcul_delete,args=((pkgs_upgrade + pkgs_install),)) + threading_emulate.start() + + except UpdateBaseError as excep: + self.dbus_send.InstallDetectStatus(False,get_error_code_from_enum(excep.code)) + self._action_done(self.action,True,False,excep.header,excep.desc,excep.code) + except UpdateProgressExit as excep: + pass + except Exception as e: + logging.error(e) + traceback.print_exc() + + def start_alone(self,push_content = [],_is_install = False, caller=''): # 安装本地deb包的接口 if self.action == self.ACTION_INSTALL_DEB: try: self._start_install_lock(caller=caller) - self.install_deb(install_path = partial_upgrade_list, install_force = _is_install) + self.install_deb(install_path = push_content, install_force = _is_install) + except Exception as e: + logging.error(str(e)) + elif self.action == self.ACTION_INSTALL_DEB_RESOLVER: + try: + self._make_problem_resolver(self.cache,push_content,[]) + pkgs_install,pkgs_upgrade,pkgs_remove = self.get_mark_from_cache(self.cache) + self._start_install_lock(caller=caller) + self.commit(self.ACTION_INSTALL,pkgs_install,pkgs_upgrade,pkgs_remove) except Exception as e: logging.error(str(e)) # 安装在线包的接口 elif self.action == self.ACTION_BACKGROUND_UPGRADE: try: - pkgs_install = [ str(pkg) for pkg in partial_upgrade_list] + pkgs_install = [ str(pkg) for pkg in push_content] logging.info("Install deb package, open cache") cache = Cache() for pkg_name in pkgs_install: if pkg_name not in cache: if "=" not in pkg_name or ("=" in pkg_name and pkg_name.split("=")[0] not in cache): # 没找到包或格式不正确 - self.window_main.dbusController.UpdateInstallFinished(False, pkgs_install, "'"+pkg_name+"' is not in cache", "") + self.dbus_send.UpdateInstallFinished(False, pkgs_install, "'"+pkg_name+"' is not in cache", "") return self._start_install_lock(caller=caller) self.commit(self.ACTION_INSTALL,pkgs_install,[],[]) except Exception as e: logging.error(str(e)) - self.window_main.dbusController.UpdateInstallFinished(False, pkgs_install, str(e), "") + self.dbus_send.UpdateInstallFinished(False, pkgs_install, str(e), "") def update(self): """Run a update to refresh the package list""" @@ -420,19 +443,19 @@ class InstallBackend(): pass return pkgs_install,pkgs_upgrade,pkgs_remove - #从cache中拿到标记的列表 - def _get_mark_from_cache(self,cache,_adjust_pkgs,upgrade_mode): + def get_mark_from_cache(self,cache): + '''从cache中拿到标记的升级新装和删除的包 + + 入参: + cache - 当前cache + 出参: + pkgs_install - 当前要安装的包列表 + pkgs_upgrade - 当前要安装的包列表 + pkgs_remove - 当前要卸载的包列表 + ''' pkgs_install = [] pkgs_upgrade = [] pkgs_remove = [] - pkgs_downgrade = [] - - #全盘升级不做任何的调整 - if upgrade_mode == self.MODE_INSTALL_SYSTEM or upgrade_mode == self.MODE_INSTALL_SINGLE: - adjust_pkgs = [] - else: - #获取调整包列表 去掉版本号 - adjust_pkgs = [i.split("=")[0] for i in _adjust_pkgs] for pkg in cache: try: @@ -440,46 +463,16 @@ class InstallBackend(): pkgname = pkg.name if pkg.is_auto_installed: pkgname += "#auto" - if pkg.name in adjust_pkgs: - pkgs_install.append(_adjust_pkgs[adjust_pkgs.index(pkg.name)]) + pkgs_install.append(pkgname) else: pkgs_install.append(pkgname) elif pkg.marked_upgrade: - if pkg.name in adjust_pkgs: - pkgs_upgrade.append(_adjust_pkgs[adjust_pkgs.index(pkg.name)]) - else: pkgs_upgrade.append(pkg.name) elif pkg.marked_delete: pkgs_remove.append(pkg.name) - elif pkg.marked_downgrade: - pkgs_downgrade.append(pkg.name+'='+pkg.candidate.source_version) except KeyError: pass - return pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_downgrade - - #获取当前升级的升级列表 - def _make_groups_list(self,upgrade_data,_upgrade_mode,partial_upgrade_list): - groups_list = [] - pkg_list = [] - - #部分升级 - if _upgrade_mode == self.MODE_INSTALL_PARTIAL: - for elem in partial_upgrade_list: - #组升级方式 - if elem in upgrade_data.upgrade_groups: - groups_list.append(elem) - #单包升级方式 - elif elem in upgrade_data.single_pkgs: - pkg_list.append(elem) - else: - logging.warning("this package(%s) not in selected list",elem) - - #全部升级列表 - elif _upgrade_mode == self.MODE_INSTALL_ALL: - groups_list = upgrade_data.upgrade_groups - pkg_list = upgrade_data.single_pkgs - - return groups_list,pkg_list + return pkgs_install,pkgs_upgrade,pkgs_remove #从本地中获取本次升级需要升级的包 部分升级和全部升级使用 全盘升级不适用 def _make_pkgs_list(self,cache,groups_pkgs,groups_list,pkg_list): @@ -542,27 +535,15 @@ class InstallBackend(): version = release = None return name, version, release - #将获取本次升级的包 进行计算依赖关系 解决依赖问题 - def _make_problem_resolver(self,cache,pkgs_install = [],pkgs_upgrade = [],adjust_pkgs = []): + def _make_problem_resolver(self,cache,pkgs_install = [],pkgs_upgrade = []): try: - logging.info("ProblemResolver install:%d , upgrade:%d",len(pkgs_install),len(pkgs_upgrade)) logging.info("Start calculating dependencies...") - #actiongroup 可以加速计算依赖关系 计算花费的时间将大幅度缩减 with cache.actiongroup(): if cache.get_changes(): cache.clear() resolver = apt.cache.ProblemResolver(cache) - for pkg_name, pkg_ver, pkg_rel in [self._split_package_id(pkg) - for pkg in adjust_pkgs]: - try: - pkg = cache[pkg_name] - pkg.candidate = pkg.versions[pkg_ver] - except KeyError: - logging.warning("The version %s of %s isn't available",pkg_ver, pkg_name) - continue - for pkg in pkgs_upgrade + pkgs_install: pkg_cache = cache[pkg] if pkg_cache.is_upgradable == False and pkg_cache.is_installed == True: @@ -630,103 +611,161 @@ class InstallBackend(): def _send_error_code(self,error_code): if error_code == ERROR_NOT_DISK_SPACE: - self.window_main.dbusController.InstallDetectStatus(False,error_code) + self.dbus_send.InstallDetectStatus(False,error_code) - def _self_upgrade_finished(self,success,error_string='',error_desc=''): + def _self_upgrade_finished(self,success,error_string='',error_desc='',error_code=''): if success: - if self.window_main.configs_cover.getWithDefault("SystemStatusCover", "priority_upgrade_restart", False,True) == True: - error_string = get_error_string_from_enum(PRIORITY_UPGRADE_SUCCCESSED) - if self.window_main.APTD_PKG_NAME in self.now_upgrade.upgrade_content: - self.window_main.dbusController.UpdateDetectFinished(False,[self.window_main.BACKEND_PKG_NAME],error_string,'') - self.window_main.dbusController.make_aptdeamon_restart() - - #当单包升级的时候 升级本身时,让程序退出,再重新启动 - if self.window_main.FRONTEND_PKG_NAME in self.now_upgrade.upgrade_content: - self.window_main.dbusController.UpdateDetectFinished(False,[self.window_main.BACKEND_PKG_NAME],error_string,'') - - #当单包升级的时候 升级本身时,让程序退出,再重新启动 - if self.window_main.BACKEND_PKG_NAME in self.now_upgrade.upgrade_content: - self.window_main.dbusController.UpdateDetectFinished(False,[self.window_main.BACKEND_PKG_NAME],error_string,'') - #升级本身完成后 退出 有systemd 来进行重启服务 - self.window_main.dbusController.Quit(None) - return + restart_ui = False - #当单包升级的时候 升级本身时,让程序退出,再重新启动 - if self.window_main.GROUPS_PKG_NAME in self.now_upgrade.upgrade_content: - self.window_main.start_available() - else: + channel_config = json_config().getWithDefault("update_channel_upgrade",default = {}) + + restart_list = channel_config.get("restart_service_list",[self.window_main.APTD_PKG_NAME,self.window_main.BACKEND_PKG_NAME]) + notify_list = channel_config.get("restart_panel_list",[self.window_main.FRONTEND_PKG_NAME]) + + error_string = get_error_string_from_enum(PRIORITY_UPGRADE_SUCCCESSED) + + if (self.window_main.APTD_PKG_NAME in self.meta_upgrade.get_content() and self.window_main.BACKEND_PKG_NAME not in self.meta_upgrade.get_content()) \ + and self.window_main.APTD_PKG_NAME in restart_list: + self.dbus_send.make_aptdeamon_restart() + + if self.window_main.FRONTEND_PKG_NAME in self.meta_upgrade.get_content() and \ + self.window_main.FRONTEND_PKG_NAME in notify_list: + self.dbus_send.UpdateDetectFinished(False,[self.window_main.BACKEND_PKG_NAME],error_string,'') + restart_ui = True + + # 异常情况 需要强制重启ui提示 + if "force_restart_ui" in notify_list: + self.dbus_send.UpdateDetectFinished(False,[self.window_main.BACKEND_PKG_NAME],error_string,'') + restart_ui = True + + if self.window_main.BACKEND_PKG_NAME in self.meta_upgrade.get_content() and \ + self.window_main.BACKEND_PKG_NAME in restart_list: + if restart_ui == False: + self.window_main.configs_uncover.setValue("SystemStatus","reboot_update",str(True)) + self.dbus_send.Quit(None) + return + + if restart_ui != True: self.window_main.start_available() else: - self.window_main.dbusController.UpdateDetectFinished(False,[''],get_error_string_from_enum(ERROR_UPDATE_DEFAULT_FAILED),\ + self.dbus_send.InstallDetectStatus(False,get_error_code_from_enum(error_code)) + self.dbus_send.UpdateDetectFinished(False,[''],get_error_string_from_enum(ERROR_UPDATE_DEFAULT_FAILED),\ error_string +' '+error_desc) + def run_steps_script(self,progress,last_steps,steps): + if progress == 50: + script_list = self.backend_data.get_pre_script(steps) + for scr in script_list: + if self.scripts.run_plugin(scr) == False: + return True + elif progress == 100: + script_list = self.backend_data.get_post_script(last_steps) + for scr in script_list: + if self.scripts.run_plugin(scr) == False: + return True + else: + script_list = self.backend_data.get_post_script(last_steps) + self.backend_data.get_pre_script(steps) + for scr in script_list: + if self.scripts.run_plugin(scr) == False: + return True + return True + + def _steps_done(self): + #分步更新任务队列 + if self.backend_data.steps_queue != []: + now_steps = self.backend_data.steps_queue.pop() + progress_begin,progress_end = self.backend_data.get_progress(now_steps) + pkgs_install,pkgs_upgrade,pkgs_remove = self.backend_data.get_resolver_steps(now_steps) + + if self.run_steps_script(progress_begin,self.backend_data.last_task,now_steps) == False: + self._action_done(self.action,False,False,get_error_string_from_enum(ERROR_RUN_SCRIPTS_FAILED),\ + get_error_description_from_enum(ERROR_RUN_SCRIPTS_FAILED)) + return + + #记录上一次的任务 + self.backend_data.last_task = now_steps + + mid_info = self.backend_data.get_mid_notify(now_steps) + if mid_info != '': + self.dbus_send.NotifyStepsInstalled(True,mid_info) + + logging.info("INSTALL(%s) install:%d , upgrade:%d remove:%d",now_steps,len(pkgs_install),len(pkgs_upgrade),len(pkgs_remove)) + self.commit_steps(self.action,pkgs_install, pkgs_upgrade, pkgs_remove,\ + progress_begin,progress_end,self.backend_data.steps_queue == []) + return + #调用aptdeamon结束之后处理的地方 不管是出错还是正常都在此处理 - def _action_done(self, action, is_cancelled,success, error_string='',error_desc='',error_code=''): - #后端的状态 到空闲状态 + def _action_done(self, action, is_cancelled,success, error_string='',error_desc='',error_code=''): self.window_main.now_working = self.ACTION_DEFUALT_STATUS - #升级完成后走的分支 if action == self.ACTION_INSTALL: - false_num = 0 - self.safe_manager.reset_safe() - self._release_install_lock() + #整个安装执行完毕 退出 self._send_error_code(error_code) - - if self.action_mode == self.MODE_INSTALL_SINGLE: - self._self_upgrade_finished(success,error_string,error_desc) - else: - if self.now_upgrade.version_upgrade == True and self.now_upgrade.need_retry == True and success == False: - #增加重试次数的限制 - if self.window_main.retry_limit != 0: - logging.warning("Retry the upgrade and installaton(%s) and retry number: %d",self.now_upgrade.upgrade_content,self.window_main.retry_limit) - self.window_main.start_install(self.action_mode,True,self.now_upgrade.upgrade_content) - self.window_main.retry_limit = self.window_main.retry_limit - 1 - return - try: - false_num = self._make_insert_info(success,is_cancelled,self.now_upgrade,error_string,error_desc) - except Exception as e: - logging.error(e) + self.exit_installed() + + if self.action_mode == self.MODE_INSTALL_STEP: + if self.run_steps_script(100,self.backend_data.last_task,'') == False: + error_string = get_error_string_from_enum(ERROR_RUN_SCRIPTS_FAILED) + error_desc = get_error_description_from_enum(ERROR_RUN_SCRIPTS_FAILED) + success = False - if success == False: - logging.info("The number of failed installations or upgrades is %d",false_num) + #弹窗的处理过程 在全部安装时不会进行弹窗 + if success and self.backend_data.last_task != self.backend_data.resolver_name: + post_info = self.backend_data.get_post_notify() + if post_info != '': + self.dbus_send.PopupStepsInstalled(True,post_info) + self.dbus_send.RebootLogoutRequired("reboot") + + if success == False or self.backend_data.last_task == self.backend_data.resolver_name: + self.database.insert_info(action,self.meta_upgrade.single_pkgs,\ + self.meta_upgrade.upgrade_groups,[],success,error_string,error_desc) - #修复bug 所有的包都安装成功了,但是却返回的失败,计算这种状况 从失败切换到安装成功的状态 - #这个 为True的很低 大多数为False 只有当系统中apt 出现问题时 才会复现这种问题 - if success == False and false_num == 0 and self.now_upgrade.upgrade_content != []: - logging.warning("Special Case switch success status from False to True...") - # success = True + self.dbus_send.InstallDetectStatus(False,get_error_code_from_enum(error_code)) + self.dbus_send.UpdateInstallFinished(success,self.meta_upgrade.get_content(),error_string,error_desc) + + self.window_main.refresh_cache() + + elif self.action_mode == self.MODE_INSTALL_SINGLE: + self._self_upgrade_finished(success,error_string,error_desc,error_code) + else: + #下载重试机制的判断 + if self.meta_upgrade.version_upgrade == True and success == False and error_code == ERROR_PACKAGE_DOWNLOAD_FAILED: + if self.dbus_send.check_connectivity_pro() == True: + if self.window_main.retry_limit != 0: + logging.warning("Retry the upgrade and installaton and retry number: %d",self.window_main.retry_limit) + self.window_main.start_install(self.action_mode,True,self.meta_upgrade.push_content) + self.window_main.retry_limit = self.window_main.retry_limit - 1 + return + + #更新完毕后执行脚本的操作 + for groups in self.meta_upgrade.upgrade_groups: + if self.run_steps_script(100,groups,'') == False: + error_string = get_error_string_from_enum(ERROR_RUN_SCRIPTS_FAILED) + error_desc = get_error_description_from_enum(ERROR_RUN_SCRIPTS_FAILED) + success = False + + self.database.insert_info(action,self.meta_upgrade.single_pkgs,self.meta_upgrade.upgrade_groups\ + ,[],success,error_string,error_desc) + self.dbus_send.InstallDetectStatus(False,get_error_code_from_enum(error_code)) + self.dbus_send.UpdateInstallFinished(success,self.meta_upgrade.get_content(),error_string,error_desc) if success: - #当组列表为空时 表示现在的单独进行安装某些包或卸载,不发信号到控制面板 - #升级完成后从升级列表删除 - for groups in self.now_upgrade.upgrade_groups: - self.upgrade_data.upgrade_groups.remove(groups) - - for pkg in self.now_upgrade.single_pkgs: - self.upgrade_data.single_pkgs.remove(pkg) - - error_string = '' - error_desc = '' - - self.window_main.dbusController.UpdateInstallFinished(success,self.now_upgrade.upgrade_content,error_string,error_desc) - - if success: - self.window_main.dbusController.CheckRebootRequired("self") - #安装完成之后 更新一次cache + self.backend_data.pop(self.meta_upgrade.get_content()) + self.dbus_send.CheckRebootRequired("self") logging.info("Install or Upgrade successful, so Now update Cache...") self.window_main.refresh_cache() - + elif action == self.ACTION_INSTALL_SHUTDOWN: # self._release_install_lock() self._send_error_code(error_code) #插入数据库 - self.window_main.sqlite3_server.insert_info(self.ACTION_INSTALL,self.now_upgrade.single_pkgs,\ - self.now_upgrade.upgrade_groups,[],success,error_string,error_desc) + self.database.insert_info(self.ACTION_INSTALL,self.meta_upgrade.single_pkgs,\ + self.meta_upgrade.upgrade_groups,[],success,error_string,error_desc) if success == True: #当升级完成时 将手动和自动安装的标志位全部清空 self.window_main.install_mode.install_finished() - self.window_main.dbusController.UpdateInstallFinished(success,self.now_upgrade.upgrade_content,error_string,error_desc) + self.dbus_send.UpdateInstallFinished(success,self.meta_upgrade.get_content(),error_string,error_desc) #释放锁 允许关机 if self.window_main.install_mode.inhibit_lock != None: @@ -735,33 +774,25 @@ class InstallBackend(): else: logging.error("Install Packages Finished and Releasing the shutdown lock Failed...") #升级本身完成后 来释放关机锁 - self.window_main.dbusController.Quit(None) + self.dbus_send.Quit(None) elif action == self.ACTION_CHECK_RESOLVER: if success == False: - self.window_main.sqlite3_server.insert_info(self.action_mode,self.now_upgrade.single_pkgs,\ - self.now_upgrade.upgrade_groups,[],success,error_string,error_desc) + self.database.insert_info(self.action_mode,self.meta_upgrade.single_pkgs,\ + self.meta_upgrade.upgrade_groups,[],success,error_string,error_desc) if self.action_mode != self.MODE_INSTALL_SYSTEM: - self.window_main.dbusController.UpdateDependResloveStatus(success,False,[''],[''],[''],error_string,error_desc) + self.dbus_send.UpdateDependResloveStatus(success,False,[''],[''],[''],error_string,error_desc) else: - self.window_main.dbusController.DistupgradeDependResloveStatus(success,False,[''],[''],[''],error_string,error_desc) + self.dbus_send.DistupgradeDependResloveStatus(success,False,[''],[''],[''],error_string,error_desc) elif action == self.ACTION_DOWNLOADONLY: - if self.now_upgrade.version_upgrade == True and self.now_upgrade.need_retry == True and success == False: - #增加重试次数的限制 - if self.window_main.retry_limit != 0: - logging.warning("Retry the upgrade and installaton(%s) and retry number: %d",self.now_upgrade.upgrade_content,self.window_main.retry_limit) - self.window_main.start_install(self.action_mode,True,self.now_upgrade.upgrade_content) - self.window_main.retry_limit = self.window_main.retry_limit - 1 - return - if success == True and self.action_mode == self.MODE_INSTALL_PARTIAL: - self.window_main.install_mode.tmp_content += self.now_upgrade.upgrade_content + self.window_main.install_mode.tmp_content += self.meta_upgrade.get_content() if success == False: - self.window_main.sqlite3_server.insert_info(self.action_mode,self.now_upgrade.single_pkgs,\ - self.now_upgrade.upgrade_groups,[],success,error_string,error_desc) + self.database.insert_info(self.action_mode,self.meta_upgrade.single_pkgs,\ + self.meta_upgrade.upgrade_groups,[],success,error_string,error_desc) #如果下载成功 就标志需要 安装重启 if success == True: @@ -770,7 +801,7 @@ class InstallBackend(): self.window_main.install_mode.set_shutdown_install(success) - self.window_main.dbusController.UpdateDownloadFinished(success,self.now_upgrade.upgrade_content,error_string,error_desc) + self.dbus_send.UpdateDownloadFinished(success,self.meta_upgrade.get_content(),error_string,error_desc) elif action == self.ACTION_UPDATE and self.action_mode == self.MODE_UPDATE_ALL: if success == False: @@ -790,21 +821,24 @@ class InstallBackend(): #开始生成列表 self.window_main.start_available() else: - self.window_main.dbusController.UpdateDetectFinished(success,[''],get_error_string_from_enum(ERROR_UPDATE_DEFAULT_FAILED),\ + self.dbus_send.InstallDetectStatus(False,get_error_code_from_enum(error_code)) + self.dbus_send.UpdateDetectFinished(False,[''],get_error_string_from_enum(ERROR_UPDATE_DEFAULT_FAILED),\ error_string +' '+error_desc) - self.window_main.sqlite3_server.insert_into_display("check_time",get_east_8_time()[0:-4]) + self.database.insert_into_display("check_time",get_east_8_time()[0:-4]) elif action == self.ACTION_UPDATE and self.action_mode == self.MODE_UPDATE_CACHE: - self.window_main.dbusController.UpdateDetectFinished(success,[''],error_string,error_desc) + self.dbus_send.InstallDetectStatus(False,get_error_code_from_enum(error_code)) + self.dbus_send.UpdateDetectFinished(success,[''],error_string,error_desc) elif action == self.ACTION_FIX_BROKEN: - self.window_main.dbusController.FixBrokenStatusChanged(True,success,100,'',error_string,error_desc) + self.dbus_send.FixBrokenStatusChanged(True,success,100,'',error_string,error_desc) logging.warning("fix broken packages is complete...") if success: logging.info("Fix broken packages is complete to success...") self.window_main.start_available() else: - self.window_main.dbusController.UpdateDetectFinished(success,[''],\ + self.dbus_send.InstallDetectStatus(False,get_error_code_from_enum(ERROR_NOT_FIX_SYSTEM)) + self.dbus_send.UpdateDetectFinished(success,[''],\ get_error_string_from_enum(ERROR_NOT_FIX_SYSTEM),error_string+' '+error_desc) logging.error("fix broken packages is complete to failed...") @@ -816,32 +850,35 @@ class InstallBackend(): elif action == self.ACTION_REMOVE_PACKAGES: self._release_install_lock() - self.window_main.dbusController.PurgePackagesFinished(success,error_string,error_desc) - - elif action == self.ACTION_INSTALL_DEB: + # self.dbus_send.PurgePackagesFinished(success,error_string,error_desc," ".join(self.window_main.sqlite3_server.current_purge_pkgs)) + self.dbus_send.PurgePackagesFinished(success,error_string,error_desc) + + elif action == self.ACTION_INSTALL_DEB or action == self.ACTION_INSTALL_DEB_RESOLVER: self._release_install_lock() - #FIXME: '\r\n: \r\n\r\n'就认为是验证失败 if success == False and '\r\n: \r\n\r\n' in self.aptd_base.error_details: error_string = _("Package validation failed and installation was rejected.") error_desc = '' - self.window_main.dbusController.InstalldebFinished(success,error_string,error_desc) - UpdateMsg = {} - if success: - status = 'success' - UpdateMsg.update({"errorCode":" "}) - else: - status = 'failed' - UpdateMsg.update({"errorCode":str(error_string+" "+error_desc)}) - #apt发送数据 - if self.window_main.configs_uncover.getWithDefault("SystemStatus", "upload_installer_log", False) == True: - - UpdateMsg.update({"appname":str(self.window_main.deb_obj.get("debname","None").split("_")[0])}) - UpdateMsg.update({"source":str(self.window_main.deb_obj.get("source","kylin-system-updater"))}) - UpdateMsg.update({"status":str(status)}) - UpdateMsg.update({"new_version":str(self.window_main.deb_obj.get("debname","None").split("_")[1])}) - UpdateMsg.update({"old_version":str(self.window_main.deb_obj.get("old_version","None"))}) - self.window_main.collector.Upgrade_Process_Msg(self.action, UpdateMsg.copy()) - self.window_main.deb_obj = {} + if error_code != None and str(error_code) != 'error-dep-resolution-failed': + if error_desc != '': + error_string = ",".join((error_string,error_desc)) + self.dbus_send.InstalldebFinished(success,error_string,'') + UpdateMsg = {} + if success: + status = 'success' + UpdateMsg.update({"errorCode":" "}) + else: + status = 'failed' + UpdateMsg.update({"errorCode":str(error_string+" "+error_desc)}) + #apt发送数据 + if self.window_main.configs_uncover.getWithDefault("SystemStatus", "upload_installer_log", False) == True: + + UpdateMsg.update({"appname":str(self.window_main.deb_obj.get("debname","None").split("_")[0])}) + UpdateMsg.update({"source":str(self.window_main.deb_obj.get("source","kylin-system-updater"))}) + UpdateMsg.update({"status":str(status)}) + UpdateMsg.update({"new_version":str(self.window_main.deb_obj.get("debname","None").split("_")[1])}) + UpdateMsg.update({"old_version":str(self.window_main.deb_obj.get("old_version","None"))}) + self.collector.Upgrade_Process_Msg(self.action, UpdateMsg.copy()) + self.window_main.deb_obj = {} elif action == self.ACTION_BACKGROUND_UPGRADE: self._release_install_lock() UpdateMsg = {} @@ -849,22 +886,38 @@ class InstallBackend(): status = 'success' else: status = 'failed' - self.window_main.collector.Generate_Msg(self.window_main.collector.background_list, self.action_mode) - for bl in self.window_main.collector.background_list: - pkg = self.window_main.collector.cache[bl] + self.collector.Generate_Msg(self.collector.background_list, self.action_mode) + for bl in self.collector.background_list: + pkg = self.collector.cache[bl] UpdateMsg.update({"appname":str(bl)}) UpdateMsg.update({"source":"Kylin Background upgrade"}) UpdateMsg.update({"status":str(status)}) UpdateMsg.update({"errorCode":str(error_string+" "+error_desc)}) - if self.window_main.collector.background_version[bl]: - UpdateMsg.update({"old_version":self.window_main.collector.background_version[bl]}) - UpdateMsg.update({"new_version":self.window_main.collector.cache[bl].candidate.source_version}) - # self.window_main.collector.Upgrade_Process_Msg(self.action, UpdateMsg.copy()) + if self.collector.background_version[bl]: + UpdateMsg.update({"old_version":self.collector.background_version[bl]}) + UpdateMsg.update({"new_version":self.collector.cache[bl].candidate.source_version}) + # self.collector.Upgrade_Process_Msg(self.action, UpdateMsg.copy()) - self.window_main.dbusController.UpdateInstallFinished(success,self.now_upgrade.upgrade_content,error_string,error_desc) + self.dbus_send.UpdateInstallFinished(success,self.meta_upgrade.get_content(),error_string,error_desc) + + def entering_installed(self): + '''进入安装的状态 + 1、禁止关机的锁 + 2、关闭安全机制 + ''' + logging.info("The process is now in the installtion phase") + # self.safe_manager.shutdown_safe() + self._start_install_lock(_("Kylin System Updater")) + def exit_installed(self): + '''退出安装的状态 + 1、释放禁止关机的锁 + 2、还原安全的配置 + ''' + # self.safe_manager.reset_safe() + self._release_install_lock() - def _start_install_lock(self, caller='Kylin System Updater'): + def _start_install_lock(self, caller='kylin-system-updater'): self.window_main.configs_uncover.setValue("SystemStatus","abnormal_reboot",str(True)) self.inhibit_shutdown.lock(caller=caller) @@ -880,22 +933,24 @@ class InstallBackend(): run_cmd = ["/bin/plymouth","system-update",tmp] subprocess.call(run_cmd) - def _update_to_config(self,now_upgrade,pkgs_install,pkgs_upgrade,pkgs_remove): - output_upgrade = {} + def _update_to_config(self,meta_upgrade,pkgs_install,pkgs_upgrade,pkgs_remove): + try: + output_upgrade = {} - output_upgrade.update({"upgrade_groups":now_upgrade.upgrade_groups}) - output_upgrade.update({"single_pkgs":now_upgrade.single_pkgs}) - output_upgrade.update({"pkgs_install":pkgs_install}) - output_upgrade.update({"pkgs_upgrade":pkgs_upgrade}) - output_upgrade.update({"pkgs_remove":pkgs_remove}) + output_upgrade.update({"push_groups":meta_upgrade.upgrade_groups}) + output_upgrade.update({"push_pkgs":meta_upgrade.single_pkgs}) + output_upgrade.update({"pkgs_install":pkgs_install}) + output_upgrade.update({"pkgs_upgrade":pkgs_upgrade}) + output_upgrade.update({"pkgs_remove":pkgs_remove}) + #6 产生JSON文件 + with open(self.INSTALL_OUTPUT_JSON, 'w', encoding='utf-8') as f: + json.dump(output_upgrade, f, ensure_ascii=False, indent=4) - #6 产生JSON文件 - with open(self.INSTALL_OUTPUT_JSON, 'w', encoding='utf-8') as f: - json.dump(output_upgrade, f, ensure_ascii=False, indent=4) - - logging.info("Generate Jsonfile(%s) to complete... ",self.INSTALL_OUTPUT_JSON) - logging.info("Update Packages list to config file in shutdown model...") + logging.info("Generate Jsonfile(%s) to complete... ",self.INSTALL_OUTPUT_JSON) + logging.info("Update Packages list to config file...") + except Exception as exc: + logging.error(exc) def _config_to_upgrade(self): #读取组JSON文件 @@ -908,87 +963,15 @@ class InstallBackend(): try: data = json.load(f) - upgrade_groups = data["upgrade_groups"] - single_pkgs = data["single_pkgs"] + upgrade_groups = data["push_groups"] + single_pkgs = data["push_pkgs"] pkgs_install = data["pkgs_install"] pkgs_upgrade = data["pkgs_upgrade"] pkgs_remove = data["pkgs_remove"] except Exception as exc: logging.error(exc) - return NowUpgradeMeta(self,upgrade_groups,single_pkgs),pkgs_install,pkgs_upgrade,pkgs_remove - - #将安装完成的插入数据库 安装失败的计算那些包安装失败了 分类插入数据库中 - #将安装失败的数据进行返回 - def _make_insert_info(self,success,is_cancelled,_now_upgrade,error_string,error_desc): - false_num = 0 - #目前去掉打印 错误日志 - # error_desc = error_desc +'\n\n'+self.aptd_base.error_details - #在安装失败 and 不是取消升级 则走下面的 否则不计算全部直接插入数据库 - if success == False and is_cancelled == False and self.action_mode != self.MODE_INSTALL_SYSTEM: - #获取当前系统中最新的cache - fresh_cache = Cache(rootdir=self.window_main.cache.rootdir) - #获取调整包列表 去掉版本号 - adjust_pkgs = [i.split("=")[0] for i in self.upgrade_data.adjust_pkgs] - - #升级存在单包更新 失败后计算每一个包是否安装完成 相应判断进行插入 - for pkg in _now_upgrade.single_pkgs: - pkg_obj = fresh_cache[pkg] - - #判断是否是源过滤调整的包 调整的话 判断安装版本 来解决是否安装成功 - if pkg in adjust_pkgs: - if pkg_obj._pkg.inst_state == apt_pkg.INSTSTATE_OK and pkg_obj._pkg.current_state == apt_pkg.CURSTATE_INSTALLED and pkg_obj.name + '=' + pkg_obj.installed.source_version in self.upgrade_data.adjust_pkgs: - self.window_main.sqlite3_server.insert_info(self.action_mode,[pkg],[],self.upgrade_data.adjust_pkgs,True,'', '') - else: - false_num += 1 - logging.warning("This single-package(%s) is not install or upgrade",pkg) - self.window_main.sqlite3_server.insert_info(self.action_mode,[pkg],[],self.upgrade_data.adjust_pkgs,False,error_string, error_desc) - else: - #非调整版本的计算方式 - if pkg_obj._pkg.inst_state == apt_pkg.INSTSTATE_OK and pkg_obj._pkg.current_state == apt_pkg.CURSTATE_INSTALLED and pkg_obj.is_now_broken == False: - self.window_main.sqlite3_server.insert_info(self.action_mode,[pkg],[],self.upgrade_data.adjust_pkgs,True,'', '') - else: - false_num += 1 - logging.warning("This single-package(%s) is not install or upgrade",pkg) - self.window_main.sqlite3_server.insert_info(self.action_mode,[pkg],[],self.upgrade_data.adjust_pkgs,False,error_string, error_desc) - - #组的计算是否升级成功的方式 将组按照单包来计算的 - if _now_upgrade.upgrade_groups != []: - pkgs_install,pkgs_upgrade = self._make_pkgs_list(self.cache,self.upgrade_data.groups_pkgs,_now_upgrade.upgrade_groups,[]) - install_error_pkgs = [] - total_pkg = pkgs_install + pkgs_upgrade - - for pkg in total_pkg[::-1]: - pkg_obj = fresh_cache[pkg] - if pkg in adjust_pkgs: - if pkg_obj.is_installed == True and pkg_obj.is_now_broken == False and pkg_obj.installed.source_version + pkg_obj.name in self.upgrade_data.adjust_pkgs: - total_pkg.remove(pkg) - else: - install_error_pkgs.append(pkg) - else: - if pkg_obj._pkg.inst_state == apt_pkg.INSTSTATE_OK and pkg_obj._pkg.current_state == apt_pkg.CURSTATE_INSTALLED and pkg_obj.is_now_broken == False: - total_pkg.remove(pkg) - else: - install_error_pkgs.append(pkg) - - # group_error_log = '\n'+ "This groups-package"+str(install_error_pkgs)+" is not install or upgrade" + '\n' - # logging.warning(group_error_log) - #如果没有 - if total_pkg == []: - self.window_main.sqlite3_server.insert_info(self.action_mode,[],_now_upgrade.upgrade_groups,self.upgrade_data.adjust_pkgs,True,'', '') - else: - false_num += 1 - self.window_main.sqlite3_server.insert_info(self.action_mode,[],_now_upgrade.upgrade_groups,self.upgrade_data.adjust_pkgs,False,error_string,error_desc) - #关闭临时cache - fresh_cache.close() - #其他情况直接写入数据库 不进行计算 - else: - #取消的话全部是失败 - if is_cancelled == True: - false_num = len(_now_upgrade.single_pkgs) + len(_now_upgrade.upgrade_groups) - self.window_main.sqlite3_server.insert_info(self.action_mode,_now_upgrade.single_pkgs,_now_upgrade.upgrade_groups,self.upgrade_data.adjust_pkgs,success,error_string, error_desc) - - return false_num + return NowUpgradeMeta(_upgrade_groups=upgrade_groups,_single_pkgs=single_pkgs),pkgs_install,pkgs_upgrade,pkgs_remove def emulate_calcul_broken(self,pkgs): args = ["apt-get", "install","--simulate"] @@ -1096,7 +1079,7 @@ class InhibitShutdownLock(): self.pidfile = None #安装时禁止关机 进行加锁 - def lock(self, caller='Kylin System Updater'): + def lock(self, caller='kylin-system-updater'): """ Send a dbus signal to logind to not suspend the system, it will be released when the return value drops out of scope @@ -1109,8 +1092,8 @@ class InhibitShutdownLock(): 'org.freedesktop.login1', '/org/freedesktop/login1', 'org.freedesktop.login1.Manager', 'Inhibit', GLib.Variant('(ssss)', - ('shutdown', - caller, 'Installing Packages', + ('shutdown:sleep', + caller, _("Installing or removing software packages."), 'block')), None, 0, -1, None, None) self.inhibit_lock = Gio.UnixInputStream(fd=fdlist.steal_fds()[var[0]]) @@ -1239,5 +1222,5 @@ class UpdateSafeManager(): logging.info("Set kysec_xattr_set_func_status %s...",str(value)) return True except Exception as e: - logging.error("Set kylin Sec Failed and fun:%d value:%d Error msg:" + str(e),fun,value) + logging.warning("Set kylin Sec Failed and fun:%d value:%d Error msg:" + str(e),fun,value) return False diff --git a/backend/data/cn.kylinos.KylinSystemUpdater.policy b/backend/data/cn.kylinos.KylinSystemUpdater.policy index 64c3262..90ef97b 100644 --- a/backend/data/cn.kylinos.KylinSystemUpdater.policy +++ b/backend/data/cn.kylinos.KylinSystemUpdater.policy @@ -8,9 +8,10 @@ www.kylinos.cn kylin-system-updater - + + <_description> - system level settings + Configuration items added for Kirin Installer <_message> To Change the settings, you need to authenticate. @@ -22,4 +23,47 @@ + + <_description> + Configuration items added for Kirin Uninstaller + + <_message> + To Change the settings, you need to authenticate. + + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + + <_description> + Configuration items added for Kirin Installer + + <_message> + To Change the settings, you need to authenticate. + + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + + <_description> + Configuration items added for Kylin Software Center + + <_message> + To Change the settings, you need to authenticate. + + + auth_admin + auth_admin + auth_admin + + diff --git a/backend/data/com.kylin.UpgradeStrategies.service b/backend/data/com.kylin.UpgradeStrategies.service index 4b70a1d..7d913e8 100644 --- a/backend/data/com.kylin.UpgradeStrategies.service +++ b/backend/data/com.kylin.UpgradeStrategies.service @@ -1,4 +1,4 @@ [D-BUS Service] Name=com.kylin.UpgradeStrategies -Exec=/bin/python3 /usr/share/kylin-system-updater/kylin-upgrade-strategies -r -d +Exec=/usr/share/kylin-system-updater/kylin-upgrade-strategies User=root \ No newline at end of file diff --git a/backend/data/kylin-system-updater.db b/backend/data/kylin-system-updater.db index 26e9d4002d4f1ae79fbb7601302d507d488dfce6..934a0759fc6287619ba617e0fcd2a90aa63aba70 100644 GIT binary patch delta 66 zcmZoTz|?SnX@WFk`a~IL#`KK|%lKKYGVovBEU0jrUtW`upOb+>9E=!5#YKhF5_5`E P!9+<>Y3k-L@;nUyf58(x delta 65 zcmZoTz|?SnX@WFk+C&*=#9E=!*#YKhF5_5`E O!9-, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: kylinos.cn\n" +"POT-Creation-Date: 2012-06-14 00:53+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Unable to access the source management server, please try again later" +msgstr "འདྲི་རྩད་ཀྱི་འབྱུང་ཁུངས་དོ་དམ་ཞབས་ཞུའི་ཡོ་བྱད་ལ་འཚམས་འདྲི་བྱེད་ཐབས་མེད་པས་རྗེས་སུ་ཡང་བསྐྱར" + +msgid "Access to the source management server timed out, please try again later" +msgstr "འཚམས་འདྲིའི་འབྱུང་ཁུངས་ཀྱི་དོ་དམ་ཞབས་ཞུའི་ཡོ་བྱད་དུས་ལས་བརྒལ་བས་རྗེས་སུ་ཡང་བསྐྱར་ཚོད་ལྟ་བྱེད་རོགས" + +msgid "Check if your network requires authentication?" +msgstr "ཁྱེད་ཀྱི་དྲ་རྒྱར་ཞིབ་བཤེར་བྱེད་དགོས་སམ།" + +msgid "Check your source public key signature" +msgstr "ཁྱེད་ཀྱི་འབྱུང་ཁུངས་ལ་ཞིབ་བཤེར་བྱས་ནས་མིང་རྟགས་བཀོད།" + +msgid "update important list occur Exception" +msgstr "ལག་ཏུ་བླངས་ནས་རྒྱུན་ལྡན་མིན་པ་བྱུང་ན་རྗེས་སུ་ཡང་བསྐྱར་ཚོད་ལྟ་ཞིག་གནང་རོགས།" + +msgid "You need to be root to run this application" +msgstr "ཁྱོད་ལ་rootཡི་དབང་ཚད་ལྟར་འཁོར་སྐྱོད་བྱེད་དགོས།" + +msgid "There is an exception in the update package." +msgstr "ཁུག་མ་གསར་སྒྱུར་བྱས་པ་རྒྱུན་ལྡན་མིན་པ་ཞིག་རེད" + +msgid "You request the removal of a system-essential package." +msgstr "ཁྱེད་ཀྱིས་མ་ལག་ཅིག་གི་དགོས་ངེས་ཀྱི་མཉེན་ཆས་ཁུག་མ་ཞིག་བསུབ་དགོས་པའི་བླང་བྱ་" + +msgid "This update cannot detect the upgradeable package." +msgstr "ཐེངས་འདིའི་གསར་སྒྱུར་གྱིས་རིམ་འཕར་ཐུབ་པའི་མཉེན་ཆས་ཁུག་མར་ཞིབ་དཔྱད་ཚད་ལེན་བྱེད་ཐབས་མེད།" + +msgid "read important list failed" +msgstr "རིམ་པ་སྤོར་བའི་རེའུ་མིག་ཀློག་ཐབས་བྲལ་བས་རྗེས་སུ་ཡང་བསྐྱར་ཚོད་ལྟ་ཞིག་བྱེད་རོགས།" + +msgid "Priority Upgrade Package being updated" +msgstr "ཁག་བགོས་ཀྱི་བཀོད་སྒྲིག་གསར་སྒྱུར་བྱེད་བཞིན་ཡོད།" + +msgid "Exceptions of Priority Upgrade." +msgstr "དམིགས་སུ་བཀར་ནས་དམིགས་སུ་བཀར་ནས་རིམ་པ" + +msgid "Due to the presence of deleted packages." +msgstr "བསུབ་པའི་མཉེན་ཆས་ཁུག་མ་ཡོད་པའི་རྐྱེན་གྱིས།" + +msgid "The system update configuration file is read abnormally, please check if the system update configuration file format is correct." +msgstr "མ་ལག་གསར་སྒྱུར་བཀོད་སྒྲིག་ཡིག་ཆ་རྒྱུན་ལྡན་མིན་པས། ཞིབ་བཤེར་མ་ལག་གི་བཀོད་སྒྲིག་ཡིག་ཆའི་རྣམ་གཞག་ཡང་དག་ཡིན་མིན་ལ་ཞིབ་བཤེར་གནང་རོགས།" + +msgid "Installation progress: " +msgstr "སྒྲིག་སྦྱོར་མྱུར་ཚད་གཤམ་གསལ། " + +msgid "Installation successful, about to shut down" +msgstr "སྒྲིག་སྦྱོར་ལེགས་འགྲུབ་བྱུང་བ་དང་འགག་སྒོ་ལས་སྒྲོལ་གྲབས་ཡོད་" + +msgid "Installation failed, about to shut down" +msgstr "སྒྲིག་སྦྱོར་བྱས་ནས་ཕམ་ཉེས་བྱུང་ན་སྒོ་རྒྱག་ལ་ཉེ།" + +msgid "groups JSON ConfigPkgs install failed" +msgstr "ཁག་བགོས་ཀྱིས་ཡིག་ཆ་སྒྲིག་སྦྱོར་བྱེད་ཐབས་མེད།" + +msgid "Installtion timeout to exit Due to inactivity" +msgstr "སྒྲིག་སྦྱོར་བྱེད་སྐབས་ཕྱིར་འཐེན་བྱས་པའི་རྐྱེན་གྱིས་རེད།" + +msgid "Command execution error" +msgstr "ཚགས་པར་འདོན་ནོར་ཤོར་བའི་བཀའ་ཕབ་པ།" + +msgid "Unsupported architecture" +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 "ཁབ་ལེན་གྱི་བར་སྟོང་མི་འདང་བས་ཁབ་ལེན་སྡེར་མ་གཙང་བཤེར་བྱས་རྗེས་རིམ་སྤར་གསར་སྒྱུར་བྱེད་རོགས།" + +msgid "Network anomaly, can't check for updates!" +msgstr "དྲ་རྒྱ་རྒྱུན་ལྡན་མིན་པས་ཞིབ་བཤེར་གསར་སྒྱུར་བྱེད་ཐབས་མེད།" + +msgid "Check for update exceptions!" +msgstr "རྒྱུན་ལྡན་མིན་པར་ཞིབ་བཤེར་བྱེད་པ།" + +msgid "Check for update exceptions,fix system APT environment error." +msgstr "ཞིབ་བཤེར་གསར་སྒྱུར་མ་ལག་APTཡི་ཁོར་ཡུག་ལ་ནོར་འཁྲུལ་བྱུང་བ་རེད།" + +msgid "The system APT environment is abnormal, please check the system APT environment." +msgstr "མ་ལག་APTཡི་ཁོར་ཡུག་རྒྱུན་ལྡན་མིན་པར་ཉམས་གསོ་བྱེད་པར་མ་ལག་APTཡི་ཁོར་ཡུག་ལ་ཞིབ་བཤེར་གནང་རོགས།" + +msgid "Priority upgrade status exception." +msgstr "དམིགས་སུ་བཀར་ནས་རིམ་པ་འཕར་བའི་རྣམ་པ་རྒྱུན་ལྡན་མིན་པ" + +msgid "Upgrade configuration acquisition exception." +msgstr "རིམ་སྤར་བཀོད་སྒྲིག་ལ་རྒྱུན་ལྡན་མིན་པའི་གྲུབ་འབྲས་ཐོབ་པ་རེད།" + +msgid "Please check your network connection and retry." +msgstr "ཁྱེད་ཀྱི་དྲ་རྒྱ་འབྲེལ་མཐུད་བྱས་རྗེས་ཡང་བསྐྱར་ཚོད་ལྟ་ཞིག་བྱེད་རོགས།" + +msgid "Please check your source list and retry." +msgstr "ཁྱེད་ཀྱི་འབྱུང་ཁུངས་རེའུ་མིག་ལ་ཞིབ་བཤེར་བྱས་རྗེས་ཡང་བསྐྱར་ཚོད་ལྟ་བྱོས།" + +msgid "Checking network connection" +msgstr "དྲ་རྒྱ་སྦྲེལ་མཐུད་བྱེད་པར་ཞིབ་བཤེར་བྱ་དགོས།" + +msgid "Updating Source Template" +msgstr "འབྱུང་ཁུངས་གསར་སྒྱུར་བྱེད་པའི་མ་དཔེའི་ནང་།" + +msgid "Update Manager upgrade is complete, please restart the setting panel before performing the system update." +msgstr "དོ་དམ་ཡོ་བྱད་རིམ་སྤར་ལེགས་འགྲུབ་བྱུང་བ་དང་། གསར་བཅོས་བྱས་རྗེས་སླར་ཡང་མ་ལག་གསར་སྒྱུར་བྱེད་རོགས།" + +msgid "Uninstallation completed" +msgstr "ཕབ་ལེན་ལེགས་འགྲུབ་བྱུང་བ།" + +msgid "Package validation failed and installation was rejected." +msgstr "མཉེན་ཆས་ཚོད་ལྟས་ར་སྤྲོད་བྱས་ནས་ཕམ་ཁ་བྱུང་བས་སྒྲིག་སྦྱོར་དང་ལེན་མ་བྱས" + +msgid "Other tasks are being updated and upgraded, please uninstall them later." +msgstr "ལས་འགན་གཞན་དག་གསར་སྒྱུར་རིམ་སྤོར་བྱེད་བཞིན་པའི་སྒང་ཡིན་" + +#: ../aptdaemon/worker/aptworker.py:1353 +msgid "The following packages have unmet dependencies:" +msgstr "གཤམ་གསལ་གྱི་མཉེན་ཆས་ཁུག་མ་ཡིད་ཚིམ་པའི་གཞན་རྟེན་གྱི་འབྲེལ་བ།" + +#: ../aptdaemon/worker/aptworker.py:1406 +msgid "but it is a virtual package" +msgstr "འོན་ཀྱང་དེ་ནི་རྟོག་བཟོའི་མཉེན་ཆས་ཁུག་མ་རེད།" + +#: ../aptdaemon/worker/aptworker.py:1409 +msgid "but it is not installed" +msgstr "但是 %s 没有安装" + +#: ../aptdaemon/worker/aptworker.py:1411 +msgid "but it is not going to be installed" +msgstr "但是无法安装 %s" + +#. TRANSLATORS: %s is a version number +#: ../aptdaemon/worker/aptworker.py:1415 +#, python-format +msgid "but %s is installed" +msgstr "但是 %s 已经安装" + +#. TRANSLATORS: %s is a version number +#: ../aptdaemon/worker/aptworker.py:1419 +#, python-format +msgid "but %s is to be installed" +msgstr "但是将要安装 %s" + +#: ../SystemUpdater/Core/enums.py:763 +msgid "Kylin System Updater" +msgstr "ཝེ།སྒྲིག་ཆས་གསར་སྒྱུར་བྱེད་དགོས།" + +#: ../SystemUpdater/Core/enums.py:609 +msgid "Kylin Installer" +msgstr "ཝེ།སྒྲིག་ཆས་སྒྲིག་སྦྱོར་བྱེད་དགོས།" + +#: ../SystemUpdater/Core/enums.py:610 +msgid "Kylin Uninstaller" +msgstr "ཝེ།བཏགས་ཆས་" + +#: ../SystemUpdater/Core/enums.py:611 +msgid "Kylin Background Upgrade" +msgstr "ཁ་རོག་གེར་གསར་སྒྱུར་བྱེད་པ།" + +#: ../SystemUpdater/Core/enums.py:612 +msgid "Kylin Software Center" +msgstr "མཉེན་ཆས་ཚོང་ཁང་།" + +#: ../SystemUpdater/UpdateManagerDbus.py:355 +msgid " requires authentication to uninstall software packages." +msgstr "མཉེན་ཆས་ཀྱི་ཁུག་མ་འདོན་པར་བདེན་དཔང་ར་སྤྲོད་བྱེད་དགོས།" + +#. 验签失败,提权 +#: ../SystemUpdater/UpdateManager.py:463 +msgid " requires authentication to install software packages." +msgstr "མཉེན་ཆས་ཀྱི་ཁུག་མ་སྒྲིག་སྦྱོར་བྱེད་པར་བདེན་དཔང་ར་སྤྲོད་བྱེད" + +#: ../SystemUpdater/Core/utils.py:750 +msgid "Authentication success." +msgstr "བདེན་དཔང་ར་སྤྲོད་ལེགས་འགྲུབ་བྱུང་" + +#: ../SystemUpdater/Core/utils.py:753 +msgid "Authentication failure." +msgstr "བདེན་དཔང་ར་སྤྲོད་ཕམ་སོང་།" + +#: ../SystemUpdater/Core/enums.py:101 +msgid "Deb format exception, read local deb file error." +msgstr "མཉེན་ཆས་ཀྱི་ཁུག་མའི་རྣམ་གཞག་རྒྱུན་ལྡན་མིན་པས་ཕམ་ཁ་བླངས།" + +#: ../SystemUpdater/Core/enums.py:102 +msgid "Install deb error." +msgstr "མཉེན་ཆས་སྒྲིག་སྦྱོར་བྱས་པ་ཕམ་སོང་།" + +msgid "Upgrade System" +msgstr "ཁྱོན་ཡོངས་ནས་རིམ་སྤར་བྱ་དགོས།" + +msgid "kylin-unattended-upgrade" +msgstr "རང་འགུལ་གྱིས་གསར་སྒྱུར་བྱེད་དགོས།" + +msgid "Please check the system time and synchronize the system time before updating." +msgstr "མ་ལག་གི་དུས་ཚོད་ལ་ཞིབ་བཤེར་གནང་རོགས། དུས་མཉམ་དུ་མ་ལག་གི་དུས་ཚོད་རྗེས་སུ་གསར་སྒྱུར་བྱེད་དགོས" + +msgid "The package is unsigned, refuses to install." +msgstr "མཉེན་ཆས་ཀྱི་ཁུག་མར་མིང་རྟགས་མ་བཀོད་པས་སྒྲིག་སྦྱོར་དང་ལེན་མི་བྱེད།" + +msgid "Program exception, please contact the administrator to solve." +msgstr "གོ་རིམ་ལག་བསྟར་རྒྱུན་ལྡན་མིན་པར་དོ་དམ་པ་དང་འབྲེལ་གཏུག་བྱས་ནས་ཐག་གཅོད" + +msgid "Exceptions to running the check script." +msgstr "འཁོར་སྐྱོད་ཞིབ་བཤེར་གྱི་རྐང་པར་རྒྱུན་ལྡན་མིན་པ་བྱུང་།" \ No newline at end of file diff --git a/backend/po/zh_CN.po b/backend/po/zh_CN.po index 6a2e677..3458214 100644 --- a/backend/po/zh_CN.po +++ b/backend/po/zh_CN.po @@ -2563,9 +2563,12 @@ msgstr "" msgid "%.0f kB" msgstr "%.0f kB" -msgid "Unable to access the source management server" +msgid "Unable to access the source management server, please try again later" msgstr "无法访问源管理服务器,请稍后再试" +msgid "Access to the source management server timed out, please try again later" +msgstr "访问源管理服务器超时,请稍后再试" + msgid "Check if your network requires authentication?" msgstr "检查您的网络需要认证吗?" @@ -2760,4 +2763,13 @@ msgid "Please check the system time and synchronize the system time before updat msgstr "请检查系统时间,同步系统时间后再进行更新。" msgid "The package is unsigned, refuses to install." -msgstr "软件包未签名,拒绝安装。" \ No newline at end of file +msgstr "软件包未签名,拒绝安装。" + +msgid "Program exception, please contact the administrator to solve." +msgstr "程序执行异常,请联系管理员解决。" + +msgid "Exceptions to running the check script." +msgstr "运行检查脚本出现异常。" + +msgid "Installing or removing software packages." +msgstr "正在安装或删除软件包。" \ No newline at end of file diff --git a/backend/po/zh_HK.po b/backend/po/zh_HK.po index 8aaec3e..a087c21 100644 --- a/backend/po/zh_HK.po +++ b/backend/po/zh_HK.po @@ -2525,7 +2525,7 @@ msgstr "因 grub 已安裝,移除 lilo (詳情見 bug #314004)" #~ msgstr "提取檔案及安裝升級可能要花數小時。一旦下載完成即不能取消升級程序。" -msgid "Unable to access the source management server" +msgid "Unable to access the source management server, please try again later" msgstr "無法存取來源管理伺服器,請稍後再試" msgid "Check if your network requires authentication?" diff --git a/backend/po/zh_TW.po b/backend/po/zh_TW.po index c69880b..f2f6a37 100644 --- a/backend/po/zh_TW.po +++ b/backend/po/zh_TW.po @@ -2557,7 +2557,7 @@ msgstr "因已安裝 grub,移除 lilo。(詳情見 bug #314004。)" #~ "請稍後從「管理」選單選擇「更新管理員」。" -msgid "Unable to access the source management server" +msgid "Unable to access the source management server, please try again later" msgstr "無法存取來源管理伺服器,請稍後再試" msgid "Check if your network requires authentication?" diff --git a/backend/report-updater-bug b/backend/report-updater-bug index 6fa4452..9505777 100755 --- a/backend/report-updater-bug +++ b/backend/report-updater-bug @@ -26,6 +26,8 @@ cp -r /var/log/apt/history.log updaterlog || true #收集aptdamon的日志 cp -r /var/log/kylin-unattended-upgrades/ updaterlog || true +#收集前端日志 +cp -r /var/run/user/1000/kylin-update-frontend.log updaterlog || true outputName="$(date +%m-%d,%H-%M-%S)-updaterLog.tar.gz" diff --git a/debian/changelog b/debian/changelog index 5c80594..151c1b7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +kylin-system-updater (2.0.5.15-ok4) yangtze; urgency=medium + + * BUG: #无 + * 需求号: 无 + * 其他改动说明: 同步2303主线代码 + * 其他改动影响域:系统更新 + + -- Kevin Duan Mon, 29 May 2023 14:47:14 +0800 + kylin-system-updater (2.0.5.15-ok3) yangtze; urgency=medium * BUG: #无 diff --git a/unattended-upgrades/kylin-unattended-upgrade b/unattended-upgrades/kylin-unattended-upgrade index fbeeef1..2e445e1 100644 --- a/unattended-upgrades/kylin-unattended-upgrade +++ b/unattended-upgrades/kylin-unattended-upgrade @@ -45,7 +45,7 @@ import grp import io import locale import logging -import logging.handlers + import re import os import select @@ -108,14 +108,16 @@ HTTPTYPE = "HTTP" FTPTYPE = "FTP" ARCHITECTUREMAP = ['arm64','amd64','armhf','i386','loongarch64','mips64el','sw64'] -KYLIN_VERSION_FILE = "/etc/kylin-version/kylin-system-version.conf" +VERSION_FILE = '/etc/kylin-version/kylin-system-version.conf' OTA_RESULT_FILE_PATH="/opt/apt_result/" OTA_RESULT_FILE="/opt/apt_result/ota_result" -SYSTEM_UPDATER_CORE_LIB_PATH="/usr/share/kylin-system-updater/SystemUpdater/Core" +#SYSTEM_UPDATER_CORE_LIB_PATH="/usr/share/kylin-system-updater/SystemUpdater/Core" # sys.path.append(SYSTEM_UPDATER_CORE_LIB_PATH) # from OriginFilter import UnattendUpgradeFilter +KYLIN_VERSION_FILE = "/etc/kylin-version/kylin-system-version.conf" CONFIG_FILE_ROOT_PATH="/var/lib/unattended-upgrades" UNATTENDED_UPGRADE_CONFIG_FILE_PATH="/var/lib/unattended-upgrades/unattended-upgrade.conf" +UNATTENDED_UPGRADE_POLICY_FILE_PATH="/var/lib/unattended-upgrades/unattended-upgrades-policy.conf" WHITE_LIST_FILE_PATH="/var/lib/kylin-system-updater/system-updater.conf" TIMESTAMP_PATH="/var/lib/kylin-software-properties/template/kylin-source-status" CONTROL_PANEL_LOCK_FILE = "/tmp/auto-upgrade/ukui-control-center.lock" @@ -152,77 +154,16 @@ pidfile = None # set from the sigint signal handler SIGNAL_STOP_REQUEST = False -class PackageComponent(): - def MarkUpgrade(self): - pass - - def MarkInstall(self): - pass - - -class PackageGroup(PackageComponent): - def __init__(self,name) -> None: - self.name = name - self.upgrade_list = [] - self.install_list = [] +def kysec_pre_upgrade(): + if os.path.exists("/usr/share/kysec-maintain/sys-upgrade-pre.sh"): + logging.debug("kysec pre-upgrade settings...") + subprocess.run(["/bin/sh","/usr/share/kysec-maintain/sys-upgrade-pre.sh"]) - def AddCache(self,cache): - for pkg in self.upgrade_list: - pkg.AddCache(cache) - for pkg in self.install_list: - pkg.AddCache(cache) - - def FindPackage(self,name): - for pkg in self.upgrade_list: - if pkg.FindPackage(name): - return True - for pkg in self.install_list: - if pkg.FindPackage(name): - return True - return False - - def AddPackageToUpgradeList(self,Package): - self.upgrade_list.append(Package) - - def RemovePackageFromUpgradeList(self,Package): - if Package in self.upgrade_list: - self.upgrade_list.remove(Package) - - def AddPackageToInstallList(self,Package): - self.install_list.append(Package) - - def RemovePackageFromInstallList(self,Package): - if Package in self.install_list: - self.install_list.remove(Package) - - def MarkUpgrade(self): - for package in self.upgrade_list: - package.MarkUpgrade() - - def MarkInstall(self): - for package in self.install_list: - package.MarkInstall() - -class Package(PackageComponent): - def __init__(self,name,version) -> None: - self.name = name - self.candidate_version = version - self.deps = [] - - def FindPackage(self,name): - if name in self.deps: - return True - return False - - def AddCache(self,cache): - self.cache = cache - - def MarkUpgrade(self): - return - - def MarkInstall(self): - return - +def kysec_post_upgrade(): + if os.path.exists("/usr/share/kysec-maintain/sys-upgrade-post.sh"): + logging.debug("kysec post-upgrade settings...") + subprocess.run(["/bin/sh","/usr/share/kysec-maintain/sys-upgrade-post.sh"]) + def reload_options_config(): #添加默认保留旧配置 apt_pkg.config["DPkg::Options::"] = "--force-confold" @@ -243,7 +184,6 @@ def reload_options_config(): apt_pkg.config["Dir::Etc::sourceparts"]="" apt_pkg.init_system() - def get_default_version(): version = "" data = {'version':""} @@ -259,7 +199,7 @@ def get_default_version(): return version def ReadOsRelease(file): - osreleasedict={} + osreleasedict = {} try: with open(file) as f: lines = f.readlines() @@ -268,11 +208,13 @@ def ReadOsRelease(file): osreleasedict.update({ls[0]:ls[1].strip('"')}) except Exception as e: pass + if 'PROJECT_CODENAME' not in osreleasedict.keys(): + osreleasedict.update({'PROJECT_CODENAME':''}) if 'SUB_PROJECT_CODENAME' not in osreleasedict.keys(): osreleasedict.update({'SUB_PROJECT_CODENAME':''}) return osreleasedict - +''' #安装时禁止关机 进行加锁 def LockedPreventShutdown(): global pidfile @@ -331,6 +273,7 @@ def unLockedEnableShutdown(): pidfile.close() pidfile = None return False +''' def is_dpkg_journal_dirty(): # type: () -> bool @@ -363,6 +306,7 @@ def get_white_list_with_version(srclist,list,namelist): def get_timestamp(): global timeStamp config=configparser.ConfigParser(allow_no_value=True) + config.optionxform = str config.read(TIMESTAMP_PATH) time_value=time.localtime(int(config.get("Server","UpdateTime"))) logging.debug(("获取软件源时间戳:%s"),time_value) @@ -372,6 +316,7 @@ def get_timestamp(): def WriteValueToFile(file,section,option,value): config=configparser.ConfigParser(allow_no_value=True) + config.optionxform = str config.add_section(section) config.set(section,option,value) config.write(open(file,"w")) @@ -400,6 +345,7 @@ logged_msgs = set() # type: AbstractSet[str] NEVER_PIN = -32768 + class InhibitShutdownLock(): def __init__(self): @@ -717,34 +663,6 @@ class OriginProperty(): self.allow_origin['ftp'].append(lo) except Exception as e: logging.error(str(e)) - -def get_allowed_origins(allow_origin): - """ return a list of allowed origins - """ - allowed_origins = [] - origin = '' - archive = '' - uri = '' - label = '' - for ao in (allow_origin['http']+allow_origin['ftp']): - if 'origin' in ao['release']: - origin = 'o='+ao['release']['origin'] - else: - origin = 'o=' - if 'archive' in ao['release']: - archive = 'a='+ao['release']['archive'] - else: - archive = 'a=' - if 'label' in ao['release']: - label = 'l='+ao['release']['label'] - else: - label = 'l=' - if 'origin_source' in ao: - uri = 'uri='+ao['origin_source'] - else: - uri = 'uri=' - allowed_origins.append(origin+","+archive+","+label+","+uri) - return allowed_origins def deleteDuplicatedElementFromList(list): resultList = [] @@ -850,7 +768,6 @@ class KylinSystemUpdater: def ConnectToSignals(self): def update_detect_finished_handler(success,updatelist,error_status,error_cause): - logging.debug(updatelist) if success: logging.info("update detect success,quiting main loop") self.update_group = updatelist @@ -872,11 +789,6 @@ class KylinSystemUpdater: PackageGroup.AddPackageToInstallList(Package(key,data['install_list'][key]['new_version'])) # install_list.append((key,data['install_list'][key]['new_version'])) self.group_list.append(gp) - - for key in data['upgrade_list'].keys(): - self.whitelist_with_candidate_version.append((key,data['upgrade_list'][key]['new_version'])) - for key in data['install_list'].keys(): - self.whitelist_with_candidate_version.append((key,data['install_list'][key]['new_version'])) ''' for key in data['upgrade_list'].keys(): if key in ["total_download_size","total_install_size"]: @@ -887,7 +799,7 @@ class KylinSystemUpdater: if key in ["total_download_size","total_install_size"]: pass else: - self.whitelist_with_candidate_version.append((key,data['install_list'][key]['new_version'])) + self.whitelist_with_candidate_version.append((key,data['install_list'][key]['new_version'])) ''' if os.path.exists(UNATTENDED_UPGRADE_PKG_LIST_FILE_PATH): with open(UNATTENDED_UPGRADE_PKG_LIST_FILE_PATH, "r") as f: @@ -1020,6 +932,7 @@ class KylinBackupManager: def ReadValueFromFile(file,section,option): config=configparser.ConfigParser(allow_no_value=True) + config.optionxform = str try: config.read(file) value = config[section][option] @@ -1031,15 +944,19 @@ def Backup(): # do backup kylin_backup_manager = KylinBackupManager() backup_partition_status = kylin_backup_manager.mount_backup_partition() + logging.info("backup partition status:%d"%backup_partition_status) if backup_partition_status not in [0,5]: logging.error("backup partition error:%d"%backup_partition_status) - return UnattendedUpgradesResult(False,"backup partition error") + # return UnattendedUpgradesResult(False,"backup partition error") + return False status_code,result = kylin_backup_manager.get_backup_state() + if result == 0 and status_code == 99: pass else: logging.error("backup state error:",status_code,result) - return UnattendedUpgradesResult(False,"backup state error") + # return UnattendedUpgradesResult(False,"backup state error") + return False #node_name,node_status = kylin_backup_manager.get_backup_comment_for_systemupdate() ts = get_timestamp() kylin_backup_manager.ConnectToSignals() @@ -1050,6 +967,7 @@ def Backup(): WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","backup") kylin_backup_manager.auto_backup_for_system_update_noreturn(ts,create_note,inc_note,userName,uid) kylin_backup_manager.RunMainloop() + return True ''' if node_name != timeStamp: logging.info("need backup") @@ -1072,11 +990,9 @@ class UnattendedUpgradesCache(apt.Cache): def __init__(self, rootdir, whitelist_with_version,blacklist): - self._cached_candidate_pkgnames = set() # type: Set[str] - - self.origin_filter = UnattendUpgradeFilter() - - self.allowed_origins = self.origin_filter.GetAllowOrigins() + # self._cached_candidate_pkgnames = set() # type: Set[str] + unattended_upgrade_filter = UnattendUpgradeFilter() + self.allowed_origins = unattended_upgrade_filter.GetAllowOrigins() logging.info(_("Allowed origins are: %s"), ", ".join(self.allowed_origins)) @@ -1275,7 +1191,7 @@ class UnattendedUpgradesCache(apt.Cache): def adjust_candidate_with_version(self,pkg,version): for v in pkg.versions: if v.version == version and is_in_allowed_origin(v,self.allowed_origins): - #logging.debug("pkg %s adjusting candidate version: %s" %(pkg.name,v)) + logging.debug("pkg %s adjusting candidate version: %s" %(pkg.name,v)) pkg.candidate = v return True return False @@ -1791,28 +1707,35 @@ def get_allowed_origins_legacy(): raise return allowed_origins -''' -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. +def get_allowed_origins(allow_origin): + """ return a list of allowed origins """ - - allowed_origins = get_allowed_origins_legacy() - key = "Unattended-Upgrade::Origins-Pattern" - try: - for s in apt_pkg.config.value_list(key): - allowed_origins.append(substitute(s)) - except ValueError: - logging.error(_("Unable to parse %s." % key)) - raise - - #logging.info("allowed origins are:%s"%"\n".join(allowed_origins)) + allowed_origins = [] + origin = '' + archive = '' + uri = '' + label = '' + for ao in (allow_origin['http']+allow_origin['ftp']): + if 'origin' in ao['release']: + origin = 'o='+ao['release']['origin'] + else: + origin = 'o=' + if 'archive' in ao['release']: + archive = 'a='+ao['release']['archive'] + else: + archive = 'a=' + if 'label' in ao['release']: + label = 'l='+ao['release']['label'] + else: + label = 'l=' + if 'origin_source' in ao: + uri = 'uri='+ao['origin_source'] + else: + uri = 'uri=' + allowed_origins.append(origin+","+archive+","+label+","+uri) return allowed_origins -''' + def match_whitelist_string(whitelist, origin): # type: (str, Union[apt.package.Origin, apt_pkg.PackageFile]) -> bool @@ -2134,12 +2057,21 @@ def sanity_problem(cache, desired_pkg): # return ("no package is selected to be upgraded or installed") changes = cache.get_changes() + if desired_pkg and desired_pkg not in changes: + logging.warning("pkg %s to be marked for upgrade/install is not marked accordingly" % desired_pkg.name) + return False + pkgs_to_remove = [] for pkg in changes: + if pkg.marked_delete: + logging.warning("pkg %s is marked to be deleted" % pkg.name) + pkgs_to_remove.append(pkg.name) + ''' if os_release_info['PROJECT_CODENAME'] == 'V10SP1-edu' and os_release_info['SUB_PROJECT_CODENAME']=='mavis': pass elif pkg.marked_delete: - return ("pkg %s is marked to be deleted" % pkg.name) + logging.warning("pkg %s is marked to be deleted" % pkg.name) + pkgs_to_remove.append(pkg.name) if pkg.marked_install or pkg.marked_upgrade: # apt will never fallback from a trusted to a untrusted @@ -2149,16 +2081,16 @@ def sanity_problem(cache, desired_pkg): # 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, cache.strict_whitelist): 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") @@ -2167,12 +2099,17 @@ def sanity_problem(cache, desired_pkg): 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 " - "accordingly" % desired_pkg.name) - return None + + # check that the package we want to upgrade is in the change set + if desired_pkg and desired_pkg not in changes: + logging.warning("pkg %s to be marked for upgrade/install is not marked " + "accordingly" % desired_pkg.name) + return False + ''' + if len(pkgs_to_remove) > 0: + logging.debug("pkgs marked to delete:%s"%",".join(pkgs_to_remove)) + return False + return True def is_deb(file): @@ -2653,37 +2590,38 @@ def _setup_logging(options,logfile): # apt_pkg.config.set("Debug::pkgDepCache::AutoInstall", "1") if options.debug: logger.setLevel(logging.DEBUG) - stdout_handler = logging.StreamHandler(sys.stdout) - logger.addHandler(stdout_handler) + # stdout_handler = logging.StreamHandler(sys.stdout) + # logger.addHandler(stdout_handler) elif options.verbose: logger.setLevel(logging.INFO) - stdout_handler = logging.StreamHandler(sys.stdout) - logger.addHandler(stdout_handler) - # if apt_pkg.config.find("Unattended-Upgrade::Mail", ""): - # mem_log_handler = logging.StreamHandler(mem_log) - # logger.addHandler(mem_log_handler) - # Configure syslog if necessary - # syslogEnable = apt_pkg.config.find_b("Unattended-Upgrade::SyslogEnable", - # False) - # if syslogEnable: - # syslogFacility = apt_pkg.config.find( - # "Unattended-Upgrade::SyslogFacility", - # "daemon") - # syslogHandler = logging.handlers.SysLogHandler( - # address='/dev/log', - # facility=syslogFacility) # type: ignore - # syslogHandler.setFormatter( - # logging.Formatter("unattended-upgrade: %(message)s")) - # known = syslogHandler.facility_names.keys() # type: ignore - # if syslogFacility.lower() in known: - # logger.addHandler(syslogHandler) - # logging.info("Enabled logging to syslog via %s facility " - # % syslogFacility) - # else: - # logging.warning("Syslog facility %s was not found" - # % syslogFacility) - # return mem_log - + stdout_handler = logging.StreamHandler(sys.stdout) + logger.addHandler(stdout_handler) + ''' + if apt_pkg.config.find("Unattended-Upgrade::Mail", ""): + mem_log_handler = logging.StreamHandler(mem_log) + logger.addHandler(mem_log_handler) + Configure syslog if necessary + syslogEnable = apt_pkg.config.find_b("Unattended-Upgrade::SyslogEnable", + False) + if syslogEnable: + syslogFacility = apt_pkg.config.find( + "Unattended-Upgrade::SyslogFacility", + "daemon") + syslogHandler = logging.handlers.SysLogHandler( + address='/dev/log', + facility=syslogFacility) # type: ignore + syslogHandler.setFormatter( + logging.Formatter("unattended-upgrade: %(message)s")) + known = syslogHandler.facility_names.keys() # type: ignore + if syslogFacility.lower() in known: + logger.addHandler(syslogHandler) + logging.info("Enabled logging to syslog via %s facility " + % syslogFacility) + else: + logging.warning("Syslog facility %s was not found" + % syslogFacility) + return mem_log + ''' def logged_in_users(): # type: () -> AbstractSet[str] @@ -2694,7 +2632,25 @@ def logged_in_users(): USERS, universal_newlines=True).rstrip('\n') return set(users.split()) - +def reboot_if_needed(): + # type: () -> None + """auto-reboot (if required and the config for this is set)""" + if not os.path.exists(REBOOT_REQUIRED_FILE): + return + needreboot = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH,"autoUpgradePolicy","automaticReboot") + if needreboot == 'off': + return + # reboot at the specified time + when = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH,"autoUpgradePolicy","automaticRebootTime") + logging.warning("Found %s, rebooting" % REBOOT_REQUIRED_FILE) + cmd = ["/sbin/shutdown", "-r", when] + try: + shutdown_msg = subprocess.check_output(cmd, stderr=subprocess.STDOUT) + if shutdown_msg.strip(): + logging.warning("Shutdown msg: %s", shutdown_msg.strip()) + except Exception as e: + logging.error("Failed to issue shutdown: %s", e) + def reboot_if_requested_and_needed(): # type: () -> None """auto-reboot (if required and the config for this is set)""" @@ -2757,7 +2713,7 @@ def try_to_upgrade(pkg, # type: apt.Package except NoAllowedOriginError: return - cache._cached_candidate_pkgnames.add(pkg.name) + # cache._cached_candidate_pkgnames.add(pkg.name) if not pkg.installed: cache.mark_install_adjusted(pkg,from_user=True) else: @@ -2794,9 +2750,27 @@ def calculate_upgradable_pkgs(cache, # type: UnattendedUpgradesCache for pkgname in whitelist: try: pkg = cache[pkgname[0]] + adjust_candidate_result = cache.adjust_candidate_with_version(pkg,pkgname[1]) + if (not adjust_candidate_result): + logging.warning("%s-%s :can not adjust candidate version"%(pkgname[0],pkgname[1])) + continue + if not pkg.installed: + cache.mark_install_adjusted(pkg,from_user=True) + elif pkg.is_upgradable: + cache.mark_upgrade_adjusted(pkg, from_user=not pkg.is_auto_installed) + else: + pass + if sanity_problem(cache,pkg): + pkgs_to_upgrade.append(pkg) except Exception as e: logging.error("error checking pkg:%s"%e) continue + + ''' + if check_changes_for_sanity(cache, pkg): + # add to packages to upgrade + pkgs_to_upgrade.append(pkg) + ''' #for pkg in cache: # if pkg.name not in cache.whitelist: # logging.debug("%s not in whitelist skipping..."%(pkg.name)) @@ -2806,7 +2780,7 @@ def calculate_upgradable_pkgs(cache, # type: UnattendedUpgradesCache 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) or not pkg.is_installed): try: ver_in_allowed_origin(pkg, cache.allowed_origins) @@ -2814,15 +2788,15 @@ def calculate_upgradable_pkgs(cache, # type: UnattendedUpgradesCache continue - try_to_upgrade(pkg, + try_to_upgrade(pkg, pkgs_to_upgrade, cache,pkgname[1]) - + ''' # logging.debug("Checking: %s (%s)" % ( # pkg.name, getattr(pkg.candidate, "origins", []))) #pkgs_to_upgrade.append(pkg) - if cache.get_changes(): - cache.clear() + if cache.get_changes(): + cache.clear() return pkgs_to_upgrade @@ -3074,16 +3048,19 @@ def main(options, rootdir="/"): # return 1 try: + kysec_pre_upgrade() res = run(options, rootdir, logfile_dpkg) + kysec_post_upgrade() logging.info("result:%s,%s"%(res.success,res.result_str)) release = '' version = '' os_release_info = ReadOsRelease('/etc/os-release') if 'KYLIN_RELEASE_ID' in os_release_info: release = os_release_info['KYLIN_RELEASE_ID'] + #version = ReadValueFromFile(VERSION_FILE,'SYSTEM','version') version = get_default_version() logging.debug("release:%s,version:%s"%(release,version)) - if options.install_only: + if options.install_only or options.download_and_install: #history record history = {} date = time.strftime("%Y-%m-%d %H:%M:%S") @@ -3105,18 +3082,20 @@ def main(options, rootdir="/"): UpdateInfos.update({"status":1}) UpdateInfos.update({"errorCode":"cache commit error"}) if res.success and len(res.pkgs) > 0 : - if res.result_str == "total_install": + #if res.result_str == "total_install": # with open(TIME_STAMP,'w') as f: # f.write(time.time()) - config=configparser.ConfigParser(allow_no_value=True) - config.read(KYLIN_VERSION_FILE) - config.set("SYSTEM","os_version",release) - config.set("SYSTEM","update_version",version) - with open(KYLIN_VERSION_FILE,'w') as f: - config.write(f) - kylin_system_updater.InsertUpgradeHistory(history) - json_file = json.dumps(UpdateInfos.copy()) - kylin_system_updater.DataBackendCollect("UpdateInfos",json_file) + config=configparser.ConfigParser(allow_no_value=True) + config.read(KYLIN_VERSION_FILE) + config.set("SYSTEM","os_version",release) + config.set("SYSTEM","update_version",version) + with open(KYLIN_VERSION_FILE,'w') as f: + config.write(f) + # kylin_system_updater.SetConfigValue("SYSTEM","os_version",release) + # kylin_system_updater.SetConfigValue("SYSTEM","update_version",original_version) + kylin_system_updater.InsertUpgradeHistory(history) + json_file = json.dumps(UpdateInfos.copy()) + kylin_system_updater.DataBackendCollect("UpdateInfos",json_file) elif not res.success: errorlist = kylin_system_updater.DumpInstallErrorRecord() errorlist.append("cache commit error") @@ -3133,35 +3112,35 @@ def main(options, rootdir="/"): else: logging.info("no pkgs to install") - - if 'PROJECT_CODENAME' in os_release_info: - if os_release_info['PROJECT_CODENAME']=='V10SP1-edu': - if 'SUB_PROJECT_CODENAME' in os_release_info: - if os_release_info['SUB_PROJECT_CODENAME']=='mavis': - localtime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time())) - config_to_result = configparser.ConfigParser(allow_no_value=True) - config_to_result.add_section("OTA") - config_to_result.set("OTA","time",localtime) - config_to_result.set("OTA","version","1.0") - config_to_result.set("OTA","upgrade","0") - config_to_result.set("OTA","status","failed") - if res.success: - if options.mode == 'shutdown': - config_to_result.set("OTA","status","success") - if len(res.pkgs) > 0 : - config_to_result.set("OTA","upgrade","1") - if not os.path.exists(OTA_RESULT_FILE_PATH): - os.makedirs(OTA_RESULT_FILE_PATH) - # os.chmod(OTA_RESULT_FILE_PATH,stat.S_IRUSR|stat.S_IWUSR|stat.S_IWGRP|stat.S_IRGRP|stat.S_IWOTH|stat.S_IROTH) - if not os.path.exists(OTA_RESULT_FILE): - f = open(OTA_RESULT_FILE,'w') - f.close() - with open(OTA_RESULT_FILE,"w+") as f: - config_to_result.write(f) - subprocess.Popen("chmod -R 777 %s"%(OTA_RESULT_FILE_PATH),shell=True) - # os.chmod(OTA_RESULT_FILE,stat.S_IRUSR|stat.S_IWUSR|stat.S_IWGRP|stat.S_IRGRP|stat.S_IWOTH|stat.S_IROTH) - # os.chmod(OTA_RESULT_FILE,stat.S_IRWXU|stat.S_IRWXG|stat.S_IRWXO) - + + if 'PROJECT_CODENAME' in os_release_info: + if os_release_info['PROJECT_CODENAME']=='V10SP1-edu': + if 'SUB_PROJECT_CODENAME' in os_release_info: + if os_release_info['SUB_PROJECT_CODENAME']=='mavis': + localtime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time())) + config_to_result = configparser.ConfigParser(allow_no_value=True) + config_to_result.add_section("OTA") + config_to_result.set("OTA","time",localtime) + config_to_result.set("OTA","version","1.0") + config_to_result.set("OTA","upgrade","0") + config_to_result.set("OTA","status","failed") + if res.success: + if options.mode == 'shutdown': + config_to_result.set("OTA","status","success") + if len(res.pkgs) > 0 : + config_to_result.set("OTA","upgrade","1") + if not os.path.exists(OTA_RESULT_FILE_PATH): + os.makedirs(OTA_RESULT_FILE_PATH) + # os.chmod(OTA_RESULT_FILE_PATH,stat.S_IRUSR|stat.S_IWUSR|stat.S_IWGRP|stat.S_IRGRP|stat.S_IWOTH|stat.S_IROTH) + if not os.path.exists(OTA_RESULT_FILE): + f = open(OTA_RESULT_FILE,'w') + f.close() + with open(OTA_RESULT_FILE,"w+") as f: + config_to_result.write(f) + subprocess.Popen("chmod -R 777 %s"%(OTA_RESULT_FILE_PATH),shell=True) + # os.chmod(OTA_RESULT_FILE,stat.S_IRUSR|stat.S_IWUSR|stat.S_IWGRP|stat.S_IRGRP|stat.S_IWOTH|stat.S_IROTH) + # os.chmod(OTA_RESULT_FILE,stat.S_IRWXU|stat.S_IRWXG|stat.S_IRWXO) + # WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","idle") ''' @@ -3197,6 +3176,8 @@ def main(options, rootdir="/"): except Exception as e: WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","idle") logging.error(e) + if options.install_only: + reboot_if_needed() # logger = logging.getLogger() # logger.exception(_("An error occurred: %s"), e) # log_content = get_dpkg_log_content(logfile_dpkg, @@ -3376,7 +3357,7 @@ def run(options, # type: Options False, _("Apt returned an error, exiting")) if cache._depcache.broken_count > 0: - #print(_("Cache has broken packages, exiting")) + print(_("Cache has broken packages, exiting")) logging.error(_("Cache has broken packages, exiting")) return UnattendedUpgradesResult( False, _("Cache has broken packages, exiting")) @@ -3394,17 +3375,20 @@ def run(options, # type: Options pass else: raise - ''' + ''' #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,white_list_with_version) + if options.install_only or options.download_and_install: + if (len(pkgs_to_upgrade)0: logging.warning("there're pkgs to download") try: @@ -3494,8 +3479,15 @@ def run(options, # type: Options if os_release_info['SUB_PROJECT_CODENAME']=='mavis': pass else: - logging.info("neeed backup") - #Backup() + logging.info("need backup") + backup_result = False + backup_result = Backup() + if (backup_result): + pass + else: + logging.debug("backup failed...") + return UnattendedUpgradesResult(False,"backup failed") + # do install WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","install") #send install start msg to notify @@ -3517,11 +3509,13 @@ def run(options, # type: Options % (cache._depcache.inst_count, cache._depcache.del_count, cache._depcache.broken_count)) - + logging.info("shutdown safe manager") + pkg_install_success = do_install(cache, pkgs, options, logfile_dpkg) + logging.info("reset safe manager") # unLockedEnableShutdown() inhibitshutdownlock.unlock() @@ -3575,7 +3569,7 @@ def run(options, # type: Options break #fetcher_statistics.ResetFetcher(fetcher) #fetcher_statistics.GetAquireStatisticsOfPkgs() - insmod = ReadValueFromFile("/var/lib/unattended-upgrades/unattended-upgrades-policy.conf","autoUpgradePolicy","installmode") + insmod = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH,"autoUpgradePolicy","installmode") if fetcher_statistics.incomplete_pkg_amount == 0 and len(pkgs_to_upgrade) > 0: if os_release_info['PROJECT_CODENAME'] == 'V10SP1-edu' and os_release_info['SUB_PROJECT_CODENAME']=='mavis': docker_image_fetch_result = 0 @@ -3605,12 +3599,87 @@ def run(options, # type: Options except SystemError: logging.error(_("lock release failed")) return UnattendedUpgradesResult(True,_("all pkgs downloaded")) - else: + elif fetcher_statistics.incomplete_pkg_amount > 0 and len(pkgs_to_upgrade) > 0: try: apt_pkg.pkgsystem_unlock() except SystemError: logging.error(_("lock release failed")) return UnattendedUpgradesResult(False,_("some pkgs incompletely fetched")) + else: + try: + apt_pkg.pkgsystem_unlock() + except SystemError: + logging.error(_("lock release failed")) + return UnattendedUpgradesResult(True,_("all pkgs downloaded")) + elif options.download_and_install: + if len(pkgs)==0: + logging.info("no pkgs to install") + return UnattendedUpgradesResult(True,_("there're no pkgs to install")) + if fetcher_statistics.remote_pkg_amount>0: + pass + else: + logging.info("no pkgs need to download") + #return UnattendedUpgradesResult(True,_("there're no pkgs to download")) + retry_times=10 + if retry_times<0: + retry_times = 1 + while retry_times >0: + try: + res = fetcher.run() + logging.debug("fetch.run() result: %s", res) + except SystemError as e: + logging.error("fetch.run() result: %s", e) + fetcher_statistics.ResetFetcher(fetcher) + fetcher_statistics.GetAquireStatisticsOfPkgs() + logging.debug("incomplete download pkg number:%d"%fetcher_statistics.incomplete_pkg_amount) + retry_times-=1 + if fetcher_statistics.incomplete_pkg_amount >0: + logging.debug("%d incomplete pkgs,%d try times left") + fetcher.shutdown() + try: + pm.get_archives(fetcher, list, recs) + except SystemError as e: + logging.error(_("GetArchives() failed: %s"), e) + else: + break + pkg_install_success = True + install_result = '' + backup_result = False + backup_result = Backup() + if (backup_result): + pass + else: + logging.debug("backup failed...") + return UnattendedUpgradesResult(False,"backup failed") + WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","install") + inhibitshutdownlock.lock() + logging.debug("InstCount=%i DelCount=%i BrokenCount=%i" + % (cache._depcache.inst_count, + cache._depcache.del_count, + cache._depcache.broken_count)) + logging.info("shutdown safe manager") + pkg_install_success = do_install(cache, + pkgs, + options, + logfile_dpkg) + logging.info("reset safe manager") + # unLockedEnableShutdown() + inhibitshutdownlock.unlock() + subprocess.Popen('dbus-send --system --type=signal / com.kylin.install.notification.InstallFinish',shell=True) + if pkg_install_success: + clean_downloaded_packages(fetcher) + kylin_system_updater.CheckRebootRequired("unattended-upgrades") + logging.debug("pkg number:%d,pkg in whitelist number:%d"%(len(pkgs),len(white_list_with_version))) + if len(pkgs) == len(white_list_with_version): + install_result = "total_install" + else: + install_result = "partial_install" + logging.debug("install result:%s"%install_result) + try: + apt_pkg.pkgsystem_unlock() + except SystemError: + logging.error(_("lock release failed")) + return UnattendedUpgradesResult(pkg_install_success,install_result,pkgs) else: try: apt_pkg.pkgsystem_unlock() @@ -3910,12 +3979,14 @@ class Options: def __init__(self): self.download_only = False self.install_only = False + self.download_and_install = False self.dry_run = False self.debug = False self.apt_debug = False self.verbose = False self.minimal_upgrade_steps = False self.mode = None + shutdown_lock = -1 @@ -3969,7 +4040,10 @@ if __name__ == "__main__": help=_("Only download, do not even try to install.")) parser.add_option("", "--install-only", action="store_true", default=False, - help=_("Only install, do not even try to download.")) + help=_("Only install, do not even try to download.")) + parser.add_option("", "--download-and-install", + action="store_true", default=False, + help=_("Download and Install.")) parser.add_option("", "--minimal-upgrade-steps", action="store_true", default=minimal_steps_default, help=_("Upgrade in minimal steps (and allow " @@ -4027,13 +4101,27 @@ if __name__ == "__main__": pass # setup logging - _setup_logging(options,logfile) + # _setup_logging(options,logfile) + logging.basicConfig(format='%(asctime)s-%(name)s-%(levelname)s-%(message)s',level=logging.DEBUG,filename=logfile) + + # logging.basicConfig() + # file_handler = logging.FileHandler(filename=logfile) + stdout_handler = logging.StreamHandler(sys.stdout) + stdout_handler.setLevel(logging.INFO) + # formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + # file_handler.setFormatter(formatter) + + logger=logging.getLogger() + logger.setLevel(logging.DEBUG) + # logger.addHandler(file_handler) + logger.addHandler(stdout_handler) #get os release info os_release_info = ReadOsRelease('/etc/os-release') #print(os_release_info) config_manager = ConfigFileManager(CONFIG_FILE_ROOT_PATH) login_manager = LoginManager() kylin_system_updater = KylinSystemUpdater() + ''' if os_release_info['PROJECT_CODENAME'] == 'V10SP1-edu' and os_release_info['SUB_PROJECT_CODENAME']=='mavis': pass @@ -4065,6 +4153,9 @@ if __name__ == "__main__": WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","download") elif options.install_only: WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","preinstall") + elif options.download_and_install: + WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","preinstall") + # run the main code install_start_time = datetime.datetime.now().replace(microsecond=0) logging.info("unattended-upgrades start time:%s"%install_start_time) diff --git a/unattended-upgrades/kylin-unattended-upgrade-shutdown b/unattended-upgrades/kylin-unattended-upgrade-shutdown index 8a4ce3e..e36189e 100644 --- a/unattended-upgrades/kylin-unattended-upgrade-shutdown +++ b/unattended-upgrades/kylin-unattended-upgrade-shutdown @@ -26,20 +26,22 @@ # import copy +# from multiprocessing.connection import wait +# from concurrent.futures import ThreadPoolExecutor +# from stat import filemode import dbus import signal import sys import time import datetime import logging -import logging.handlers + import gettext import subprocess import os.path import os import configparser import psutil -from pytz import timezone # for dbus signal handling try: from dbus.mainloop.glib import DBusGMainLoop @@ -49,10 +51,10 @@ except ImportError: from optparse import OptionParser, Values Values # pyflakes -from gettext import gettext as _ +from gettext import gettext as _, install from threading import Event from enum import IntEnum, Enum -from apscheduler.schedulers.blocking import BlockingScheduler +from apscheduler.schedulers.blocking import BlockingScheduler from apscheduler.schedulers.background import BackgroundScheduler import random import threading @@ -85,7 +87,6 @@ AUTO_UPGRADE_POLICY_OPTION_UPGRADE_INTERVAL = "upgradeInverval" INTERVAL_DOWN_INSTALL = 120 # 下载安装的间隔 分钟 INSTALL_RANDOM = 5 # 安装时间随机数范围0-INSTALL_RANDOM 分钟 DOWNLOAD_RANDOM = 180 # 下载时间随机数范围0-DOWNLOAD_RANDOM 分钟 -PREDOWNLOAD_RANDOM = 180 class FeatureSwitch(Enum): ON = 'on' @@ -115,6 +116,60 @@ UNATTENDED_UPGRADE_TIMESTAMP = "/var/lib/unattended-upgrades/unattended-upgrades flag_file_list = ["/var/lib/unattended-upgrades/OTA_PKGS_TO_INSTALL",\ "/var/lib/kylin-auto-upgrade/kylin-autoupgrade.conf","/tmp/notify.pid"] +def _setup_logging(options,logfile): + # ensure this is run only once + if len(logging.root.handlers) > 0: + return None + + # init the logging + # logdir = _get_logdir() + # logfile = os.path.join( + # logdir, + # apt_pkg.config.find( + # "Unattended-Upgrade::LogFile", + # # COMPAT only + # apt_pkg.config.find("APT::UnattendedUpgrades::LogFile", + # "unattended-upgrades.log"))) + # if not options.dry_run and not os.path.exists(logdir): + # os.makedirs(logdir) + + logging.basicConfig(level=logging.INFO, + format='%(asctime)s %(levelname)s %(message)s', + filename=logfile) + + # additional logging + logger = logging.getLogger() + # mem_log = StringIO() + # if options.apt_debug: + # apt_pkg.config.set("Debug::pkgProblemResolver", "1") + # apt_pkg.config.set("Debug::pkgDepCache::AutoInstall", "1") + if options.debug: + logger.setLevel(logging.DEBUG) + # stdout_handler = logging.StreamHandler(sys.stdout) + # logger.addHandler(stdout_handler) + elif options.verbose: + logger.setLevel(logging.INFO) + logging.getLogger('apscheduler').setLevel(logging.DEBUG) + stdout_handler = logging.StreamHandler(sys.stdout) + logger.addHandler(stdout_handler) + +def get_random_time(time_interval): + try: + start_time = datetime.datetime.strptime(time_interval.split("-")[0],"%H:%M") + end_time = datetime.datetime.strptime(time_interval.split("-")[1],"%H:%M") + now = datetime.datetime.now() + start=datetime.datetime(now.year,now.month,now.day,start_time.hour,start_time.minute,0,0) + end=datetime.datetime(now.year,now.month,now.day,end_time.hour,end_time.minute,0,0) + time_diff = int((end-start).total_seconds()) + if time_diff<0: + time_diff=time_diff+86400 + delta = random.randint(0,time_diff) + actual_time = start+datetime.timedelta(seconds=delta) + return actual_time + except Exception as e: + logging.error(e) + + def reload_options_config(): #添加默认保留旧配置 apt_pkg.config["DPkg::Options::"] = "--force-confold" @@ -178,6 +233,8 @@ def ReadOsRelease(file): osreleasedict.update({ls[0]:ls[1].strip('"')}) except Exception as e: pass + if 'PROJECT_CODENAME' not in osreleasedict.keys(): + osreleasedict.update({'PROJECT_CODENAME':''}) if 'SUB_PROJECT_CODENAME' not in osreleasedict.keys(): osreleasedict.update({'SUB_PROJECT_CODENAME':''}) return osreleasedict @@ -196,6 +253,7 @@ def FindRuningUnattendedUpgrades(): def ReadValueFromFile(file,section,option): config=configparser.ConfigParser(allow_no_value=True) + config.optionxform = str try: config.read(file) value = config[section][option] @@ -205,6 +263,7 @@ def ReadValueFromFile(file,section,option): def WriteValueToFile(file,section,option,value): config=configparser.ConfigParser(allow_no_value=True) + config.optionxform = str config.add_section(section) config.set(section,option,value) config.write(open(file,"w")) @@ -217,68 +276,6 @@ def clean_flag_files(filelist): def init(): if not os.path.exists(NOTIFICATION_PIPE): os.mkfifo(NOTIFICATION_PIPE) - -def get_random_time(stime,random_range): - now = datetime.datetime.now() - delta = random.randint(0,random_range) - actual_time = now + datetime.timedelta(minutes=delta) - try: - start_time = datetime.datetime.strptime(stime,"%H:%M") - start=datetime.datetime(now.year,now.month,now.day,start_time.hour,start_time.minute,0,0) - actual_time = start+datetime.timedelta(minutes=delta) - except Exception as e: - logging.error(e) - return actual_time - -def task(task): - env = copy.copy(os.environ) - cmd = "date" - if task in ["predownload","download"]: - cmd = "kylin-unattended-upgrade --download-only" - elif task == "install": - cmd = "kylin-unattended-upgrade --install-only --mode=timing" - elif task == "download_and_install": - cmd = "kylin-unattended-upgrade --download-only&&kylin-unattended-upgrade --install-only --mode=timing" - #do not check updgrade period when download and install - else: - pass - ret = subprocess.run([cmd], shell=True,env=env) - logging.debug("task:%s return code:%d"%(task,ret.returncode)) - return ret.returncode - -def background_scheduler_init(background_scheduler): - - background_scheduler.start() - - random_time = get_random_time(autoupgradepolicy.GetOptionValue('downloadTime'),DOWNLOAD_RANDOM) - background_scheduler.add_job(task,'cron', args=['download'],id='download', \ - hour = random_time.hour,minute = random_time.minute,replace_existing=True) - - random_time = random_time + datetime.timedelta(minutes=INTERVAL_DOWN_INSTALL) - background_scheduler.add_job(task,'cron', args=['install'],id='install', \ - hour = random_time.hour,minute = random_time.minute,replace_existing=True) - - random_time = get_random_time(autoupgradepolicy.GetOptionValue('preDownloadTime'),PREDOWNLOAD_RANDOM) - background_scheduler.add_job(task,'cron', args=['predownload'],id='predownload', \ - hour = random_time.hour,minute = random_time.minute,replace_existing=True) - - if autoupgradepolicy.GetOptionValue('autoUpgradeState') == 'on': - if autoupgradepolicy.GetOptionValue('downloadMode') != 'timing': - background_scheduler.pause_job('download') - if autoupgradepolicy.GetOptionValue('installMode') != 'timing': - background_scheduler.pause_job('install') - else: - background_scheduler.pause_job('download') - background_scheduler.pause_job('install') - - if autoupgradepolicy.GetOptionValue('preDownload') != 'on': - background_scheduler.pause_job('predownload') - - - joblist = background_scheduler.get_jobs() - - for job in joblist: - logging.debug("job:%s,next run time:%s"%(job.id,job.next_run_time)) ''' def do_usplash(msg): # type: (str) -> None @@ -391,7 +388,110 @@ class TimerThread(threading.Thread): self.scheduler = scheduler def run(self): self.scheduler.start() + +def empty_task(): + pass + +def task(task): + env = copy.copy(os.environ) + last_run_time = '2022-01-01 00:00:00' + config=configparser.ConfigParser(allow_no_value=True) + config.optionxform = str + config.read(UNATTENDED_UPGRADE_TIMESTAMP) + last_run_time = config['timestamp'][task] + logging.debug("%s timestamp:%s,"%(task,last_run_time)) + last_run_date = datetime.datetime.strptime(last_run_time,"%Y-%m-%d %H:%M:%S") + now = datetime.datetime.now() + duration = (now - last_run_date).days + update_interval = int(autoupgradepolicy.GetOptionValue('updateDays')) + cmd = "date" + if task in ["predownload","download"]: + cmd = "kylin-unattended-upgrade --download-only" + elif task == "install": + cmd = "kylin-unattended-upgrade --install-only --mode=timing" + elif task == "download_and_install": + cmd = "kylin-unattended-upgrade --download-and-install" + #do not check updgrade period when download and install + update_interval = 0 + else: + pass + if duration < update_interval: + logging.info("not long enough from last run") + return + ret = subprocess.run([cmd], shell=True,env=env) + logging.debug("task:%s return code:%d"%(task,ret.returncode)) + if ret.returncode == 0: + now = datetime.datetime.now() + config['timestamp'][task] = now.strftime("%Y-%m-%d %H:%M:%S") + with open(UNATTENDED_UPGRADE_TIMESTAMP,"w") as f: + config.write(f) + logging.info("successful run,new time stamp:%s"%now.strftime("%Y-%m-%d %H:%M:%S")) + return ret.returncode +def timing_predownload(): + env = copy.copy(os.environ) + logging.debug("starting unattended-upgrades in pre-download mode") + pre_download_ret = subprocess.run(["kylin-unattended-upgrade","--download-only"], env=env) + if pre_download_ret.returncode == 0: + logging.debug("kylin-unattended-upgrade download success.") + else: + logging.debug("kylin-unattended-upgrade download %d .",pre_download_ret.returncode) + +def timing_download(): + env = copy.copy(os.environ) + logging.debug("starting unattended-upgrades in timing download mode") + timing_download_ret = subprocess.run(["kylin-unattended-upgrade","--download-only"], env=env) + if timing_download_ret.returncode == 0: + logging.debug("kylin-unattended-upgrade download success.") + else: + logging.debug("kylin-unattended-upgrade download %d .",timing_download_ret.returncode) + +def timing_install(): + env = copy.copy(os.environ) + logging.debug("starting unattended-upgrades in timing install mode") + timing_install_ret = subprocess.run(["kylin-unattended-upgrade","--install-only","--mode=timing"], env=env) + if timing_install_ret.returncode == 0: + logging.debug("kylin-unattended-upgrade install success.") + else: + logging.debug("kylin-unattended-upgrade install %d .",timing_install_ret.returncode) + +def background_scheduler_init(background_scheduler): + + background_scheduler.start() + + random_time = get_random_time(autoupgradepolicy.GetOptionValue('downloadTime')) + background_scheduler.add_job(task,'cron', args=['download'],id='download', \ + hour = random_time.hour,minute = random_time.minute,replace_existing=True) + + instime = autoupgradepolicy.GetOptionValue('installTime') + # random_time = get_random_time("%s-%s"%(instime,instime)) + random_time = get_random_time(instime) + background_scheduler.add_job(task,'cron', args=['install'],id='install', \ + hour = random_time.hour,minute = random_time.minute,replace_existing=True) + + random_time = get_random_time(autoupgradepolicy.GetOptionValue('preDownloadTime')) + background_scheduler.add_job(task,'cron', args=['predownload'],id='predownload', \ + hour = random_time.hour,minute = random_time.minute,replace_existing=True) + + if autoupgradepolicy.GetOptionValue('autoUpgradeState') == 'on': + if autoupgradepolicy.GetOptionValue('downloadMode') != 'timing': + background_scheduler.pause_job('download') + if autoupgradepolicy.GetOptionValue('installMode') != 'timing': + background_scheduler.pause_job('install') + else: + background_scheduler.pause_job('download') + background_scheduler.pause_job('install') + + if autoupgradepolicy.GetOptionValue('preDownload') != 'on': + background_scheduler.pause_job('predownload') + + + joblist = background_scheduler.get_jobs() + + for job in joblist: + logging.debug("job:%s,next run time:%s"%(job.id,job.next_run_time)) + + class KylinSystemUpdater: def __init__(self) -> None: DBusGMainLoop(set_as_default=True) @@ -405,7 +505,8 @@ class KylinSystemUpdater: def SetConfigValue(self,section,option,value): return self.update_interface.SetConfigValue(section,option,value) - + + class AutoUpgradePolicy(): def __init__(self) -> None: self.autoupgradepolicy = {} @@ -425,33 +526,77 @@ class AutoUpgradePolicy(): try: return self.autoupgradepolicy[option] except Exception: - return '' - - def reload_config(self): - if os.path.exists(UNATTENDED_UPGRADE_POLICY_FILE_PATH): - config=configparser.ConfigParser(allow_no_value=True) - config.optionxform = str - config.read(UNATTENDED_UPGRADE_POLICY_FILE_PATH) - for option in config.options('autoUpgradePolicy'): - self.autoupgradepolicy.update({option:config['autoUpgradePolicy'][option]}) - for key in self.autoupgradepolicy.keys(): - logging.debug("%s:%s"%(key,self.autoupgradepolicy[key])) - + return '' + + def ExecutePolicy(self,property,value): + if property == 'autoUpgradeState': + if value == 'off': + background_scheduler.pause_job('download') + background_scheduler.pause_job('install') + elif value == 'on': + if self.autoupgradepolicy['downloadMode'] == 'timing': + background_scheduler.resume_job('download') + if self.autoupgradepolicy['installMode'] == 'timing': + background_scheduler.resume_job('install') + else: + pass + elif property == 'downloadMode': + if value == 'timing': + if self.autoupgradepolicy['autoUpgradeState'] == 'on': + background_scheduler.resume_job('download') + elif value == 'manual': + background_scheduler.pause_job('download') + else: + pass + elif property == 'downloadTime': + if self.autoupgradepolicy['autoUpgradeState'] == 'on' and \ + self.autoupgradepolicy['downloadMode'] == 'timing': + random_time = get_random_time(value) + background_scheduler.reschedule_job('download',trigger='cron',hour=random_time.hour,minute = random_time.minute) + elif property == 'installMode': + if value == 'timing': + if self.autoupgradepolicy['autoUpgradeState'] == 'on': + background_scheduler.resume_job('install') + elif value == 'manual': + background_scheduler.pause_job('install') + elif value == 'bshutdown': + background_scheduler.pause_job('install') + else: + pass + elif property == 'installTime': + if self.autoupgradepolicy['autoUpgradeState'] == 'on' and \ + self.autoupgradepolicy['installMode'] == 'timing': + random_time = get_random_time(value) + background_scheduler.reschedule_job('install',trigger='cron',hour=random_time.hour,minute = random_time.minute) + elif property == 'preDownload': + if value == 'off': + background_scheduler.pause_job('predownload') + elif value == 'on': + background_scheduler.resume_job('predownload') + else: + pass + elif property == 'preDownloadTime': + if self.autoupgradepolicy['preDownload'] == 'on': + random_time = get_random_time(value) + background_scheduler.reschedule_job('predownload',trigger='cron',hour=random_time.hour,minute = random_time.minute) + else: + pass + + class UnattendedUpgradesShutdown(): # 加载配置文件 unattended-upgrades-policy.conf - ''' def loadcfg(self): - if os.path.exists(UNATTENDED_UPGRADE_POLICY_FILE_PATH): + if os.path.isfile(UNATTENDED_UPGRADE_POLICY_FILE_PATH): self.preDownload = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, AUTO_UPGRADE_POLICY_OPTION_PREDOWNLOAD) self.autoUpgrade = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, AUTO_UPGRADE_POLICY_OPTION_AUTOUPGRADE) self.download_mode = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, AUTO_UPGRADE_POLICY_OPTION_DOWNLOAD_MODE) self.install_mode = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, AUTO_UPGRADE_POLICY_OPTION_INSTALL_MODE) download_time = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, AUTO_UPGRADE_POLICY_OPTION_DOWNLOAD_TIME) - # self.download_random = int(kylin_system_updater.GetConfigValue('AutoUpgradeConfig','downloadRandom')[1]) - # self.upgrade_interval = int(kylin_system_updater.GetConfigValue('AutoUpgradeConfig','upgradeInterval')[1]) - # logging.info("download random:%s,upgrade interval:%s"%(self.download_random,self.upgrade_interval)) + self.download_random = int(kylin_system_updater.GetConfigValue('AutoUpgradeConfig','downloadRandom')[1]) + self.upgrade_interval = int(kylin_system_updater.GetConfigValue('AutoUpgradeConfig','upgradeInterval')[1]) + logging.info("download random:%s,upgrade interval:%s"%(self.download_random,self.upgrade_interval)) # upgradeInterval = int(ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, 'upgradeInverval')) - + ''' if os_release_info['PROJECT_CODENAME'] == 'V10SP1-edu' and os_release_info['SUB_PROJECT_CODENAME']=='mavis': self.download_time['h'] = 10 self.download_time['m'] = 0 @@ -460,13 +605,11 @@ class UnattendedUpgradesShutdown(): self.download_time_r['h'], self.download_time_r['m'],self.preDownload, self.autoUpgrade, \ self.download_mode, self.install_mode) return - + ''' timelist = download_time.strip().split(':') - if len(timelist) != TimeElement.TIME_NUM: logging.debug("unattended-upgrades-policy.conf time err %s",download_time) return - # 检查 传入时间 安全性 try: tmphour = int(timelist[TimeElement.TIME_HOUR]) @@ -490,8 +633,7 @@ class UnattendedUpgradesShutdown(): self.preDownload, self.autoUpgrade, self.download_mode, self.install_mode) else: logging.debug("unattended-upgrades-policy.conf not exist") - return - ''' + def __init__(self, options): # type: (Values) -> None self.options = options @@ -518,8 +660,9 @@ class UnattendedUpgradesShutdown(): self.download_job = None self.install_job = None self.startup_download_job = None - self.scheduler = BlockingScheduler(timezone = "Asia/Shanghai") + self.scheduler = BlockingScheduler() ''' + try: hasattr(GLib, "MainLoop") DBusGMainLoop(set_as_default=True) @@ -534,15 +677,26 @@ class UnattendedUpgradesShutdown(): self.inhibit_lock = None self.logind_proxy = None self.update_proxy = None + self.upgrade_strategy_proxy = None self.wait_period = min(3, self.get_inhibit_max_delay() / 3) self.preparing_for_shutdown = False #self.loadcfg() + def get_upgrade_strategy_proxy(self): + if not self.upgrade_strategy_proxy: + bus = dbus.SystemBus() + self.upgrade_strategy_proxy = bus.get_object('com.kylin.UpgradeStrategies','/com/kylin/UpgradeStrategies') + return self.upgrade_strategy_proxy + + def get_upgrade_strategy_interface(self): + self.upgrade_strategy_interface = dbus.Interface(self.upgrade_strategy_proxy,dbus_interface='com.kylin.UpgradeStrategies.interface') + def get_update_proxy(self): if not self.update_proxy: bus = dbus.SystemBus() self.update_proxy = bus.get_object('com.kylin.systemupgrade','/com/kylin/systemupgrade') - return self.update_proxy + return self.update_proxy + def get_update_interface(self): self.update_interface = dbus.Interface(self.update_proxy,dbus_interface='com.kylin.systemupgrade.interface') @@ -593,7 +747,7 @@ class UnattendedUpgradesShutdown(): / (1000 * 1000)) except dbus.exceptions.DBusException: return 3 - + ''' def is_preparing_for_shutdown(self): if not self.shutdown_pending: try: @@ -606,7 +760,7 @@ class UnattendedUpgradesShutdown(): except dbus.exceptions.DBusException: return False return self.shutdown_pending - + ''' def start_iterations(self): while self.iter(): time.sleep(1) @@ -644,7 +798,7 @@ class UnattendedUpgradesShutdown(): while not self.iter(): # TODO iter on sigterm and sighup, too time.sleep(self.wait_period) - ''' + # 定时下载 执行函数 def timing_download(self): env = copy.copy(os.environ) @@ -659,7 +813,7 @@ class UnattendedUpgradesShutdown(): def timing_install(self): env = copy.copy(os.environ) logging.debug("starting unattended-upgrades in timing install mode") - timing_install_ret = subprocess.run(["kylin-unattended-upgrade","--install-only","--mode=timing"], env=env) + timing_install_ret = subprocess.run(["kylin-unattended-upgrade","--install-only"], env=env) if timing_install_ret.returncode == 0: logging.debug("kylin-unattended-upgrade install success.") else: @@ -679,7 +833,7 @@ class UnattendedUpgradesShutdown(): logging.info("wait for uu time out") return return 0 - + def _pause_timer(self): if self.download_job is not None: self.download_job.pause() @@ -693,7 +847,7 @@ class UnattendedUpgradesShutdown(): if self.install_job is not None: self.install_job.resume() - + ''' def run(self): """ delay shutdown and wait for PrepareForShutdown or other signals""" # if os_release_info['PROJECT_CODENAME'] == 'V10SP1-edu' and os_release_info['SUB_PROJECT_CODENAME']=='mavis': @@ -713,7 +867,7 @@ class UnattendedUpgradesShutdown(): "only if it is running") self.stop_signal_received.set() #self.start_iterations() - + ''' # fall back to polling without GLib try: hasattr(GLib, "MainLoop") @@ -721,41 +875,22 @@ class UnattendedUpgradesShutdown(): logging.error("MainLoop Not Found") #self.run_polling(signal_handler) return - + ''' for sig in (signal.SIGTERM, signal.SIGHUP): GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, sig, signal_handler, None, None) ''' if self.options.wait_for_signal: + def property_changed_handler(property, value): + logging.debug("property change:%s:%s"%(property,value)) + autoupgradepolicy.SetOptionValue(property,value) + autoupgradepolicy.ExecutePolicy(property,value) + joblist = background_scheduler.get_jobs() + for job in joblist: + logging.debug("job:%s,next run time:%s"%(job.id,job.next_run_time)) + ''' def change_upgrade_policy_handler(): - if os.path.exists(UNATTENDED_UPGRADE_POLICY_FILE_PATH): - autoupgradepolicy.reload_config() - - if autoupgradepolicy.GetOptionValue('autoUpgradeState') == 'on': - random_time = get_random_time(autoupgradepolicy.GetOptionValue('downloadTime'),DOWNLOAD_RANDOM) - if autoupgradepolicy.GetOptionValue('downloadMode') == 'timing': - background_scheduler.add_job(task,'cron', args=['download'],id='download', \ - hour = random_time.hour,minute = random_time.minute,replace_existing=True) - if autoupgradepolicy.GetOptionValue('installMode') == 'timing': - random_time = random_time + datetime.timedelta(minutes=INTERVAL_DOWN_INSTALL) - background_scheduler.add_job(task,'cron', args=['install'],id='install', \ - hour = random_time.hour,minute = random_time.minute,replace_existing=True) - else: - background_scheduler.pause_job('download') - background_scheduler.pause_job('install') - - if autoupgradepolicy.GetOptionValue('preDownload') == 'on': - random_time = get_random_time(autoupgradepolicy.GetOptionValue('preDownloadTime'),PREDOWNLOAD_RANDOM) - background_scheduler.add_job(task,'cron', args=['predownload'],id='download', \ - hour = random_time.hour,minute = random_time.minute,replace_existing=True) - else: - background_scheduler.pause_job('predownload') - - joblist = background_scheduler.get_jobs() - - for job in joblist: - logging.debug("job:%s,next run time:%s"%(job.id,job.next_run_time)) - ''' + if os.path.isfile(UNATTENDED_UPGRADE_POLICY_FILE_PATH): self.download_mode = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, AUTO_UPGRADE_POLICY_OPTION_DOWNLOAD_MODE) self.install_mode = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, AUTO_UPGRADE_POLICY_OPTION_INSTALL_MODE) self.preDownload = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, AUTO_UPGRADE_POLICY_OPTION_PREDOWNLOAD) @@ -887,37 +1022,35 @@ class UnattendedUpgradesShutdown(): logging.info("upgrade time: [%d:%d] [%d:%d] predown[%s] autoupgrade[%s] d-mode[%s] i-mode[%s]", self.download_time_r['h'], self.download_time_r['m'],self.install_time_r['h'],self.install_time_r['m'], self.preDownload, self.autoUpgrade, self.download_mode, self.install_mode) - ''' + else: logging.debug("unattended-upgrades-policy.conf not exist") - + ''' def upgrade_all_now_handler(): - now=datetime.datetime.now() - random_time = now + datetime.timedelta(minutes=DOWNLOAD_RANDOM) - background_scheduler.add_job(task,'date', args=['download_and_install'],id='download', \ - hour = random_time.hour,minute = random_time.minute,replace_existing=True) - - joblist = background_scheduler.get_jobs() - - for job in joblist: - logging.debug("job:%s,next run time:%s"%(job.id,job.next_run_time)) #self._wait_for_unattended_upgrade_finish() - ''' + logging.info("upgrade all now sinal received") + delta = random.randint(0,int(autoupgradepolicy.GetOptionValue('randomRange'))) + run_date = datetime.datetime.now() + datetime.timedelta(minutes=delta) + background_scheduler.add_job(task,'date', run_date = run_date,args=['download_and_install'],\ + id='download_and_install', replace_existing=True) + joblist = background_scheduler.get_jobs() + for job in joblist: + logging.debug("job:%s,next run time:%s"%(job.id,job.next_run_time)) + ''' if FindRuningUnattendedUpgrades(): logging.warning("find runing unattended-upgrades,please wait") return False else: - self._pause_timer() + #self._pause_timer() env = copy.copy(os.environ) retdownload = subprocess.run(["kylin-unattended-upgrade","--download-only"], env=env) retinstall = subprocess.run(["kylin-unattended-upgrade","--install-only"], env=env) - self._resume_timer() + #self._resume_timer() if retdownload == 0 and retinstall == 0: return True else: return False ''' - def prepare_for_shutdown_handler(active): """ Handle PrepareForShutdown() """ if not active: @@ -946,8 +1079,13 @@ class UnattendedUpgradesShutdown(): self.mainloop.quit() self.get_update_proxy() self.get_update_interface() - self.update_proxy.connect_to_signal("ChangeUpgradePolicy",change_upgrade_policy_handler) - self.update_proxy.connect_to_signal("UpgradeAllNow",upgrade_all_now_handler) + self.get_upgrade_strategy_proxy() + self.get_upgrade_strategy_interface() + + self.upgrade_strategy_proxy.connect_to_signal("PropertyChanged",property_changed_handler) + self.upgrade_strategy_proxy.connect_to_signal("UpgradeAllNow",upgrade_all_now_handler) + #self.update_proxy.connect_to_signal("ChangeUpgradePolicy",change_upgrade_policy_handler) + #self.update_proxy.connect_to_signal("UpgradeAllNow",upgrade_all_now_handler) try: self.get_logind_proxy().connect_to_signal( @@ -967,21 +1105,22 @@ class UnattendedUpgradesShutdown(): logging.debug("Skip waiting for signals, starting operation " "now") # self.start_iterations() - ''' + if os_release_info['PROJECT_CODENAME'] == 'V10SP1-edu' and os_release_info['SUB_PROJECT_CODENAME']=='mavis': logging.info("setting startup download timer") GLib.timeout_add(300*1000, lambda: self.timing_download() and False) #local_time =time.localtime(time.time()+300) - self.startup_download_job = self.scheduler.add_job(self.timing_download,'cron',hour=self.download_time_r['h'],minute = self.download_time_r['m']) - + #self.startup_download_job = self.scheduler.add_job(self.timing_download,'cron',hour=self.download_time_r['h'],minute = self.download_time_r['m']) else: + ''' if self.autoUpgrade == FeatureSwitch.ON.value: logging.debug("download time:[%d:%d] install time:[%d:%d]", self.download_time_r['h'], self.download_time_r['m'],self.install_time_r['h'],self.install_time_r['m']) self.download_job = self.scheduler.add_job(self.timing_download, 'cron', hour=self.download_time_r['h'], minute=self.download_time_r['m']) self.install_job = self.scheduler.add_job(self.timing_install, 'cron', hour=self.install_time_r['h'], minute=self.install_time_r['m']) elif self.autoUpgrade == FeatureSwitch.OFF.value: logging.info("auto upgrade turned off") - ''' + ''' + pass #TimerThread(self.scheduler).start() self.mainloop.run() logging.info("quit mainloop") @@ -1017,9 +1156,11 @@ class UnattendedUpgradesShutdown(): env = copy.copy(os.environ) #env["UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN"] = "1" logging.info("starting unattended-upgrades in shutdown mode") + ''' if FindRuningUnattendedUpgrades(): logging.warning("another unattended-upgrade is running , quit") return False + ''' self.on_shutdown_mode_uu_proc = subprocess.Popen( ["kylin-unattended-upgrade","--install-only","--mode=shutdown"], env=env) #log_msg(_("Running unattended-upgrades in shutdown mode")) @@ -1178,18 +1319,37 @@ if __name__ == "__main__": if not os.path.exists(logdir): os.makedirs(logdir) logfile = os.path.join(logdir, "unattended-upgrades-shutdown.log") - logging.basicConfig(filename=logfile, - level=level, - format="%(asctime)s %(levelname)s - %(message)s") - logging.getLogger('apscheduler').setLevel(logging.DEBUG) + #_setup_logging(options,logfile) + # logging.basicConfig(filename=logfile, + # level=level, + # format="%(asctime)s %(levelname)s - %(message)s") + logging.basicConfig(format='%(asctime)s-%(name)s-%(levelname)s-%(message)s',level=logging.DEBUG,filename=logfile) + # file_handler = logging.FileHandler(filename=logfile) + # file_handler.setLevel(logging.DEBUG) + # formatter = logging.Formatter() + # file_handler.setFormatter(formatter) + # stdout_handler = logging.StreamHandler(sys.stdout) + # stdout_handler.setLevel(logging.DEBUG) + + # logger=logging.getLogger() + # logger.setLevel(logging.DEBUG) + # logger.addHandler(file_handler) + # logger.addHandler(stdout_handler) + + # scheduler_logger = logging.getLogger('apscheduler') + # scheduler_logger.setLevel(logging.DEBUG) + # scheduler_logger.addHandler(file_handler) + # scheduler_logger.addHandler(stdout_handler) + os_release_info = ReadOsRelease('/etc/os-release') logging.info("project id:%s,sub-project id:%s"%(os_release_info['PROJECT_CODENAME'],os_release_info['SUB_PROJECT_CODENAME'])) - + ''' time_stamp = "0" if os.path.exists(TIME_STAMP): with open(TIME_STAMP,'r') as f: time_stamp = f.readline() logging.info("time stamp:%s"%time_stamp) + ''' # setup gettext localesApp = "unattended-upgrades" localesDir = "/usr/share/locale" @@ -1214,6 +1374,7 @@ if __name__ == "__main__": signal.signal(signal.SIGTERM, signal_term_handler) signal.signal(signal.SIGHUP, signal.SIG_IGN) dpkg_fix=None + ''' if os_release_info['PROJECT_CODENAME'] == 'V10SP1-edu' and os_release_info['SUB_PROJECT_CODENAME']=='mavis': dpkg_journal_dirty = is_dpkg_journal_dirty() logging.info("dpkg dirty:%s"%(dpkg_journal_dirty)) @@ -1232,9 +1393,11 @@ if __name__ == "__main__": logging.info("abnormal pkg count:%s"%(abnormal_pkg_count)) if abnormal_pkg_count != '0': apt_fix = subprocess.run("echo y|apt install -f",shell=True,stdout=open(logfile,'a+'),stderr=open(logfile,'a+')) + ''' kylin_system_updater = KylinSystemUpdater() autoupgradepolicy = AutoUpgradePolicy() - background_scheduler = BackgroundScheduler(timezone = "Asia/Shanghai") + background_scheduler = BackgroundScheduler() background_scheduler_init(background_scheduler) + #executor = ThreadPoolExecutor(max_workers=1) UnattendedUpgradesShutdown(options).run() #main()