core/manager: when running in test mode, use a temp dir for generated stuff

When running through systemd-analyze verify or with --test, we would
not run generators (environment or unit). But at the end, we would nuke
the generator dirs anyway.

Simplify things by actually running generators of both types, but redirecting
their output to a temporary directory. This has the advantage that we test more
code, and the verification is more complete.

Since now we are not touching the real generator directories, we also don't
delete them, which fixes #5609.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2017-09-14 19:26:29 +02:00
parent 81fe6cdee2
commit a1f31f4715
3 changed files with 68 additions and 55 deletions

View File

@ -1127,8 +1127,7 @@ Manager* manager_free(Manager *m) {
if (unit_vtable[c]->shutdown)
unit_vtable[c]->shutdown(m);
/* If we reexecute ourselves, we keep the root cgroup
* around */
/* If we reexecute ourselves, we keep the root cgroup around */
manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE);
lookup_paths_flush_generator(&m->lookup_paths);
@ -1311,7 +1310,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
assert(m);
r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, 0, NULL);
/* If we are running in test mode, we still want to run the generators,
* but we should not touch the real generator directories. */
r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope,
m->test_run ? LOOKUP_PATHS_TEMPORARY_GENERATED : 0,
NULL);
if (r < 0)
return r;
@ -1319,12 +1322,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
if (r < 0)
return r;
/* Make sure the transient directory always exists, so that it remains in the search path */
if (!m->test_run) {
r = mkdir_p_label(m->lookup_paths.transient, 0755);
if (r < 0)
return r;
}
/* Make sure the transient directory always exists, so that it remains
* in the search path */
r = mkdir_p_label(m->lookup_paths.transient, 0755);
if (r < 0)
return r;
dual_timestamp_get(&m->generators_start_timestamp);
r = manager_run_generators(m);
@ -3146,9 +3148,6 @@ static int manager_run_environment_generators(Manager *m) {
const char **paths;
void* args[] = {&tmp, &tmp, &m->environment};
if (m->test_run)
return 0;
paths = MANAGER_IS_SYSTEM(m) ? system_env_generator_binary_paths : user_env_generator_binary_paths;
if (!generator_path_any(paths))
@ -3164,9 +3163,6 @@ static int manager_run_generators(Manager *m) {
assert(m);
if (m->test_run)
return 0;
paths = generator_binary_paths(m->unit_file_scope);
if (!paths)
return log_oom();

View File

@ -23,6 +23,8 @@
#include <string.h>
#include "alloc-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "install.h"
#include "log.h"
#include "macro.h"
@ -226,50 +228,48 @@ static char** user_dirs(
static int acquire_generator_dirs(
UnitFileScope scope,
const char *tempdir,
char **generator,
char **generator_early,
char **generator_late) {
_cleanup_(rmdir_and_freep) char *t = NULL;
_cleanup_free_ char *x = NULL, *y = NULL, *z = NULL;
const char *prefix;
assert(generator);
assert(generator_early);
assert(generator_late);
assert(IN_SET(scope, UNIT_FILE_SYSTEM, UNIT_FILE_USER, UNIT_FILE_GLOBAL));
switch (scope) {
if (scope == UNIT_FILE_GLOBAL)
return -EOPNOTSUPP;
case UNIT_FILE_SYSTEM:
prefix = "/run/systemd/";
break;
if (tempdir)
prefix = tempdir;
case UNIT_FILE_USER: {
else if (scope == UNIT_FILE_SYSTEM)
prefix = "/run/systemd";
else if (scope == UNIT_FILE_USER) {
const char *e;
e = getenv("XDG_RUNTIME_DIR");
if (!e)
return -ENXIO;
prefix = strjoina(e, "/systemd/");
break;
prefix = strjoina(e, "/systemd");
}
case UNIT_FILE_GLOBAL:
return -EOPNOTSUPP;
default:
assert_not_reached("Hmm, unexpected scope value.");
}
x = strappend(prefix, "generator");
x = strappend(prefix, "/generator");
if (!x)
return -ENOMEM;
y = strappend(prefix, "generator.early");
y = strappend(prefix, "/generator.early");
if (!y)
return -ENOMEM;
z = strappend(prefix, "generator.late");
z = strappend(prefix, "/generator.late");
if (!z)
return -ENOMEM;
@ -281,31 +281,30 @@ static int acquire_generator_dirs(
return 0;
}
static int acquire_transient_dir(UnitFileScope scope, char **ret) {
static int acquire_transient_dir(
UnitFileScope scope,
const char *tempdir,
char **ret) {
char *transient;
assert(ret);
assert(IN_SET(scope, UNIT_FILE_SYSTEM, UNIT_FILE_USER, UNIT_FILE_GLOBAL));
switch (scope) {
case UNIT_FILE_SYSTEM: {
char *transient;
transient = strdup("/run/systemd/transient");
if (!transient)
return -ENOMEM;
*ret = transient;
return 0;
}
case UNIT_FILE_USER:
return user_runtime_dir(ret, "/systemd/transient");
case UNIT_FILE_GLOBAL:
if (scope == UNIT_FILE_GLOBAL)
return -EOPNOTSUPP;
default:
assert_not_reached("Hmm, unexpected scope value.");
}
if (tempdir)
transient = strjoin(tempdir, "/transient");
else if (scope == UNIT_FILE_SYSTEM)
transient = strdup("/run/systemd/transient");
else
return user_runtime_dir(ret, "/systemd/transient");
if (!transient)
return -ENOMEM;
*ret = transient;
return 0;
}
static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **runtime) {
@ -457,6 +456,7 @@ int lookup_paths_init(
LookupPathsFlags flags,
const char *root_dir) {
_cleanup_(rmdir_and_freep) char *tempdir = NULL;
_cleanup_free_ char
*root = NULL,
*persistent_config = NULL, *runtime_config = NULL,
@ -487,6 +487,12 @@ int lookup_paths_init(
return -ENOMEM;
}
if (flags & LOOKUP_PATHS_TEMPORARY_GENERATED) {
r = mkdtemp_malloc("/tmp/systemd-temporary-XXXXXX", &tempdir);
if (r < 0)
return log_error_errno(r, "Failed to create temporary directory: %m");
}
/* Note: when XDG_RUNTIME_DIR is not set this will not return -ENXIO, but simply set runtime_config to NULL */
r = acquire_config_dirs(scope, &persistent_config, &runtime_config);
if (r < 0)
@ -494,13 +500,14 @@ int lookup_paths_init(
if ((flags & LOOKUP_PATHS_EXCLUDE_GENERATED) == 0) {
/* Note: if XDG_RUNTIME_DIR is not set, this will fail completely with ENXIO */
r = acquire_generator_dirs(scope, &generator, &generator_early, &generator_late);
r = acquire_generator_dirs(scope, tempdir,
&generator, &generator_early, &generator_late);
if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO)
return r;
}
/* Note: if XDG_RUNTIME_DIR is not set, this will fail completely with ENXIO */
r = acquire_transient_dir(scope, &transient);
r = acquire_transient_dir(scope, tempdir, &transient);
if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO)
return r;
@ -669,6 +676,9 @@ int lookup_paths_init(
p->root_dir = root;
root = NULL;
p->temporary_dir = tempdir;
tempdir = NULL;
return 0;
}
@ -811,6 +821,9 @@ void lookup_paths_flush_generator(LookupPaths *p) {
(void) rm_rf(p->generator_early, REMOVE_ROOT);
if (p->generator_late)
(void) rm_rf(p->generator_late, REMOVE_ROOT);
if (p->temporary_dir)
(void) rm_rf(p->temporary_dir, REMOVE_ROOT);
}
char **generator_binary_paths(UnitFileScope scope) {

View File

@ -28,6 +28,7 @@ typedef struct LookupPaths LookupPaths;
typedef enum LookupPathsFlags {
LOOKUP_PATHS_EXCLUDE_GENERATED = 1,
LOOKUP_PATHS_TEMPORARY_GENERATED,
} LookupPathsFlags;
struct LookupPaths {
@ -60,6 +61,9 @@ struct LookupPaths {
/* The root directory prepended to all items above, or NULL */
char *root_dir;
/* A temporary directory when running in test mode, to be nuked */
char *temporary_dir;
};
int lookup_paths_init(LookupPaths *p, UnitFileScope scope, LookupPathsFlags flags, const char *root_dir);