mirror of
https://github.com/systemd/systemd.git
synced 2025-03-31 14:50:15 +03:00
systemctl: introduce reset-maintenance command
This commit is contained in:
parent
b9975629f0
commit
5632e3743d
4
fixme
4
fixme
@ -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...
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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" \
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
||||
|
13
src/mount.c
13
src/mount.c
@ -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,
|
||||
|
13
src/path.c
13
src/path.c
@ -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
|
||||
};
|
||||
|
@ -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,
|
||||
|
||||
|
13
src/socket.c
13
src/socket.c
@ -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
|
||||
};
|
||||
|
27
src/swap.c
27
src/swap.c
@ -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
|
||||
};
|
||||
|
@ -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;
|
||||
|
13
src/timer.c
13
src/timer.c
@ -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
|
||||
};
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user