diff --git a/unattended-upgrades/kylin-unattended-upgrade b/unattended-upgrades/kylin-unattended-upgrade index 0f92995..9b0caef 100644 --- a/unattended-upgrades/kylin-unattended-upgrade +++ b/unattended-upgrades/kylin-unattended-upgrade @@ -21,6 +21,8 @@ # along with unattended-upgrades; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +#from backend.build.lib.SystemUpdater.backend.DownloadBackend import FetchProgress +from email.policy import default import stat import atexit import copy @@ -30,6 +32,7 @@ import email.charset import fcntl import fnmatch import gettext +#from zoneinfo import ZoneInfoNotFoundError ''' try: from gi.repository.Gio import NetworkMonitor @@ -452,6 +455,21 @@ class KylinSystemUpdater: logging.info("update manager:quiting mainloop") self.loop.quit() + +class LoginManager: + def __init__(self) -> None: + DBusGMainLoop(set_as_default=True) + self.loop = GLib.MainLoop() + self.system_bus = dbus.SystemBus() + self.login_proxy = self.system_bus.get_object('org.freedesktop.login1', '/org/freedesktop/login1') + self.login_interface = dbus.Interface(self.login_proxy,dbus_interface='org.freedesktop.login1.Manager') + + def SetExtraInhibitShutdownDelaySec(self,time): + try: + self.login_interface.SetExtraInhibitShutdownDelaySec(time) + except Exception as e: + logging.error(e) + class KylinBackupManager: def __init__(self) -> None: DBusGMainLoop(set_as_default=True) @@ -1339,10 +1357,9 @@ def cache_commit(cache, # type: apt.Cache res = False if iprogress is None: iprogress = LogInstallProgress(logfile_dpkg, verbose,progress_log=PROGRESS_LOG) - try: - res = cache.commit(install_progress=iprogress) - cache.open() + res = cache.commit(fetch_progress=None,install_progress=iprogress,allow_unauthenticated=True) + #cache.open() except SystemError as e: error = e if verbose: @@ -2021,10 +2038,18 @@ def do_install(cache, # type: UnattendedUpgradesCache logging.info(_("Writing dpkg log to %s"), logfile_dpkg) - if cache.get_changes(): - cache.clear() + # if cache.get_changes(): + # cache.clear() pkg_install_success = False + + iprogress = LogInstallProgress(logfile_dpkg, verbose=True,progress_log=PROGRESS_LOG) + try: + pkg_install_success = cache.commit(fetch_progress=apt.progress.text.AcquireProgress(outfile = logfile_fd),install_progress=iprogress,allow_unauthenticated=True) + except Exception as e: + logging.error("cache commit errot:%s"%e) + + ''' try: if options.minimal_upgrade_steps: # try upgrade all "pkgs" in minimal steps @@ -2040,7 +2065,7 @@ def do_install(cache, # type: UnattendedUpgradesCache # print unhandled exceptions here this way, while stderr is redirected os.write(2, ("Exception: %s\n" % e).encode('utf-8')) pkg_install_success = False - + ''' return pkg_install_success @@ -2496,15 +2521,18 @@ def main(options, rootdir="/"): # _setup_alternative_rootdir(rootdir) # see debian #776752 - install_start_time = datetime.datetime.now().replace(microsecond=0) - logging.info("unattended-upgrades start time:%s"%install_start_time) + # install_start_time = datetime.datetime.now().replace(microsecond=0) + # logging.info("unattended-upgrades start time:%s"%install_start_time) # get log + ''' dpkg_journal_dirty = is_dpkg_journal_dirty() abnormal_pkg_count = get_abnormally_installed_pkg_count() - logging.info("abnormal pkg count:%d,dpkg dirty:%s"%(abnormal_pkg_count,dpkg_journal_dirty)) - if dpkg_journal_dirty and abnormal_pkg_count > 0: - ret = subprocess.run(["dpkg", "--force-confold", "--configure", "-a"],shell=True,stdout=open(logfile,'a+'),stderr=open(logfile,'a+')) - logging.info("dpkg fix return :%s"%ret.returncode) + logging.info("abnormal pkg count:%s,dpkg dirty:%s"%(abnormal_pkg_count,dpkg_journal_dirty)) + if os_release_info['PROJECT_CODENAME'] == 'V10SP1-edu' and os_release_info['SUB_PROJECT_CODENAME']=='mavis': + if dpkg_journal_dirty or abnormal_pkg_count != '0': + ret = subprocess.run("dpkg --configure -a",shell=True,stdout=open(logfile,'a+'),stderr=open(logfile,'a+')) + logging.info("dpkg fix return :%s"%ret.returncode) + ''' # lock for the shutdown check # shutdown_lock = apt_pkg.get_lock(LOCK_FILE) # if shutdown_lock < 0: @@ -2783,7 +2811,7 @@ def run(options, # type: Options pkgs = [pkg.name for pkg in pkgs_to_upgrade] logging.debug("pkgs that look like they should be upgraded or installed: %s" % "\n".join(pkgs)) - + # FIXME: make this into a ContextManager # stop being nice os.nice(old_priority - os.nice(0)) @@ -2794,7 +2822,7 @@ def run(options, # type: Options mark_pkgs_to_upgrade(cache, pkgs) if options.debug: - fetcher = apt_pkg.Acquire(apt.progress.text.AcquireProgress()) + fetcher = apt_pkg.Acquire(apt.progress.text.AcquireProgress(outfile = logfile_fd)) else: fetcher = apt_pkg.Acquire() list = apt_pkg.SourceList() @@ -2816,7 +2844,7 @@ def run(options, # type: Options fetcher_statistics.GetAquireStatisticsOfPkgs() logging.debug("%d local,%d remote"%(fetcher_statistics.local_pkg_amount,fetcher_statistics.remote_pkg_amount)) - if options.install_only: + if options.install_only: if options.mode == 'shutdown': if kylin_system_updater.GetConfigValue('InstallMode','shutdown_install'): pass @@ -2831,15 +2859,69 @@ def run(options, # type: Options return UnattendedUpgradesResult(False,_("there're pkgs to download")) else: #only write the pkg list when dpkg journal is clean - if not is_dpkg_journal_dirty(): - configfilemanager.WriteListToFile(pkgs,"OTA_PKGS_TO_INSTALL_LIST") + # if not is_dpkg_journal_dirty(): + # configfilemanager.WriteListToFile(pkgs,"OTA_PKGS_TO_INSTALL_LIST") try: res = fetcher.run() logging.debug("fetch.run() result: %s", res) except SystemError as e: logging.error("fetch.run() result: %s", e) - + + # if cache.get_changes(): + # cache.clear() + + pkg_install_success = True + if len(pkgs_to_upgrade) > 0: + 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': + pass + else: + logging.info("neeed backup") + Backup() + # do install + WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","install") + #send install start msg to notify + # if os.path.exists(NOTIFICATION_PIPE): + # with open(NOTIFICATION_PIPE,'w') as p: + # p.write('install start') + with open(PROGRESS_LOG,'w+') as f: + f.write('0') + subprocess.Popen('dbus-send --system --type=signal / com.kylin.install.notification.InstallStart',shell=True) + if LockedPreventShutdown(): + pass + else: + logging.error("cannot get shutdown lock,exiting...") + WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","idle") + sys.exit(1) + + logging.debug("InstCount=%i DelCount=%i BrokenCount=%i" + % (cache._depcache.inst_count, + cache._depcache.del_count, + cache._depcache.broken_count)) + + pkg_install_success = do_install(cache, + pkgs, + options, + logfile_dpkg) + unLockedEnableShutdown() + subprocess.Popen('dbus-send --system --type=signal / com.kylin.install.notification.InstallFinish',shell=True) + if pkg_install_success: + kylin_system_updater.CheckRebootRequired("unattended-upgrades") + install_result = '' + logging.debug("pkg number:%d,pkg in whitelist number:%d"%(len(pkgs),len(namelist_with_version))) + if len(pkgs) == len(namelist_with_version): + install_result = "total_install" + else: + install_result = "partial_install" + logging.debug("install result:%s"%install_result) + return UnattendedUpgradesResult(pkg_install_success, + install_result, + pkgs) + elif options.download_only: + if fetcher_statistics.remote_pkg_amount>0: pass else: @@ -2867,9 +2949,11 @@ def run(options, # type: Options logging.error(_("GetArchives() failed: %s"), e) else: break - fetcher_statistics.ResetFetcher(fetcher) - fetcher_statistics.GetAquireStatisticsOfPkgs() + #fetcher_statistics.ResetFetcher(fetcher) + #fetcher_statistics.GetAquireStatisticsOfPkgs() if fetcher_statistics.incomplete_pkg_amount == 0: + logging.info("pkg number:%d,shutdown delay time:%d s"%(len(pkgs),30*len(pkgs))) + login_manager.SetExtraInhibitShutdownDelaySec(30*len(pkgs)) docker_image_fetch_result = None #docker image fetch for mavis and laika if os.path.exists("/usr/bin/service_runtime_ota.sh"): @@ -2900,8 +2984,7 @@ def run(options, # type: Options logging.error("fetch.run() result: %s", e) return UnattendedUpgradesResult(False,_("option is not install-only or download-only")) - if cache.get_changes(): - cache.clear() + ''' pkg_conffile_prompt = False if dpkg_conffile_prompt(): @@ -3060,7 +3143,7 @@ def run(options, # type: Options # do the install based on the new list of pkgs pkgs = [pkg.name for pkg in pkgs_to_upgrade] logging.info(_("Packages that will be upgraded: %s"), " ".join(pkgs)) - ''' + # only perform install step if we actually have packages to install pkg_install_success = True if len(pkgs_to_upgrade) > 0: @@ -3109,18 +3192,18 @@ def run(options, # type: Options # with open(NOTIFICATION_PIPE,'w') as p: # p.write('install finish') # now check if any auto-removing needs to be done - ''' + if cache._depcache.broken_count > 0: print(_("Cache has broken packages, exiting")) logging.error(_("Cache has broken packages, exiting")) return UnattendedUpgradesResult( False, _("Cache has broken packages, exiting"), pkgs=pkgs) - ''' + # make sure we start autoremovals with a clear cache # if cache.get_changes(): # cache.clear() - ''' + # the user wants *all* auto-removals to be removed # (unless u-u got signalled to stop gracefully quickly) pkgs_removed = [] # type: List[str] @@ -3170,7 +3253,7 @@ def run(options, # type: Options kernel_pkgs_removed + pkgs_removed, kernel_pkgs_kept_installed + pkgs_kept_installed, update_stamp=True) - ''' + install_result = '' logging.debug("pkg number:%d,pkg in whitelist number:%d"%(len(pkgs),len(namelist_with_version))) if len(pkgs) == len(namelist_with_version): @@ -3181,7 +3264,7 @@ def run(options, # type: Options return UnattendedUpgradesResult(pkg_install_success, install_result, pkgs) - + ''' class Options: def __init__(self): @@ -3224,8 +3307,9 @@ if __name__ == "__main__": parser = OptionParser() parser.add_option("-d", "--debug", action="store_true", - default=apt_pkg.config.find_b( - "Unattended-Upgrade::Debug", False), + default=True, + # default=apt_pkg.config.find_b( + # "Unattended-Upgrade::Debug", False), help=_("print debug messages")) parser.add_option("", "--apt-debug", action="store_true", default=False, @@ -3291,7 +3375,8 @@ if __name__ == "__main__": logfile = os.path.join(logdir, 'unattended-upgrades.log') if not os.path.exists(logfile): with open(logfile, 'w'): - pass + pass + logfile_fd = open(logfile,'a+') #setup dpkg log logfile_dpkg = os.path.join(logdir, 'unattended-upgrades-dpkg.log') if not os.path.exists(logfile_dpkg): @@ -3304,13 +3389,17 @@ if __name__ == "__main__": 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() - allow_autoupdate = kylin_system_updater.GetDatabaseInfo("display","autoupdate_allow") - if allow_autoupdate == "true": + if os_release_info['PROJECT_CODENAME'] == 'V10SP1-edu' and os_release_info['SUB_PROJECT_CODENAME']=='mavis': pass else: - logging.info("auto upgrade not allow, exit") - sys.exit(0) + allow_autoupdate = kylin_system_updater.GetDatabaseInfo("display","autoupdate_allow") + if allow_autoupdate == "true": + pass + else: + logging.info("auto upgrade not allow, exit") + sys.exit(0) #check control center lock ''' if os.path.exists(CONTROL_PANEL_LOCK_FILE): @@ -3327,4 +3416,14 @@ if __name__ == "__main__": elif options.install_only: 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) + # get log + dpkg_journal_dirty = is_dpkg_journal_dirty() + abnormal_pkg_count = get_abnormally_installed_pkg_count() + logging.info("abnormal pkg count:%s,dpkg dirty:%s"%(abnormal_pkg_count,dpkg_journal_dirty)) + if os_release_info['PROJECT_CODENAME'] == 'V10SP1-edu' and os_release_info['SUB_PROJECT_CODENAME']=='mavis': + if dpkg_journal_dirty or abnormal_pkg_count != '0': + ret = subprocess.run("dpkg --configure -a",shell=True,stdout=open(logfile,'a+'),stderr=open(logfile,'a+')) + logging.info("dpkg fix return :%s"%ret.returncode) sys.exit(main(options)) diff --git a/unattended-upgrades/kylin-unattended-upgrade-shutdown b/unattended-upgrades/kylin-unattended-upgrade-shutdown index 5098e28..978072c 100644 --- a/unattended-upgrades/kylin-unattended-upgrade-shutdown +++ b/unattended-upgrades/kylin-unattended-upgrade-shutdown @@ -106,7 +106,10 @@ NOTIFICATION_PIPE = '/tmp/notification.pipe' flag_file_list = ["/var/lib/unattended-upgrades/OTA_PKGS_TO_INSTALL",\ "/var/lib/kylin-auto-upgrade/kylin-autoupgrade.conf","/tmp/notify.pid"] - + + + + def GetDateTime(): return datetime.datetime.now().replace(microsecond=0) @@ -197,6 +200,10 @@ def log_progress(): msg = "upgrage progress %s"%progress_text log_msg(msg) +def signal_term_handler(signal,frame): + # type: (int, object) -> None + logging.warning("SIGTERM received, will stop") + os._exit(1) def signal_stop_unattended_upgrade(): """ send SIGTERM to running unattended-upgrade if there is any """ @@ -210,7 +217,6 @@ def signal_stop_unattended_upgrade(): logging.debug("sending SIGTERM failed because unattended-upgrades " "already stopped") - def exit_log_result(success): if os.path.exists(PKGS_TO_INSTALL_FLAG_FILE): os.remove(PKGS_TO_INSTALL_FLAG_FILE) @@ -347,7 +353,7 @@ class UnattendedUpgradesShutdown(): def get_update_interface(self): self.update_interface = dbus.Interface(self.update_proxy,dbus_interface='com.kylin.systemupgrade.interface') return self.update_interface - + ''' def set_max_inhibit_time(self,time): login_proxy = self.get_logind_proxy() #首先设置systemd默认延长时间为1800 @@ -358,7 +364,7 @@ class UnattendedUpgradesShutdown(): ret = getter_interface.SetInhibitDelayMaxSec(time) except Exception as e: logging.error(e) - + ''' def get_logind_proxy(self): """ Get logind dbus proxy object """ @@ -408,6 +414,9 @@ class UnattendedUpgradesShutdown(): return self.shutdown_pending def start_iterations(self): + while self.iter(): + time.sleep(1) + ''' if not self.iter_timer_set: try: GLib.timeout_add(self.wait_period * 1000, self.iter) @@ -415,6 +424,7 @@ class UnattendedUpgradesShutdown(): GLib.timeout_add(0, lambda: self.iter() and False) except NameError: pass + ''' return True def run_polling(self, signal_handler): @@ -509,10 +519,11 @@ 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 change_upgrade_policy_handler(): if os.path.isfile(UNATTENDED_UPGRADE_POLICY_FILE_PATH): @@ -596,18 +607,24 @@ class UnattendedUpgradesShutdown(): do_plymouth_splash() self.start_iterations() logging.info("finished iteration") - self.set_max_inhibit_time(5) - logging.debug("quiting mainloop") + ''' self.mainloop.quit() else: - self.set_max_inhibit_time(5) self.mainloop.quit() - else: - self.set_max_inhibit_time(5) + else: self.mainloop.quit() - else: - self.set_max_inhibit_time(5) + else: self.mainloop.quit() + ''' + elif os_release_info['PROJECT_CODENAME'] == 'V10SP1-edu' and os_release_info['SUB_PROJECT_CODENAME']=='mavis': + if os.path.exists(PKGS_TO_INSTALL_FLAG_FILE): + logging.info("mavis shutdown install") + do_plymouth_splash() + self.start_iterations() + logging.info("finished iteration") + else: + pass + self.mainloop.quit() self.get_update_proxy() self.get_update_interface() self.update_proxy.connect_to_signal("ChangeUpgradePolicy",change_upgrade_policy_handler) @@ -624,7 +641,7 @@ class UnattendedUpgradesShutdown(): _("Maybe systemd-logind service is not running.")) # self.run_polling(signal_handler) return - self.set_max_inhibit_time(1800) + #self.set_max_inhibit_time(1800) logging.debug("Waiting for signal to start operation ") else: # starting final iterations immediately @@ -635,14 +652,16 @@ class UnattendedUpgradesShutdown(): 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']) if os_release_info['PROJECT_CODENAME'] == 'V10SP1-edu' and os_release_info['SUB_PROJECT_CODENAME']=='mavis': - logging.info("setting download timer") - local_time =time.localtime(time.time()+300) - self.startup_download_job = self.scheduler.add_job(self.timing_download,'cron',hour=local_time.tm_hour,minute = local_time.tm_min) + logging.info("setting startup download timer") + GLib.timeout_add(300, 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=local_time.tm_hour,minute = local_time.tm_min) else: self.install_job = self.scheduler.add_job(self.timing_install, 'cron', hour=self.install_time_r['h'], minute=self.install_time_r['m']) TimerThread(self.scheduler).start() self.mainloop.run() logging.info("quit mainloop") + os._exit(0) #GLib.MainLoop().run() def try_iter_on_shutdown(self): @@ -673,10 +692,10 @@ class UnattendedUpgradesShutdown(): if self.on_shutdown_mode: env = copy.copy(os.environ) #env["UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN"] = "1" - logging.debug("starting unattended-upgrades in shutdown mode") + logging.info("starting unattended-upgrades in shutdown mode") 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")) + #log_msg(_("Running unattended-upgrades in shutdown mode")) # run u-u, but switch to stopping when receiving stop signal # because it means shutdown progressed despite holding the lock @@ -684,12 +703,21 @@ class UnattendedUpgradesShutdown(): log_progress() if self.on_shutdown_mode_uu_proc.poll() is not None: # unattended-upgrades stopped on its own - exit_log_result(True) + #exit_log_result(True) + if os.path.exists(PKGS_TO_INSTALL_FLAG_FILE): + os.remove(PKGS_TO_INSTALL_FLAG_FILE) + subprocess.call(["/bin/plymouth","system-update","--progress=100"]) + time.sleep(1) + subprocess.run(["/bin/plymouth","quit","--retain-splash"]) + return False else: return True + return False + def iter(self): + ''' if self.start_time is None: self.start_time = time.time() logging.debug("Starting countdown of %s minutes", @@ -699,13 +727,17 @@ class UnattendedUpgradesShutdown(): logging.warning(_( "Giving up on lockfile after %s minutes of delay"), self.max_delay / 60) - os._exit(1) + #os._exit(1) #sys.exit(1) + return False if not self.stop_signal_received.is_set(): if self.try_iter_on_shutdown(): return True - + else: + return False + + # run monitoring and keep "UI" updated res = apt_pkg.get_lock(self.options.lock_file) logging.debug("get_lock returned %i" % res) @@ -722,8 +754,10 @@ class UnattendedUpgradesShutdown(): self.signal_sent = True # show log log_progress() - return True - + ''' + return self.try_iter_on_shutdown() + #return True + def main(): # setup gettext @@ -778,12 +812,14 @@ def main(): level=level, format="%(asctime)s %(levelname)s - %(message)s") clean_flag_files(flag_file_list) + signal.signal(signal.SIGTERM, signal_term_handler) + signal.signal(signal.SIGHUP, signal.SIG_IGN) # init() - + logging.info("project id:%s,sub-project id:%s"%(os_release_info['PROJECT_CODENAME'],os_release_info['SUB_PROJECT_CODENAME'])) UnattendedUpgradesShutdown(options).run() if __name__ == "__main__": 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'])) + main()