From: Ivan Kruglov Date: Tue, 13 May 2025 18:40:49 +0000 (-0700) Subject: core: Unit Runtime in io.systemd.Unit.List method X-Git-Tag: v258-rc1~479^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c5ff8283b05157dd6125bad839c602cd417ab568;p=thirdparty%2Fsystemd.git core: Unit Runtime in io.systemd.Unit.List method --- diff --git a/src/core/varlink-unit.c b/src/core/varlink-unit.c index 8967cc6bd43..f2ab708b237 100644 --- a/src/core/varlink-unit.c +++ b/src/core/varlink-unit.c @@ -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; diff --git a/src/shared/varlink-io.systemd.Unit.c b/src/shared/varlink-io.systemd.Unit.c index bd8e6cc1c93..5c134ecd5dc 100644 --- a/src/shared/varlink-io.systemd.Unit.c +++ b/src/shared/varlink-io.systemd.Unit.c @@ -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);