mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 10:13:34 +08:00
Merge pull request #34472 from ikruglov/ikruglov/io-systemd-Machine
machine: implement varlink interfaces io.systemd.Machine.{List, Unregister, Terminate, Kill}
This commit is contained in:
commit
a417592b06
@ -14,6 +14,7 @@
|
|||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "pidref.h"
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
|
#include "signal-util.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "varlink-util.h"
|
#include "varlink-util.h"
|
||||||
@ -188,3 +189,197 @@ int vl_method_register(sd_varlink *link, sd_json_variant *parameters, sd_varlink
|
|||||||
|
|
||||||
return sd_varlink_reply(link, NULL);
|
return sd_varlink_reply(link, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lookup_machine_by_name(sd_varlink *link, Manager *manager, const char *machine_name, Machine **ret_machine) {
|
||||||
|
assert(link);
|
||||||
|
assert(manager);
|
||||||
|
assert(ret_machine);
|
||||||
|
|
||||||
|
if (!machine_name)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!hostname_is_valid(machine_name, /* flags= */ VALID_HOSTNAME_DOT_HOST))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
Machine *machine = hashmap_get(manager->machines, machine_name);
|
||||||
|
if (!machine)
|
||||||
|
return -ESRCH;
|
||||||
|
|
||||||
|
*ret_machine = machine;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lookup_machine_by_pid(sd_varlink *link, Manager *manager, pid_t pid, Machine **ret_machine) {
|
||||||
|
Machine *machine;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(link);
|
||||||
|
assert(manager);
|
||||||
|
assert(ret_machine);
|
||||||
|
assert_cc(sizeof(pid_t) == sizeof(uint32_t));
|
||||||
|
|
||||||
|
if (pid == 0) {
|
||||||
|
int pidfd = sd_varlink_get_peer_pidfd(link);
|
||||||
|
if (pidfd < 0)
|
||||||
|
return log_debug_errno(pidfd, "Failed to get peer pidfd: %m");
|
||||||
|
|
||||||
|
r = pidfd_get_pid(pidfd, &pid);
|
||||||
|
if (r < 0)
|
||||||
|
return log_debug_errno(r, "Failed to get pid from pidfd: %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid <= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
r = manager_get_machine_by_pid(manager, pid, &machine);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (!machine)
|
||||||
|
return -ESRCH;
|
||||||
|
|
||||||
|
*ret_machine = machine;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lookup_machine_by_name_or_pid(sd_varlink *link, Manager *manager, const char *machine_name, pid_t pid, Machine **ret_machine) {
|
||||||
|
Machine *machine = NULL, *pid_machine = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(link);
|
||||||
|
assert(manager);
|
||||||
|
assert(ret_machine);
|
||||||
|
|
||||||
|
if (machine_name) {
|
||||||
|
r = lookup_machine_by_name(link, manager, machine_name, &machine);
|
||||||
|
if (r == -EINVAL)
|
||||||
|
return sd_varlink_error_invalid_parameter_name(link, "name");
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid >= 0) {
|
||||||
|
r = lookup_machine_by_pid(link, manager, pid, &pid_machine);
|
||||||
|
if (r == -EINVAL)
|
||||||
|
return sd_varlink_error_invalid_parameter_name(link, "pid");
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (machine && pid_machine && machine != pid_machine)
|
||||||
|
return log_debug_errno(SYNTHETIC_ERRNO(ESRCH), "Search by machine name '%s' and pid %d resulted in two different machines", machine_name, pid);
|
||||||
|
else if (machine)
|
||||||
|
*ret_machine = machine;
|
||||||
|
else if (pid_machine)
|
||||||
|
*ret_machine = pid_machine;
|
||||||
|
else
|
||||||
|
return -ESRCH;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vl_method_unregister_internal(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||||
|
Machine *machine = ASSERT_PTR(userdata);
|
||||||
|
Manager *manager = ASSERT_PTR(machine->manager);
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = varlink_verify_polkit_async(
|
||||||
|
link,
|
||||||
|
manager->bus,
|
||||||
|
"org.freedesktop.machine1.manage-machines",
|
||||||
|
(const char**) STRV_MAKE("name", machine->name,
|
||||||
|
"verb", "unregister"),
|
||||||
|
&manager->polkit_registry);
|
||||||
|
if (r <= 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = machine_finalize(machine);
|
||||||
|
if (r < 0)
|
||||||
|
return log_debug_errno(r, "Failed to finalize machine: %m");
|
||||||
|
|
||||||
|
return sd_varlink_reply(link, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vl_method_terminate_internal(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||||
|
Machine *machine = ASSERT_PTR(userdata);
|
||||||
|
Manager *manager = ASSERT_PTR(machine->manager);
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = varlink_verify_polkit_async(
|
||||||
|
link,
|
||||||
|
manager->bus,
|
||||||
|
"org.freedesktop.machine1.manage-machines",
|
||||||
|
(const char**) STRV_MAKE("name", machine->name,
|
||||||
|
"verb", "terminate"),
|
||||||
|
&manager->polkit_registry);
|
||||||
|
if (r <= 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = machine_stop(machine);
|
||||||
|
if (r < 0)
|
||||||
|
return log_debug_errno(r, "Failed to stop machine: %m");
|
||||||
|
|
||||||
|
return sd_varlink_reply(link, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vl_method_kill(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||||
|
struct params {
|
||||||
|
const char *machine_name;
|
||||||
|
pid_t pid;
|
||||||
|
const char *swhom;
|
||||||
|
int32_t signo;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
|
VARLINK_DISPATCH_MACHINE_LOOKUP_FIELDS(struct params),
|
||||||
|
{ "whom", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(struct params, swhom), 0 },
|
||||||
|
{ "signal", _SD_JSON_VARIANT_TYPE_INVALID , sd_json_dispatch_int32, offsetof(struct params, signo), SD_JSON_MANDATORY },
|
||||||
|
VARLINK_DISPATCH_POLKIT_FIELD,
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
Manager *manager = ASSERT_PTR(userdata);
|
||||||
|
struct params p = { .pid = -1 };
|
||||||
|
KillWhom whom;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(link);
|
||||||
|
assert(parameters);
|
||||||
|
|
||||||
|
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
|
||||||
|
if (r != 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
Machine *machine;
|
||||||
|
r = lookup_machine_by_name_or_pid(link, manager, p.machine_name, p.pid, &machine);
|
||||||
|
if (r == -ESRCH)
|
||||||
|
return sd_varlink_error(link, "io.systemd.Machine.NoSuchMachine", NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (isempty(p.swhom))
|
||||||
|
whom = KILL_ALL;
|
||||||
|
else {
|
||||||
|
whom = kill_whom_from_string(p.swhom);
|
||||||
|
if (whom < 0)
|
||||||
|
return sd_varlink_error_invalid_parameter_name(link, "whom");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SIGNAL_VALID(p.signo))
|
||||||
|
return sd_varlink_error_invalid_parameter_name(link, "signal");
|
||||||
|
|
||||||
|
r = varlink_verify_polkit_async(
|
||||||
|
link,
|
||||||
|
manager->bus,
|
||||||
|
"org.freedesktop.machine1.manage-machines",
|
||||||
|
(const char**) STRV_MAKE("name", machine->name,
|
||||||
|
"verb", "kill"),
|
||||||
|
&manager->polkit_registry);
|
||||||
|
if (r <= 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = machine_kill(machine, whom, p.signo);
|
||||||
|
if (r < 0)
|
||||||
|
return log_debug_errno(r, "Failed to send signal to machine: %m");
|
||||||
|
|
||||||
|
return sd_varlink_reply(link, NULL);
|
||||||
|
}
|
||||||
|
@ -3,4 +3,23 @@
|
|||||||
|
|
||||||
#include "sd-varlink.h"
|
#include "sd-varlink.h"
|
||||||
|
|
||||||
|
#include "machine.h"
|
||||||
|
|
||||||
|
#define VARLINK_DISPATCH_MACHINE_LOOKUP_FIELDS(t) { \
|
||||||
|
.name = "name", \
|
||||||
|
.type = SD_JSON_VARIANT_STRING, \
|
||||||
|
.callback = sd_json_dispatch_const_string, \
|
||||||
|
.offset = offsetof(t, machine_name) \
|
||||||
|
}, { \
|
||||||
|
.name = "pid", \
|
||||||
|
.type = _SD_JSON_VARIANT_TYPE_INVALID, \
|
||||||
|
.callback = sd_json_dispatch_uint32, \
|
||||||
|
.offset = offsetof(t, pid) \
|
||||||
|
}
|
||||||
|
|
||||||
|
int lookup_machine_by_name_or_pid(sd_varlink *link, Manager *manager, const char *machine_name, pid_t pid, Machine **ret_machine);
|
||||||
|
|
||||||
int vl_method_register(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
|
int vl_method_register(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
|
||||||
|
int vl_method_unregister_internal(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
|
||||||
|
int vl_method_terminate_internal(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
|
||||||
|
int vl_method_kill(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "sd-varlink.h"
|
#include "sd-varlink.h"
|
||||||
|
|
||||||
|
#include "bus-polkit.h"
|
||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
#include "hostname-util.h"
|
#include "hostname-util.h"
|
||||||
#include "json-util.h"
|
#include "json-util.h"
|
||||||
@ -399,13 +400,14 @@ static int list_machine_one(sd_varlink *link, Machine *m, bool more) {
|
|||||||
SD_JSON_BUILD_PAIR("name", SD_JSON_BUILD_STRING(m->name)),
|
SD_JSON_BUILD_PAIR("name", SD_JSON_BUILD_STRING(m->name)),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(m->id), "id", SD_JSON_BUILD_ID128(m->id)),
|
SD_JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(m->id), "id", SD_JSON_BUILD_ID128(m->id)),
|
||||||
SD_JSON_BUILD_PAIR("class", SD_JSON_BUILD_STRING(machine_class_to_string(m->class))),
|
SD_JSON_BUILD_PAIR("class", SD_JSON_BUILD_STRING(machine_class_to_string(m->class))),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(!!m->service, "service", SD_JSON_BUILD_STRING(m->service)),
|
JSON_BUILD_PAIR_STRING_NON_EMPTY("service", m->service),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(!!m->root_directory, "rootDirectory", SD_JSON_BUILD_STRING(m->root_directory)),
|
JSON_BUILD_PAIR_STRING_NON_EMPTY("rootDirectory", m->root_directory),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(!!m->unit, "unit", SD_JSON_BUILD_STRING(m->unit)),
|
JSON_BUILD_PAIR_STRING_NON_EMPTY("unit", m->unit),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(pidref_is_set(&m->leader), "leader", SD_JSON_BUILD_UNSIGNED(m->leader.pid)),
|
SD_JSON_BUILD_PAIR_CONDITION(pidref_is_set(&m->leader), "leader", SD_JSON_BUILD_UNSIGNED(m->leader.pid)),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(dual_timestamp_is_set(&m->timestamp), "timestamp", JSON_BUILD_DUAL_TIMESTAMP(&m->timestamp)),
|
SD_JSON_BUILD_PAIR_CONDITION(dual_timestamp_is_set(&m->timestamp), "timestamp", JSON_BUILD_DUAL_TIMESTAMP(&m->timestamp)),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(m->vsock_cid != VMADDR_CID_ANY, "vSockCid", SD_JSON_BUILD_UNSIGNED(m->vsock_cid)),
|
SD_JSON_BUILD_PAIR_CONDITION(m->vsock_cid != VMADDR_CID_ANY, "vSockCid", SD_JSON_BUILD_UNSIGNED(m->vsock_cid)),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(!!m->ssh_address, "sshAddress", SD_JSON_BUILD_STRING(m->ssh_address)));
|
JSON_BUILD_PAIR_STRING_NON_EMPTY("sshAddress", m->ssh_address),
|
||||||
|
JSON_BUILD_PAIR_STRING_NON_EMPTY("sshPrivateKeyPath", m->ssh_private_key_path));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -415,29 +417,36 @@ static int list_machine_one(sd_varlink *link, Machine *m, bool more) {
|
|||||||
return sd_varlink_reply(link, v);
|
return sd_varlink_reply(link, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct MachineLookupParameters {
|
||||||
|
const char *machine_name;
|
||||||
|
pid_t pid;
|
||||||
|
} MachineLookupParameters;
|
||||||
|
|
||||||
static int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
static int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||||
static const sd_json_dispatch_field dispatch_table[] = {
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, 0, 0 },
|
VARLINK_DISPATCH_MACHINE_LOOKUP_FIELDS(MachineLookupParameters),
|
||||||
|
VARLINK_DISPATCH_POLKIT_FIELD,
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
Manager *m = ASSERT_PTR(userdata);
|
Manager *m = ASSERT_PTR(userdata);
|
||||||
const char *mn = NULL;
|
MachineLookupParameters p = { .pid = -1 };
|
||||||
|
Machine *machine;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(link);
|
||||||
assert(parameters);
|
assert(parameters);
|
||||||
|
|
||||||
r = sd_varlink_dispatch(link, parameters, dispatch_table, &mn);
|
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (mn) {
|
if (p.machine_name || p.pid >= 0) {
|
||||||
if (!hostname_is_valid(mn, /* flags= */ VALID_HOSTNAME_DOT_HOST))
|
r = lookup_machine_by_name_or_pid(link, m, p.machine_name, p.pid, &machine);
|
||||||
return sd_varlink_error_invalid_parameter_name(link, "name");
|
if (r == -ESRCH)
|
||||||
|
|
||||||
Machine *machine = hashmap_get(m->machines, mn);
|
|
||||||
if (!machine)
|
|
||||||
return sd_varlink_error(link, "io.systemd.Machine.NoSuchMachine", NULL);
|
return sd_varlink_error(link, "io.systemd.Machine.NoSuchMachine", NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
return list_machine_one(link, machine, /* more= */ false);
|
return list_machine_one(link, machine, /* more= */ false);
|
||||||
}
|
}
|
||||||
@ -462,6 +471,42 @@ static int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varl
|
|||||||
return sd_varlink_error(link, "io.systemd.Machine.NoSuchMachine", NULL);
|
return sd_varlink_error(link, "io.systemd.Machine.NoSuchMachine", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lookup_machine_and_call_method(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata, sd_varlink_method_t method) {
|
||||||
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
|
VARLINK_DISPATCH_MACHINE_LOOKUP_FIELDS(MachineLookupParameters),
|
||||||
|
VARLINK_DISPATCH_POLKIT_FIELD,
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
Manager *manager = ASSERT_PTR(userdata);
|
||||||
|
MachineLookupParameters p = { .pid = -1 };
|
||||||
|
Machine *machine;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(link);
|
||||||
|
assert(parameters);
|
||||||
|
|
||||||
|
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
|
||||||
|
if (r != 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = lookup_machine_by_name_or_pid(link, manager, p.machine_name, p.pid, &machine);
|
||||||
|
if (r == -ESRCH)
|
||||||
|
return sd_varlink_error(link, "io.systemd.Machine.NoSuchMachine", NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return method(link, parameters, flags, machine);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vl_method_unregister(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||||
|
return lookup_machine_and_call_method(link, parameters, flags, userdata, vl_method_unregister_internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vl_method_terminate(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||||
|
return lookup_machine_and_call_method(link, parameters, flags, userdata, vl_method_terminate_internal);
|
||||||
|
}
|
||||||
|
|
||||||
static int manager_varlink_init_userdb(Manager *m) {
|
static int manager_varlink_init_userdb(Manager *m) {
|
||||||
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *s = NULL;
|
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *s = NULL;
|
||||||
int r;
|
int r;
|
||||||
@ -524,8 +569,11 @@ static int manager_varlink_init_machine(Manager *m) {
|
|||||||
|
|
||||||
r = sd_varlink_server_bind_method_many(
|
r = sd_varlink_server_bind_method_many(
|
||||||
s,
|
s,
|
||||||
"io.systemd.Machine.Register", vl_method_register,
|
"io.systemd.Machine.Register", vl_method_register,
|
||||||
"io.systemd.Machine.List", vl_method_list);
|
"io.systemd.Machine.List", vl_method_list,
|
||||||
|
"io.systemd.Machine.Unregister", vl_method_unregister,
|
||||||
|
"io.systemd.Machine.Terminate", vl_method_terminate,
|
||||||
|
"io.systemd.Machine.Kill", vl_method_kill);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to register varlink methods: %m");
|
return log_error_errno(r, "Failed to register varlink methods: %m");
|
||||||
|
|
||||||
|
@ -28,11 +28,32 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
|||||||
SD_VARLINK_FIELD_COMMENT("Timestamp in µs in the CLOCK_MONOTONIC clock"),
|
SD_VARLINK_FIELD_COMMENT("Timestamp in µs in the CLOCK_MONOTONIC clock"),
|
||||||
SD_VARLINK_DEFINE_FIELD(monotonic, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
|
SD_VARLINK_DEFINE_FIELD(monotonic, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
|
||||||
|
|
||||||
|
static SD_VARLINK_DEFINE_METHOD(
|
||||||
|
Unregister,
|
||||||
|
SD_VARLINK_FIELD_COMMENT("The name of a machine to unregister."),
|
||||||
|
SD_VARLINK_DEFINE_INPUT(name, SD_VARLINK_STRING, 0));
|
||||||
|
|
||||||
|
static SD_VARLINK_DEFINE_METHOD(
|
||||||
|
Terminate,
|
||||||
|
SD_VARLINK_FIELD_COMMENT("The name of a machine to terminate."),
|
||||||
|
SD_VARLINK_DEFINE_INPUT(name, SD_VARLINK_STRING, 0));
|
||||||
|
|
||||||
|
static SD_VARLINK_DEFINE_METHOD(
|
||||||
|
Kill,
|
||||||
|
SD_VARLINK_FIELD_COMMENT("The name of a machine to send signal to."),
|
||||||
|
SD_VARLINK_DEFINE_INPUT(name, SD_VARLINK_STRING, 0),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("Identifier that specifies what precisely to send the signal to (either 'leader' or 'all')."),
|
||||||
|
SD_VARLINK_DEFINE_INPUT(whom, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("Numeric UNIX signal integer."),
|
||||||
|
SD_VARLINK_DEFINE_INPUT(signal, SD_VARLINK_INT, 0));
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_METHOD_FULL(
|
static SD_VARLINK_DEFINE_METHOD_FULL(
|
||||||
List,
|
List,
|
||||||
SD_VARLINK_SUPPORTS_MORE,
|
SD_VARLINK_SUPPORTS_MORE,
|
||||||
SD_VARLINK_FIELD_COMMENT("If non-null the name of a running machine to report details on. If null/unspecified enumerates all running machines."),
|
SD_VARLINK_FIELD_COMMENT("If non-null the name of a running machine to report details on. If both 'name' and 'pid' are null/unspecified enumerates all running machines."),
|
||||||
SD_VARLINK_DEFINE_INPUT(name, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_INPUT(name, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("If non-null the PID of a running machine to report details on."),
|
||||||
|
SD_VARLINK_DEFINE_INPUT(pid, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("Name of the machine"),
|
SD_VARLINK_FIELD_COMMENT("Name of the machine"),
|
||||||
SD_VARLINK_DEFINE_OUTPUT(name, SD_VARLINK_STRING, 0),
|
SD_VARLINK_DEFINE_OUTPUT(name, SD_VARLINK_STRING, 0),
|
||||||
SD_VARLINK_FIELD_COMMENT("128bit ID identifying this machine, formatted in hexadecimal"),
|
SD_VARLINK_FIELD_COMMENT("128bit ID identifying this machine, formatted in hexadecimal"),
|
||||||
@ -52,7 +73,9 @@ static SD_VARLINK_DEFINE_METHOD_FULL(
|
|||||||
SD_VARLINK_FIELD_COMMENT("AF_VSOCK CID of the machine if known and applicable"),
|
SD_VARLINK_FIELD_COMMENT("AF_VSOCK CID of the machine if known and applicable"),
|
||||||
SD_VARLINK_DEFINE_OUTPUT(vSockCid, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_OUTPUT(vSockCid, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_FIELD_COMMENT("SSH address to connect to"),
|
SD_VARLINK_FIELD_COMMENT("SSH address to connect to"),
|
||||||
SD_VARLINK_DEFINE_OUTPUT(sshAddress, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
|
SD_VARLINK_DEFINE_OUTPUT(sshAddress, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("Path to private SSH key"),
|
||||||
|
SD_VARLINK_DEFINE_OUTPUT(sshPrivateKeyPath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_ERROR(NoSuchMachine);
|
static SD_VARLINK_DEFINE_ERROR(NoSuchMachine);
|
||||||
static SD_VARLINK_DEFINE_ERROR(MachineExists);
|
static SD_VARLINK_DEFINE_ERROR(MachineExists);
|
||||||
@ -63,6 +86,11 @@ SD_VARLINK_DEFINE_INTERFACE(
|
|||||||
SD_VARLINK_SYMBOL_COMMENT("A timestamp object consisting of both CLOCK_REALTIME and CLOCK_MONOTONIC timestamps"),
|
SD_VARLINK_SYMBOL_COMMENT("A timestamp object consisting of both CLOCK_REALTIME and CLOCK_MONOTONIC timestamps"),
|
||||||
&vl_type_Timestamp,
|
&vl_type_Timestamp,
|
||||||
&vl_method_Register,
|
&vl_method_Register,
|
||||||
|
&vl_method_Unregister,
|
||||||
|
SD_VARLINK_SYMBOL_COMMENT("Terminate machine, killing its processes"),
|
||||||
|
&vl_method_Terminate,
|
||||||
|
SD_VARLINK_SYMBOL_COMMENT("Send a UNIX signal to the machine's processes"),
|
||||||
|
&vl_method_Kill,
|
||||||
SD_VARLINK_SYMBOL_COMMENT("List running machines"),
|
SD_VARLINK_SYMBOL_COMMENT("List running machines"),
|
||||||
&vl_method_List,
|
&vl_method_List,
|
||||||
SD_VARLINK_SYMBOL_COMMENT("No matching machine currently running"),
|
SD_VARLINK_SYMBOL_COMMENT("No matching machine currently running"),
|
||||||
|
@ -57,11 +57,19 @@ while :; do
|
|||||||
done
|
done
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
rm -f /var/lib/machines/long-running/ready
|
long_running_machine_start() {
|
||||||
machinectl start long-running
|
# shellcheck disable=SC2015
|
||||||
# !!!! DO NOT REMOVE THIS TEST
|
machinectl status long-running >/dev/null && return 0 || true
|
||||||
# The test makes sure that the long-running's init script has enough time to start and registered signal traps
|
|
||||||
timeout 10 bash -c "until test -e /var/lib/machines/long-running/ready; do sleep .5; done"
|
rm -f /var/lib/machines/long-running/ready
|
||||||
|
# sometime `machinectl start` returns 1 and then do a success
|
||||||
|
machinectl start long-running || machinectl start long-running
|
||||||
|
# !!!! DO NOT REMOVE THIS TEST
|
||||||
|
# The test makes sure that the long-running's init script has enough time to start and registered signal traps
|
||||||
|
timeout 30 bash -c "until test -e /var/lib/machines/long-running/ready; do sleep .5; done"
|
||||||
|
}
|
||||||
|
|
||||||
|
long_running_machine_start
|
||||||
|
|
||||||
machinectl
|
machinectl
|
||||||
machinectl --no-pager --help
|
machinectl --no-pager --help
|
||||||
@ -232,5 +240,51 @@ done
|
|||||||
(! machinectl read-only container1 foo)
|
(! machinectl read-only container1 foo)
|
||||||
(! machinectl read-only container1 -- -1)
|
(! machinectl read-only container1 -- -1)
|
||||||
|
|
||||||
varlinkctl --more call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{}'
|
####################
|
||||||
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{"name":".host"}'
|
# varlinkctl tests #
|
||||||
|
# ##################
|
||||||
|
|
||||||
|
long_running_machine_start
|
||||||
|
|
||||||
|
# test io.systemd.Machine.List
|
||||||
|
varlinkctl --more call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{}' | grep 'long-running'
|
||||||
|
varlinkctl --more call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{}' | grep '.host'
|
||||||
|
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{"name":"long-running"}'
|
||||||
|
|
||||||
|
pid=$(varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{"name":"long-running"}' | jq '.leader')
|
||||||
|
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{"name":"long-running"}' >/tmp/expected
|
||||||
|
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List "{\"pid\":$pid}" >/tmp/got
|
||||||
|
diff -u /tmp/expected /tmp/got
|
||||||
|
|
||||||
|
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List "{\"name\":\"long-running\", \"pid\":$pid}"
|
||||||
|
(! varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List "{\"name\":\"non-existent\", \"pid\":$pid}")
|
||||||
|
|
||||||
|
# test io.systemd.Machine.Kill
|
||||||
|
# sending TRAP signal
|
||||||
|
rm -f /var/lib/machines/long-running/trap
|
||||||
|
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Kill '{"name":"long-running", "whom": "leader", "signal": 5}'
|
||||||
|
timeout 30 bash -c "until test -e /var/lib/machines/long-running/trap; do sleep .5; done"
|
||||||
|
|
||||||
|
# sending KILL signal
|
||||||
|
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Kill '{"name":"long-running", "signal": 9}'
|
||||||
|
timeout 30 bash -c "while varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{\"name\":\"long-running\"}'; do sleep 0.5; done"
|
||||||
|
|
||||||
|
# test io.systemd.Machine.Terminate
|
||||||
|
long_running_machine_start
|
||||||
|
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Terminate '{"name":"long-running"}'
|
||||||
|
timeout 120 bash -c "while varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{\"name\":\"long-running\"}'; do sleep 0.5; done"
|
||||||
|
|
||||||
|
# test io.systemd.Machine.Register
|
||||||
|
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Register '{"name": "registered-container", "class": "container"}'
|
||||||
|
timeout 30 bash -c "until varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{\"name\":\"registered-container\"}'; do sleep 0.5; done"
|
||||||
|
|
||||||
|
# test io.systemd.Machine.Unregister
|
||||||
|
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Unregister '{"name": "registered-container"}'
|
||||||
|
timeout 30 bash -c "while varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{\"name\":\"registered-container\"}'; do sleep 0.5; done"
|
||||||
|
|
||||||
|
# test io.systemd.Machine.List with sshAddress and sshPrivateKeyPath fields
|
||||||
|
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Register '{"name": "registered-container", "class": "container", "sshAddress": "localhost", "sshPrivateKeyPath": "/non-existent"}'
|
||||||
|
timeout 30 bash -c "until varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{\"name\":\"registered-container\"}'; do sleep 0.5; done"
|
||||||
|
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{"name":"registered-container"}' | jq '.sshAddress' | grep -q 'localhost'
|
||||||
|
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{"name":"registered-container"}' | jq '.sshPrivateKeyPath' | grep -q 'non-existent'
|
||||||
|
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Unregister '{"name": "registered-container"}'
|
Loading…
Reference in New Issue
Block a user