mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-30 01:48:54 +00:00
New "config sync" command
This commit is contained in:
parent
6859b85731
commit
8bc746af25
106
commandline.c
106
commandline.c
@ -653,7 +653,7 @@ int app_log(const struct cli_parsed *parsed, struct cli_context *UNUSED(context)
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 mdp_sockfd;
|
||||
@ -1368,6 +1387,33 @@ int app_config_dump(const struct cli_parsed *parsed, struct cli_context *context
|
||||
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))
|
||||
{
|
||||
if (config.debug.verbose)
|
||||
@ -1396,7 +1442,7 @@ int app_config_set(const struct cli_parsed *parsed, struct cli_context *UNUSED(c
|
||||
unsigned i;
|
||||
for (i = 1; i < parsed->argc; ++i) {
|
||||
const char *arg = parsed->args[i];
|
||||
int iv;
|
||||
int iv = -1;
|
||||
if (strcmp(arg, "set") == 0) {
|
||||
if (i + 2 > parsed->argc)
|
||||
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);
|
||||
var[nvar] = parsed->args[iv = ++i];
|
||||
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);
|
||||
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]);
|
||||
++nvar;
|
||||
}
|
||||
for (i = 0; i < nvar; ++i)
|
||||
int changed = 0;
|
||||
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;
|
||||
if (cf_reload() == -1) // logs an error if the new config is bad
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2337,25 +2412,6 @@ static int app_keyring_set_tag(const struct cli_parsed *parsed, struct cli_conte
|
||||
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)
|
||||
{
|
||||
const char *pin, *sid_hex;
|
||||
@ -3044,6 +3100,8 @@ struct cli_schema command_line_options[]={
|
||||
"Set and del specified configuration variables."},
|
||||
{app_config_set,{"config","del","<variable>","...",NULL},CLIFLAG_PERMISSIVE_CONFIG,
|
||||
"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,
|
||||
"Get specified configuration variable."},
|
||||
{app_config_paths,{"config","paths",NULL},CLIFLAG_PERMISSIVE_CONFIG,
|
||||
|
@ -75,6 +75,12 @@ struct mdp_identity_request {
|
||||
*/
|
||||
#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{
|
||||
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));
|
||||
mdp_search_identities(client, header, payload);
|
||||
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:
|
||||
mdp_reply_error(client, header);
|
||||
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
|
||||
}
|
||||
|
||||
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 "$@"
|
||||
|
Loading…
Reference in New Issue
Block a user