units: introduce new Documentation= field and make use of it everywhere
This should help making the boot process a bit easier to explore and understand for the administrator. The simple idea is that "systemctl status" now shows a link to documentation alongside the other status and decriptionary information of a service. This patch adds the necessary fields to all our shipped units if we have proper documentation for them.
This commit is contained in:
@@ -808,6 +808,7 @@ const BusProperty bus_unit_properties[] = {
|
||||
{ "PropagateReloadTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATE_RELOAD_TO]), true },
|
||||
{ "PropagateReloadFrom", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATE_RELOAD_FROM]), true },
|
||||
{ "RequiresMountsFor", bus_property_append_strv, "as", offsetof(Unit, requires_mounts_for), true },
|
||||
{ "Documentation", bus_property_append_strv, "as", offsetof(Unit, documentation), true },
|
||||
{ "Description", bus_unit_append_description, "s", 0 },
|
||||
{ "LoadState", bus_unit_append_load_state, "s", offsetof(Unit, load_state) },
|
||||
{ "ActiveState", bus_unit_append_active_state, "s", 0 },
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
" <property name=\"PropagateReloadFrom\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"RequiresMountsFor\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"Description\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"Documentation\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"LoadState\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"ActiveState\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"SubState\" type=\"s\" access=\"read\"/>\n" \
|
||||
|
||||
@@ -92,6 +92,7 @@ $1.ControlGroupPersistent, config_parse_tristate, 0,
|
||||
)m4_dnl
|
||||
Unit.Names, config_parse_unit_names, 0, 0
|
||||
Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)
|
||||
Unit.Documentation, config_parse_documentation, 0, offsetof(Unit, documentation)
|
||||
Unit.Requires, config_parse_unit_deps, UNIT_REQUIRES, 0
|
||||
Unit.RequiresOverridable, config_parse_unit_deps, UNIT_REQUIRES_OVERRIDABLE, 0
|
||||
Unit.Requisite, config_parse_unit_deps, UNIT_REQUISITE, 0
|
||||
|
||||
@@ -2063,6 +2063,43 @@ int config_parse_unit_requires_mounts_for(
|
||||
return r;
|
||||
}
|
||||
|
||||
int config_parse_documentation(
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
Unit *u = userdata;
|
||||
int r;
|
||||
char **a, **b;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(u);
|
||||
|
||||
r = config_parse_unit_strv_printf(filename, line, section, lvalue, ltype, rvalue, data, userdata);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (a = b = u->documentation; a && *a; a++) {
|
||||
|
||||
if (is_valid_documentation_url(*a))
|
||||
*(b++) = *a;
|
||||
else {
|
||||
log_error("[%s:%u] Invalid URL, ignoring: %s", filename, line, *a);
|
||||
free(*a);
|
||||
}
|
||||
}
|
||||
*b = NULL;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#define FOLLOW_MAX 8
|
||||
|
||||
static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
|
||||
|
||||
@@ -36,6 +36,7 @@ int config_parse_unit_names(const char *filename, unsigned line, const char *sec
|
||||
int config_parse_unit_string_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_unit_strv_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_unit_path_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_documentation(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_socket_listen(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_socket_bind(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_exec_nice(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
||||
+5
-3
@@ -397,6 +397,7 @@ void unit_free(Unit *u) {
|
||||
cgroup_attribute_free_list(u->cgroup_attributes);
|
||||
|
||||
free(u->description);
|
||||
strv_free(u->documentation);
|
||||
free(u->fragment_path);
|
||||
free(u->instance);
|
||||
|
||||
@@ -624,7 +625,7 @@ const char *unit_description(Unit *u) {
|
||||
}
|
||||
|
||||
void unit_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
char *t;
|
||||
char *t, **j;
|
||||
UnitDependency d;
|
||||
Iterator i;
|
||||
char *p2;
|
||||
@@ -672,6 +673,9 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
SET_FOREACH(t, u->names, i)
|
||||
fprintf(f, "%s\tName: %s\n", prefix, t);
|
||||
|
||||
STRV_FOREACH(j, u->documentation)
|
||||
fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);
|
||||
|
||||
if ((following = unit_following(u)))
|
||||
fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
|
||||
|
||||
@@ -698,8 +702,6 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
}
|
||||
|
||||
if (!strv_isempty(u->requires_mounts_for)) {
|
||||
char **j;
|
||||
|
||||
fprintf(f,
|
||||
"%s\tRequiresMountsFor:", prefix);
|
||||
|
||||
|
||||
@@ -157,6 +157,7 @@ struct Unit {
|
||||
char **requires_mounts_for;
|
||||
|
||||
char *description;
|
||||
char **documentation;
|
||||
|
||||
char *fragment_path; /* if loaded from a config file this is the primary path to it */
|
||||
usec_t fragment_mtime;
|
||||
|
||||
Reference in New Issue
Block a user