diff --git a/src/Makefile.dir b/src/Makefile.dir index fecabb32c0f1f80c0f0724e1cd1426f2de8b8f0b..3317f9e904262d5f2187357bbad240c5d6592577 100644 --- a/src/Makefile.dir +++ b/src/Makefile.dir @@ -1,2 +1,2 @@ -SRC_SUBDIRS := lib opkg-trans pkgupdate +SRC_SUBDIRS := lib pkgtransaction pkgupdate include $(patsubst %,$(S)/src/%/Makefile.dir,$(SRC_SUBDIRS)) diff --git a/src/localrepo/content2localrepo b/src/localrepo/content2localrepo deleted file mode 100755 index 9edafd9772cedbb6e8cc7752f8a03f9669640666..0000000000000000000000000000000000000000 --- a/src/localrepo/content2localrepo +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh -# Simple script for migration from Content to localrepo -set -ex - -# Because we no way depend on updater-ng it self we can be easily installed before -# or after it. So if we are migrating in version 60 auto.lua to opkg-auto.lua we -# can encounter both cases. So here check which one we have with preference on new -# place. -if [ -f "/etc/updater/conf.d/opkg-auto.lua" ]; then - UPDATER_CONFIG="/etc/updater/conf.d/opkg-auto.lua" -elif [ -f "/etc/updater/auto.lua" ]; then - UPDATER_CONFIG="/etc/updater/auto.lua" -else - # No automatic configuration file. This is ok if this is clean new install - exit 0 -fi - -# Add all content packages to localrepo -sed -n 's/^Package.*content *= *"file:\/\/\([^"]*\)".*/\1/p' "$UPDATER_CONFIG" | \ - while read PKG; do - localrepo add --repo auto "$PKG" - done -# Clean localrepo from unused packages -localrepo clean --repo auto - -# Drop all lines added because of package content -sed -i '/^Package.*content/d' "$UPDATER_CONFIG" - -# And remove local store -rm -rf /usr/share/updater/local-pkgs diff --git a/src/opkg-trans/Makefile.dir b/src/opkg-trans/Makefile.dir deleted file mode 100644 index 21f6a68ec9c1407aa1b260bb4906cf35b61f7373..0000000000000000000000000000000000000000 --- a/src/opkg-trans/Makefile.dir +++ /dev/null @@ -1,4 +0,0 @@ -BINARIES += src/opkg-trans/opkg-trans - -opkg-trans_MODULES := main -opkg-trans_LOCAL_LIBS := updater diff --git a/src/opkg-trans/Makefile b/src/pkgtransaction/Makefile similarity index 61% rename from src/opkg-trans/Makefile rename to src/pkgtransaction/Makefile index f5cc925b46558e98ae5952ff78e284b8b7bdd1db..136bccd054379a2cf893cb864d5d8ebe6d18bc22 100644 --- a/src/opkg-trans/Makefile +++ b/src/pkgtransaction/Makefile @@ -1,4 +1,4 @@ -RESTRICT := src/opkg-trans +RESTRICT := src/pkgtransaction RELATIVE := ../../ include $(RELATIVE)/Makefile diff --git a/src/pkgtransaction/Makefile.dir b/src/pkgtransaction/Makefile.dir new file mode 100644 index 0000000000000000000000000000000000000000..e64c4f71bde65e41be002ac351135dc65df9e2ec --- /dev/null +++ b/src/pkgtransaction/Makefile.dir @@ -0,0 +1,4 @@ +BINARIES += src/pkgtransaction/pkgtransaction + +pkgtransaction_MODULES := main +pkgtransaction_LOCAL_LIBS := updater diff --git a/src/opkg-trans/main.c b/src/pkgtransaction/main.c similarity index 93% rename from src/opkg-trans/main.c rename to src/pkgtransaction/main.c index 4849e521e145f86779b42677a87af0efd80f28f6..5ed6fc911f6bd03acca39dfb66b294e68c829021 100644 --- a/src/opkg-trans/main.c +++ b/src/pkgtransaction/main.c @@ -1,5 +1,5 @@ /* - * Copyright 2016, CZ.NIC z.s.p.o. (http://www.nic.cz/) + * Copyright 2016-2018, CZ.NIC z.s.p.o. (http://www.nic.cz/) * * This file is part of the turris updater. * @@ -43,12 +43,14 @@ static const enum cmd_op_type cmd_op_allows[] = { COT_JOURNAL_ABORT, COT_JOURNAL_RESUME, COT_INSTALL, COT_REMOVE, COT_ROOT_DIR, COT_SYSLOG_LEVEL, COT_STDERR_LEVEL, COT_SYSLOG_NAME, COT_REEXEC, COT_USIGN, COT_LAST }; static void print_help() { - fputs("Usage: opkg-trans [OPTION]...\n", stderr); + fputs("Usage: pkgtransaction [OPTION]...\n", stderr); + fputs("Tool to create and apply updater-ng transactions on to the system.\n", stderr); + fputs("Note that this tool does only minimal verification and because of that it allows you to trash your system.\n", stderr); cmd_args_help(cmd_op_allows); } static void print_version() { - fputs("opkg-trans ", stderr); + fputs("pkgtransaction ", stderr); cmd_args_version(); } diff --git a/src/pkgupdate/init b/src/pkgupdate/init deleted file mode 100755 index b1d76fb457751c855bd2b4d80d3953dc9802d94c..0000000000000000000000000000000000000000 --- a/src/pkgupdate/init +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=85 - -status() { - return 0 -} - -start() { - # Recover updater's journal if it exists - if [ -e "/usr/share/updater/journal" ]; then - # If journal recovery is successful then updater should be run again - # because it might not be finished because of replan package option. - opkg-trans -s dbg -j && updater.sh - fi -} - -stop() { - : -} - -restart() { - : -} - -reload() { - : -} diff --git a/src/supervisor/immediate_reboot.init b/src/supervisor/immediate_reboot.init new file mode 100755 index 0000000000000000000000000000000000000000..099c4f1e4e008ec79ff5a4c861018a7bee3a1495 --- /dev/null +++ b/src/supervisor/immediate_reboot.init @@ -0,0 +1,34 @@ +#!/bin/sh /etc/rc.common + +# This script handles updater-ng immediate reboot recovery. After an immediate +# reboot there is going to be a journal and we should continue execution from it +# as soon as possible. + +START=85 + +status() { + return 0 +} + +start() { + # Recover updater's journal if it exists + if [ -e "/usr/share/updater/journal" ]; then + # Note: supervisor runs pkgupdate that recovers run from journal and later + # checks for update. This update is required because there could have been + # replan planned after reboot and this ensures that we do replan as soon + # as possible. + updater-supervisor + fi +} + +stop() { + : +} + +restart() { + : +} + +reload() { + : +} diff --git a/src/supervisor/svupdater/__init__.py b/src/supervisor/svupdater/__init__.py index b050dfd996290b0f92a53c6b63197d327ac5acfd..53e2508c8ddc733bae91ba565a5a03130a758527 100644 --- a/src/supervisor/svupdater/__init__.py +++ b/src/supervisor/svupdater/__init__.py @@ -22,12 +22,10 @@ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from .const import OPKG_LOCK, PING_TIMEOUT, PKGUPDATE_TIMEOUT -from .const import PKGUPDATE_TIMEOUT_KILL +from . import autorun, const from .utils import check_exclusive_lock as _check_exclusive_lock from .utils import daemonize as _daemonize from ._pidlock import pid_locked as _pid_locked -from .config import Config from .exceptions import ExceptionUpdaterDisabled from ._supervisor import run as _run from .prerun import wait_for_network as _wait_for_network @@ -37,7 +35,7 @@ def opkg_lock(): """Returns True if opkg lock is taken. It can be taken by any other process. It doesn't have to be updater. """ - return _check_exclusive_lock(OPKG_LOCK, False) + return _check_exclusive_lock(const.OPKG_LOCK, False) def updater_supervised(): @@ -48,8 +46,8 @@ def updater_supervised(): return _pid_locked() -def run(wait_for_network=False, ensure_run=False, timeout=PKGUPDATE_TIMEOUT, - timeout_kill=PKGUPDATE_TIMEOUT_KILL, hooklist=None): +def run(wait_for_network=False, ensure_run=False, timeout=const.PKGUPDATE_TIMEOUT, + timeout_kill=const.PKGUPDATE_TIMEOUT_KILL, hooklist=None): """Run updater. This call will spawn daemon process and returns. But be aware that at first it checks if some other supervisor is not running and it takes file lock @@ -60,17 +58,16 @@ def run(wait_for_network=False, ensure_run=False, timeout=PKGUPDATE_TIMEOUT, exits. You can pass hooks (single line shell scripts) to be run after updater. """ - with Config() as cnf: - if cnf.disable(): - raise ExceptionUpdaterDisabled( - "Can't run. Updater is configured to be disabled.") + if not autorun.enabled(): + raise ExceptionUpdaterDisabled( + "Can't run. Updater is configured to be disabled.") # Fork to daemon if _daemonize(): return # Wait for network if configured if wait_for_network: if type(wait_for_network == bool): - wait_for_network = PING_TIMEOUT + wait_for_network = const.PING_TIMEOUT _wait_for_network(wait_for_network) # And run updater _run( diff --git a/src/supervisor/svupdater/approvals.py b/src/supervisor/svupdater/approvals.py index 2cc8925cce19f4c389feef50c59b48e2932e029f..6821b3dd40f68e31dfb44890447d56c255377f02 100644 --- a/src/supervisor/svupdater/approvals.py +++ b/src/supervisor/svupdater/approvals.py @@ -24,11 +24,14 @@ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os import time -from .config import Config -from .const import APPROVALS_ASK_FILE, APPROVALS_STAT_FILE +from uci import Uci, UciExceptionNotFound +from . import const, autorun, notify from .utils import report from .exceptions import ExceptionUpdaterApproveInvalid -from . import notify + +# TODO do we want to have list of packages that are auto approved? +# This would be beneficial for packages such as base-files that are updated +# very often but do not change at all. def current(): @@ -63,22 +66,21 @@ def current(): update. Note that this is forced immediate reboot. """ # Both files have to exists otherwise it is invalid approval request - with Config() as cnf: - if not os.path.isfile(APPROVALS_ASK_FILE) or \ - not os.path.isfile(APPROVALS_STAT_FILE) or \ - not cnf.approvals_need(): - return None + if not os.path.isfile(const.APPROVALS_ASK_FILE) or \ + not os.path.isfile(const.APPROVALS_STAT_FILE) or \ + not autorun.approvals(): + return None result = dict() result['reboot'] = False - with open(APPROVALS_STAT_FILE, 'r') as file: + with open(const.APPROVALS_STAT_FILE, 'r') as file: cols = file.readline().split(' ') result['hash'] = cols[0].strip() result['status'] = cols[1].strip() result['time'] = int(cols[2].strip()) - with open(APPROVALS_ASK_FILE, 'r') as file: + with open(const.APPROVALS_ASK_FILE, 'r') as file: # First line contains hash. We have has from stat file so just compare if file.readline().strip() != result['hash']: return None # Invalid request @@ -104,16 +106,15 @@ def current(): def _set_stat(status, hsh, allowed): "Set given status to APPROVALS_STAT_FILE if hsh matches current hash" # Both files have to exists otherwise it is invalid approval request - with Config() as cnf: - if not os.path.isfile(APPROVALS_ASK_FILE) or \ - not os.path.isfile(APPROVALS_STAT_FILE) or \ - not cnf.approvals_need(): - return + if not os.path.isfile(const.APPROVALS_ASK_FILE) or \ + not os.path.isfile(const.APPROVALS_STAT_FILE) or \ + not autorun.approvals(): + return # TODO locks (we should lock stat file before doing this) # Read current stat cols = list() - with open(APPROVALS_STAT_FILE, 'r') as file: + with open(const.APPROVALS_STAT_FILE, 'r') as file: cols.extend(file.readline().split(' ')) if hsh is not None and cols[0].strip() != hsh: @@ -125,7 +126,7 @@ def _set_stat(status, hsh, allowed): # Write new stat cols[1] = status - with open(APPROVALS_STAT_FILE, 'w') as file: + with open(const.APPROVALS_STAT_FILE, 'w') as file: file.write(' '.join(cols)) @@ -150,27 +151,24 @@ def _approved(): """This returns hash of approved plan. If there is no approved plan then it returns None. """ - with Config() as cnf: - if not os.path.isfile(APPROVALS_ASK_FILE) or \ - not os.path.isfile(APPROVALS_STAT_FILE) or \ - not cnf.approvals_need(): - return None - - with open(APPROVALS_STAT_FILE, 'r') as file: - cols = file.readline().split(' ') - auto_grant = cnf.approvals_auto_grant_seconds() - if cols[1].strip() == 'granted' or \ - (auto_grant is not None and - int(cols[2]) < (time.time() - auto_grant)): - return cols[0] - return None + if not os.path.isfile(const.APPROVALS_ASK_FILE) or \ + not os.path.isfile(const.APPROVALS_STAT_FILE) or \ + not autorun.approvals(): + return None + + with open(const.APPROVALS_STAT_FILE, 'r') as file: + cols = file.readline().split(' ') + auto_grant_time = autorun.auto_approve_time() + if cols[1].strip() == 'granted' or (auto_grant_time is not None and int(cols[2]) < (time.time() - (auto_grant_time * 3600))): + return cols[0] + return None def _gen_new_stat(new_hash): "Generate new stat file and send notification." report('Generating new approval request') # Write to stat file - with open(APPROVALS_STAT_FILE, 'w') as file: + with open(const.APPROVALS_STAT_FILE, 'w') as file: file.write(' '.join((new_hash, 'asked', str(int(time.time()))))) # Send notification notify.approval() @@ -183,25 +181,23 @@ def _update_stat(): When new plan is presented then it also sends notification to user about it. """ - with Config() as cnf: - if not os.path.isfile(APPROVALS_ASK_FILE) or \ - not cnf.approvals_need(): - # Drop any existing stat file - if os.path.isfile(APPROVALS_STAT_FILE): - os.remove(APPROVALS_STAT_FILE) - return + if not os.path.isfile(const.APPROVALS_ASK_FILE) or not autorun.approvals(): + # Drop any existing stat file + if os.path.isfile(const.APPROVALS_STAT_FILE): + os.remove(const.APPROVALS_STAT_FILE) + return new_hash = '' - with open(APPROVALS_ASK_FILE, 'r') as file: + with open(const.APPROVALS_ASK_FILE, 'r') as file: new_hash = file.readline().strip() - if not os.path.isfile(APPROVALS_STAT_FILE): + if not os.path.isfile(const.APPROVALS_STAT_FILE): # No previous stat file so just generate it _gen_new_stat(new_hash) return # For existing stat file compare hashes and if they differ then generate - with open(APPROVALS_STAT_FILE, 'r') as file: + with open(const.APPROVALS_STAT_FILE, 'r') as file: cols = file.readline().split(' ') if cols[0].strip() != new_hash: _gen_new_stat(new_hash) diff --git a/src/supervisor/svupdater/autorun.py b/src/supervisor/svupdater/autorun.py new file mode 100644 index 0000000000000000000000000000000000000000..847b9881921fd86af2e3831c6df92eaee7abebb1 --- /dev/null +++ b/src/supervisor/svupdater/autorun.py @@ -0,0 +1,94 @@ +# Copyright (c) 2018, CZ.NIC, z.s.p.o. (http://www.nic.cz/) +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the CZ.NIC nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL CZ.NIC BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +from uci import Uci, UciExceptionNotFound + +def enabled(): + """Returns True if updater can be automatically started by various system + utils. This includes automatic periodic execution, after-boot recovery and + other tools call to configuration aplication. + Relevant uci configuration is: updater.autorun.enable + """ + with Uci() as uci: + try: + # TODO use EUci instead of this retype (as this is not perfect) + return bool(int(uci.get("updater", "autorun", "enabled"))) + except UciExceptionNotFound: + return False # No option means disabled + + +def set_enabled(enabled): + """Set value that can be later received with enabled function. + It sets uci configuration value: updater.autorun.enable + """ + with Uci() as uci: + uci.set('updater', 'autorun', 'autorun') + uci.set('updater', 'autorun', 'enabled', int(bool(enabled))) + + +def approvals(): + """Returns True if updater approvals are enabled. + Relevant uci configuration is: updater.autorun.approvals + """ + with Uci() as uci: + try: + # TODO use EUci instead of this retype (as this is not perfect) + return bool(int(uci.get("updater", "autorun", "approvals"))) + except UciExceptionNotFound: + return False # No option means disabled + + +def set_approvals(enabled): + """Set value that can later be received by enabled function. + This is relevant to uci config: updater.autorun.approvals + """ + with Uci() as uci: + uci.set('updater', 'autorun', 'approvals') + uci.set('updater', 'autorun', 'approvals', int(bool(enabled))) + + +def auto_approve_time(): + """Returns number of hours before automatic approval is granted. If no + approval time is configured then this function returns None. + This is releavant to uci config: updater.autorun.auto_approve_time + """ + with Uci() as uci: + try: + value = int(uci.get("updater", "autorun", "auto_approve_time")) + return value if value > 0 else None + except UciExceptionNotFound: + return None + + +def set_auto_approve_time(approve_time): + """Sets time in hours after which approval is granted. You can provide None + or value that is less or equal to zero and in that case this feature is + disabled and if approvals are enabled only manual approve can be granted. + """ + with Uci() as uci: + if approve_time > 0: + uci.set('updater', 'autorun', 'autorun') + uci.set('updater', 'autorun', 'auto_approve_time', int(approve_time)) + else: + uci.delete('updater', 'autorun', 'auto_approve_time') diff --git a/src/supervisor/svupdater/config.py b/src/supervisor/svupdater/config.py deleted file mode 100644 index 16190a9fb888455da3b231fcaf6ceb43db0324b9..0000000000000000000000000000000000000000 --- a/src/supervisor/svupdater/config.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright (c) 2018, CZ.NIC, z.s.p.o. (http://www.nic.cz/) -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the CZ.NIC nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL CZ.NIC BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from uci import Uci, UciExceptionNotFound - - -class Config: - "Updater's configuration wrapper." - def __init__(self): - self.uci = None - - def __enter__(self): - self.uci = Uci() - return self - - def __exit__(self, *args): - del self.uci - self.uci = None - - def _get(self, package, section, option, req_type): - "Internal uci_get function" - if self.uci is None: - return None - try: - value = self.uci.get(package, section, option) - except UciExceptionNotFound: - return None - # TODO use EUci instead of this retype (as this is not perfect) - if req_type == bool: - return bool(int(value)) - return req_type(value) - - def disable(self): - """Returns True if updater is set to be disabled. - This is config: updater.override.disable - """ - return self._get("updater", "override", "disable", bool) - - def branch(self): - """Return name of configured branch. But on top of that if nothing is - configured then it returns deploy instead of empty string. - This is config: updater.override.branch - """ - branch = self._get("updater", "override", "branch", str) - if not branch: - branch = "deploy" - return branch - - def approvals_need(self): - """Returns True if updater.approvals.need is set. - """ - return self._get("updater", "approvals", "need", bool) - - def approvals_auto_grant_seconds(self): - """Returns number of seconds after which should be approval - automatically granted. In configuration it's a - updater.approvals.auto_grant_seconds option. It returns None if - approvals are disabled or if such option is not set. - """ - if not self.approvals_need(): - return None - return self._get("updater", "approvals", "auto_grant_seconds", int) diff --git a/src/supervisor/svupdater/const.py b/src/supervisor/svupdater/const.py index f15ef7aba4327c806726287c41341448b6f93550..5d9f280bb381d54533e9c76f7a5c96b78c61de9c 100644 --- a/src/supervisor/svupdater/const.py +++ b/src/supervisor/svupdater/const.py @@ -44,8 +44,8 @@ NOTIFY_MESSAGE_EN = "Your approval is required to apply pending updates." + \ # File containing l10n symbols as a list of supported ones L10N_FILE = "/usr/share/updater/l10n_supported" -# File containing list of known userlists in json -USERLISTS_FILE = "/usr/share/updater/definitions.json" +# File containing list of known pkglists in json +PKGLISTS_FILE = "/usr/share/updater/pkglists.json" # Hooks file containing commands to be run after updater execution finished. POSTRUN_HOOK_FILE = "/tmp/updater-postrun-hook" diff --git a/src/supervisor/svupdater/hook.py b/src/supervisor/svupdater/hook.py index 2e10424cdc0528c1858ce7c471c5129201207344..4b0791fc19bccbfeb5540cd286f473867f4ec521 100644 --- a/src/supervisor/svupdater/hook.py +++ b/src/supervisor/svupdater/hook.py @@ -60,7 +60,7 @@ def __run_command(command): def register(command): """Add given command (format is expected to be same as if you call subprocess.run) to be executed when updater exits. Note that this hook is - executed no matter if updater passer or failed or even if it just requested + executed no matter if updater passed or failed or even if it just requested user's approval. In all of those cases when updater exits this hook is executed. diff --git a/src/supervisor/svupdater/lists.py b/src/supervisor/svupdater/lists.py index 9b78a70aa2c6b12e56f0e1a9eefd2bd0b582ce0a..3c5854a6f45c31a2527844056cba2f3653201a16 100644 --- a/src/supervisor/svupdater/lists.py +++ b/src/supervisor/svupdater/lists.py @@ -30,25 +30,25 @@ from .const import USERLISTS_FILE from .exceptions import ExceptionUpdaterNoSuchList -def userlists(lang=None): - """Returns dict of userlists. +def pkglists(lang=None): + """Returns dict of pkglists. Argument lang is expected to be a string containing language code. This code is then used for gettext translations of titles and descriptions of messages. - Return userlists are in dictionary where key is name of userlist and value - is another dictionary with following content: - "enabled": This is boolean value containing info if userlist is enabled. - "hidden": This is boolean value specifying if userlist is user visible. - "title": This is title text describing userlist (human readable name). This + Return pkglists are in dictionary where key is name of pkglist and value is + another dictionary with following content: + "enabled": This is boolean value containing info if pkglist is enabled. + "hidden": This is boolean value specifying if pkglist is pkg visible. + "title": This is title text describing pkglist (human readable name). This field can be None if "hidden" field is set to True. - "message": This is human readable description of given userlist. This can - be None if "hidden" is set to True. + "message": This is human readable description of given pkglist. This can be + None if "hidden" is set to True. """ result = dict() trans = gettext.translation( - 'userlists', + 'pkglists', languages=[lang] if lang is not None else None, fallback=True) @@ -66,7 +66,7 @@ def userlists(lang=None): with Uci() as uci: try: - lists = uci.get("updater", "pkglists", "lists") + lists = uci.get("updater", "turris", "pkglists") except (UciExceptionNotFound, KeyError): # If we fail to get that section then just ignore return result @@ -78,7 +78,7 @@ def userlists(lang=None): return result -def update_userlists(lists): +def update_pkglists(lists): """ List is expected to be a array of strings (list ids) that should be enabled. Anything omitted will be disabled. @@ -96,5 +96,15 @@ def update_userlists(lists): # Set with Uci() as uci: - uci.set('updater', 'pkglists', 'pkglists') - uci.set('updater', 'pkglists', 'lists', tuple(lists)) + uci.set('updater', 'turris', 'turris') + uci.set('updater', 'turris', 'pkglists', tuple(lists)) + + +def userlists(lang=None): + """Backward compatibility API. Please use pkglists instead.""" + return pkglists(lang) + + +def update_userlists(lists): + """Backward compatibility API. Please use update_pkglists instead.""" + update_pkglists(lists) diff --git a/src/supervisor/updater.sh b/src/supervisor/updater.sh deleted file mode 100755 index f3d01f0df4bd313b2b10242d4b3ad898b3b12ba8..0000000000000000000000000000000000000000 --- a/src/supervisor/updater.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -SUPERVISOR_ARGS="--wait-for-network" - -WIPE=true -for ARG in "$@"; do - if $WIPE; then - shift $# - WIPE=false - fi - - case "$ARG" in - --rand-sleep) - SUPERVISOR_ARGS="$SUPERVISOR_ARGS --rand-sleep" - ;; - -b|--background|-w|-n) - echo "Argument $ARG ignored." >&2 - ;; - *) - set "$@" "$ARG" - ;; - esac -done - -if [ -t 1 ] ; then - echo "updater.sh is obsoleted. Please use pkgupdate directly instead." >&2 - if $BACKGROUND; then - pkgupdate --batch "$@" & - else - pkgupdate --batch "$@" - fi -else - if which updater-supervisor 2>/dev/null >&2; then - updater-supervisor -d - else - pkgupdate --batch & - fi -fi diff --git a/tests/arguments.c b/tests/arguments.c index 6cbd3b3bb661d8d4ef9e59876ca911680c9a719c..bbe2140296f48b9310a1fbc39e37491751e0f669 100644 --- a/tests/arguments.c +++ b/tests/arguments.c @@ -486,7 +486,7 @@ START_TEST(cmd_args_parse_test) { for (char **arg = c->args; *arg; arg ++) count ++; char **args = malloc((count + 1) * sizeof *args); - *args = "opkg-trans"; + *args = "pkgupdate"; for (int i = 1; i < count; i ++) args[i] = c->args[i - 1]; args[count] = NULL; diff --git a/tests/system/Makefile.dir b/tests/system/Makefile.dir index b8c8224cc0c2cc04e084a0a7bbb659dc2fc22f3b..47efdb561006eb8f1fcc173724cdff290eb221d5 100644 --- a/tests/system/Makefile.dir +++ b/tests/system/Makefile.dir @@ -31,8 +31,8 @@ UPD_SYS_TESTS := \ check: test-sys valgrind-sys # As secondary tool we use pkgupdate in reboot-recover test -test-sys-opkg-trans-reboot-recover: $(O)/bin/pkgupdate -valgrind-sys-opkg-trans-reboot-recover: $(O)/bin/pkgupdate +test-sys-pkgtransaction-reboot-recover: $(O)/bin/pkgupdate +valgrind-sys-pkgtransaction-reboot-recover: $(O)/bin/pkgupdate define DO_SYS_TEST @@ -48,5 +48,5 @@ valgrind-sys-$(1)-$(2): $(O)/bin/$(1) endef -$(eval $(foreach TEST,$(TRANS_SYS_TESTS),$(call DO_SYS_TEST,opkg-trans,$(TEST)))) +$(eval $(foreach TEST,$(TRANS_SYS_TESTS),$(call DO_SYS_TEST,pkgtransaction,$(TEST)))) $(eval $(foreach TEST,$(UPD_SYS_TESTS),$(call DO_SYS_TEST,pkgupdate,$(TEST)))) diff --git a/tests/system/run b/tests/system/run index 89d2cff62855e2eff71e96526d73c66048ed8a53..fda36645116e7480f72b4b1f8b678128ed2504fd 100755 --- a/tests/system/run +++ b/tests/system/run @@ -49,7 +49,7 @@ find "$TMP_DIR" -type f -name .keep -exec rm {} \; # Launch it export COVERAGEDIR="$O/.lua_coverage" MODEL=" --model Turris --board unknown" -[ "$1" != opkg-trans ] || MODEL="" # No model specification for backend tool opkg-trans +[ "$1" != "pkgtransaction" ] || MODEL="" # No model specification for backend tool pkgtransaction eval $LAUNCHER "$O"/bin/"$1" $MODEL $(cat "$DEFINITION"/params) # Do we need to de-randomize the output somehow? if [ -f "$DEFINITION"/cleanup ] ; then