chiark / gitweb /
condition: take a timestamp and store last result of conditions
authorLennart Poettering <lennart@poettering.net>
Wed, 9 Mar 2011 22:58:17 +0000 (23:58 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 9 Mar 2011 22:58:17 +0000 (23:58 +0100)
TODO
src/dbus-unit.h
src/systemctl.c
src/unit.c
src/unit.h

diff --git a/TODO b/TODO
index a8b8797802c73dfaf4f89a70b1e4cb8b888511aa..935978216a8fb6f00700dd822571227320236afd 100644 (file)
--- a/TODO
+++ b/TODO
@@ -26,8 +26,6 @@ Features:
 
 * consider services with no [Install] section and stored in /lib enabled by "systemctl is-enabled"
 
-* store time when conditions where checked to inform admins about whether a unit was considered at all
-
 * consider services with any kind of link in /etc/systemd/system enabled
 
 * show failure error string in "systemctl status"
index 4e46fc4825a575ec790b07eb2dfc86068da9815f..efb61797f40521efdb976b7c3e540a7d438b8c35 100644 (file)
         "  <property name=\"ControlGroup\" type=\"as\" access=\"read\"/>\n" \
         "  <property name=\"NeedDaemonReload\" type=\"b\" access=\"read\"/>\n" \
         "  <property name=\"JobTimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"ConditionTimestamp\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"ConditionResult\" type=\"b\" access=\"read\"/>\n" \
         " </interface>\n"
 
 #define BUS_UNIT_INTERFACES_LIST                \
         { "org.freedesktop.systemd1.Unit", "ActiveState",          bus_unit_append_active_state,   "s",    u                                 }, \
         { "org.freedesktop.systemd1.Unit", "SubState",             bus_unit_append_sub_state,      "s",    u                                 }, \
         { "org.freedesktop.systemd1.Unit", "FragmentPath",         bus_property_append_string,     "s",    u->meta.fragment_path             }, \
-        { "org.freedesktop.systemd1.Unit", "InactiveExitTimestamp",bus_property_append_uint64,     "t",    &u->meta.inactive_exit_timestamp.realtime  }, \
-        { "org.freedesktop.systemd1.Unit", "ActiveEnterTimestamp", bus_property_append_uint64,     "t",    &u->meta.active_enter_timestamp.realtime }, \
-        { "org.freedesktop.systemd1.Unit", "ActiveExitTimestamp",  bus_property_append_uint64,     "t",    &u->meta.active_exit_timestamp.realtime    }, \
-        { "org.freedesktop.systemd1.Unit", "InactiveEnterTimestamp",bus_property_append_uint64,    "t",    &u->meta.inactive_enter_timestamp.realtime }, \
+        { "org.freedesktop.systemd1.Unit", "InactiveExitTimestamp",bus_property_append_usec,       "t",    &u->meta.inactive_exit_timestamp.realtime  }, \
+        { "org.freedesktop.systemd1.Unit", "ActiveEnterTimestamp", bus_property_append_usec,       "t",    &u->meta.active_enter_timestamp.realtime   }, \
+        { "org.freedesktop.systemd1.Unit", "ActiveExitTimestamp",  bus_property_append_usec,       "t",    &u->meta.active_exit_timestamp.realtime    }, \
+        { "org.freedesktop.systemd1.Unit", "InactiveEnterTimestamp",bus_property_append_usec,      "t",    &u->meta.inactive_enter_timestamp.realtime }, \
         { "org.freedesktop.systemd1.Unit", "CanStart",             bus_unit_append_can_start,      "b",    u                                 }, \
         { "org.freedesktop.systemd1.Unit", "CanStop",              bus_unit_append_can_stop,       "b",    u                                 }, \
         { "org.freedesktop.systemd1.Unit", "CanReload",            bus_unit_append_can_reload,     "b",    u                                 }, \
         { "org.freedesktop.systemd1.Unit", "DefaultControlGroup",  bus_unit_append_default_cgroup, "s",    u                                 }, \
         { "org.freedesktop.systemd1.Unit", "ControlGroup",         bus_unit_append_cgroups,        "as",   u                                 }, \
         { "org.freedesktop.systemd1.Unit", "NeedDaemonReload",     bus_unit_append_need_daemon_reload, "b", u                                }, \
-        { "org.freedesktop.systemd1.Unit", "JobTimeoutUSec",       bus_property_append_usec,       "t",    &u->meta.job_timeout              }
+        { "org.freedesktop.systemd1.Unit", "JobTimeoutUSec",       bus_property_append_usec,       "t",    &u->meta.job_timeout              }, \
+        { "org.freedesktop.systemd1.Unit", "ConditionTimestamp",   bus_property_append_usec,       "t",    &u->meta.condition_timestamp.realtime }, \
+        { "org.freedesktop.systemd1.Unit", "ConditionResult",      bus_property_append_bool,       "b",    &u->meta.condition_result         }
 
 int bus_unit_append_names(Manager *m, DBusMessageIter *i, const char *property, void *data);
 int bus_unit_append_following(Manager *m, DBusMessageIter *i, const char *property, void *data);
index 63e74d904a93d0cceac7c3ac3d80fd17080b3b70..5b205fec56d9f12a746876c0a148f88fdad29725 100644 (file)
@@ -1831,6 +1831,9 @@ typedef struct UnitStatusInfo {
 
         int exit_code, exit_status;
 
+        usec_t condition_timestamp;
+        bool condition_result;
+
         /* Socket */
         unsigned n_accepted;
         unsigned n_connections;
@@ -1922,6 +1925,16 @@ static void print_status_info(UnitStatusInfo *i) {
         else
                 printf("\n");
 
+        if (!i->condition_result && i->condition_timestamp > 0) {
+                s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
+                s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
+
+                if (s1)
+                        printf("\t          start condition failed at %s; %s\n", s2, s1);
+                else if (s2)
+                        printf("\t          start condition failed at %s\n", s2);
+        }
+
         if (i->sysfs_path)
                 printf("\t  Device: %s\n", i->sysfs_path);
         if (i->where)
@@ -2117,6 +2130,8 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
                         i->accept = b;
                 else if (streq(name, "NeedDaemonReload"))
                         i->need_daemon_reload = b;
+                else if (streq(name, "ConditionResult"))
+                        i->condition_result = b;
 
                 break;
         }
@@ -2174,6 +2189,8 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
                         i->inactive_exit_timestamp = (usec_t) u;
                 else if (streq(name, "ActiveExitTimestamp"))
                         i->active_exit_timestamp = (usec_t) u;
+                else if (streq(name, "ConditionTimestamp"))
+                        i->condition_timestamp = (usec_t) u;
 
                 break;
         }
index 450b190c0eb17ef9655ce66f3abbfcf2e8fe6499..117af4df4477700d06c4a88c2732a5236d4c6e67 100644 (file)
@@ -825,6 +825,15 @@ fail:
         return r;
 }
 
