同步主线变动

This commit is contained in:
wangsong 2023-05-29 14:47:39 +08:00
parent 192a914ee6
commit 7c74313253
31 changed files with 3089 additions and 1339 deletions

View File

@ -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):
#秘钥

View File

@ -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()

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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())

View File

@ -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):
#关机安装完成之后开机时进行提醒

View File

@ -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=''):

View File

@ -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,

View File

@ -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')

View File

@ -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()

File diff suppressed because it is too large Load Diff

View File

@ -8,9 +8,10 @@
<vendor_url>www.kylinos.cn</vendor_url>
<icon_name>kylin-system-updater</icon_name>
<action id="cn.kylinos.KylinSystemUpdater.action">
<!--Kylin Installer Config-->
<action id="cn.kylin.installer.action">
<_description>
system level settings
Configuration items added for Kirin Installer
</_description>
<_message>
To Change the settings, you need to authenticate.
@ -22,4 +23,47 @@
</defaults>
</action>
<action id="cn.kylin.uninstaller.action">
<_description>
Configuration items added for Kirin Uninstaller
</_description>
<_message>
To Change the settings, you need to authenticate.
</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<!--Kylin System Updater Config-->
<action id="cn.kylinos.KylinSystemUpdater.action">
<_description>
Configuration items added for Kirin Installer
</_description>
<_message>
To Change the settings, you need to authenticate.
</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<!--Kylin Software Center Config-->
<action id="cn.kylin.software.center.action">
<_description>
Configuration items added for Kylin Software Center
</_description>
<_message>
To Change the settings, you need to authenticate.
</_message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin</allow_active>
</defaults>
</action>
</policyconfig>

View File

@ -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

Binary file not shown.

View File

@ -1,5 +1,6 @@
[SystemStatus]
abnormal_reboot = False
reboot_update = False
upload_upgrade_log = True
upload_installer_log = False

View File

@ -6,7 +6,7 @@ autoUpgradeState = off
preDownload = off
# 预下载的时间为时间段 例如10:00-11:00
preDownloadTime = 10:00
preDownloadTime = 00:00-06:00
#添加检查更新的周期 以天为单位
updateDays = 1
@ -15,13 +15,16 @@ updateDays = 1
downloadMode = timing
# 下载的时间为时间段 例如10:00-11:00
downloadTime = 10:00
downloadTime = 00:00-05:00
#安装存在定时timing 手动:manual 关机安装bshutdown
installMode = timing
installMode = timing
#安装也为时间段 例如00:00
installTime = 10:00
installTime = 05:30-06:00
#立即更新随机波动范围(单位:分钟)
randomRange = 60
#是否开启自动重启 以及自动重启时间可以调节
automaticReboot = off

View File

@ -1 +1,5 @@
0
[timestamp]
predownload = 2022-01-01 00:00:00
download = 2022-01-01 00:00:00
install = 2022-01-01 00:00:00
download_and_install = 2022-01-01 00:00:00

View File

@ -83,7 +83,7 @@ if __name__ == "__main__":
signal.signal(signal.SIGINT,signal_handler_term)
if options.debug:
logging.basicConfig(format=FORMAT,level=logging.INFO,datefmt='%m-%d,%H:%M:%S')
logging.basicConfig(format=FORMAT,level=logging.DEBUG,datefmt='%m-%d,%H:%M:%S')
else:
logging.basicConfig(format=FORMAT,level=logging.DEBUG,datefmt='%m-%d,%H:%M:%S',filename = logfile(),filemode = 'a')
@ -91,13 +91,14 @@ if __name__ == "__main__":
app = UpdateManager(options)
#当出现安装过程中异常的重启时 开机直接进行修复操作
# if app.configs_cover.getWithDefault("ConfigPkgStatus", "check_frontend_pkg", False) == True:
# app.configs_cover.setValue("ConfigPkgStatus","check_frontend_pkg",str(False),True)
# app.check_frontend_pkg()
#当出现安装过程中异常的重启时 开机直接进行修复操作
if app.configs_uncover.getWithDefault("SystemStatus", "abnormal_reboot", False) == True:
app.configs_uncover.setValue("SystemStatus","abnormal_reboot",str(False),True)
app.start_update()
#自我升级完成后 初始化列表
if app.configs_uncover.getWithDefault("SystemStatus", "reboot_update", False) == True:
app.configs_uncover.setValue("SystemStatus","reboot_update",str(False),True)
app.start_available()
app.run()

226
backend/po/bo_CN.po Normal file
View File

@ -0,0 +1,226 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 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 <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\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 "འཁོར་སྐྱོད་ཞིབ་བཤེར་གྱི་རྐང་པར་རྒྱུན་ལྡན་མིན་པ་བྱུང་།"

View File

@ -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 "软件包未签名,拒绝安装。"
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 "正在安装或删除软件包。"

View File

@ -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?"

View File

@ -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?"

View File

@ -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"

9
debian/changelog vendored
View File

@ -1,3 +1,12 @@
kylin-system-updater (2.0.5.15-ok4) yangtze; urgency=medium
* BUG: #无
* 需求号: 无
* 其他改动说明: 同步2303主线代码
* 其他改动影响域:系统更新
-- Kevin Duan <duankaiwen@kylinos.cn> Mon, 29 May 2023 14:47:14 +0800
kylin-system-updater (2.0.5.15-ok3) yangtze; urgency=medium
* BUG: #无

View File

@ -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)<len(white_list_with_version)):
logging.warning("some pkgs failed in sanity check")
return UnattendedUpgradesResult(False,"sanity check failed")
pkgs_to_upgrade.sort(key=lambda p: p.name)
pkgs = [pkg.name for pkg in pkgs_to_upgrade]
logging.debug("%d pkgs that look like they should be upgraded or installed: %s"
% (len(pkgs),"\n".join(pkgs)))
logging.debug("pkgs that look like they should be upgraded or installed: %s"
% "\n".join(pkgs))
# FIXME: make this into a ContextManager
# stop being nice
@ -3448,6 +3432,7 @@ def run(options, # type: Options
logging.debug("%d local,%d remote"%(fetcher_statistics.local_pkg_amount,fetcher_statistics.remote_pkg_amount))
if options.install_only:
if options.mode == 'shutdown':
if kylin_system_updater.GetConfigValue('InstallMode','shutdown_install'):
pass
@ -3464,7 +3449,7 @@ def run(options, # type: Options
apt_pkg.pkgsystem_unlock()
except SystemError:
logging.error(_("lock release failed"))
return UnattendedUpgradesResult(True,_("no local pkgs to install"))
return UnattendedUpgradesResult(False,_("no local pkgs to install"))
elif fetcher_statistics.remote_pkg_amount >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)

View File

@ -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()