mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-20 21:53:12 +00:00
New "config sync" command
This commit is contained in:
parent
6859b85731
commit
8bc746af25
116
commandline.c
116
commandline.c
@ -653,7 +653,7 @@ int app_log(const struct cli_parsed *parsed, struct cli_context *UNUSED(context)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lookup_send_request(int mdp_sockfd, const sid_t *srcsid, int srcport, const sid_t *dstsid, const char *did)
|
static void lookup_send_request(int mdp_sockfd, const sid_t *srcsid, int srcport, const sid_t *dstsid, const char *did)
|
||||||
{
|
{
|
||||||
overlay_mdp_frame mdp;
|
overlay_mdp_frame mdp;
|
||||||
bzero(&mdp,sizeof(mdp));
|
bzero(&mdp,sizeof(mdp));
|
||||||
@ -1069,6 +1069,25 @@ int app_server_status(const struct cli_parsed *parsed, struct cli_context *conte
|
|||||||
return pid > 0 ? 0 : 1;
|
return pid > 0 ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns -1 on error, -2 on timeout, packet length on success.
|
||||||
|
ssize_t mdp_poll_recv(int mdp_sock, time_ms_t deadline, struct mdp_header *rev_header, unsigned char *payload, size_t buffer_size)
|
||||||
|
{
|
||||||
|
time_ms_t now = gettime_ms();
|
||||||
|
if (now > deadline)
|
||||||
|
return -2;
|
||||||
|
int p=mdp_poll(mdp_sock, deadline - now);
|
||||||
|
if (p<0)
|
||||||
|
return WHY_perror("mdp_poll");
|
||||||
|
if (p==0)
|
||||||
|
return -2;
|
||||||
|
ssize_t len = mdp_recv(mdp_sock, rev_header, payload, buffer_size);
|
||||||
|
if (len<0)
|
||||||
|
return WHY_perror("mdp_recv");
|
||||||
|
if (rev_header->flags & MDP_FLAG_ERROR)
|
||||||
|
return WHY("Operation failed, check the log for more information");
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
int app_mdp_ping(const struct cli_parsed *parsed, struct cli_context *context)
|
int app_mdp_ping(const struct cli_parsed *parsed, struct cli_context *context)
|
||||||
{
|
{
|
||||||
int mdp_sockfd;
|
int mdp_sockfd;
|
||||||
@ -1368,6 +1387,33 @@ int app_config_dump(const struct cli_parsed *parsed, struct cli_context *context
|
|||||||
return ret == CFOK ? 0 : 1;
|
return ret == CFOK ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mdp_client_sync_config(time_ms_t timeout)
|
||||||
|
{
|
||||||
|
/* Bind to MDP socket and await confirmation */
|
||||||
|
struct mdp_header mdp_header = {
|
||||||
|
.remote.port = MDP_SYNC_CONFIG,
|
||||||
|
};
|
||||||
|
int mdpsock = mdp_socket();
|
||||||
|
if (mdpsock == -1)
|
||||||
|
return WHY("cannot create MDP socket");
|
||||||
|
set_nonblock(mdpsock);
|
||||||
|
int r = mdp_send(mdpsock, &mdp_header, NULL, 0);
|
||||||
|
if (r == -1)
|
||||||
|
return -1;
|
||||||
|
time_ms_t deadline = gettime_ms() + timeout; // TODO add --timeout option
|
||||||
|
struct mdp_header rev_header;
|
||||||
|
do {
|
||||||
|
ssize_t len = mdp_poll_recv(mdpsock, deadline, &rev_header, NULL, 0);
|
||||||
|
if (len == -1)
|
||||||
|
return -1;
|
||||||
|
if (len == -2) {
|
||||||
|
WHYF("timeout while synchronising daemon configuration");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} while (!(rev_header.flags & MDP_FLAG_CLOSE));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int app_config_set(const struct cli_parsed *parsed, struct cli_context *UNUSED(context))
|
int app_config_set(const struct cli_parsed *parsed, struct cli_context *UNUSED(context))
|
||||||
{
|
{
|
||||||
if (config.debug.verbose)
|
if (config.debug.verbose)
|
||||||
@ -1396,7 +1442,7 @@ int app_config_set(const struct cli_parsed *parsed, struct cli_context *UNUSED(c
|
|||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 1; i < parsed->argc; ++i) {
|
for (i = 1; i < parsed->argc; ++i) {
|
||||||
const char *arg = parsed->args[i];
|
const char *arg = parsed->args[i];
|
||||||
int iv;
|
int iv = -1;
|
||||||
if (strcmp(arg, "set") == 0) {
|
if (strcmp(arg, "set") == 0) {
|
||||||
if (i + 2 > parsed->argc)
|
if (i + 2 > parsed->argc)
|
||||||
return WHYF("malformed command at args[%d]: 'set' not followed by two arguments", i);
|
return WHYF("malformed command at args[%d]: 'set' not followed by two arguments", i);
|
||||||
@ -1407,19 +1453,48 @@ int app_config_set(const struct cli_parsed *parsed, struct cli_context *UNUSED(c
|
|||||||
return WHYF("malformed command at args[%d]: 'del' not followed by one argument", i);
|
return WHYF("malformed command at args[%d]: 'del' not followed by one argument", i);
|
||||||
var[nvar] = parsed->args[iv = ++i];
|
var[nvar] = parsed->args[iv = ++i];
|
||||||
val[nvar] = NULL;
|
val[nvar] = NULL;
|
||||||
} else
|
} else if (strcmp(arg, "sync") == 0)
|
||||||
|
var[nvar] = val[nvar] = NULL;
|
||||||
|
else
|
||||||
return WHYF("malformed command at args[%d]: unsupported action '%s'", i, arg);
|
return WHYF("malformed command at args[%d]: unsupported action '%s'", i, arg);
|
||||||
if (!is_configvarname(var[nvar]))
|
if (var[nvar] && !is_configvarname(var[nvar]))
|
||||||
return WHYF("malformed command at args[%d]: '%s' is not a valid config option name", iv, var[nvar]);
|
return WHYF("malformed command at args[%d]: '%s' is not a valid config option name", iv, var[nvar]);
|
||||||
++nvar;
|
++nvar;
|
||||||
}
|
}
|
||||||
for (i = 0; i < nvar; ++i)
|
int changed = 0;
|
||||||
if (cf_om_set(&cf_om_root, var[i], val[i]) == -1)
|
for (i = 0; i < nvar; ++i) {
|
||||||
|
if (var[i]) {
|
||||||
|
if (cf_om_set(&cf_om_root, var[i], val[i]) == -1)
|
||||||
|
return -1;
|
||||||
|
if (val[i])
|
||||||
|
INFOF("config set %s %s", var[i], alloca_str_toprint(val[i]));
|
||||||
|
else
|
||||||
|
INFOF("config del %s", var[i]);
|
||||||
|
changed = 1;
|
||||||
|
} else {
|
||||||
|
if (changed) {
|
||||||
|
if (cf_om_save() == -1)
|
||||||
|
return -1;
|
||||||
|
if (cf_reload() == -1) // logs an error if the new config is bad
|
||||||
|
return 2;
|
||||||
|
changed = 0;
|
||||||
|
}
|
||||||
|
int pid = server_pid();
|
||||||
|
if (pid) {
|
||||||
|
INFO("config sync");
|
||||||
|
// TODO make timeout configurable with --timeout option.
|
||||||
|
if (mdp_client_sync_config(10000) == -1)
|
||||||
|
return 3;
|
||||||
|
} else
|
||||||
|
INFO("config sync -- skipped, server not running");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
if (cf_om_save() == -1)
|
||||||
return -1;
|
return -1;
|
||||||
if (cf_om_save() == -1)
|
if (cf_reload() == -1) // logs an error if the new config is bad
|
||||||
return -1;
|
return 2;
|
||||||
if (cf_reload() == -1) // logs an error if the new config is bad
|
}
|
||||||
return 2;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2337,25 +2412,6 @@ static int app_keyring_set_tag(const struct cli_parsed *parsed, struct cli_conte
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns -1 on error, -2 on timeout, packet length on success.
|
|
||||||
ssize_t mdp_poll_recv(int mdp_sock, time_ms_t timeout, struct mdp_header *rev_header, unsigned char *payload, size_t buffer_size)
|
|
||||||
{
|
|
||||||
time_ms_t now = gettime_ms();
|
|
||||||
if (now>timeout)
|
|
||||||
return -2;
|
|
||||||
int p=mdp_poll(mdp_sock, timeout - now);
|
|
||||||
if (p<0)
|
|
||||||
return WHY_perror("mdp_poll");
|
|
||||||
if (p==0)
|
|
||||||
return -2;
|
|
||||||
ssize_t len = mdp_recv(mdp_sock, rev_header, payload, buffer_size);
|
|
||||||
if (len<0)
|
|
||||||
return WHY_perror("mdp_recv");
|
|
||||||
if (rev_header->flags & MDP_FLAG_ERROR)
|
|
||||||
return WHY("Operation failed, check the log for more information");
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_pins(const struct cli_parsed *parsed, struct cli_context *UNUSED(context), int revoke)
|
static int handle_pins(const struct cli_parsed *parsed, struct cli_context *UNUSED(context), int revoke)
|
||||||
{
|
{
|
||||||
const char *pin, *sid_hex;
|
const char *pin, *sid_hex;
|
||||||
@ -3044,6 +3100,8 @@ struct cli_schema command_line_options[]={
|
|||||||
"Set and del specified configuration variables."},
|
"Set and del specified configuration variables."},
|
||||||
{app_config_set,{"config","del","<variable>","...",NULL},CLIFLAG_PERMISSIVE_CONFIG,
|
{app_config_set,{"config","del","<variable>","...",NULL},CLIFLAG_PERMISSIVE_CONFIG,
|
||||||
"Del and set specified configuration variables."},
|
"Del and set specified configuration variables."},
|
||||||
|
{app_config_set,{"config","sync","...",NULL},CLIFLAG_PERMISSIVE_CONFIG,
|
||||||
|
"Synchronise with the daemon's configuration."},
|
||||||
{app_config_get,{"config","get","[<variable>]",NULL},CLIFLAG_PERMISSIVE_CONFIG,
|
{app_config_get,{"config","get","[<variable>]",NULL},CLIFLAG_PERMISSIVE_CONFIG,
|
||||||
"Get specified configuration variable."},
|
"Get specified configuration variable."},
|
||||||
{app_config_paths,{"config","paths",NULL},CLIFLAG_PERMISSIVE_CONFIG,
|
{app_config_paths,{"config","paths",NULL},CLIFLAG_PERMISSIVE_CONFIG,
|
||||||
|
@ -75,6 +75,12 @@ struct mdp_identity_request {
|
|||||||
*/
|
*/
|
||||||
#define MDP_SEARCH_IDS 2
|
#define MDP_SEARCH_IDS 2
|
||||||
|
|
||||||
|
/* Synchronise with the daemon's configuration.
|
||||||
|
*
|
||||||
|
* Once the daemon has (re)loaded all its configuration files, so that its
|
||||||
|
* running (active) configuration is up to date, then sends a reply packet.
|
||||||
|
*/
|
||||||
|
#define MDP_SYNC_CONFIG 3
|
||||||
|
|
||||||
struct overlay_route_record{
|
struct overlay_route_record{
|
||||||
sid_t sid;
|
sid_t sid;
|
||||||
|
@ -1438,6 +1438,12 @@ static void mdp_process_packet(struct socket_address *client, struct mdp_header
|
|||||||
DEBUGF("Processing MDP_SEARCH_IDS from %s", alloca_socket_address(client));
|
DEBUGF("Processing MDP_SEARCH_IDS from %s", alloca_socket_address(client));
|
||||||
mdp_search_identities(client, header, payload);
|
mdp_search_identities(client, header, payload);
|
||||||
break;
|
break;
|
||||||
|
case MDP_SYNC_CONFIG:
|
||||||
|
if (config.debug.mdprequests)
|
||||||
|
DEBUGF("Processing MDP_SYNC_CONFIG from %s", alloca_socket_address(client));
|
||||||
|
server_config_reload(NULL);
|
||||||
|
mdp_reply_ok(client, header);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
mdp_reply_error(client, header);
|
mdp_reply_error(client, header);
|
||||||
WHYF("Unknown command port %d", header->remote.port);
|
WHYF("Unknown command port %d", header->remote.port);
|
||||||
|
48
tests/server
48
tests/server
@ -204,4 +204,52 @@ test_ReloadConfigAuto() {
|
|||||||
assert_servald_server_no_errors
|
assert_servald_server_no_errors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doc_ReloadConfigSync="Server configuration sync"
|
||||||
|
setup_ReloadConfigSync() {
|
||||||
|
cat >watchdog1 <<EOF
|
||||||
|
#!/bin/sh
|
||||||
|
date >> $PWD/trace1
|
||||||
|
EOF
|
||||||
|
cat >watchdog2 <<EOF
|
||||||
|
#!/bin/sh
|
||||||
|
date >> $PWD/trace2
|
||||||
|
EOF
|
||||||
|
chmod 0550 watchdog1 watchdog2
|
||||||
|
>trace1
|
||||||
|
>trace2
|
||||||
|
setup
|
||||||
|
executeOk_servald config \
|
||||||
|
set log.console.level debug \
|
||||||
|
set log.console.show_time true \
|
||||||
|
set log.console.show_pid true \
|
||||||
|
set debug.config on \
|
||||||
|
set debug.watchdog on \
|
||||||
|
set debug.mdprequests on \
|
||||||
|
set server.config_reload_interval_ms 600000 \
|
||||||
|
set server.watchdog.executable "$PWD/watchdog1" \
|
||||||
|
set server.watchdog.interval_ms 100
|
||||||
|
start_servald_server
|
||||||
|
}
|
||||||
|
test_ReloadConfigSync() {
|
||||||
|
wait_until --sleep=0.5 --timeout=15 line_count_at_least trace1 10
|
||||||
|
assert [ $(wc -l <trace2) -eq 0 ]
|
||||||
|
executeOk_servald config set server.watchdog.executable "$PWD/watchdog2"
|
||||||
|
tfw_cat --stderr
|
||||||
|
>trace1
|
||||||
|
wait_until --sleep=0.5 --timeout=15 line_count_at_least trace1 3
|
||||||
|
assert [ $(wc -l <trace2) -eq 0 ]
|
||||||
|
# Must let at least 1 second elapse since starting the server before doing
|
||||||
|
# the "config sync", otherwise the server will not detect the config file as
|
||||||
|
# changed and will not re-load it.
|
||||||
|
# TODO: make the "config set" command ensure that the config file's mtime
|
||||||
|
# always advances if the size does not change.
|
||||||
|
executeOk_servald config sync
|
||||||
|
tfw_cat --stderr
|
||||||
|
>trace1
|
||||||
|
wait_until --sleep=0.5 --timeout=15 line_count_at_least trace2 3
|
||||||
|
assert [ $(wc -l <trace1) -eq 0 ]
|
||||||
|
stop_servald_server
|
||||||
|
assert_servald_server_no_errors
|
||||||
|
}
|
||||||
|
|
||||||
runTests "$@"
|
runTests "$@"
|
||||||
|
Loading…
Reference in New Issue
Block a user