add dpkg fix before each downlaod/install for mavis

This commit is contained in:
shenyafeng 2022-05-24 17:48:58 +08:00
parent 03f385a9be
commit 91c47f2bbb
2 changed files with 195 additions and 60 deletions

View File

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

View File

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