Skip to content

Commit

Permalink
Get Default Target
Browse files Browse the repository at this point in the history
This feature will get the default target for a specific node.

Solves #944
Signed-off-by: Artiom Divak <[email protected]>
  • Loading branch information
ArtiomDivak committed Sep 30, 2024
1 parent 959f92a commit ee6a46c
Show file tree
Hide file tree
Showing 13 changed files with 212 additions and 20 deletions.
10 changes: 10 additions & 0 deletions data/org.eclipse.bluechi.Node.xml
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,16 @@
<arg name="name" type="s" direction="in" />
</method>

<!--
DefaultTarget:
Get the default value of the system to boot into.
@defaulttarget the default target.
-->
<method name="GetDefaultTarget">
<arg name="defaulttarget" type="s" direction="out" />
</method>

<!--
Name:
Expand Down
3 changes: 3 additions & 0 deletions data/org.eclipse.bluechi.internal.Agent.xml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@
<method name="ResetFailedUnit">
<arg name="name" type="s" direction="in" />
</method>
<method name="GetDefaultTarget">
<arg name="defaulttarget" type="s" direction="out" />
</method>

<signal name="JobDone">
<arg name="id" type="u" />
Expand Down
1 change: 1 addition & 0 deletions src/agent/agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -1786,6 +1786,7 @@ static const sd_bus_vtable internal_agent_vtable[] = {
SD_BUS_METHOD("KillUnit", "ssi", "", agent_method_passthrough_to_systemd, 0),
SD_BUS_METHOD("StartDep", "s", "", agent_method_start_dep, 0),
SD_BUS_METHOD("StopDep", "s", "", agent_method_stop_dep, 0),
SD_BUS_METHOD("GetDefaultTarget", "", "s", agent_method_passthrough_to_systemd, 0),
SD_BUS_SIGNAL_WITH_NAMES("JobDone", "us", SD_BUS_PARAM(id) SD_BUS_PARAM(result), 0),
SD_BUS_SIGNAL_WITH_NAMES("JobStateChanged", "us", SD_BUS_PARAM(id) SD_BUS_PARAM(state), 0),
SD_BUS_SIGNAL_WITH_NAMES(
Expand Down
9 changes: 9 additions & 0 deletions src/bindings/python/bluechi/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,15 @@ def freeze_unit(self, name: str) -> None:
name,
)

def get_default_target(self) -> str:
"""
DefaultTarget:
Get the default value of the system to boot into.
@defaulttarget the default target.
"""
return self.get_proxy().GetDefaultTarget()

def get_unit_properties(self, name: str, interface: str) -> Structure:
"""
GetUnitProperties:
Expand Down
42 changes: 22 additions & 20 deletions src/client/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "method-daemon-reload.h"
#include "method-enable-disable.h"
#include "method-freeze-thaw.h"
#include "method-get-default-target.h"
#include "method-help.h"
#include "method-kill.h"
#include "method-list-unit-files.h"
Expand Down Expand Up @@ -41,26 +42,27 @@ int method_version(UNUSED Command *command, UNUSED void *userdata) {
}

const Method methods[] = {
{ "help", 0, 0, OPT_NONE, method_help, usage_bluechi },
{ "list-unit-files", 0, 1, OPT_FILTER, method_list_unit_files, usage_method_list_unit_files },
{ "list-units", 0, 1, OPT_FILTER, method_list_units, usage_method_list_units },
{ "start", 2, 2, OPT_NONE, method_start, usage_method_lifecycle },
{ "stop", 2, 2, OPT_NONE, method_stop, usage_method_lifecycle },
{ "freeze", 2, 2, OPT_NONE, method_freeze, usage_method_freeze },
{ "thaw", 2, 2, OPT_NONE, method_thaw, usage_method_thaw },
{ "restart", 2, 2, OPT_NONE, method_restart, usage_method_lifecycle },
{ "reload", 2, 2, OPT_NONE, method_reload, usage_method_lifecycle },
{ "reset-failed", 0, ARG_ANY, OPT_NONE, method_reset_failed, usage_method_reset_failed },
{ "kill", 2, 2, OPT_KILL_WHOM | OPT_SIGNAL, method_kill, usage_method_kill },
{ "monitor", 0, 2, OPT_NONE, method_monitor, usage_method_monitor },
{ "metrics", 1, 1, OPT_NONE, method_metrics, usage_method_metrics },
{ "enable", 2, ARG_ANY, OPT_FORCE | OPT_RUNTIME | OPT_NO_RELOAD, method_enable, usage_method_enable },
{ "disable", 2, ARG_ANY, OPT_NO_RELOAD, method_disable, usage_method_disable },
{ "daemon-reload", 1, 1, OPT_NONE, method_daemon_reload, usage_method_daemon_reload },
{ "status", 0, ARG_ANY, OPT_WATCH, method_status, usage_method_status },
{ "set-loglevel", 1, 2, OPT_NONE, method_set_loglevel, usage_method_set_loglevel },
{ "version", 0, 0, OPT_NONE, method_version, usage_bluechi },
{ NULL, 0, 0, 0, NULL, NULL }
{ "help", 0, 0, OPT_NONE, method_help, usage_bluechi },
{ "list-unit-files", 0, 1, OPT_FILTER, method_list_unit_files, usage_method_list_unit_files },
{ "list-units", 0, 1, OPT_FILTER, method_list_units, usage_method_list_units },
{ "start", 2, 2, OPT_NONE, method_start, usage_method_lifecycle },
{ "stop", 2, 2, OPT_NONE, method_stop, usage_method_lifecycle },
{ "freeze", 2, 2, OPT_NONE, method_freeze, usage_method_freeze },
{ "thaw", 2, 2, OPT_NONE, method_thaw, usage_method_thaw },
{ "restart", 2, 2, OPT_NONE, method_restart, usage_method_lifecycle },
{ "reload", 2, 2, OPT_NONE, method_reload, usage_method_lifecycle },
{ "reset-failed", 0, ARG_ANY, OPT_NONE, method_reset_failed, usage_method_reset_failed },
{ "kill", 2, 2, OPT_KILL_WHOM | OPT_SIGNAL, method_kill, usage_method_kill },
{ "monitor", 0, 2, OPT_NONE, method_monitor, usage_method_monitor },
{ "metrics", 1, 1, OPT_NONE, method_metrics, usage_method_metrics },
{ "enable", 2, ARG_ANY, OPT_FORCE | OPT_RUNTIME | OPT_NO_RELOAD, method_enable, usage_method_enable },
{ "disable", 2, ARG_ANY, OPT_NO_RELOAD, method_disable, usage_method_disable },
{ "daemon-reload", 1, 1, OPT_NONE, method_daemon_reload, usage_method_daemon_reload },
{ "status", 0, ARG_ANY, OPT_WATCH, method_status, usage_method_status },
{ "set-loglevel", 1, 2, OPT_NONE, method_set_loglevel, usage_method_set_loglevel },
{ "get-default", 1, 1, OPT_NONE, method_get_default_target, usage_method_get_default_target },
{ "version", 0, 0, OPT_NONE, method_version, usage_bluechi },
{ NULL, 0, 0, 0, NULL, NULL }
};

const OptionType option_types[] = {
Expand Down
1 change: 1 addition & 0 deletions src/client/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ client_src = [
'method-enable-disable.c',
'method-reset-failed.c',
'method-daemon-reload.c',
'method-get-default-target.c',
'usage.c',
]

Expand Down
57 changes: 57 additions & 0 deletions src/client/method-get-default-target.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright Contributors to the Eclipse BlueChi project
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "method-get-default-target.h"
#include "client.h"
#include "usage.h"

#include "libbluechi/common/opt.h"

static int method_get_default_target_on(Client *client, char *node_name) {
_cleanup_sd_bus_error_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_sd_bus_message_ sd_bus_message *message = NULL;
char *result = NULL;
int r = 0;

r = assemble_object_path_string(NODE_OBJECT_PATH_PREFIX, node_name, &client->object_path);
if (r < 0) {
return r;
}

r = sd_bus_call_method(
client->api_bus,
BC_INTERFACE_BASE_NAME,
client->object_path,
NODE_INTERFACE,
"GetDefaultTarget",
&error,
&message,
"");
if (r < 0) {
fprintf(stderr, "Failed to issue method call: %s\n", error.message);
return r;
}

r = sd_bus_message_read(message, "s", &result);
if (r < 0) {
fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r));
return r;
}

printf("The default target of this node is: %s\n", result);

return r;
}

void usage_method_get_default_target() {
usage_print_header();
usage_print_description("Start/Stop/Restart/Reload a unit on a node");
usage_print_usage("bluechictl get-default [nodename]");
}


int method_get_default_target(Command *command, void *userdata) {
return method_get_default_target_on(userdata, command->opargv[0]);
}
11 changes: 11 additions & 0 deletions src/client/method-get-default-target.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright Contributors to the Eclipse BlueChi project
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#pragma once

#include "libbluechi/cli/command.h"

int method_get_default_target(Command *command, void *userdata);
void usage_method_get_default_target();
2 changes: 2 additions & 0 deletions src/client/method-help.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ void usage_bluechi() {
printf(" usage: daemon-reload nodename\n");
printf(" - set-loglevel: change the log level of the bluechi-controller or a connected node\n");
printf(" usage: set-loglevel [nodename] [loglevel]\n");
printf(" - get-default: get a default target of connected node\n");
printf(" usage: get-dafault [nodename]\n");
}

int method_help(UNUSED Command *command, UNUSED void *userdata) {
Expand Down
37 changes: 37 additions & 0 deletions src/controller/node.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ static int node_method_restart_unit(sd_bus_message *m, void *userdata, UNUSED sd
static int node_method_reload_unit(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error);
static int node_method_passthrough_to_agent(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error);
static int node_method_set_log_level(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error);
static int node_method_get_default_target(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error);
static int node_property_get_status(
sd_bus *bus,
const char *path,
Expand Down Expand Up @@ -86,6 +87,7 @@ static const sd_bus_vtable node_vtable[] = {
SD_BUS_METHOD("Reload", "", "", node_method_passthrough_to_agent, 0),
SD_BUS_METHOD("KillUnit", "ssi", "", node_method_passthrough_to_agent, 0),
SD_BUS_METHOD("SetLogLevel", "s", "", node_method_set_log_level, 0),
SD_BUS_METHOD("GetDefaultTarget", "", "s", node_method_get_default_target, 0),
SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Node, name), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Status", "s", node_property_get_status, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("PeerIp", "s", node_property_get_peer_ip, 0, SD_BUS_VTABLE_PROPERTY_EXPLICIT),
Expand Down Expand Up @@ -1686,6 +1688,41 @@ static int node_method_set_log_level(sd_bus_message *m, UNUSED void *userdata, U
}
return sd_bus_reply_method_return(m, "");
}
/*************************************************************************
********** org.eclipse.bluechi.Node.GetDefaultTarget *******************
************************************************************************/

static int node_method_get_default_target(UNUSED sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
Node *node = (Node *) userdata;
_cleanup_sd_bus_message_ sd_bus_message *empty = NULL;
_cleanup_sd_bus_message_ sd_bus_message *reply = NULL;
int r = sd_bus_message_new_method_call(
node->agent_bus,
&empty,
BC_AGENT_DBUS_NAME,
INTERNAL_AGENT_OBJECT_PATH,
INTERNAL_AGENT_INTERFACE,
"GetDefaultTarget");
if (r < 0) {
fprintf(stderr, "Failed creating new method call: %s\n", strerror(-r));
return r;
}

r = sd_bus_call(node->agent_bus, empty, BC_DEFAULT_DBUS_TIMEOUT, ret_error, &reply);
if (r < 0) {
fprintf(stderr, "Failed to call method: %s\n", strerror(-r));
return r;
}

const char *default_target = NULL;
r = sd_bus_message_read(reply, "s", &default_target);
if (r < 0) {
fprintf(stderr, "Failed reading the mesaage: %s\n", strerror(-r));
return r;
}

return sd_bus_reply_method_return(m, "s", default_target);
}

static int send_agent_simple_message(Node *node, const char *method, const char *arg) {
_cleanup_sd_bus_message_ sd_bus_message *m = NULL;
Expand Down
14 changes: 14 additions & 0 deletions tests/bluechi_test/bluechictl.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,20 @@ def reset_failed(
expected_result,
)

def get_default_target(
self,
node_name: str = "",
check_result: bool = True,
expected_result: int = 0,
) -> Tuple[Optional[int], Union[Iterator[bytes], Any, Tuple[bytes, bytes]]]:
cmd = f"get-default {node_name}".strip()
return self._run(
f"GetDefaultTarget of node {node_name}",
cmd,
check_result,
expected_result,
)

def kill_unit(
self,
node_name: str,
Expand Down
2 changes: 2 additions & 0 deletions tests/tests/tier0/bluechi-get-default-target/main.fmf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
summary: Test the get default target function
id: 64c26c46-e50e-4297-a2ef-811a72ef9966
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#
# Copyright Contributors to the Eclipse BlueChi project
#
# SPDX-License-Identifier: LGPL-2.1-or-later

from typing import Dict

from bluechi_test.config import BluechiAgentConfig, BluechiControllerConfig
from bluechi_test.machine import BluechiAgentMachine, BluechiControllerMachine
from bluechi_test.test import BluechiTest

NODE_FOO = "node-foo"


def exec(ctrl: BluechiControllerMachine, nodes: Dict[str, BluechiAgentMachine]):
node_foo = nodes[NODE_FOO]

_, bc_result = ctrl.bluechictl.get_default_target(NODE_FOO)
_, systemd_result = node_foo.exec_run("systemctl get-default")
assert systemd_result in bc_result

node_foo.exec_run("systemctl set-default multi-user.target")

_, bc_result = ctrl.bluechictl.get_default_target(NODE_FOO)
_, systemd_result = node_foo.exec_run("systemctl get-default")
assert systemd_result in bc_result


def test_bluechi_get_default_target(
bluechi_test: BluechiTest,
bluechi_node_default_config: BluechiAgentConfig,
bluechi_ctrl_default_config: BluechiControllerConfig,
):

node_foo_cfg = bluechi_node_default_config.deep_copy()
node_foo_cfg.node_name = NODE_FOO

bluechi_ctrl_default_config.allowed_node_names = [NODE_FOO]
bluechi_test.set_bluechi_controller_config(bluechi_ctrl_default_config)

bluechi_test.add_bluechi_agent_config(node_foo_cfg)

bluechi_test.run(exec)

0 comments on commit ee6a46c

Please sign in to comment.