Commit 0bc60d2f authored by Karel Koci's avatar Karel Koci 🤘

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"
local DBG = DBG
local WARN = WARN
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 log_event = log_event
local sha256 = sha256
......@@ -66,6 +73,7 @@ end
-- Stages of the transaction. Each one is written into the journal, with its results.
local function pkg_unpack(operations, status)
update_state(LS_UNPACK)
INFO("Unpacking download packages")
local dir_cleanups = {}
--[[
......@@ -138,6 +146,7 @@ local function pkg_unpack(operations, status)
end
local function pkg_collision_check(status, to_remove, to_install)
update_state(LS_CHECK)
INFO("Checking for file collisions between packages")
local collisions, early_remove, removes = backend.collision_check(status, to_remove, to_install)
if next(collisions) then
......@@ -156,6 +165,7 @@ local function pkg_collision_check(status, to_remove, to_install)
end
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")
-- Prepare table of not installed confs for config stealing
local installed_confs = backend.installed_confs(status)
......@@ -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
for _, op in ipairs(plan) do
if op.op == "install" then
state_dump("install")
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.
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)
end
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")
for _, op in ipairs(plan) do
if op.op == "install" then
......@@ -227,7 +237,7 @@ local function pkg_scripts(status, plan, removes, to_install, errors_collected,
end
-- Clean up the files from removed or upgraded packages
INFO("Removing packages and leftover files")
state_dump("remove")
update_state(LS_REM)
backend.pkg_cleanup_files(removes, all_configs)
for _, op in ipairs(plan) do
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,
end
local function pkg_cleanup(status)
update_state(LS_CLEANUP)
INFO("Cleaning up control files")
backend.control_cleanup(status)
backend.status_dump(status)
......
......@@ -24,7 +24,10 @@ local INFO = INFO
local md5 = md5
local sha256 = sha256
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 utils = require "utils"
local syscnf = require "syscnf"
......@@ -51,14 +54,14 @@ function required_pkgs(entrypoint)
local ep_uri = uri(tlc, entrypoint)
local ok, tls = ep_uri:get()
if not ok then error(tls) end
state_dump("get list")
update_state(LS_CONF)
--[[
Run the top level script with full privileges.
The script shall be part of updater anyway.
]]
local err = sandbox.run_sandboxed(tls, "", 'Full')
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
postprocess.run()
return planner.required_pkgs(postprocess.available_packages, requests.content_requests)
......@@ -71,6 +74,7 @@ function prepare(entrypoint)
local required = required_pkgs(entrypoint)
local run_state = backend.run_state()
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
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) {
return 0;
}
static int lua_state_dump(lua_State *L) {
const char *state = luaL_checkstring(L, 1);
state_dump(state);
static int lua_update_state(lua_State *L) {
enum log_state state = luaL_checkint(L, 1);
update_state(state);
return 0;
}
......@@ -833,7 +833,7 @@ struct injected_func {
static const struct injected_func injected_funcs[] = {
{ lua_log, "log" },
{ 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_unregister_handle, "cleanup_unregister_handle" },
{ lua_run_command, "run_command" },
......@@ -865,6 +865,27 @@ static const struct injected_func injected_funcs[] = {
{ 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
// From the embed file. Coverage lua code.
extern struct file_index_element lcoverage[];
......@@ -925,6 +946,12 @@ struct interpreter *interpreter_create(struct events *events) {
lua_pushcfunction(L, injected_funcs[i].func);
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
journal_mod_init(L);
locks_mod_init(L);
......
......@@ -23,6 +23,23 @@
#include <stdarg.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 {
const char *prefix;
const char *name;
......@@ -49,11 +66,11 @@ void set_state_log(bool state_log) {
state_log_enabled = state_log;
}
void state_dump(const char *msg) {
void update_state(enum log_state state) {
if (state_log_enabled) {
FILE *f = fopen("/tmp/update-state/state", "w");
if (f) {
fprintf(f, "%s\n", msg);
fprintf(f, "%s\n", log_state_str[state]);
fclose(f);
} else {
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
fprintf(stderr, "%s:%s:%zu (%s):%s\n", levels[level].prefix, file, line, func, msg);
}
if (level == LL_DIE) {
state_dump("error");
update_state(LS_FAIL);
err_dump(msg);
}
}
......
......@@ -24,6 +24,25 @@
#include <stdlib.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 {
LL_DISABLE,
LL_DIE,
......@@ -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
void set_state_log(bool state_log);
// In the full updater mode, dump current state into /tmp/update-state/state
void state_dump(const char *msg) __attribute__((nonnull));
// Log state change of updater
void update_state(enum log_state);
// In the full updater mode, dump the error into /tmp/update-state/error
void err_dump(const char *msg) __attribute__((nonnull));
......
......@@ -30,8 +30,23 @@ TRACE(msg, msg, ...)::
DIE(msg, msg, ...)::
In addition to outputting the message on the ``DIE`` level, it also
terminates the application with error exit code.
state_dump(msg)::
Dump the given message into `/tmp/update-state/state`.
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
-------
......
......@@ -214,7 +214,7 @@ int main(int argc, char *argv[]) {
enum cmd_op_type exit_type = op->type;
free(ops);
state_dump("startup");
update_state(LS_INIT);
struct events *events = events_new();
// Prepare the interpreter and load it with the embedded lua scripts
struct interpreter *interpreter = interpreter_create(events);
......@@ -276,6 +276,7 @@ int main(int argc, char *argv[]) {
// Otherwise user approves on terminal in previous code block.
GOTO_CLEANUP;
if (!replan) {
update_state(LS_PREUPD);
INFO("Executing preupdate hooks...");
const char *hook_path = aprintf("%s%s", root_dir, hook_preupdate);
setenv("ROOT_DIR", root_dir, true);
......@@ -319,6 +320,7 @@ int main(int argc, char *argv[]) {
WARN("Could not store task log end %s: %s", task_log, strerror(errno));
}
REPLAN_CLEANUP:
update_state(LS_POSTUPD);
INFO("Executing postupdate hooks...");
const char *hook_path = aprintf("%s%s", root_dir, hook_postupdate);
setenv("SUCCESS", trans_ok ? "true" : "false", true); // ROOT_DIR is already set
......@@ -332,10 +334,10 @@ CLEANUP:
system_reboot(false);
if (exit_type == COT_EXIT) {
if (trans_ok) {
state_dump("done");
update_state(LS_EXIT);
return 0;
} else {
state_dump("error");
update_state(LS_FAIL);
return 2;
}
} else
......
......@@ -10,7 +10,8 @@ globals = {
-- lua51 doesn't contains?
"_M",
-- 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
"ERROR", "WARN", "INFO", "DBG", "TRACE", "DIE", "log_event", "c_pcall_error_handler",
-- 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