Verified Commit 0ecb39fc authored by Karel Koci's avatar Karel Koci 🤘

lib: move prerm to be run before postinst in transaction

This moves execution of prerm script from pkg_scripts step to pkg_move
step. This effectivelly means that prerm and preinst scripts are run in
plan order at the same time. This solves problems where prerm disables
service or in general does operation which revers one done previous
preinst.

There are two consideration required. This code defines content of
journal. The difference is that instead of editing all_configs table in
pkg_scripts we generate it in its fullest in pkg_move. That is all right
and fully compatible. The more problematic case is when we update from
previous version of updater and there is journal stuck with completed
pkg_move step but not yet completed pkg_scripts step. The result is that
in such case prerm scripts are not run and packages are not in reality
removed (removed from state). The real removal happens with next updater
execution. So this is self healing problem that happens only with small
probability.

This also does one degradation in behavior. Previously we were ignoring
removal operation for packages that were intended to be installed. In
that case we just skipped remove section. The problem is that pkg_move
does not have to_install argument and that makes it impossible to check
if operation tries to remove package that is installed by some other
one. The effect of such operation in this new implementation is that we
would run in such case prerm script and removed given package info from
status while preserved its files in system. That is worst case scenario.
Other case where install request comes after remove request returns
given info to state and runs preinst. That effectively just causes us to
run both prerm and preinst where it should have been reinstall. That
effectively should not cause anything bad.
The real reason why we do not care too much is that only case when
something like that happens is when pkgtransaction is used. pkgupdate
never generates two operations for same package. Because pkgtransaction
is dangerous tool in general I don't see it as huge problem.
Other option is to pass to_install table to pkg_move as well but we
would have to take care of situation where this field is not part of
journal.
parent 8089fc51
Pipeline #49273 passed with stage
in 3 minutes and 18 seconds
......@@ -161,7 +161,7 @@ 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")
INFO("Running pre-install and pre-rm scripts and merging packages to root file system")
-- Prepare table of not installed confs for config stealing
local installed_confs = backend.installed_confs(status)
......@@ -199,23 +199,8 @@ local function pkg_move(status, plan, early_remove, errors_collected)
-- Note: This causes reexecution of already executed preinst scripts.
system_reboot(true)
end
end
-- Ignore others, at least for now.
end
-- Remove all other files (see note in backend.collision_check)
if early_remove[true] then
backend.pkg_cleanup_files(early_remove[true], all_configs)
end
return status, errors_collected, all_configs
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
script(errors_collected, op.control.Package, "postinst", "configure")
elseif op.op == "remove" and not to_install[op.name] and utils.arr2set(utils.multi_index(status, op.name, 'Status') or {})['installed'] then
elseif op.op == "remove" and utils.arr2set(utils.multi_index(status, op.name, 'Status') or {})['installed'] then
log_event("R", op.name)
utils.table_merge(all_configs, status[op.name].Conffiles or {})
local cfiles = status[op.name].Conffiles or {}
for f in pairs(cfiles) do
......@@ -230,16 +215,29 @@ local function pkg_scripts(status, plan, removes, to_install, errors_collected,
else
status[op.name] = nil
end
log_event("R", op.name)
script(errors_collected, op.name, "prerm", "remove")
end
-- Ignore others, at least for now.
end
-- Remove all other files (see note in backend.collision_check)
if early_remove[true] then
backend.pkg_cleanup_files(early_remove[true], all_configs)
end
return status, errors_collected, all_configs
end
local function pkg_scripts(status, plan, removes, to_install, errors_collected, all_configs)
-- Clean up the files from removed or upgraded packages
INFO("Removing packages and leftover files")
update_state(LS_REM)
backend.pkg_cleanup_files(removes, all_configs)
-- Run post install and remove scripts
update_state(LS_POST)
INFO("Running post-install and post-rm scripts")
for _, op in ipairs(plan) do
if op.op == "remove" and not to_install[op.name] then
if op.op == "install" then
script(errors_collected, op.control.Package, "postinst", "configure")
elseif op.op == "remove" and not to_install[op.name] then
script(errors_collected, op.name, "postrm", "remove")
end
end
......
......@@ -278,6 +278,14 @@ function test_perform_ok()
f = "backend.pkg_merge_files",
p = {"pkg_dir/data", {d = true}, {f = true}, {c = "12345678901234567890123456789012"}}
},
{
f = "backend.pkg_config_info",
p = {"remconf", { remconf = "12345678901234567890123456789012" } }
},
{
f = "backend.script_run",
p = {"pkg-rem", "prerm", "remove"}
},
{
f = "journal.write",
p = {
......@@ -289,32 +297,19 @@ function test_perform_ok()
Version = "1",
files = { f = true },
Status = {"install", "user", "installed"}
},
["pkg-rem"] = {
Package = "pkg-rem",
Conffiles = { remconf = "12345678901234567890123456789012" },
Status = {"install", "user", "installed"}
}
},
{},
{c = "12345678901234567890123456789012"}
{c = "12345678901234567890123456789012", remconf = "12345678901234567890123456789012"}
}
},
{
f = "backend.script_run",
p = {"pkg-name", "postinst", "configure"}
},
{
f = "backend.pkg_config_info",
p = {"remconf", { remconf = "12345678901234567890123456789012" } }
f = "backend.pkg_cleanup_files",
p = {{d2 = true}, {c = "12345678901234567890123456789012", remconf = "12345678901234567890123456789012"}}
},
{
f = "backend.script_run",
p = {"pkg-rem", "prerm", "remove"}
},
{
f = "backend.pkg_cleanup_files",
p = {{d2 = true}, {c = "12345678901234567890123456789012", remconf = "12345678901234567890123456789012"}}
p = {"pkg-name", "postinst", "configure"}
},
{
f = "backend.script_run",
......
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