systemctl: introduce reset-maintenance command

This commit is contained in:
Lennart Poettering 2010-07-18 04:58:01 +02:00
parent b9975629f0
commit 5632e3743d
18 changed files with 249 additions and 17 deletions

4
fixme
View File

@ -47,8 +47,6 @@
* debian deadlock when partition auf noauto is.
* maintenance units müssen vergessen werden
* fingerprint.target, wireless.target, gps.target
* fix merging of device units
@ -57,6 +55,8 @@
* pahole
* color aus bei stdout auf !tty
External:
* default.target must be %ghosted...

View File

@ -314,6 +314,25 @@
properties of the job is
shown.</para></listitem>
</varlistentry>
<varlistentry>
<term><command>reset-maintenance [NAME...]</command></term>
<listitem><para>Reset maintenance
state of the specified units, or if no
unit name is passed of all units. When
a unit fails in some way (i.e. process
exiting with non-zero error code,
terminating abnormally or timing out)
it will automatically enter
maintenance state and its exit codes
and status is recorded for
introspection by the administrator
until the service is restarted or
reset with this
command.</para></listitem>
</varlistentry>
<varlistentry>
<term><command>load [NAME...]</command></term>

View File

@ -226,7 +226,7 @@
<para>systemd provides a dependency system between
various entities called "units". Units encapsulate
various objects that are relevant for system boot-up
and maintainance. The majority of units are configured
and maintenance. The majority of units are configured
in unit configuration files, whose syntax and basic
set of options is described in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,

View File

@ -791,6 +791,17 @@ static void automount_shutdown(Manager *m) {
close_nointr_nofail(m->dev_autofs_fd);
}
static void automount_reset_maintenance(Unit *u) {
Automount *a = AUTOMOUNT(u);
assert(a);
if (a->state == AUTOMOUNT_MAINTENANCE)
automount_set_state(a, AUTOMOUNT_DEAD);
a->failure = false;
}
static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
[AUTOMOUNT_DEAD] = "dead",
[AUTOMOUNT_WAITING] = "waiting",
@ -827,6 +838,8 @@ const UnitVTable automount_vtable = {
.fd_event = automount_fd_event,
.reset_maintenance = automount_reset_maintenance,
.bus_message_handler = bus_automount_message_handler,
.shutdown = automount_shutdown

View File

@ -72,11 +72,15 @@
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"ResetMaintenanceUnit\">\n" \
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
" </method>\n" \
" <method name=\"GetJob\">\n" \
" <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
" <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"ClearJobs\"/>\n" \
" <method name=\"ResetMaintenance\"/>\n" \
" <method name=\"ListUnits\">\n" \
" <arg name=\"units\" type=\"a(sssssouso)\" direction=\"out\"/>\n" \
" </method>\n" \
@ -362,6 +366,34 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetMaintenance")) {
manager_reset_maintenance(m);
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetMaintenanceUnit")) {
const char *name;
Unit *u;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
return bus_send_error_reply(m, connection, message, &error, -EINVAL);
if (!(u = manager_get_unit(m, name))) {
dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
return bus_send_error_reply(m, connection, message, &error, -ENOENT);
}
unit_reset_maintenance(u);
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
DBusMessageIter iter, sub;
Iterator i;
@ -733,7 +765,6 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
} else
return bus_default_message_handler(m, connection, message, NULL, properties);
if (job_type != _JOB_TYPE_INVALID) {
const char *name, *smode;
JobMode mode;

View File

@ -298,6 +298,13 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ReloadOrTryRestart")) {
reload_if_possible = true;
job_type = JOB_TRY_RESTART;
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ResetMaintenance")) {
unit_reset_maintenance(u);
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
} else if (UNIT_VTABLE(u)->bus_message_handler)
return UNIT_VTABLE(u)->bus_message_handler(u, connection, message);
else

View File

@ -56,6 +56,7 @@
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"ResetMaintenance\"/>\n" \
" <signal name=\"Changed\"/>\n" \
" <property name=\"Id\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Names\" type=\"as\" access=\"read\"/>\n" \

View File

