core: Unit Runtime in io.systemd.Unit.List method

This commit is contained in:
Ivan Kruglov
2025-05-27 01:16:42 -07:00
parent 472abf7bec
commit c5ff8283b0
2 changed files with 192 additions and 2 deletions
+117 -1
View File
@@ -2,6 +2,10 @@
#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"
@@ -183,6 +187,115 @@ static int unit_context_build_json(sd_json_variant **ret, const char *name, void
// 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;
@@ -190,7 +303,10 @@ static int list_unit_one(sd_varlink *link, Unit *unit, bool more) {
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;
+75 -1
View File
@@ -154,13 +154,81 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
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,
@@ -172,5 +240,11 @@ SD_VARLINK_DEFINE_INTERFACE(
&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);