Verified Commit 0bc60d2f authored by Karel Koci's avatar Karel Koci 🤘
Browse files

Add new states updates to pkgupdate

This replaces way how we define state in pkgupdate. Now we have
predefined enum that we use to identify sate instead of just using
string.
parent 119ee8c6
...@@ -41,7 +41,14 @@ local journal = require "journal" ...@@ -41,7 +41,14 @@ local journal = require "journal"
local DBG = DBG local DBG = DBG
local WARN = WARN local WARN = WARN
local INFO = INFO local INFO = INFO
local state_dump = state_dump local LS_UNPACK = LS_UNPACK
local LS_INST = LS_INST
local LS_CHECK = LS_CHECK
local LS_INST = LS_INST
local LS_POST = LS_POST
local LS_REM = LS_REM
local LS_CLEANUP = LS_CLEANUP
local update_state = update_state
local sync = sync local sync = sync
local log_event = log_event local log_event = log_event
local sha256 = sha256 local sha256 = sha256
...@@ -66,6 +73,7 @@ end ...@@ -66,6 +73,7 @@ end
-- Stages of the transaction. Each one is written into the journal, with its results. -- Stages of the transaction. Each one is written into the journal, with its results.
local function pkg_unpack(operations, status) local function pkg_unpack(operations, status)
update_state(LS_UNPACK)
INFO("Unpacking download packages") INFO("Unpacking download packages")
local dir_cleanups = {} local dir_cleanups = {}
--[[ --[[
...@@ -138,6 +146,7 @@ local function pkg_unpack(operations, status) ...@@ -138,6 +146,7 @@ local function pkg_unpack(operations, status)
end end
local function pkg_collision_check(status, to_remove, to_install) local function pkg_collision_check(status, to_remove, to_install)
update_state(LS_CHECK)
INFO("Checking for file collisions between packages") INFO("Checking for file collisions between packages")
local collisions, early_remove, removes = backend.collision_check(status, to_remove, to_install) local collisions, early_remove, removes = backend.collision_check(status, to_remove, to_install)
if next(collisions) then if next(collisions) then
...@@ -156,6 +165,7 @@ local function pkg_collision_check(status, to_remove, to_install) ...@@ -156,6 +165,7 @@ local function pkg_collision_check(status, to_remove, to_install)
end end
local function pkg_move(status, plan, early_remove, errors_collected) local function pkg_move(status, plan, early_remove, errors_collected)
update_state(LS_INST)
INFO("Running pre-install scripts and merging packages to root file system") INFO("Running pre-install scripts and merging packages to root file system")
-- Prepare table of not installed confs for config stealing -- Prepare table of not installed confs for config stealing
local installed_confs = backend.installed_confs(status) local installed_confs = backend.installed_confs(status)
...@@ -172,7 +182,6 @@ local function pkg_move(status, plan, early_remove, errors_collected) ...@@ -172,7 +182,6 @@ local function pkg_move(status, plan, early_remove, errors_collected)
-- Go through the list once more and perform the prepared operations -- Go through the list once more and perform the prepared operations
for _, op in ipairs(plan) do for _, op in ipairs(plan) do
if op.op == "install" then if op.op == "install" then
state_dump("install")
log_event("I", op.control.Package .. " " .. op.control.Version) log_event("I", op.control.Package .. " " .. op.control.Version)
-- Unfortunately, we need to merge the control files first, otherwise the maintainer scripts won't run. They expect to live in the info dir when they are run. And we need to run the preinst script before merging the files. -- Unfortunately, we need to merge the control files first, otherwise the maintainer scripts won't run. They expect to live in the info dir when they are run. And we need to run the preinst script before merging the files.
backend.pkg_merge_control(op.dir .. "/control", op.control.Package, op.control.files) backend.pkg_merge_control(op.dir .. "/control", op.control.Package, op.control.files)
...@@ -202,6 +211,7 @@ local function pkg_move(status, plan, early_remove, errors_collected) ...@@ -202,6 +211,7 @@ local function pkg_move(status, plan, early_remove, errors_collected)
end end
local function pkg_scripts(status, plan, removes, to_install, errors_collected, all_configs) local function pkg_scripts(status, plan, removes, to_install, errors_collected, all_configs)
update_state(LS_POST)
INFO("Running post-install and post-rm scripts") INFO("Running post-install and post-rm scripts")
for _, op in ipairs(plan) do for _, op in ipairs(plan) do
if op.op == "install" then if op.op == "install" then
...@@ -227,7 +237,7 @@ local function pkg_scripts(status, plan, removes, to_install, errors_collected, ...@@ -227,7 +237,7 @@ local function pkg_scripts(status, plan, removes, to_install, errors_collected,
end end
-- Clean up the files from removed or upgraded packages -- Clean up the files from removed or upgraded packages
INFO("Removing packages and leftover files") INFO("Removing packages and leftover files")
state_dump("remove") update_state(LS_REM)
backend.pkg_cleanup_files(removes, all_configs) backend.pkg_cleanup_files(removes, all_configs)
for _, op in ipairs(plan) do for _, op in ipairs(plan) do
if op.op == "remove" and not to_install[op.name] then if op.op == "remove" and not to_install[op.name] then
...@@ -238,6 +248,7 @@ local function pkg_scripts(status, plan, removes, to_install, errors_collected, ...@@ -238,6 +248,7 @@ local function pkg_scripts(status, plan, removes, to_install, errors_collected,
end end
local function pkg_cleanup(status) local function pkg_cleanup(status)
update_state(LS_CLEANUP)
INFO("Cleaning up control files") INFO("Cleaning up control files")
backend.control_cleanup(status) backend.control_cleanup(status)
backend.status_dump(status) backend.status_dump(status)
......
...@@ -24,7 +24,10 @@ local INFO = INFO ...@@ -24,7 +24,10 @@ local INFO = INFO
local md5 = md5 local md5 = md5
local sha256 = sha256 local sha256 = sha256
local reexec = reexec local reexec = reexec
local state_dump = state_dump local LS_CONF = LS_CONF
local LS_PLAN = LS_PLAN
local LS_DOWN = LS_DOWN
local update_state = update_state
local log_event = log_event local log_event = log_event
local utils = require "utils" local utils = require "utils"
local syscnf = require "syscnf" local syscnf = require "syscnf"
...@@ -51,14 +54,14 @@ function required_pkgs(entrypoint) ...@@ -51,14 +54,14 @@ function required_pkgs(entrypoint)
local ep_uri = uri(tlc, entrypoint) local ep_uri = uri(tlc, entrypoint)
local ok, tls = ep_uri:get() local ok, tls = ep_uri:get()
if not ok then error(tls) end if not ok then error(tls) end
state_dump("get list") update_state(LS_CONF)
--[[ --[[
Run the top level script with full privileges. Run the top level script with full privileges.
The script shall be part of updater anyway. The script shall be part of updater anyway.
]] ]]
local err = sandbox.run_sandboxed(tls, "", 'Full') local err = sandbox.run_sandboxed(tls, "", 'Full')
if err and err.tp == 'error' then error(err) end if err and err.tp == 'error' then error(err) end
state_dump("examine") update_state(LS_PLAN)
-- Go through all the requirements and decide what we need -- Go through all the requirements and decide what we need
postprocess.run() postprocess.run()
return planner.required_pkgs(postprocess.available_packages, requests.content_requests) return planner.required_pkgs(postprocess.available_packages, requests.content_requests)
...@@ -71,6 +74,7 @@ function prepare(entrypoint) ...@@ -71,6 +74,7 @@ function prepare(entrypoint)
local required = required_pkgs(entrypoint) local required = required_pkgs(entrypoint)
local run_state = backend.run_state() local run_state = backend.run_state()
local tasks = planner.filter_required(run_state.status, required, allow_replan) local tasks = planner.filter_required(run_state.status, required, allow_replan)
update_state(LS_DOWN)
--[[ --[[
Start download of all the packages. They all start (or queue, if there are Start download of all the packages. They all start (or queue, if there are
too many). We then start taking them one by one, but that doesn't stop it too many). We then start taking them one by one, but that doesn't stop it
......
...@@ -149,9 +149,9 @@ static int lua_log(lua_State *L) { ...@@ -149,9 +149,9 @@ static int lua_log(lua_State *L) {
return 0; return 0;
} }
static int lua_state_dump(lua_State *L) { static int lua_update_state(lua_State *L) {
const char *state = luaL_checkstring(L, 1); enum log_state state = luaL_checkint(L, 1);
state_dump(state); update_state(state);
return 0; return 0;
} }
...@@ -833,7 +833,7 @@ struct injected_func { ...@@ -833,7 +833,7 @@ struct injected_func {
static const struct injected_func injected_funcs[] = { static const struct injected_func injected_funcs[] = {
{ lua_log, "log" }, { lua_log, "log" },
{ lua_state_log_enabled, "state_log_enabled" }, { lua_state_log_enabled, "state_log_enabled" },
{ lua_state_dump, "state_dump" }, { lua_update_state, "update_state" },
{ lua_cleanup_register_handle, "cleanup_register_handle" }, { lua_cleanup_register_handle, "cleanup_register_handle" },
{ lua_cleanup_unregister_handle, "cleanup_unregister_handle" }, { lua_cleanup_unregister_handle, "cleanup_unregister_handle" },
{ lua_run_command, "run_command" }, { lua_run_command, "run_command" },
...@@ -865,6 +865,27 @@ static const struct injected_func injected_funcs[] = { ...@@ -865,6 +865,27 @@ static const struct injected_func injected_funcs[] = {
{ lua_get_updater_version, "get_updater_version" } { lua_get_updater_version, "get_updater_version" }
}; };
struct {
int cnst;
const char *name;
} injected_const[] = {
{ LS_INIT, "LS_INIT"},
{ LS_CONF, "LS_CONF"},
{ LS_PLAN, "LS_PLAN"},
{ LS_DOWN, "LS_DOWN"},
{ LS_PREUPD, "LS_PREUPD"},
{ LS_UNPACK, "LS_UNPACK"},
{ LS_CHECK, "LS_CHECK"},
{ LS_INST, "LS_INST"},
{ LS_POST, "LS_POST"},
{ LS_REM, "LS_REM"},
{ LS_CLEANUP, "LS_CLEANUP"},
{ LS_POSTUPD, "LS_POSTUPD"},
{ LS_EXIT, "LS_EXIT"},
{ LS_FAIL, "LS_FAIL"}
};
// Various enum values that we want to inject
#ifdef COVERAGE #ifdef COVERAGE
// From the embed file. Coverage lua code. // From the embed file. Coverage lua code.
extern struct file_index_element lcoverage[]; extern struct file_index_element lcoverage[];
...@@ -925,6 +946,12 @@ struct interpreter *interpreter_create(struct events *events) { ...@@ -925,6 +946,12 @@ struct interpreter *interpreter_create(struct events *events) {
lua_pushcfunction(L, injected_funcs[i].func); lua_pushcfunction(L, injected_funcs[i].func);
lua_setglobal(L, injected_funcs[i].name); lua_setglobal(L, injected_funcs[i].name);
} }
// Inject some constant/variables
for (size_t i = 0; i < sizeof injected_const / sizeof *injected_const; i ++) {
TRACE("Injecting constant no %zu %s/%d", i, injected_const[i].name, injected_const[i].cnst);
lua_pushinteger(L, injected_const[i].cnst);
lua_setglobal(L, injected_const[i].name);
}
// Some binary embedded modules // Some binary embedded modules
journal_mod_init(L); journal_mod_init(L);
locks_mod_init(L); locks_mod_init(L);
......
...@@ -23,6 +23,23 @@ ...@@ -23,6 +23,23 @@
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
const char* log_state_str[] = {
[LS_INIT] = "initialize",
[LS_CONF] = "configuration",
[LS_PLAN] = "planning",
[LS_DOWN] = "downloading",
[LS_PREUPD] = "preupdate-hooks",
[LS_UNPACK] = "unpacking",
[LS_CHECK] = "checking",
[LS_INST] = "install",
[LS_POST] = "post-install",
[LS_REM] = "removals",
[LS_CLEANUP] = "cleanup",
[LS_POSTUPD] = "postupdate-hooks",
[LS_EXIT] = "exit",
[LS_FAIL] = "failure"
};
struct level_info { struct level_info {
const char *prefix; const char *prefix;
const char *name; const char *name;
...@@ -49,11 +66,11 @@ void set_state_log(bool state_log) { ...@@ -49,11 +66,11 @@ void set_state_log(bool state_log) {
state_log_enabled = state_log; state_log_enabled = state_log;
} }
void state_dump(const char *msg) { void update_state(enum log_state state) {
if (state_log_enabled) { if (state_log_enabled) {
FILE *f = fopen("/tmp/update-state/state", "w"); FILE *f = fopen("/tmp/update-state/state", "w");
if (f) { if (f) {
fprintf(f, "%s\n", msg); fprintf(f, "%s\n", log_state_str[state]);
fclose(f); fclose(f);
} else { } else {
WARN("Could not dump state: %s", strerror(errno)); WARN("Could not dump state: %s", strerror(errno));
...@@ -96,7 +113,7 @@ void log_internal(enum log_level level, const char *file, size_t line, const cha ...@@ -96,7 +113,7 @@ void log_internal(enum log_level level, const char *file, size_t line, const cha
fprintf(stderr, "%s:%s:%zu (%s):%s\n", levels[level].prefix, file, line, func, msg); fprintf(stderr, "%s:%s:%zu (%s):%s\n", levels[level].prefix, file, line, func, msg);
} }
if (level == LL_DIE) { if (level == LL_DIE) {
state_dump("error"); update_state(LS_FAIL);
err_dump(msg); err_dump(msg);
} }
} }
......
...@@ -24,6 +24,25 @@ ...@@ -24,6 +24,25 @@
#include <stdlib.h> #include <stdlib.h>
#include "util.h" #include "util.h"
enum log_state {
LS_INIT, // Initial state
LS_CONF, // Running configuration scripts
LS_PLAN, // Generating plan
LS_DOWN, // Downloading needed packages
LS_PREUPD, // Running updater's preupdate hooks
// These are states in critical section
LS_UNPACK, // Unpacking downloaded packages
LS_CHECK, // Checking for files collisions and more
LS_INST, // Running preinst scripts and merging files to filesystem
LS_POST, // Running postinst scripts
LS_REM, // Removing leftover files
LS_CLEANUP, // Cleaning up control files
// End of critical section
LS_POSTUPD, // Running updater's postupdate hooks
LS_EXIT, // Updater exit
LS_FAIL, // Detected failure, exiting.
};
enum log_level { enum log_level {
LL_DISABLE, LL_DISABLE,
LL_DIE, LL_DIE,
...@@ -69,8 +88,8 @@ void log_buffer_init(struct log_buffer *buf, enum log_level level) __attribute__ ...@@ -69,8 +88,8 @@ void log_buffer_init(struct log_buffer *buf, enum log_level level) __attribute__
// Sets if state and error should be dumped into files in /tmp/updater-state directory // Sets if state and error should be dumped into files in /tmp/updater-state directory
void set_state_log(bool state_log); void set_state_log(bool state_log);
// In the full updater mode, dump current state into /tmp/update-state/state // Log state change of updater
void state_dump(const char *msg) __attribute__((nonnull)); void update_state(enum log_state);
// In the full updater mode, dump the error into /tmp/update-state/error // In the full updater mode, dump the error into /tmp/update-state/error
void err_dump(const char *msg) __attribute__((nonnull)); void err_dump(const char *msg) __attribute__((nonnull));
......
...@@ -30,8 +30,23 @@ TRACE(msg, msg, ...):: ...@@ -30,8 +30,23 @@ TRACE(msg, msg, ...)::
DIE(msg, msg, ...):: DIE(msg, msg, ...)::
In addition to outputting the message on the ``DIE`` level, it also In addition to outputting the message on the ``DIE`` level, it also
terminates the application with error exit code. terminates the application with error exit code.
state_dump(msg):: update_state(state)::
Dump the given message into `/tmp/update-state/state`. Dump the message for given state into `/tmp/update-state/state`.
Allowed states are as follow:
- `LS_INIT`: Initial state (`initialize`)
- `LS_CONF`: Running configuration scripts (`configuration`)
- `LS_PLAN`: Generating plan (`planning`)
- `LS_DOWN`: Downloading needed packages (`downloading`)
- `LS_PREUPD`: Running updater's preupdate hooks (`preupdate-hooks`)
- `LS_UNPACK`: Unpacking downloaded packages (`unpacking`)
- `LS_CHECK`: Checking for files collisions and more (`checking`)
- `LS_INST`: Running preinst scripts and merging files to filesystem (`install`)
- `LS_POST`: Running postinst scripts (`post-install`)
- `LS_REM`: Removing leftover files (`removals`)
- `LS_CLEANUP`: Cleaning up control files (`cleanup`)
- `LS_POSTUPD`: Running updater's postupdate hooks (`postupdate-hooks`)
- `LS_EXIT`: Updater exit (`exit`)
- `LS_FAIL`: Detected failure, exiting. (`failure`)
Cleanup Cleanup
------- -------
......
...@@ -214,7 +214,7 @@ int main(int argc, char *argv[]) { ...@@ -214,7 +214,7 @@ int main(int argc, char *argv[]) {
enum cmd_op_type exit_type = op->type; enum cmd_op_type exit_type = op->type;
free(ops); free(ops);
state_dump("startup"); update_state(LS_INIT);
struct events *events = events_new(); struct events *events = events_new();
// Prepare the interpreter and load it with the embedded lua scripts // Prepare the interpreter and load it with the embedded lua scripts
struct interpreter *interpreter = interpreter_create(events); struct interpreter *interpreter = interpreter_create(events);
...@@ -276,6 +276,7 @@ int main(int argc, char *argv[]) { ...@@ -276,6 +276,7 @@ int main(int argc, char *argv[]) {
// Otherwise user approves on terminal in previous code block. // Otherwise user approves on terminal in previous code block.
GOTO_CLEANUP; GOTO_CLEANUP;
if (!replan) { if (!replan) {
update_state(LS_PREUPD);
INFO("Executing preupdate hooks..."); INFO("Executing preupdate hooks...");
const char *hook_path = aprintf("%s%s", root_dir, hook_preupdate); const char *hook_path = aprintf("%s%s", root_dir, hook_preupdate);
setenv("ROOT_DIR", root_dir, true); setenv("ROOT_DIR", root_dir, true);
...@@ -319,6 +320,7 @@ int main(int argc, char *argv[]) { ...@@ -319,6 +320,7 @@ int main(int argc, char *argv[]) {
WARN("Could not store task log end %s: %s", task_log, strerror(errno)); WARN("Could not store task log end %s: %s", task_log, strerror(errno));
} }
REPLAN_CLEANUP: REPLAN_CLEANUP:
update_state(LS_POSTUPD);
INFO("Executing postupdate hooks..."); INFO("Executing postupdate hooks...");
const char *hook_path = aprintf("%s%s", root_dir, hook_postupdate); const char *hook_path = aprintf("%s%s", root_dir, hook_postupdate);
setenv("SUCCESS", trans_ok ? "true" : "false", true); // ROOT_DIR is already set setenv("SUCCESS", trans_ok ? "true" : "false", true); // ROOT_DIR is already set
...@@ -332,10 +334,10 @@ CLEANUP: ...@@ -332,10 +334,10 @@ CLEANUP:
system_reboot(false); system_reboot(false);
if (exit_type == COT_EXIT) { if (exit_type == COT_EXIT) {
if (trans_ok) { if (trans_ok) {
state_dump("done"); update_state(LS_EXIT);
return 0; return 0;
} else { } else {
state_dump("error"); update_state(LS_FAIL);
return 2; return 2;
} }
} else } else
......
...@@ -10,7 +10,8 @@ globals = { ...@@ -10,7 +10,8 @@ globals = {
-- lua51 doesn't contains? -- lua51 doesn't contains?
"_M", "_M",
-- From interpreter.c -- From interpreter.c
"log", "state_log_enabled", "state_dump", "cleanup_register_handle", "cleanup_unregister_handle", "run_command", "run_util", "download", "events_wait", "mkdtemp", "chdir", "getcwd", "mkdir", "move", "copy", "ls", "stat", "lstat", "sync", "setenv", "md5", "sha256", "md5_file", "sha256_file", "reexec", "uri_internal_get", "system_reboot", "get_updater_version", "log", "state_log_enabled", "update_state", "cleanup_register_handle", "cleanup_unregister_handle", "run_command", "run_util", "download", "events_wait", "mkdtemp", "chdir", "getcwd", "mkdir", "move", "copy", "ls", "stat", "lstat", "sync", "setenv", "md5", "sha256", "md5_file", "sha256_file", "reexec", "uri_internal_get", "system_reboot", "get_updater_version",
"LS_INIT", "LS_CONF", "LS_PLAN", "LS_DOWN", "LS_PREUPD", "LS_UNPACK", "LS_CHECK", "LS_INST", "LS_POST", "LS_REM", "LS_CLEANUP", "LS_POSTUPD", "LS_EXIT", "LS_FAIL",
-- From logging -- From logging
"ERROR", "WARN", "INFO", "DBG", "TRACE", "DIE", "log_event", "c_pcall_error_handler", "ERROR", "WARN", "INFO", "DBG", "TRACE", "DIE", "log_event", "c_pcall_error_handler",
-- Picosat -- Picosat
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment