Skip to content

Commit

Permalink
Merge 3e9ac53 into 1b47cfa
Browse files Browse the repository at this point in the history
  • Loading branch information
sam-leonard-ct committed Apr 23, 2024
2 parents 1b47cfa + 3e9ac53 commit e70ba54
Show file tree
Hide file tree
Showing 15 changed files with 387 additions and 35 deletions.
55 changes: 53 additions & 2 deletions src/machine/machine-dbus.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include <errno.h>
#include <stdlib.h>
#include <sys/mount.h>
#include <sys/wait.h>

Expand Down Expand Up @@ -482,6 +483,7 @@ static int container_bus_new(Machine *m, sd_bus_error *error, sd_bus **ret) {

switch (m->class) {

case MACHINE_VM:
case MACHINE_HOST:
*ret = NULL;
break;
Expand Down Expand Up @@ -585,7 +587,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
sd_bus *container_bus = NULL;
_cleanup_close_ int master = -EBADF, slave = -EBADF;
_cleanup_strv_free_ char **env = NULL, **args_wire = NULL, **args = NULL;
_cleanup_free_ char *command_line = NULL;
_cleanup_free_ char *command_line = NULL, *ssh_path = NULL;
Machine *m = ASSERT_PTR(userdata);
const char *p, *unit, *user, *path, *description, *utmp_id;
int r;
Expand Down Expand Up @@ -638,6 +640,55 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
if (!strv_env_is_valid(env))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");

/* if we are a VM we need to transform args/path/env into an SSH command line */
if (m->class == MACHINE_VM) {
_cleanup_strv_free_ char **ssh_cmdline = NULL;

if (isempty(m->ssh_address) || isempty(m->ssh_private_key_path))
return -EOPNOTSUPP;

r = find_executable("ssh", &ssh_path);
if (r < 0)
return r;

ssh_cmdline = strv_new("ssh", "-t", "-o", "IdentitiesOnly yes");
if (!ssh_cmdline)
return -ENOMEM;

r = strv_extend(&ssh_cmdline, "-o");
if (r < 0)
return r;

r = strv_extendf(&ssh_cmdline, "IdentityFile=%s", m->ssh_private_key_path);
if (r < 0)
return r;

STRV_FOREACH(envvar, env) {
r = strv_extend(&ssh_cmdline, "-o");
if (r < 0)
return r;

r = strv_extendf(&ssh_cmdline, "SetEnv %s", *envvar);
if (r < 0)
return r;
}

r = strv_extend(&ssh_cmdline, m->ssh_address);
if (r < 0)
return r;

r = strv_extend(&ssh_cmdline, path);
if (r < 0)
return r;

r = strv_extend_strv(&ssh_cmdline, strv_skip(args, 1), /* filter_duplicates= */ false);
if (r < 0)
return r;

path = ssh_path;
strv_free_and_replace(args, ssh_cmdline);
}

command_line = strv_join(args, " ");
if (!command_line)
return -ENOMEM;
Expand Down Expand Up @@ -718,7 +769,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
if (r < 0)
return r;

if (!strv_isempty(env)) {
if (!strv_isempty(env) && m->class != MACHINE_VM) {
r = sd_bus_message_open_container(tm, 'r', "sv");
if (r < 0)
return r;
Expand Down
171 changes: 171 additions & 0 deletions src/machine/machine-varlink.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include "hostname-util.h"
#include "json.h"
#include "machine-varlink.h"
#include "machine.h"
#include "path-util.h"
#include "process-util.h"
#include "sd-id128.h"
#include "string-util.h"
#include "varlink.h"

static int machine_name(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
char **m = ASSERT_PTR(userdata);
int r;

assert(variant);

if (!json_variant_is_string(variant))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));

if (!hostname_is_valid(json_variant_string(variant), 0))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Invalid machine name");

r = free_and_strdup(m, json_variant_string(variant));
if (r < 0)
return json_log(variant, flags, r, "Failed to allocate string: %m");

return 0;
}

static int machine_class(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
MachineClass *class = ASSERT_PTR(userdata);

assert(variant);

if (!json_variant_is_string(variant))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));

*class = machine_class_from_string(json_variant_string(variant));

return 0;
}

static int machine_leader(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
PidRef *leader = ASSERT_PTR(userdata);
uint64_t k;
int r;

if (!json_variant_is_unsigned(variant))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name));

k = json_variant_unsigned(variant);
if (k > PID_T_MAX || !pid_is_valid(k))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid PID.", strna(name));

if (k == 1)
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid leader PID.", strna(name));

r = pidref_set_pid(leader, k);
if (r < 0)
return json_log(variant, flags, r, "Failed to pin process " PID_FMT ": %m", leader->pid);

return 0;
}

static int json_dispatch_path(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
const char *path;
char **p = ASSERT_PTR(userdata);
int r;

assert(variant);

if (!json_variant_is_string(variant))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));

path = strempty(json_variant_string(variant));
if (!isempty(path) && !path_is_absolute(path))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' must be empty or an absolute path.", strna(name));

r = free_and_strdup(p, path);
if (r < 0)
return json_log(variant, flags, r, "Failed to allocate string: %m");

return 0;
}

