#include "sd-json.h"
+#include "bitfield.h"
+#include "condition.h"
+#include "execute.h"
+#include "install.h"
#include "json-util.h"
#include "manager.h"
#include "set.h"
// Socket context
}
+static int can_clean_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+ Unit *u = ASSERT_PTR(userdata);
+ ExecCleanMask mask;
+ int r;
+
+ assert(ret);
+
+ r = unit_can_clean(u, &mask);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to check if unit can be cleaned: %m");
+
+ for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
+ if (!BIT_SET(mask, t))
+ continue;
+
+ r = sd_json_variant_append_arrayb(&v, SD_JSON_BUILD_STRING(exec_resource_type_to_string(t)));
+ if (r < 0)
+ return r;
+ }
+
+ if (FLAGS_SET(mask, EXEC_CLEAN_FDSTORE)) {
+ r = sd_json_variant_append_arrayb(&v, SD_JSON_BUILD_STRING("fdstore"));
+ if (r < 0)
+ return r;
+ }
+
+ *ret = TAKE_PTR(v);
+ return 0;
+}
+
+static int markers_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+ unsigned *markers = ASSERT_PTR(userdata);
+ int r;
+
+ assert(ret);
+
+ BIT_FOREACH(m, *markers) {
+ r = sd_json_variant_append_arrayb(&v, SD_JSON_BUILD_STRING(unit_marker_to_string(m)));
+ if (r < 0)
+ return r;
+ }
+
+ *ret = TAKE_PTR(v);
+ return 0;
+}
+
+static int activation_details_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+ const ActivationDetails *activation_details = userdata;
+ _cleanup_strv_free_ char **pairs = NULL;
+ int r;
+
+ assert(ret);
+
+ /* activation_details_append_pair() gracefully takes activation_details==NULL */
+ r = activation_details_append_pair(activation_details, &pairs);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to get activation details: %m");
+
+ STRV_FOREACH_PAIR(key, value, pairs) {
+ r = sd_json_variant_append_arraybo(&v,
+ SD_JSON_BUILD_PAIR_STRING("type", *key),
+ SD_JSON_BUILD_PAIR_STRING("name", *value));
+ if (r < 0)
+ return r;
+ }
+
+ *ret = TAKE_PTR(v);
+ return 0;
+}
+
+static int unit_runtime_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ Unit *u = ASSERT_PTR(userdata);
+ Unit *f = unit_following(u);
+
+ return sd_json_buildo(
+ ASSERT_PTR(ret),
+ JSON_BUILD_PAIR_STRING_NON_EMPTY("Following", f ? f->id : NULL),
+ SD_JSON_BUILD_PAIR_STRING("LoadState", unit_load_state_to_string(u->load_state)),
+ SD_JSON_BUILD_PAIR_STRING("ActiveState", unit_active_state_to_string(unit_active_state(u))),
+ SD_JSON_BUILD_PAIR_STRING("FreezerState", freezer_state_to_string(u->freezer_state)),
+ SD_JSON_BUILD_PAIR_STRING("SubState", unit_sub_state_to_string(u)),
+ JSON_BUILD_PAIR_STRING_NON_EMPTY("UnitFileState", unit_file_state_to_string(unit_get_unit_file_state(u))),
+ JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("StateChangeTimestamp", &u->state_change_timestamp),
+ JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("ActiveEnterTimestamp", &u->active_enter_timestamp),
+ JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("ActiveExitTimestamp", &u->active_exit_timestamp),
+ JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("InactiveEnterTimestamp", &u->inactive_enter_timestamp),
+ JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("InactiveExitTimestamp", &u->inactive_exit_timestamp),
+ SD_JSON_BUILD_PAIR_BOOLEAN("CanStart", unit_can_start_refuse_manual(u)),
+ SD_JSON_BUILD_PAIR_BOOLEAN("CanStop", unit_can_stop_refuse_manual(u)),
+ SD_JSON_BUILD_PAIR_BOOLEAN("CanReload", unit_can_reload(u)),
+ SD_JSON_BUILD_PAIR_BOOLEAN("CanIsolate", unit_can_isolate_refuse_manual(u)),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("CanClean", can_clean_build_json, u),
+ SD_JSON_BUILD_PAIR_BOOLEAN("CanFreeze", unit_can_freeze(u)),
+ SD_JSON_BUILD_PAIR_BOOLEAN("CanLiveMount", unit_can_live_mount(u, /* error= */ NULL) >= 0),
+ JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("JobId", u->job ? u->job->id : 0),
+ SD_JSON_BUILD_PAIR_BOOLEAN("NeedDaemonReload", unit_need_daemon_reload(u)),
+ SD_JSON_BUILD_PAIR_BOOLEAN("ConditionResult", u->condition_result),
+ SD_JSON_BUILD_PAIR_BOOLEAN("AssertResult", u->assert_result),
+ JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("ConditionTimestamp", &u->condition_timestamp),
+ JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("AssertTimestamp", &u->assert_timestamp),
+ SD_JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(u->invocation_id), "InvocationID", SD_JSON_BUILD_UUID(u->invocation_id)),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("Markers", markers_build_json, &u->markers),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("ActivationDetails", activation_details_build_json, u->activation_details),
+ SD_JSON_BUILD_PAIR_BOOLEAN("DebugInvocation", u->debug_invocation));
+}
+
static int list_unit_one(sd_varlink *link, Unit *unit, bool more) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
int r;
assert(link);
assert(unit);
- r = sd_json_buildo(&v, SD_JSON_BUILD_PAIR_CALLBACK("context", unit_context_build_json, unit));
+ r = sd_json_buildo(
+ &v,
+ SD_JSON_BUILD_PAIR_CALLBACK("context", unit_context_build_json, unit),
+ SD_JSON_BUILD_PAIR_CALLBACK("runtime", unit_runtime_build_json, unit));
if (r < 0)
return r;
SD_VARLINK_FIELD_COMMENT("Whether this unit is perpetual"),
SD_VARLINK_DEFINE_FIELD(Perpetual, SD_VARLINK_BOOL, 0));
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+ ActivationDetails,
+ SD_VARLINK_FIELD_COMMENT("Trigger unit type"),
+ SD_VARLINK_DEFINE_FIELD(type, SD_VARLINK_STRING, 0),
+ SD_VARLINK_FIELD_COMMENT("Trigger unit name"),
+ SD_VARLINK_DEFINE_FIELD(name, SD_VARLINK_STRING, 0));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+ UnitRuntime,
+ SD_VARLINK_FIELD_COMMENT("If not empty, the field contains the name of another unit that this unit follows in state"),
+ SD_VARLINK_DEFINE_FIELD(Following, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Reflects whether the configuration file of this unit has been loaded"),
+ SD_VARLINK_DEFINE_FIELD(LoadState, SD_VARLINK_STRING, 0),
+ SD_VARLINK_FIELD_COMMENT("Reflects whether the unit is currently active or not"),
+ SD_VARLINK_DEFINE_FIELD(ActiveState, SD_VARLINK_STRING, 0),
+ SD_VARLINK_FIELD_COMMENT("Reflects whether the unit is currently frozen or not"),
+ SD_VARLINK_DEFINE_FIELD(FreezerState, SD_VARLINK_STRING, 0),
+ SD_VARLINK_FIELD_COMMENT("Reflect more fine-grained state that is unit-type-specific"),
+ SD_VARLINK_DEFINE_FIELD(SubState, SD_VARLINK_STRING, 0),
+ SD_VARLINK_FIELD_COMMENT("Reflects the install state of the unit file"),
+ SD_VARLINK_DEFINE_FIELD(UnitFileState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Timestamp when the firmware first began execution"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(StateChangeTimestamp, Timestamp, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Timestamp when the unit entered active state"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(ActiveEnterTimestamp, Timestamp, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Timestamp when the unit exited active state"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(ActiveExitTimestamp, Timestamp, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Timestamp when the unit entered inactive state"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(InactiveEnterTimestamp, Timestamp, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Timestamp when the unit exited inactive state"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(InactiveExitTimestamp, Timestamp, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Reflects whether the unit can be started or not"),
+ SD_VARLINK_DEFINE_FIELD(CanStart, SD_VARLINK_BOOL, 0),
+ SD_VARLINK_FIELD_COMMENT("Reflects whether the unit can be stopped or not"),
+ SD_VARLINK_DEFINE_FIELD(CanStop, SD_VARLINK_BOOL, 0),
+ SD_VARLINK_FIELD_COMMENT("Reflects whether the unit can be reloaded or not"),
+ SD_VARLINK_DEFINE_FIELD(CanReload, SD_VARLINK_BOOL, 0),
+ SD_VARLINK_FIELD_COMMENT("Reflects whether the unit may be started in isolation mode"),
+ SD_VARLINK_DEFINE_FIELD(CanIsolate, SD_VARLINK_BOOL, 0),
+ SD_VARLINK_FIELD_COMMENT("Returns which unit resources can be cleaned up"),
+ SD_VARLINK_DEFINE_FIELD(CanClean, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Whether the unit supports the freeze operation"),
+ SD_VARLINK_DEFINE_FIELD(CanFreeze, SD_VARLINK_BOOL, 0),
+ SD_VARLINK_FIELD_COMMENT("Whether the unit supports live mounting"),
+ SD_VARLINK_DEFINE_FIELD(CanLiveMount, SD_VARLINK_BOOL, 0),
+ SD_VARLINK_FIELD_COMMENT("The job ID of the job currently scheduled or being executed for this unit, if there is any."),
+ SD_VARLINK_DEFINE_FIELD(JobId, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Whether the configuration file this unit is loaded from (i.e. FragmentPath or SourcePath) has changed since the configuration was read and hence whether a configuration reload is recommended"),
+ SD_VARLINK_DEFINE_FIELD(NeedDaemonReload, SD_VARLINK_BOOL, 0),
+ SD_VARLINK_FIELD_COMMENT("Condition result of the last time the configured conditions of this unit were checked"),
+ SD_VARLINK_DEFINE_FIELD(ConditionResult, SD_VARLINK_BOOL, 0),
+ SD_VARLINK_FIELD_COMMENT("Assert result of the last time the configured asserts of this unit were checked"),
+ SD_VARLINK_DEFINE_FIELD(AssertResult, SD_VARLINK_BOOL, 0),
+ SD_VARLINK_FIELD_COMMENT("The last time the configured conditions of the unit have been checked"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(ConditionTimestamp, Timestamp, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The last time the configured asserts of the unit have been checked"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(AssertTimestamp, Timestamp, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Current invocation ID"),
+ SD_VARLINK_DEFINE_FIELD(InvocationID, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Reflects whether the unit has been marked for reload, restart, etc."),
+ SD_VARLINK_DEFINE_FIELD(Markers, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Provides details about why a unit was activated"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(ActivationDetails, ActivationDetails, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("When true, logs about this unit will be at debug level regardless of other log level settings"),
+ SD_VARLINK_DEFINE_FIELD(DebugInvocation, SD_VARLINK_BOOL, 0));
+
static SD_VARLINK_DEFINE_ERROR(NoSuchUnit);
static SD_VARLINK_DEFINE_METHOD_FULL(
List,
SD_VARLINK_SUPPORTS_MORE,
SD_VARLINK_FIELD_COMMENT("Configuration of the unit"),
- SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(context, UnitContext, 0));
+ SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(context, UnitContext, 0),
+ SD_VARLINK_FIELD_COMMENT("Runtime information of the unit"),
+ SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(runtime, UnitRuntime, 0));
SD_VARLINK_DEFINE_INTERFACE(
io_systemd_Unit,
&vl_type_Condition,
SD_VARLINK_SYMBOL_COMMENT("An object to represent a unit's context"),
&vl_type_UnitContext,
+ SD_VARLINK_SYMBOL_COMMENT("An object to represent a unit's runtime information"),
+ &vl_type_UnitRuntime,
+ SD_VARLINK_SYMBOL_COMMENT("A timestamp object consisting of both CLOCK_REALTIME and CLOCK_MONOTONIC timestamps"),
+ &vl_type_Timestamp,
+ SD_VARLINK_SYMBOL_COMMENT("An object to represent a unit's activation details"),
+ &vl_type_ActivationDetails,
SD_VARLINK_SYMBOL_COMMENT("No matching unit found"),
&vl_error_NoSuchUnit);