#!/usr/bin/python3 from optparse import OptionParser import dbus from dbus.mainloop.glib import DBusGMainLoop from gi.repository import GLib from threading import Event from gettext import gettext as _ import gettext import apt_pkg #from apt.progress.base import AcquireProgress from apt.progress.text import AcquireProgress import apt import os import json ''' class FetchProgress(AcquireProgress): def __init__(self) -> None: super().__init__() def fetch(self, item: apt_pkg.AcquireItemDesc) -> None: print("%s [%d%%]"%(item.description,self.current_bytes*100/self.total_bytes)) return super().fetch(item) def fail(self, item: apt_pkg.AcquireItemDesc) -> None: print("package fetch failed:%s"%item.description) return super().fail(item) def ims_hit(self, item: apt_pkg.AcquireItemDesc) -> None: return super().ims_hit(item) def media_change(self, media: str, drive: str) -> bool: return super().media_change(media, drive) def pulse(self, owner: apt_pkg.Acquire) -> bool: return super().pulse(owner) def start(self) -> None: print("download start") return super().start() def stop(self) -> None: print("download finished") return super().stop() ''' class SystemUpdater: def __init__(self) -> None: self.update_detect_status = False self.update_detect_event = Event() self.update_list = [] self.resolve_depend_status = False self.resolve_depend_status_event = Event() self.remove_pkgs = [] self.install_finish_status = False self.install_finish_status_event = Event() self.install_finish_group = [] DBusGMainLoop(set_as_default=True) self.loop = GLib.MainLoop() self.system_bus = dbus.SystemBus() self.update_proxy = self.system_bus.get_object('com.kylin.systemupgrade','/com/kylin/systemupgrade',follow_name_owner_changes=True) self.update_interface = dbus.Interface(self.update_proxy,dbus_interface='com.kylin.systemupgrade.interface') self.update_proxy.connect_to_signal('UpdateDetectFinished',self.update_detect_finished_handler) self.update_proxy.connect_to_signal('UpdateFixBrokenStatus',self.update_fix_broken_status) self.update_proxy.connect_to_signal('UpdateDependResloveStatus',self.update_depend_resolve_status) self.update_proxy.connect_to_signal('UpdateDloadAndInstStaChanged',self.update_download_install_status) self.update_proxy.connect_to_signal('UpdateInstallFinished',self.update_install_finished) def update_detect_finished_handler(self,success,updatelist,error_status,error_cause): print(_("update detect finished:sucess:%s,updatelist:%s,error_status:%s,error_cause:%s")\ %(success,",".join(updatelist),error_status,error_cause)) self.update_detect_status = success self.update_list = [] if success: try: for update_group in updatelist: json_file_path = ("/var/lib/kylin-system-updater/json/%s.json"%(update_group)) if os.path.exists(json_file_path): with open(json_file_path,'r') as f: data = json.load(f) for key in data['upgrade_list'].keys(): if key in ["total_download_size","total_install_size"]: pass else: self.update_list.append(key) for key in data['install_list'].keys(): if key in ["total_download_size","total_install_size"]: pass else: self.update_list.append(key) except Exception as e: print(e) self.update_detect_event.set() self.QuitMainLoop() def update_fix_broken_status(self,resolver_status,remove_status,remove_pkgs,pkg_raw_description,delete_desc,error_string,error_desc): print(_("update fix broken status:resolver_status:%s,remove_status:%s,error_string:%s,error_desc:%s")%(resolver_status,remove_status,error_string,error_desc)) print(remove_pkgs,pkg_raw_description,delete_desc) self.update_detect_status = False self.update_list = [] self.update_detect_event.set() self.QuitMainLoop() def update_depend_resolve_status(self,resolver_status,remove_status,remove_pkgs,pkg_raw_description,delete_description,error_string,error_desc): print(_("update depend resove status:%s,remove status:%s,remove pkgs:%s,pkg raw description:%s,delete_descrition:%s,error string:%s,error desc:%s")\ %(resolver_status,remove_status,",".join(remove_pkgs),",".join(pkg_raw_description),",".join(delete_description),error_string,error_desc)) self.resolve_depend_status = resolver_status self.remove_pkgs = remove_pkgs self.resolve_depend_status_event.set() self.QuitMainLoop() def update_download_install_status(self,group,progress,status,details): print(_("%s update progress:%d,status:%s,details:%s")%(",".join(group),progress,status,details)) def update_install_finished(self,success,group,error_string,error_desc): print(_("update install finisih success:%s,group:%s,error string:%s,error desc:%s")\ %(success,",".join(group),error_string,error_desc)) self.install_finish_status = success self.install_finish_group=group self.install_finish_status_event.set() self.QuitMainLoop() def download(self): print(_("start download")) self.UpdateDetect() self.RunMainLoop() print(_("update detect finish:%s,%s")%(self.update_detect_status,",".join(self.update_list))) if self.update_detect_status and len(self.update_list)>0: pass # elif not self.update_detect_status and 'kylin-system-updater' in self.update_list: # print(_("self update finished")) else: print(_("no pkgs to download")) return False cache = apt.Cache() for pkg in self.update_list: try: package = cache[pkg] if not package.installed: package.mark_install() else: package.mark_upgrade() except Exception as e: print(e) return False list = apt_pkg.SourceList() list.read_main_list() recs = cache._records pm = apt_pkg.PackageManager(cache._depcache) fetcher = apt_pkg.Acquire(AcquireProgress()) try: pm.get_archives(fetcher, list, recs) except Exception as e: print(e) res = fetcher.run() print("fetch.run() result: %d"%res) if res == 0: return True else: return False def install(self): print(_("start install")) self.UpdateDetect() self.RunMainLoop() print(_("update detect finish:%s,%s")%(self.update_detect_status,",".join(self.update_list))) if self.update_detect_status and len(self.update_list)>0: pass # elif not self.update_detect_status and 'kylin-system-updater' in self.update_list: # print(_("self update finished")) else: return False self.DistUpgradeAll(False) self.RunMainLoop() print(_("resolve dependency status:%s,%s")%(self.resolve_depend_status,",".join(self.remove_pkgs))) if self.resolve_depend_status and len(self.remove_pkgs)==0: pass else: return False self.DistUpgradeAll(True) self.RunMainLoop() print(_("install finish status:%s,%s")%(self.install_finish_status,",".join(self.install_finish_group))) if self.install_finish_status and len(self.install_finish_group)>0: pass else: return False return True def UpdateDetect(self): return self.update_interface.UpdateDetect() def DistUpgradeAll(self,is_install): return self.update_interface.DistUpgradeAll(is_install) def RunMainLoop(self): self.loop.run() def QuitMainLoop(self): self.loop.quit() if __name__ == "__main__": gettext.bindtextdomain("unattended-upgrades","/usr/share/locale") gettext.textdomain("unattended-upgrades") parser = OptionParser() parser.add_option("", "--download-only", action="store_true", dest="download_only", default=False,help="only download without install") parser.add_option("", "--install-only", action="store_true", dest="install_only", default=False,help="only install without download") (options, args) = parser.parse_args() print(options,args) systemupdater = SystemUpdater() if options.download_only: systemupdater.download() elif options.install_only: systemupdater.install() else: pass