Merge branch 'uu_test' into 'backend_uu'

add os-release info

See merge request kylin-desktop/update-manager-group/kylin-system-updater!398
This commit is contained in:
wangsong 2022-04-13 08:47:12 +00:00
commit f7e45dd10d
9 changed files with 463 additions and 258 deletions

View File

@ -17,13 +17,10 @@ backend/data/unattended-upgrades-policy.conf /var/lib/unattended-upgrades/
#uu
unattended-upgrades/*.service /lib/systemd/system/
unattended-upgrades/*.timer /lib/systemd/system/
unattended-upgrades/unattended-upgrades-daily /usr/bin/
unattended-upgrades/notify /usr/bin/
unattended-upgrades/*.desktop /etc/xdg/autostart/
unattended-upgrades/kylin-unattended-upgrade /usr/bin
unattended-upgrades/kylin-unattended-upgrade-shutdown /usr/bin
unattended-upgrades/unattended-upgrades-daily /usr/bin
unattended-upgrades/kylin-unattended-upgrades /etc/apt/apt.conf.d/
unattended-upgrades/logrotate.d/* /etc/logrotate.d/
unattended-upgrades/kylin-unattended-upgrades-logind-maxdelay.conf /usr/lib/systemd/logind.conf.d/

3
debian/postinst vendored
View File

@ -9,11 +9,8 @@ fi
systemctl enable kylin-system-updater.service
mkdir -p /var/lib/unattended-upgrades
chmod +x /usr/bin/unattended-upgrades-daily
chmod +x /usr/bin/kylin-unattended-upgrade
chmod +x /usr/bin/kylin-unattended-upgrade-shutdown
systemctl enable unattended-upgrades-download.timer
systemctl enable unattended-upgrades-install.timer
systemctl enable kylin-unattended-upgrades.service
if [ -f /usr/share/kylin-system-updater/SystemUpdater/Core/DataMigration.py ];then
echo "Database record migration"

View File

@ -21,7 +21,7 @@
# along with unattended-upgrades; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import stat
import atexit
import copy
import datetime
@ -92,6 +92,7 @@ import fcntl
import time
import subprocess
OTA_RESULT_FILE_PATH="/opt/apt_result/ota_result"
SYSTEM_UPDATER_CORE_LIB_PATH="/usr/share/kylin-system-updater/SystemUpdater/Core"
sys.path.append(SYSTEM_UPDATER_CORE_LIB_PATH)
from OriginFilter import UnattendUpgradeFilter
@ -129,6 +130,20 @@ SHUTDOWN_BLOCK_FILELOCK = "kylin-update.lock"
pidfile = None
# set from the sigint signal handler
SIGNAL_STOP_REQUEST = False
def ReadOsRelease(file):
osreleasedict={}
try:
with open(file) as f:
lines = f.readlines()
for line in lines:
ls = line.strip().split('=',1)
osreleasedict.update({ls[0]:ls[1]})
except Exception as e:
pass
return osreleasedict
#安装时禁止关机 进行加锁
def LockedPreventShutdown():
global pidfile
@ -365,6 +380,12 @@ class KylinSystemUpdater:
self.update_interface = dbus.Interface(self.update_proxy,dbus_interface='com.kylin.systemupgrade.interface')
self.success = False
def GetConfigValue(self,section,value):
return self.update_interface.GetConfigValue(section,value)
def SetConfigValue(self,section,option,value):
return self.update_interface.SetConfigValue(section,option,value)
def GetWhiteList(self):
ret = self.update_interface.UpdateDetect()
return ret
@ -466,6 +487,52 @@ class KylinBackupManager:
logging.info("backup manager:quiting mainloop")
self.loop.quit()
def ReadValueFromFile(file,section,option):
config=configparser.ConfigParser(allow_no_value=True)
try:
config.read(file)
value = config[section][option]
except Exception as e:
return None
return value
def Backup():
# do backup
kylin_backup_manager = KylinBackupManager()
backup_partition_status = kylin_backup_manager.mount_backup_partition()
if backup_partition_status not in [0,5]:
logging.error("backup partition error:%d"%backup_partition_status)
return UnattendedUpgradesResult(False,"backup partition error")
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")
#node_name,node_status = kylin_backup_manager.get_backup_comment_for_systemupdate()
ts = get_timestamp()
kylin_backup_manager.ConnectToSignals()
create_note = "系统升级新建备份"
inc_note="系统升级增量备份"
userName="root"
uid=os.getuid()
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()
'''
if node_name != timeStamp:
logging.info("need backup")
#do actual backup
kylin_backup_manager.ConnectToSignals()
create_note = "系统升级新建备份"
inc_note="系统升级增量备份"
userName="root"
uid=os.getuid()
kylin_backup_manager.auto_backup_for_system_update_noreturn(timeStamp,create_note,inc_note,userName,uid)
WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","backup")
kylin_backup_manager.RunMainloop()
'''
PkgPin = namedtuple('PkgPin', ['pkg', 'priority'])
PkgFilePin = namedtuple('PkgFilePin', ['id', 'priority'])
@ -683,7 +750,7 @@ class UnattendedUpgradesCache(apt.Cache):
# Only adjust to lower versions to avoid flipping back and forth
# and to avoid picking a newer version, not selected by apt.
# This helps avoiding upgrades to experimental's packages.
if pkg.candidate is not None and new_cand < pkg.candidate:
if pkg.candidate is not None: #and new_cand < pkg.candidate:
logging.debug("adjusting candidate version: %s" % new_cand)
pkg.candidate = new_cand
return True
@ -1025,6 +1092,7 @@ def should_stop():
if SIGNAL_STOP_REQUEST:
logging.warning("SIGNAL received, stopping")
return True
'''
try:
if apt_pkg.config.find_b("Unattended-Upgrade::OnlyOnACPower", True) \
and subprocess.call("on_ac_power") == 1:
@ -1046,6 +1114,7 @@ def should_stop():
log_once(_("Checking if connection is metered is skipped. Please "
"install python3-gi package to detect metered "
"connections and skip downloading updates."))
'''
return False
@ -1272,7 +1341,11 @@ def upgrade_in_minimal_steps(cache, # type: UnattendedUpgradesCache
continue
if should_stop():
return False
pkg = cache[pkgname]
try:
pkg = cache[pkgname]
except KeyError:
continue
try:
if pkg.is_upgradable \
or candidate_version_changed(pkg):
@ -1446,7 +1519,10 @@ def upgrade_order(to_upgrade, cache):
# calculate upgrade sets
follow_deps = {'Depends', 'PreDepends', 'Recommends'}
for pkgname in to_upgrade:
pkg = cache[pkgname]
try:
pkg = cache[pkgname]
except KeyError:
continue
upgrade_set_sizes[pkgname] = len(transitive_dependencies(
pkg, cache, valid_types=follow_deps).intersection(to_upgrade))
return sorted(upgrade_set_sizes, key=upgrade_set_sizes.get)
@ -2262,7 +2338,11 @@ def do_auto_remove(cache, # type: UnattendedUpgradesCache
logging.debug("marking %s for removal" % pkgname)
if pkgname in pkgs_removed:
continue
cache[pkgname].mark_delete()
try:
pkg = cache[pkgname]
except KeyError:
continue
pkg.mark_delete()
if not is_autoremove_valid(cache, pkgname, auto_removable):
# this situation can occur when removing newly unused packages
# would also remove old unused packages which are not set
@ -2281,7 +2361,11 @@ def do_auto_remove(cache, # type: UnattendedUpgradesCache
cache.clear()
else:
for pkgname in auto_removable:
cache[pkgname].mark_delete()
try:
pkg = cache[pkgname]
except KeyError:
continue
pkg.mark_delete()
if is_autoremove_valid(cache, "", auto_removable):
# do it in one step
if not dry_run:
@ -2375,7 +2459,8 @@ def main(options, rootdir="/"):
if not os.path.exists(logfile_dpkg):
with open(logfile_dpkg, 'w'):
pass
global os_release_info
os_release_info = ReadOsRelease('/etc/os-release')
# lock for the shutdown check
# shutdown_lock = apt_pkg.get_lock(LOCK_FILE)
# if shutdown_lock < 0:
@ -2386,6 +2471,22 @@ def main(options, rootdir="/"):
try:
res = run(options, rootdir, mem_log, logfile_dpkg,
install_start_time)
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 and options.mode == 'shutdown':
if len(res.pkgs) > 0 :
config_to_result.set("OTA","upgrade","1")
config_to_result.set("OTA","status","success")
config_to_result.set("OTA","status","success")
with open(OTA_RESULT_FILE_PATH,"w+") as f:
config_to_result.write(f)
os.chmod(OTA_RESULT_FILE_PATH,stat.S_IRWXU|stat.S_IRWXG|stat.S_IRWXO)
WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","idle")
if res.success and res.result_str:
# complete, successful run
@ -2431,7 +2532,10 @@ def main(options, rootdir="/"):
def mark_pkgs_to_upgrade(cache, pkgs_to_upgrade):
# type (apt.Cache, List[str]) -> None
for pkg_name in pkgs_to_upgrade:
pkg = cache[pkg_name]
try:
pkg = cache[pkg_name]
except KeyError:
continue
if pkg.is_upgradable \
or (pkg.is_installed
and pkg.candidate.version != pkg.installed.version) \
@ -2444,7 +2548,10 @@ def mark_pkgs_to_upgrade(cache, pkgs_to_upgrade):
def adjust_candidate_with_version(cache,pkgnamelist,versionlist):
for pkgname in pkgnamelist:
pkg = cache[pkgname]
try:
pkg = cache[pkgname]
except KeyError:
continue
for v in pkg.versions:
if is_in_allowed_origin(v,cache.allowed_origins):
if str(v) in versionlist:
@ -2459,13 +2566,13 @@ def run(options, # type: Options
# type: (...) -> UnattendedUpgradesResult
# check if today is a patch day
if not is_update_day():
return UnattendedUpgradesResult(True)
# if not is_update_day():
# return UnattendedUpgradesResult(True)
# check if u-u should be stopped already
if should_stop():
return UnattendedUpgradesResult(False)
global os_release_info
# check to see if want to auto-upgrade the devel release
'''
if apt_pkg.config.find("Unattended-Upgrade::DevRelease") == "auto":
@ -2524,6 +2631,7 @@ def run(options, # type: Options
# check if the journal is dirty and if so, take emergceny action
# the alternative is to leave the system potentially unsecure until
# the user comes in and fixes
'''
if is_dpkg_journal_dirty() and \
apt_pkg.config.find_b("Unattended-Upgrade::AutoFixInterruptedDpkg",
False):
@ -2541,7 +2649,7 @@ def run(options, # type: Options
except subprocess.CalledProcessError as e:
output = e.output
logging.warning(_("dpkg --configure -a output:\n%s"), output)
'''
config_manager = ConfigFileManager(CONFIG_FILE_ROOT_PATH)
white_list = config_manager.ReadListFromFile(WHITE_LIST_FILE_PATH,'AutoUpgrade','upgradelist')
global wl
@ -2633,12 +2741,19 @@ def run(options, # type: Options
#only write the pkg list when dpkg journal is clean
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)
logging.error("fetch.run() result: %s", e)
if options.mode == 'shutdown':
if kylin_system_updater.GetConfigValue('InstallMode','shutdown_install'):
pass
else:
logging.info("system updater need to run shutdown install quiting...")
return UnattendedUpgradesResult(False,_("system updater install override"))
elif options.download_only:
if fetcher_statistics.remote_pkg_amount>0:
@ -2666,9 +2781,24 @@ def run(options, # type: Options
except SystemError as e:
logging.error(_("GetArchives() failed: %s"), e)
else:
logging.info("all pkgs downloaded")
configfilemanager.AddFileName("OTA_PKGS_TO_INSTALL")
return UnattendedUpgradesResult(True,_("all pkgs downloaded"))
docker_image_fetch_result = 0
#docker image fetch for mavis and laika
if os.path.exists("/usr/bin/service_runtime_ota.sh"):
docker_image_fetch_result = subprocess.run(["/usr/bin/service_runtime_ota.sh"], shell=True)
if docker_image_fetch_result == 0:
logging.info("all pkgs downloaded")
insmod = ReadValueFromFile("/var/lib/unattended-upgrades/unattended-upgrades-policy.conf","autoUpgradePolicy","installMode")
if insmod == 'bshutdown':
configfilemanager.AddFileName("OTA_PKGS_TO_INSTALL")
subprocess.Popen('dbus-send --system --type=signal / com.kylin.update.notification.DownloadFinish', shell=True)
kylin_system_updater.SetConfigValue('InstallMode','auto_install','True')
elif insmod == 'timing':
pass
else:
pass
return UnattendedUpgradesResult(True,_("all pkgs downloaded"))
else:
return UnattendedUpgradesResult(False,_("docker fetch failed"))
return UnattendedUpgradesResult(False,_("some pkgs incompletely fetched"))
else:
logging.debug(_("option is not install-only or download-only"))
@ -2842,41 +2972,13 @@ def run(options, # type: Options
# only perform install step if we actually have packages to install
pkg_install_success = True
if len(pkgs_to_upgrade) > 0:
# do backup
kylin_backup_manager = KylinBackupManager()
backup_partition_status = kylin_backup_manager.mount_backup_partition()
if backup_partition_status not in [0,5]:
logging.error("backup partition error:%d"%backup_partition_status)
return UnattendedUpgradesResult(False,"backup partition error")
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")
#node_name,node_status = kylin_backup_manager.get_backup_comment_for_systemupdate()
ts = get_timestamp()
kylin_backup_manager.ConnectToSignals()
create_note = "系统升级新建备份"
inc_note="系统升级增量备份"
userName="root"
uid=os.getuid()
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()
'''
if node_name != timeStamp:
logging.info("need backup")
#do actual backup
kylin_backup_manager.ConnectToSignals()
create_note = "系统升级新建备份"
inc_note="系统升级增量备份"
userName="root"
uid=os.getuid()
kylin_backup_manager.auto_backup_for_system_update_noreturn(timeStamp,create_note,inc_note,userName,uid)
WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","backup")
kylin_backup_manager.RunMainloop()
'''
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:
Backup()
# do install
WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","install")
#send install start msg to notify
@ -2978,6 +3080,7 @@ class Options:
self.apt_debug = False
self.verbose = False
self.minimal_upgrade_steps = False
self.mode = None
shutdown_lock = -1
@ -2985,7 +3088,7 @@ if __name__ == "__main__":
WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","idle")
# lock for the shutdown check
shutdown_lock = apt_pkg.get_lock(LOCK_FILE)
if shutdown_lock < 0:
if shutdown_lock < 0:
logging.error("Lock file is already taken, exiting")
#WriteValueToFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status","idle")
sys.exit(0)
@ -3042,6 +3145,7 @@ if __name__ == "__main__":
action="store_true",
help=SUPPRESS_HELP,
default=minimal_steps_default)
parser.add_option(""''"","--mode",action = "store",type = "string" ,dest = "mode",help="start mode.")
options = cast(Options, (parser.parse_args())[0])
if os.getuid() != 0:
@ -3067,7 +3171,6 @@ if __name__ == "__main__":
atexit.register(os.remove, pidf)
system_updater = KylinSystemUpdater()
allow_autoupdate = system_updater.GetDatabaseInfo("display","autoupdate_allow")
if allow_autoupdate == "true":
pass
else:

315
unattended-upgrades/kylin-unattended-upgrade-shutdown Executable file → Normal file
View File

@ -30,6 +30,7 @@ import dbus
import signal
import sys
import time
import datetime
import logging
import logging.handlers
import gettext
@ -48,6 +49,10 @@ from optparse import OptionParser, Values
Values # pyflakes
from gettext import gettext as _
from threading import Event
from enum import IntEnum, Enum
from apscheduler.schedulers.blocking import BlockingScheduler
import random
import threading
try:
import apt_pkg
@ -56,11 +61,68 @@ except Exception:
# need to stop the shutdown
logging.exception("importing of apt_pkg failed, exiting")
sys.exit(0)
## analytic unattended-upgrades-policy.conf start
POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY = "autoUpgradePolicy"
AUTO_UPGRADE_POLICY_OPTION_PREDOWNLOAD = "preDownload"
AUTO_UPGRADE_POLICY_OPTION_AUTOUPGRADE = "autoUpgradeState"
AUTO_UPGRADE_POLICY_OPTION_DOWNLOAD_MODE = "downloadMode"
AUTO_UPGRADE_POLICY_OPTION_DOWNLOAD_TIME = "downloadTime"
AUTO_UPGRADE_POLICY_OPTION_INSTALL_MODE = "installMode"
INTERVAL_DOWN_INSTALL = 120 # 下载安装的间隔 分钟
INSTALL_RANDOM = 5 # 安装时间随机数范围0-INSTALL_RANDOM 分钟
DOWNLOAD_RANDOM = 3 # 下载时间随机数范围0-DOWNLOAD_RANDOM 分钟
class FeatureSwitch(Enum):
ON = 'on'
OFF = 'off'
class DownloadMode(Enum): # 下载模式
TIMING_DOWNLOAD = 'timing' # 定时下载
MANUAL_DOWNLOAD = 'manual' # 手动下载
class InstallMode(Enum): # 安装模式
TIMING_INSTALL = 'timing' # 定时安装
MANUAL_INSTALL = 'manual' # 手动安装
BEFORE_SHUTDOWN_INSTALL = 'bshutdown' # 关机前安装
class TimeElement(IntEnum):
TIME_HOUR = 0
TIME_MINUTE = 1
TIME_NUM = 2
## analytic unattended-upgrades-policy.conf end
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"
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)
def ReadOsRelease(file):
osreleasedict = {}
try:
with open(file) as f:
lines = f.readlines()
for line in lines:
ls = line.strip().split('=',1)
osreleasedict.update({ls[0]:ls[1]})
except Exception as e:
pass
return osreleasedict
def ReadValueFromFile(file,section,option):
config=configparser.ConfigParser(allow_no_value=True)
try:
config.read(file)
value = config[section][option]
except Exception as e:
return None
return value
def WriteValueToFile(file,section,option,value):
config=configparser.ConfigParser(allow_no_value=True)
@ -76,14 +138,14 @@ def clean_flag_files(filelist):
def init():
if not os.path.exists(NOTIFICATION_PIPE):
os.mkfifo(NOTIFICATION_PIPE)
'''
def do_usplash(msg):
# type: (str) -> None
if os.path.exists("/sbin/usplash_write"):
logging.debug("Running usplash_write")
subprocess.call(["/sbin/usplash_write", "TEXT", msg])
subprocess.call(["/sbin/usplash_write", "PULSATE"])
'''
def do_plymouth(msg):
# type: (str) -> None
@ -92,13 +154,21 @@ def do_plymouth(msg):
logging.debug("Running plymouth --text")
subprocess.call(["/bin/plymouth", "message", "--text", line])
def do_plymouth_splash():
if os.path.exists("/bin/plymouth"):
logging.debug("Running plymouth --splash")
subprocess.run(["/sbin/plymouthd", "--mode=shutdown","--attach-to-session"])
#subprocess.run(["/sbin/plymouthd", "--mode=update","--attach-to-session"])
#subprocess.run(["/bin/plymouth","--update=kylin update"])
subprocess.Popen(["/bin/plymouth", "show-splash","--wait"])
subprocess.call(["/bin/plymouth","system-update","--progress=0"])
def log_msg(msg, level=logging.WARN):
# type: (str, int) -> None
""" helper that will print msg to usplash, plymouth, console """
logging.log(level, msg)
do_plymouth(msg)
do_usplash(msg)
#do_usplash(msg)
def log_progress():
@ -131,14 +201,79 @@ def signal_stop_unattended_upgrade():
def exit_log_result(success):
if success:
log_msg(_("All upgrades installed"), logging.INFO)
os._exit(0)
sys.exit(0)
else:
log_msg(_("Unattended-upgrades stopped. There may be upgrades"
" left to be installed in the next run."), logging.INFO)
os._exit(1)
sys.exit(1)
# 检查时间安全性 -- minute > 59; hour > 23;
def check_time_safety(inTime):
if inTime['m'] > 59 :
inTime['h'] = inTime['h'] + inTime['m']//60
inTime['m'] = inTime['m']%60
if inTime['h'] > 23 :
inTime['h'] = inTime['h'] - 24
outTime = inTime
return outTime
# 时间添加随机数
def convert_time_by_random(inTime, inRandom):
diff = random.randint(0,inRandom)
inTime['h']=inTime['h'] + diff // 60
inTime['m']=inTime['m'] + diff % 60
outTime = check_time_safety(inTime)
return outTime
class TimerThread(threading.Thread):
def __init__(self, scheduler):
threading.Thread.__init__(self)
self.scheduler = scheduler
def run(self):
self.scheduler.start()
class UnattendedUpgradesShutdown():
# 加载配置文件 unattended-upgrades-policy.conf
def loadcfg(self):
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)
timelist = download_time.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])
except ValueError:
logging.debug("unattended-upgrades-policy.conf download_time h error")
return
try:
tmpminute = int(timelist[TimeElement.TIME_MINUTE])
except ValueError:
logging.debug("unattended-upgrades-policy.conf download_time m error")
return
self.download_time['h'] = tmphour
self.download_time['m'] = tmpminute
self.download_time_r = convert_time_by_random(self.download_time, DOWNLOAD_RANDOM)
self.install_time['h'] = self.download_time_r['h']
self.install_time['m'] = self.download_time_r['m'] + INTERVAL_DOWN_INSTALL
self.install_time_r = convert_time_by_random(self.install_time, INSTALL_RANDOM)
logging.debug("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 __init__(self, options):
# type: (Values) -> None
@ -153,6 +288,18 @@ class UnattendedUpgradesShutdown():
self.lock_was_taken = False
self.signal_sent = False
self.stop_signal_received = Event()
self.download_mode = DownloadMode.TIMING_DOWNLOAD.value #下载模式
self.install_mode = InstallMode.TIMING_INSTALL.value #安装模式
self.download_time = {'h':9, 'm':0} #定时下载时间 09:00
self.install_time = {'h':12, 'm':0} #定时安装时间 12:00
self.download_time_r = convert_time_by_random(self.download_time, DOWNLOAD_RANDOM) #随机化定时下载时间
self.install_time_r = convert_time_by_random(self.install_time, INSTALL_RANDOM) #随机化定时安装时间
self.preDownload = False #预下载开关
self.autoUpgrade = True #自动更新开关
self.download_job = None
self.install_job = None
self.scheduler = BlockingScheduler()
try:
hasattr(GLib, "MainLoop")
DBusGMainLoop(set_as_default=True)
@ -164,8 +311,20 @@ class UnattendedUpgradesShutdown():
logging.warning("Could not get delay inhibitor lock")
self.inhibit_lock = None
self.logind_proxy = None
self.update_proxy = None
self.wait_period = min(3, self.get_inhibit_max_delay() / 3)
self.preparing_for_shutdown = False
self.loadcfg()
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
def get_update_interface(self):
self.update_interface = dbus.Interface(self.update_proxy,dbus_interface='com.kylin.systemupgrade.interface')
return self.update_interface
def get_logind_proxy(self):
""" Get logind dbus proxy object """
@ -247,12 +406,55 @@ class UnattendedUpgradesShutdown():
# TODO iter on sigterm and sighup, too
time.sleep(self.wait_period)
# 定时下载 执行函数
def timing_download(self):
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(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)
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 _wait_for_unattended_upgrade_finish(self):
#read unattended-upgrade status
status = ReadValueFromFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status")
while (status != "idle"):
ReadValueFromFile(UNATTENDED_UPGRADE_CONFIG_FILE_PATH,"UNATTENDED_UPGRADE","autoupdate_run_status")
time.sleep(1)
return 0
def _pause_timer(self):
if self.download_job is not None:
self.download_job.pause()
if self.install_job is not None:
self.install_job.pause()
def _resume_timer(self):
if self.download_job is not None:
self.download_job.resume()
if self.install_job is not None:
self.install_job.resume()
def run(self):
""" delay shutdown and wait for PrepareForShutdown or other signals"""
# set signal handlers
def signal_handler(signum, frame):
# type: (object) -> None
logging.warning(
"SIGTERM or SIGHUP received, stopping unattended-upgrades "
"only if it is running")
@ -270,13 +472,97 @@ class UnattendedUpgradesShutdown():
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):
download_mode = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, AUTO_UPGRADE_POLICY_OPTION_DOWNLOAD_MODE)
install_mode = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, AUTO_UPGRADE_POLICY_OPTION_INSTALL_MODE)
preDownload = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, AUTO_UPGRADE_POLICY_OPTION_PREDOWNLOAD)
autoUpgrade = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, AUTO_UPGRADE_POLICY_OPTION_AUTOUPGRADE)
if autoUpgrade == FeatureSwitch.ON.value or preDownload == FeatureSwitch.ON.value: #open download timing
download_time_tmp = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH, POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY, AUTO_UPGRADE_POLICY_OPTION_DOWNLOAD_TIME)
timelist = download_time_tmp.split(':')
if len(timelist) != TimeElement.TIME_NUM:
logging.debug("unattended-upgrades-policy.conf time err %s",download_time_tmp)
return
# 检查 传入时间 安全性
try:
tmphour = int(timelist[TimeElement.TIME_HOUR])
except ValueError:
logging.debug("unattended-upgrades-policy.conf download_time h error")
else:
self.download_time['h'] = tmphour
try:
tmpminute = int(timelist[TimeElement.TIME_MINUTE])
except ValueError:
logging.debug("unattended-upgrades-policy.conf download_time m error")
else:
self.download_time['m'] = tmpminute
self.download_time_r = convert_time_by_random(self.download_time, DOWNLOAD_RANDOM)
if self.download_job is not None:
self.download_job.remove()
self.download_job = self.scheduler.add_job(self.timing_download, 'cron', hour=self.download_time_r['h'], minute=self.download_time_r['m'])
else: #close download timing
self.download_job.pause()
if autoUpgrade == FeatureSwitch.ON.value and install_mode == InstallMode.TIMING_INSTALL.value: #open install timing
self.install_time['h'] = self.download_time_r['h']
self.install_time['m'] = self.download_time_r['m'] + INTERVAL_DOWN_INSTALL
self.install_time_r = convert_time_by_random(self.install_time, INSTALL_RANDOM)
if self.install_job is not None:
self.install_job.remove()
self.install_job = self.scheduler.add_job(self.timing_install, 'cron', hour=self.install_time_r['h'], minute=self.install_time_r['m'])
else: #close install timing
self.install_job.pause()
if self.install_mode == InstallMode.BEFORE_SHUTDOWN_INSTALL.value:
if self.install_job is not None:
self.install_job.remove()
logging.debug("install job removed,installation will conduct before shutdown")
logging.debug("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():
self._wait_for_unattended_upgrade_finish()
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()
if retdownload == 0 and retinstall == 0:
return True
def prepare_for_shutdown_handler(active):
""" Handle PrepareForShutdown() """
if not active:
logging.warning("PrepareForShutdown(false) received, "
"this should not happen")
# PrepareForShutdown arrived, starting final iterations
self.start_iterations()
self.install_mode = ReadValueFromFile(UNATTENDED_UPGRADE_POLICY_FILE_PATH,POLICY_CONF_SECTION_AUTO_UPGRADE_POLICY,AUTO_UPGRADE_POLICY_OPTION_INSTALL_MODE)
if self.install_mode == InstallMode.BEFORE_SHUTDOWN_INSTALL.value:
if self.update_interface.GetConfigValue('InstallMode','shutdown_install'):
#show plymouth splash if bsshutdown is set
if os.path.exists('/var/lib/unattended-upgrades/OTA_PKGS_TO_INSTALL'):
do_plymouth_splash()
self.start_iterations()
else:
os._exit(0)
else:
os._exit(0)
else:
os._exit(0)
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)
try:
self.get_logind_proxy().connect_to_signal(
"PrepareForShutdown", prepare_for_shutdown_handler)
@ -295,6 +581,12 @@ class UnattendedUpgradesShutdown():
logging.debug("Skip waiting for signals, starting operation "
"now")
self.start_iterations()
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'])
TimerThread(self.scheduler).start()
GLib.MainLoop().run()
def try_iter_on_shutdown(self):
@ -318,14 +610,15 @@ class UnattendedUpgradesShutdown():
not self.options.stop_only
and not self.stop_signal_received.is_set()
and self.apt_pkg_reinit_done
and apt_pkg.config.find_b(
"Unattended-Upgrade::InstallOnShutdown", False))
# and apt_pkg.config.find_b(
# "Unattended-Upgrade::InstallOnShutdown", False)
)
if self.on_shutdown_mode:
env = copy.copy(os.environ)
env["UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN"] = "1"
#env["UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN"] = "1"
logging.debug("starting unattended-upgrades in shutdown mode")
self.on_shutdown_mode_uu_proc = subprocess.Popen(
["kylin-unattended-upgrade","--install-only"], env=env)
["kylin-unattended-upgrade","--install-only","--mode=shutdown"], env=env)
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
@ -349,7 +642,8 @@ class UnattendedUpgradesShutdown():
logging.warning(_(
"Giving up on lockfile after %s minutes of delay"),
self.max_delay / 60)
sys.exit(1)
os._exit(1)
#sys.exit(1)
if not self.stop_signal_received.is_set():
if self.try_iter_on_shutdown():
@ -361,6 +655,7 @@ class UnattendedUpgradesShutdown():
# exit here if there is no lock
if res > 0:
logging.debug("lock not taken")
os._exit(0)
if self.lock_was_taken:
exit_log_result(self.signal_sent)
else:

View File

@ -1,145 +0,0 @@
#!/bin/sh
check_stamp()
{
stamp="$1"
interval="$2"
if [ "$interval" = always ]; then
debug_echo "check_stamp: ignoring time stamp file, interval set to always"
# treat as enough time has passed
return 0
fi
if [ "$interval" = 0 ]; then
debug_echo "check_stamp: interval=0"
# treat as no time has passed
return 1
fi
if [ ! -f "$stamp" ]; then
debug_echo "check_stamp: missing time stamp file: $stamp."
# treat as enough time has passed
return 0
fi
# compare midnight today to midnight the day the stamp was updated
stamp_file="$stamp"
stamp=$(date --date="$(date -r "$stamp_file" --iso-8601)" +%s 2>/dev/null)
if [ "$?" != "0" ]; then
# Due to some timezones returning 'invalid date' for midnight on
# certain dates (e.g. America/Sao_Paulo), if date returns with error
# remove the stamp file and return 0. See coreutils bug:
# http://lists.gnu.org/archive/html/bug-coreutils/2007-09/msg00176.html
rm -f "$stamp_file"
return 0
fi
now=$(date --date="$(date --iso-8601)" +%s 2>/dev/null)
if [ "$?" != "0" ]; then
# As above, due to some timezones returning 'invalid date' for midnight
# on certain dates (e.g. America/Sao_Paulo), if date returns with error
# return 0.
return 0
fi
delta=$((now-stamp))
# Calculate the interval in seconds depending on the unit specified
if [ "${interval%s}" != "$interval" ] ; then
interval="${interval%s}"
elif [ "${interval%m}" != "$interval" ] ; then
interval="${interval%m}"
interval=$((interval*60))
elif [ "${interval%h}" != "$interval" ] ; then
interval="${interval%h}"
interval=$((interval*60*60))
else
interval="${interval%d}"
interval=$((interval*60*60*24))
fi
debug_echo "check_stamp: interval=$interval, now=$now, stamp=$stamp, delta=$delta (sec)"
# remove timestamps a day (or more) in the future and force re-check
if [ "$stamp" -gt $((now+86400)) ]; then
echo "WARNING: file $stamp_file has a timestamp in the future: $stamp"
rm -f "$stamp_file"
return 0
fi
if [ $delta -ge $interval ]; then
return 0
fi
return 1
}
update_stamp()
{
stamp="$1"
touch "$stamp"
}
debug_echo()
{
# Display message if $VERBOSE >= 1
if [ "$VERBOSE" -ge 1 ]; then
echo "$1" 1>&2
fi
}
# ------------------------ main ----------------------------
VERBOSE=5
debug_echo "verbose level $VERBOSE"
# Global current time in seconds since 1970-01-01 00:00:00 UTC
now=$(date +%s)
KylinAutodownloadInterval=7
KylinAutoInstallInterval=7
# check if we actually have to do anything that requires locking the cache
if [ $KylinAutodownloadInterval = always ] ||
[ $KylinAutoInstallInterval = always ] ; then
:
elif [ $KylinAutodownloadInterval = 0 ] &&
[ $KylinAutoInstallInterval = 0 ] ; then
exit 0
fi
if [ "$1" = "download" ] || [ -z "$1" ] ; then
# download all upgradeable packages (if it is requested)
DOWNLOAD_STAMP=/var/lib/apt/periodic/kylin-auto-download-stamp
if which kylin-unattended-upgrade >/dev/null 2>&1 && check_stamp $DOWNLOAD_STAMP $KylinAutodownloadInterval; then
if kylin-unattended-upgrade --download-only; then
update_stamp $DOWNLOAD_STAMP
debug_echo "kylin-autoupdate-download (success)"
else
debug_echo "kylin-autoupdate-download (error)"
fi
else
debug_echo "kylin-autoupdate-download (not run)"
fi
fi
if [ "$1" = "install" ] || [ -z "$1" ] ; then
# auto upgrade all upgradeable packages
INSTALL_STAMP=/var/lib/apt/periodic/kylin-auto-install-stamp
if which kylin-unattended-upgrade >/dev/null 2>&1 && check_stamp $INSTALL_STAMP $KylinAutoInstallInterval; then
if kylin-unattended-upgrade --install-only; then
update_stamp $INSTALL_STAMP
debug_echo "kylin-autoupdate-install (success)"
else
debug_echo "kylin-autoupdate-install (error)"
fi
else
debug_echo "kylin-autoupdate-install (not run)"
fi
fi
#
#

View File

@ -1,10 +0,0 @@
[Unit]
Description=Daily auto-download activities
ConditionACPower=true
After=network.target network-online.target systemd-networkd.service NetworkManager.service connman.service
[Service]
Type=oneshot
ExecStartPre=-/usr/lib/apt/apt-helper wait-online
ExecStart=/usr/bin/unattended-upgrades-daily download

View File

@ -1,11 +0,0 @@
[Unit]
Description=Daily auto-download activities
[Timer]
OnCalendar=*-*-* 10:00
RandomizedDelaySec=1h
Persistent=true
[Install]
WantedBy=timers.target

View File

@ -1,9 +0,0 @@
[Unit]
Description=Daily auto-upgrade activities
ConditionACPower=true
#After=network.target network-online.target systemd-networkd.service NetworkManager.service connman.service
[Service]
Type=oneshot
ExecStart=/usr/bin/unattended-upgrades-daily install

View File

@ -1,12 +0,0 @@
[Unit]
Description=Daily auto-upgrade activities
After=unattended-upgrades-download.timer
[Timer]
OnCalendar=*-*-* 14:00
RandomizedDelaySec=5m
Persistent=true
[Install]
WantedBy=timers.target