+bool unit_condition_test(Unit *u) {
+        assert(u);
+
+        dual_timestamp_get(&u->meta.condition_timestamp);
+        u->meta.condition_result = condition_test_list(u->meta.conditions);
+
+        return u->meta.condition_result;
+}
+
 /* Errors:
  *         -EBADR:     This unit type does not support starting.
  *         -EALREADY:  Unit is already started.
@@ -849,7 +858,7 @@ int unit_start(Unit *u) {
                 return -EALREADY;
 
         /* If the conditions failed, don't do anything at all */
-        if (!condition_test_list(u->meta.conditions)) {
+        if (!unit_condition_test(u)) {
                 log_debug("Starting of %s requested but condition failed. Ignoring.", u->meta.id);
                 return -EALREADY;
         }
index 5f55a89da8d7f456181b2df90347689ad1369c9a..9b7eb5e854ca3c8bc0c59336f7418734e24e2760 100644 (file)
@@ -160,6 +160,8 @@ struct Meta {
         /* Conditions to check */
         LIST_HEAD(Condition, conditions);
 
+        dual_timestamp condition_timestamp;
+
         dual_timestamp inactive_exit_timestamp;
         dual_timestamp active_enter_timestamp;
         dual_timestamp active_exit_timestamp;
@@ -208,6 +210,9 @@ struct Meta {
         /* Allow isolation requests */
         bool allow_isolate;
 
+        /* Did the last condition check suceed? */
+        bool condition_result;
+
         bool in_load_queue:1;
         bool in_dbus_queue:1;
         bool in_cleanup_queue:1;
@@ -513,6 +518,8 @@ bool unit_name_is_valid(const char *n, bool template_ok);
 
 void unit_trigger_on_failure(Unit *u);
 
+bool unit_condition_test(Unit *u);
+
 const char *unit_load_state_to_string(UnitLoadState i);
 UnitLoadState unit_load_state_from_string(const char *s);