mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-10-28 20:25:25 +03:00
systemctl: add new "get-cgroup-attr" to query current cgroup attribute value
Also adds a pair of bus calls for this to the daemon.
This commit is contained in:
parent
d54110d11d
commit
d2a3097582
@ -25,8 +25,7 @@
|
||||
|
||||
int cgroup_attribute_apply(CGroupAttribute *a, CGroupBonding *b) {
|
||||
int r;
|
||||
char *path = NULL;
|
||||
char *v = NULL;
|
||||
_cleanup_free_ char *path = NULL, *v = NULL;
|
||||
|
||||
assert(a);
|
||||
|
||||
@ -41,18 +40,13 @@ int cgroup_attribute_apply(CGroupAttribute *a, CGroupBonding *b) {
|
||||
}
|
||||
|
||||
r = cg_get_path(a->controller, b->path, a->name, &path);
|
||||
if (r < 0) {
|
||||
free(v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = write_one_line_file(path, v ? v : a->value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to write '%s' to %s: %s", v ? v : a->value, path, strerror(-r));
|
||||
|
||||
free(path);
|
||||
free(v);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -102,15 +102,10 @@
|
||||
" <method name=\"ResetFailedUnit\">\n" \
|
||||
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"SetUnitControlGroups\">\n" \
|
||||
" <method name=\"GetUnitControlGroupAttributes\">\n" \
|
||||
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"UnsetUnitControlGroups\">\n" \
|
||||
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
|
||||
" <arg name=\"attributes\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"values\" type=\"as\" direction=\"out\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"SetUnitControlGroupAttributes\">\n" \
|
||||
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
|
||||
@ -122,6 +117,16 @@
|
||||
" <arg name=\"attributes\" type=\"a(ss)\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"SetUnitControlGroups\">\n" \
|
||||
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"UnsetUnitControlGroups\">\n" \
|
||||
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
|
||||
" </method>\n" \
|
||||
" <method name=\"GetJob\">\n" \
|
||||
" <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
|
||||
@ -979,6 +984,38 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitControlGroupAttributes")) {
|
||||
const char *name;
|
||||
Unit *u;
|
||||
DBusMessageIter iter;
|
||||
_cleanup_strv_free_ char **list = NULL;
|
||||
|
||||
if (!dbus_message_iter_init(message, &iter))
|
||||
goto oom;
|
||||
|
||||
r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, NULL, r);
|
||||
|
||||
u = manager_get_unit(m, name);
|
||||
if (!u) {
|
||||
dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
|
||||
return bus_send_error_reply(connection, message, &error, -ENOENT);
|
||||
}
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
|
||||
r = bus_unit_cgroup_attribute_get(u, &iter, &list);
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, NULL, r);
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
if (bus_append_strv_iter(&iter, list) < 0)
|
||||
goto oom;
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
|
||||
DBusMessageIter iter, sub;
|
||||
Iterator i;
|
||||
|
@ -502,6 +502,27 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
} else if (streq_ptr(dbus_message_get_member(message), "GetControlGroupAttributes")) {
|
||||
DBusMessageIter iter;
|
||||
_cleanup_strv_free_ char **list = NULL;
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
|
||||
|
||||
if (!dbus_message_iter_init(message, &iter))
|
||||
goto oom;
|
||||
|
||||
r = bus_unit_cgroup_attribute_get(u, &iter, &list);
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, NULL, r);
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
if (bus_append_strv_iter(&iter, list) < 0)
|
||||
goto oom;
|
||||
|
||||
} else if (streq_ptr(dbus_message_get_member(message), "SetControlGroupAttributes")) {
|
||||
DBusMessageIter iter;
|
||||
|
||||
@ -965,6 +986,74 @@ int bus_unit_cgroup_unset(Unit *u, DBusMessageIter *iter) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bus_unit_cgroup_attribute_get(Unit *u, DBusMessageIter *iter, char ***_result) {
|
||||
_cleanup_strv_free_ char **l = NULL, **result = NULL;
|
||||
char **name;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
assert(iter);
|
||||
assert(_result);
|
||||
|
||||
if (!unit_get_exec_context(u))
|
||||
return -EINVAL;
|
||||
|
||||
r = bus_parse_strv_iter(iter, &l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(name, l) {
|
||||
_cleanup_free_ char *controller = NULL;
|
||||
const char *dot;
|
||||
CGroupAttribute *a;
|
||||
CGroupBonding *b;
|
||||
|
||||
dot = strchr(*name, '.');
|
||||
if (dot) {
|
||||
controller = strndup(*name, dot - *name);
|
||||
if (!controller)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* First attempt, read the value from the kernel */
|
||||
b = cgroup_bonding_find_list(u->cgroup_bondings, controller);
|
||||
if (b) {
|
||||
_cleanup_free_ char *p = NULL, *v = NULL;
|
||||
|
||||
r = cg_get_path(b->controller, b->path, *name, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = read_full_file(p, &v, NULL);
|
||||
if (r >= 0) {
|
||||
r = strv_extend(&result, v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
continue;
|
||||
} else if (r != -ENOENT)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* If that didn't work, read our cached value */
|
||||
a = cgroup_attribute_find_list(u->cgroup_attributes, NULL, *name);
|
||||
if (a) {
|
||||
r = strv_extend(&result, a->value);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
*_result = result;
|
||||
result = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bus_unit_cgroup_attribute_set(Unit *u, DBusMessageIter *iter) {
|
||||
DBusMessageIter sub, sub2;
|
||||
int r;
|
||||
|
@ -127,13 +127,9 @@
|
||||
" <property name=\"DefaultControlGroup\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"ControlGroups\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"ControlGroupAttributes\" type=\"a(sss)\" access=\"read\"/>\n" \
|
||||
" <method name=\"SetControlGroups\">\n" \
|
||||
" <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"UnsetControlGroups\">\n" \
|
||||
" <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" <method name=\"GetControlGroupAttributes\">\n" \
|
||||
" <arg name=\"attributes\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"values\" type=\"as\" direction=\"out\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"SetControlGroupAttributes\">\n" \
|
||||
" <arg name=\"attributes\" type=\"a(ss)\" direction=\"in\"/>\n" \
|
||||
@ -142,6 +138,14 @@
|
||||
" <method name=\"UnsetControlGroupAttributes\">\n" \
|
||||
" <arg name=\"attributes\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"SetControlGroups\">\n" \
|
||||
" <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"UnsetControlGroups\">\n" \
|
||||
" <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" </method>\n"
|
||||
|
||||
#define BUS_UNIT_INTERFACES_LIST \
|
||||
@ -164,6 +168,7 @@ DBusHandlerResult bus_unit_queue_job(
|
||||
|
||||
int bus_unit_cgroup_set(Unit *u, DBusMessageIter *iter);
|
||||
int bus_unit_cgroup_unset(Unit *u, DBusMessageIter *iter);
|
||||
int bus_unit_cgroup_attribute_get(Unit *u, DBusMessageIter *iter, char ***_result);
|
||||
int bus_unit_cgroup_attribute_set(Unit *u, DBusMessageIter *iter);
|
||||
int bus_unit_cgroup_attribute_unset(Unit *u, DBusMessageIter *iter);
|
||||
|
||||
|
@ -641,6 +641,9 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
struct stat st;
|
||||
|
||||
assert(fn);
|
||||
assert(contents);
|
||||
|
||||
f = fopen(fn, "re");
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
@ -2273,6 +2273,64 @@ static int set_cgroup_attr(DBusConnection *bus, char **args) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_cgroup_attr(DBusConnection *bus, char **args) {
|
||||
_cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
|
||||
DBusError error;
|
||||
DBusMessageIter iter;
|
||||
int r;
|
||||
_cleanup_free_ char *n = NULL;
|
||||
_cleanup_strv_free_ char **list = NULL;
|
||||
char **a;
|
||||
|
||||
assert(bus);
|
||||
assert(args);
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
n = unit_name_mangle(args[1]);
|
||||
if (!n)
|
||||
return log_oom();
|
||||
|
||||
m = dbus_message_new_method_call(
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"GetUnitControlGroupAttributes");
|
||||
if (!m)
|
||||
return log_oom();
|
||||
|
||||
dbus_message_iter_init_append(m, &iter);
|
||||
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
|
||||
return log_oom();
|
||||
|
||||
r = bus_append_strv_iter(&iter, args + 2);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
|
||||
if (!reply) {
|
||||
log_error("Failed to issue method call: %s", bus_error_message(&error));
|
||||
dbus_error_free(&error);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
dbus_message_iter_init(reply, &iter);
|
||||
r = bus_parse_strv_iter(&iter, &list);
|
||||
if (r < 0) {
|
||||
log_error("Failed to parse value list.");
|
||||
return r;
|
||||
}
|
||||
|
||||
STRV_FOREACH(a, list) {
|
||||
if (endswith(*a, "\n"))
|
||||
fputs(*a, stdout);
|
||||
else
|
||||
puts(*a);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct ExecStatusInfo {
|
||||
char *name;
|
||||
|
||||
@ -4276,12 +4334,14 @@ static int systemctl_help(void) {
|
||||
" help [NAME...|PID...] Show manual for one or more units\n"
|
||||
" reset-failed [NAME...] Reset failed state for all, one, or more\n"
|
||||
" units\n"
|
||||
" set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
|
||||
" unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
|
||||
" get-cgroup-attr [NAME] [ATTR] ...\n"
|
||||
" Get control group attrubute\n"
|
||||
" set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
|
||||
" Set control group attribute\n"
|
||||
" unset-cgroup-attr [NAME] [ATTR...]\n"
|
||||
" Unset control group attribute\n"
|
||||
" set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
|
||||
" unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
|
||||
" load [NAME...] Load one or more units\n"
|
||||
" list-dependencies [NAME] Recursively show units which are required\n"
|
||||
" or wanted by this unit\n\n"
|
||||
@ -5261,6 +5321,7 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
|
||||
{ "isolate", EQUAL, 2, start_unit },
|
||||
{ "set-cgroup", MORE, 2, set_cgroup },
|
||||
{ "unset-cgroup", MORE, 2, set_cgroup },
|
||||
{ "get-cgroup-attr", MORE, 2, get_cgroup_attr },
|
||||
{ "set-cgroup-attr", MORE, 2, set_cgroup_attr },
|
||||
{ "unset-cgroup-attr", MORE, 2, set_cgroup },
|
||||
{ "kill", MORE, 2, kill_unit },
|
||||
|
Loading…
Reference in New Issue
Block a user