@ -2466,6 +2466,16 @@ bool manager_is_booting_or_shutting_down(Manager *m) {
return false;
}
void manager_reset_maintenance(Manager *m) {
Unit *u;
Iterator i;
assert(m);
HASHMAP_FOREACH(u, m->units, i)
unit_reset_maintenance(u);
}
static const char* const manager_running_as_table[_MANAGER_RUNNING_AS_MAX] = {
[MANAGER_SYSTEM] = "system",
[MANAGER_SESSION] = "session"

View File

@ -247,6 +247,8 @@ int manager_reload(Manager *m);
bool manager_is_booting_or_shutting_down(Manager *m);
void manager_reset_maintenance(Manager *m);
const char *manager_running_as_to_string(ManagerRunningAs i);
ManagerRunningAs manager_running_as_from_string(const char *s);

View File

@ -1538,6 +1538,17 @@ finish:
return r;
}
static void mount_reset_maintenance(Unit *u) {
Mount *m = MOUNT(u);
assert(m);
if (m->state == MOUNT_MAINTENANCE)
mount_set_state(m, MOUNT_DEAD);
m->failure = false;
}
static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
[MOUNT_DEAD] = "dead",
[MOUNT_MOUNTING] = "mounting",
@ -1595,6 +1606,8 @@ const UnitVTable mount_vtable = {
.sigchld_event = mount_sigchld_event,
.timer_event = mount_timer_event,
.reset_maintenance = mount_reset_maintenance,
.bus_message_handler = bus_mount_message_handler,
.enumerate = mount_enumerate,

View File

@ -560,6 +560,17 @@ fail:
log_error("Failed find path unit: %s", strerror(-r));
}
static void path_reset_maintenance(Unit *u) {
Path *p = PATH(u);
assert(p);
if (p->state == PATH_MAINTENANCE)
path_set_state(p, PATH_DEAD);
p->failure = false;
}
static const char* const path_state_table[_PATH_STATE_MAX] = {
[PATH_DEAD] = "dead",
[PATH_WAITING] = "waiting",
@ -598,5 +609,7 @@ const UnitVTable path_vtable = {
.fd_event = path_fd_event,
.reset_maintenance = path_reset_maintenance,
.bus_message_handler = bus_path_message_handler
};

View File

@ -2734,6 +2734,17 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock) {
return 0;
}
static void service_reset_maintenance(Unit *u) {
Service *s = SERVICE(u);
assert(s);
if (s->state == SERVICE_MAINTENANCE)
service_set_state(s, SERVICE_DEAD);
s->failure = false;
}
static const char* const service_state_table[_SERVICE_STATE_MAX] = {
[SERVICE_DEAD] = "dead",
[SERVICE_START_PRE] = "start-pre",
@ -2821,6 +2832,8 @@ const UnitVTable service_vtable = {
.sigchld_event = service_sigchld_event,
.timer_event = service_timer_event,
.reset_maintenance = service_reset_maintenance,
.cgroup_notify_empty = service_cgroup_notify_event,
.notify_message = service_notify_message,

View File

@ -1698,6 +1698,17 @@ void socket_connection_unref(Socket *s) {
log_debug("%s: One connection closed, %u left.", s->meta.id, s->n_connections);
}
static void socket_reset_maintenance(Unit *u) {
Socket *s = SOCKET(u);
assert(s);
if (s->state == SOCKET_MAINTENANCE)
socket_set_state(s, SOCKET_DEAD);
s->failure = false;
}
static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
[SOCKET_DEAD] = "dead",
[SOCKET_START_PRE] = "start-pre",
@ -1750,5 +1761,7 @@ const UnitVTable socket_vtable = {
.sigchld_event = socket_sigchld_event,
.timer_event = socket_timer_event,
.reset_maintenance = socket_reset_maintenance,
.bus_message_handler = bus_socket_message_handler
};

View File

@ -542,14 +542,6 @@ static void swap_shutdown(Manager *m) {
}
}
static const char* const swap_state_table[_SWAP_STATE_MAX] = {
[SWAP_DEAD] = "dead",
[SWAP_ACTIVE] = "active",
[SWAP_MAINTENANCE] = "maintenance"
};
DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
static int swap_enumerate(Manager *m) {
int r;
assert(m);
@ -564,6 +556,23 @@ static int swap_enumerate(Manager *m) {
return r;
}
static void swap_reset_maintenance(Unit *u) {
Swap *s = SWAP(u);
assert(s);
if (s->state == SWAP_MAINTENANCE)
swap_set_state(s, SWAP_DEAD);
}
static const char* const swap_state_table[_SWAP_STATE_MAX] = {
[SWAP_DEAD] = "dead",
[SWAP_ACTIVE] = "active",
[SWAP_MAINTENANCE] = "maintenance"
};
DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
const UnitVTable swap_vtable = {
.suffix = ".swap",
@ -592,6 +601,8 @@ const UnitVTable swap_vtable = {
.bus_message_handler = bus_swap_message_handler,
.reset_maintenance = swap_reset_maintenance,
.enumerate = swap_enumerate,
.shutdown = swap_shutdown
};

View File

@ -2639,10 +2639,11 @@ static int clear_jobs(DBusConnection *bus, char **args, unsigned n) {
assert(arg_action == ACTION_SYSTEMCTL);
method =
streq(args[0], "clear-jobs") ? "ClearJobs" :
streq(args[0], "daemon-reload") ? "Reload" :
streq(args[0], "daemon-reexec") ? "Reexecute" :
"Exit";
streq(args[0], "clear-jobs") ? "ClearJobs" :
streq(args[0], "daemon-reload") ? "Reload" :
streq(args[0], "daemon-reexec") ? "Reexecute" :
streq(args[0], "reset-maintenance") ? "ResetMaintenance" :
"Exit";
}
if (!(m = dbus_message_new_method_call(
@ -2682,6 +2683,63 @@ finish:
return r;
}
static int reset_maintenance(DBusConnection *bus, char **args, unsigned n) {
DBusMessage *m = NULL, *reply = NULL;
unsigned i;
int r;
DBusError error;
assert(bus);
dbus_error_init(&error);
if (n <= 1)
return clear_jobs(bus, args, n);
for (i = 1; i < n; i++) {
if (!(m = dbus_message_new_method_call(
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"ResetMaintenanceUnit"))) {
log_error("Could not allocate message.");
r = -ENOMEM;
goto finish;
}
if (!dbus_message_append_args(m,
DBUS_TYPE_STRING, args + i,
DBUS_TYPE_INVALID)) {
log_error("Could not append arguments to message.");
r = -ENOMEM;
goto finish;
}
if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
log_error("Failed to issue method call: %s", error.message);
r = -EIO;
goto finish;
}
dbus_message_unref(m);
dbus_message_unref(reply);
m = reply = NULL;
}
r = 0;
finish:
if (m)
dbus_message_unref(m);
if (reply)
dbus_message_unref(reply);
dbus_error_free(&error);
return r;
}
static int show_enviroment(DBusConnection *bus, char **args, unsigned n) {
DBusMessage *m = NULL, *reply = NULL;
DBusError error;
@ -2832,7 +2890,7 @@ finish:
static int systemctl_help(void) {
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Send control commands to the systemd manager.\n\n"
"Send control commands to or query the systemd manager.\n\n"
" -h --help Show this help\n"
" -t --type=TYPE List only units of a particular type\n"
" -p --property=NAME Show only properties by this name\n"
@ -2862,6 +2920,8 @@ static int systemctl_help(void) {
" status [NAME...] Show status of one or more units\n"
" show [NAME...|JOB...] Show properties of one or more\n"
" units/jobs/manager\n"
" reset-maintenance [NAME...] Reset maintenance state for all, one\n"
" or more units\n"
" load [NAME...] Load one or more units\n"
" list-jobs List jobs\n"
" cancel [JOB...] Cancel one or more jobs\n"
@ -3579,6 +3639,7 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[]) {
{ "default", EQUAL, 1, start_special },
{ "rescue", EQUAL, 1, start_special },
{ "emergency", EQUAL, 1, start_special },
{ "reset-maintenance", MORE, 1, reset_maintenance },
};
int left;

View File

@ -450,6 +450,17 @@ fail:
log_error("Failed find timer unit: %s", strerror(-r));
}
static void timer_reset_maintenance(Unit *u) {
Timer *t = TIMER(u);
assert(t);
if (t->state == TIMER_MAINTENANCE)
timer_set_state(t, TIMER_DEAD);
t->failure = false;
}
static const char* const timer_state_table[_TIMER_STATE_MAX] = {
[TIMER_DEAD] = "dead",
[TIMER_WAITING] = "waiting",
@ -492,5 +503,7 @@ const UnitVTable timer_vtable = {
.timer_event = timer_timer_event,
.reset_maintenance = timer_reset_maintenance,
.bus_message_handler = bus_timer_message_handler
};

View File

@ -2071,6 +2071,13 @@ bool unit_need_daemon_reload(Unit *u) {
timespec_load(&st.st_mtim) != u->meta.fragment_mtime;
}
void unit_reset_maintenance(Unit *u) {
assert(u);
if (UNIT_VTABLE(u)->reset_maintenance)
UNIT_VTABLE(u)->reset_maintenance(u);
}
static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
[UNIT_SERVICE] = "service",
[UNIT_TIMER] = "timer",

View File

@ -290,6 +290,9 @@ struct UnitVTable {
void (*sigchld_event)(Unit *u, pid_t pid, int code, int status);
void (*timer_event)(Unit *u, uint64_t n_elapsed, Watch *w);
/* Reset maintenance state if we are in maintainance state */
void (*reset_maintenance)(Unit *u);
/* Called whenever any of the cgroups this unit watches for
* ran empty */
void (*cgroup_notify_empty)(Unit *u);
@ -467,6 +470,8 @@ void unit_status_printf(Unit *u, const char *format, ...);
bool unit_need_daemon_reload(Unit *u);
void unit_reset_maintenance(Unit *u);
const char *unit_type_to_string(UnitType i);
UnitType unit_type_from_string(const char *s);