static int machine_ifindices(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
Machine *m = ASSERT_PTR(userdata);
_cleanup_free_ int *netif = NULL;
size_t n_netif, k = 0;

assert(variant);

if (!json_variant_is_array(variant))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));


n_netif = json_variant_elements(variant);

netif = new(int, n_netif);
if (!netif)
return json_log(variant, flags, SYNTHETIC_ERRNO(ENOMEM), "Out of memory.");

JsonVariant *i;
JSON_VARIANT_ARRAY_FOREACH(i, variant) {
uint64_t b;

if (!json_variant_is_unsigned(i))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Element %zu of JSON field '%s' is not an unsigned integer.", k, strna(name));

b = json_variant_unsigned(i);
if (b > INT_MAX || b <= 0)
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Invalid network interface index %"PRIu64, b);

netif[k++] = (int) b;
}
assert(k == n_netif);

m->netif = TAKE_PTR(netif);
m->n_netif = n_netif;

return 0;
}

int vl_method_register(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
Manager *manager = ASSERT_PTR(userdata);
_cleanup_(machine_freep) Machine *user_machine = NULL;
Machine *managed_machine;
int r;

static const JsonDispatch dispatch_table[] = {
{ "name", JSON_VARIANT_STRING, machine_name, offsetof(Machine, name), JSON_MANDATORY },
{ "id", JSON_VARIANT_STRING, json_dispatch_id128, offsetof(Machine, id), 0 },
{ "service", JSON_VARIANT_STRING, json_dispatch_string, offsetof(Machine, service), 0 },
{ "class", JSON_VARIANT_STRING, machine_class, offsetof(Machine, class), JSON_MANDATORY },
{ "leader", JSON_VARIANT_UNSIGNED, machine_leader, offsetof(Machine, leader), 0 },
{ "rootDirectory", JSON_VARIANT_STRING, json_dispatch_path, offsetof(Machine, root_directory), 0 },
{ "ifIndices", JSON_VARIANT_ARRAY, machine_ifindices, 0, 0 },
{ "sshAddress", JSON_VARIANT_STRING, json_dispatch_string, offsetof(Machine, ssh_address), JSON_SAFE },
{ "sshPrivateKeyPath", JSON_VARIANT_STRING, json_dispatch_path, offsetof(Machine, ssh_private_key_path), JSON_SAFE },
{}
};

user_machine = new0(Machine, 1);
if (!user_machine)
return log_oom();

r = varlink_dispatch(link, parameters, dispatch_table, user_machine);
if (r != 0)
return r;

r = manager_add_machine(manager, user_machine->name, &managed_machine);
if (r < 0)
return r;

managed_machine->name = user_machine->name;
managed_machine->id = user_machine->id;
managed_machine->service = user_machine->service;
managed_machine->class = user_machine->class;
managed_machine->leader = user_machine->leader;
managed_machine->root_directory = user_machine->root_directory;
managed_machine->netif = user_machine->netif;
managed_machine->n_netif = user_machine->n_netif;
managed_machine->ssh_address = user_machine->ssh_address;
managed_machine->ssh_private_key_path = user_machine->ssh_private_key_path;

user_machine = mfree(user_machine);

return varlink_reply(link, NULL);
}
6 changes: 6 additions & 0 deletions src/machine/machine-varlink.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once

#include "varlink.h"

int vl_method_register(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata);
6 changes: 4 additions & 2 deletions src/machine/machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@
#include "unit-name.h"
#include "user-util.h"

DEFINE_TRIVIAL_CLEANUP_FUNC(Machine*, machine_free);

int machine_new(Manager *manager, MachineClass class, const char *name, Machine **ret) {
_cleanup_(machine_freep) Machine *m = NULL;
int r;
Expand Down Expand Up @@ -117,6 +115,8 @@ Machine* machine_free(Machine *m) {
free(m->service);
free(m->root_directory);
free(m->netif);
free(m->ssh_address);
free(m->ssh_private_key_path);
return mfree(m);
}

Expand Down Expand Up @@ -604,6 +604,7 @@ int machine_openpt(Machine *m, int flags, char **ret_slave) {

switch (m->class) {

case MACHINE_VM:
case MACHINE_HOST:
return openpt_allocate(flags, ret_slave);

Expand All @@ -623,6 +624,7 @@ int machine_open_terminal(Machine *m, const char *path, int mode) {

switch (m->class) {

case MACHINE_VM:
case MACHINE_HOST:
return open_terminal(path, mode);

Expand Down
5 changes: 5 additions & 0 deletions src/machine/machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ struct Machine {
int *netif;
size_t n_netif;

char *ssh_address;
char *ssh_private_key_path;

LIST_HEAD(Operation, operations);

LIST_FIELDS(Machine, gc_queue);
Expand All @@ -78,6 +81,8 @@ int machine_save(Machine *m);
int machine_load(Machine *m);
int machine_kill(Machine *m, KillWho who, int signo);

DEFINE_TRIVIAL_CLEANUP_FUNC(Machine*, machine_free);

void machine_release_unit(Machine *m);

MachineState machine_get_state(Machine *u);
Expand Down

0 comments on commit e70ba54

Please sign in to comment.