mirror of
https://gitlab.labs.nic.cz/labs/bird.git
synced 2024-05-11 16:54:54 +00:00
Implements undo command and optional timeout for configuration
Several new configure command variants: configure undo - undo last reconfiguration configure timeout - configure with scheduled undo if not confirmed in timeout configure confirm - confirm last configuration configure check - just parse and validate config file
This commit is contained in:
@@ -14,9 +14,9 @@ CF_HDR
|
||||
CF_DECLS
|
||||
|
||||
CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT)
|
||||
CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, BASE, NAME)
|
||||
CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, BASE, NAME, CONFIRM, UNDO, CHECK, TIMEOUT)
|
||||
|
||||
%type <i> log_mask log_mask_list log_cat
|
||||
%type <i> log_mask log_mask_list log_cat cfg_timeout
|
||||
%type <g> log_file
|
||||
%type <t> cfg_name
|
||||
%type <tf> timeformat_which
|
||||
@@ -104,13 +104,26 @@ timeformat_base:
|
||||
|
||||
/* Unix specific commands */
|
||||
|
||||
CF_CLI_HELP(CONFIGURE, [soft] [\"<file>\"], [[Reload configuration]])
|
||||
CF_CLI_HELP(CONFIGURE, ..., [[Reload configuration]])
|
||||
|
||||
CF_CLI(CONFIGURE, cfg_name, [\"<file>\"], [[Reload configuration]])
|
||||
{ cmd_reconfig($2, RECONFIG_HARD); } ;
|
||||
CF_CLI(CONFIGURE, cfg_name cfg_timeout, [\"<file>\"] [timeout [<sec>]], [[Reload configuration]])
|
||||
{ cmd_reconfig($2, RECONFIG_HARD, $3); } ;
|
||||
|
||||
CF_CLI(CONFIGURE SOFT, cfg_name, [\"<file>\"], [[Reload configuration and ignore changes in filters]])
|
||||
{ cmd_reconfig($3, RECONFIG_SOFT); } ;
|
||||
CF_CLI(CONFIGURE SOFT, cfg_name cfg_timeout, [\"<file>\"] [timeout [<sec>]], [[Reload configuration and ignore changes in filters]])
|
||||
{ cmd_reconfig($3, RECONFIG_SOFT, $4); } ;
|
||||
|
||||
/* Hack to get input completion for 'timeout' */
|
||||
CF_CLI_CMD(CONFIGURE TIMEOUT, [<sec>], [[Reload configuration with undo timeout]])
|
||||
CF_CLI_CMD(CONFIGURE SOFT TIMEOUT, [<sec>], [[Reload configuration with undo timeout]])
|
||||
|
||||
CF_CLI(CONFIGURE CONFIRM,,, [[Confirm last configuration change - deactivate undo timeout]])
|
||||
{ cmd_reconfig_confirm(); } ;
|
||||
|
||||
CF_CLI(CONFIGURE UNDO,,, [[Undo last configuration change]])
|
||||
{ cmd_reconfig_undo(); } ;
|
||||
|
||||
CF_CLI(CONFIGURE CHECK, cfg_name, [\"<file>\"], [[Parse configuration and check its validity]])
|
||||
{ cmd_check_config($3); } ;
|
||||
|
||||
CF_CLI(DOWN,,, [[Shut the daemon down]])
|
||||
{ cmd_shutdown(); } ;
|
||||
@@ -120,6 +133,12 @@ cfg_name:
|
||||
| TEXT
|
||||
;
|
||||
|
||||
cfg_timeout:
|
||||
/* empty */ { $$ = 0; }
|
||||
| TIMEOUT { $$ = UNIX_DEFAULT_CONFIGURE_TIMEOUT; }
|
||||
| TIMEOUT expr { $$ = $2; }
|
||||
;
|
||||
|
||||
CF_CODE
|
||||
|
||||
CF_END
|
||||
|
||||
@@ -121,7 +121,7 @@ static list near_timers, far_timers;
|
||||
static bird_clock_t first_far_timer = TIME_INFINITY;
|
||||
|
||||
/* now must be different from 0, because 0 is a special value in timer->expires */
|
||||
bird_clock_t now = 1, now_real;
|
||||
bird_clock_t now = 1, now_real, boot_time;
|
||||
|
||||
static void
|
||||
update_times_plain(void)
|
||||
@@ -1530,6 +1530,7 @@ io_init(void)
|
||||
krt_io_init();
|
||||
init_times();
|
||||
update_times();
|
||||
boot_time = now;
|
||||
srandom((int) now_real);
|
||||
}
|
||||
|
||||
@@ -1557,7 +1558,7 @@ io_loop(void)
|
||||
tm_shot();
|
||||
continue;
|
||||
}
|
||||
timo.tv_sec = events ? 0 : tout - now;
|
||||
timo.tv_sec = events ? 0 : MIN(tout - now, 3);
|
||||
timo.tv_usec = 0;
|
||||
|
||||
if (sock_recalc_fdsets_p)
|
||||
|
||||
@@ -900,7 +900,7 @@ krt_notify(struct proto *P, struct rtable *table UNUSED, net *net,
|
||||
{
|
||||
struct krt_proto *p = (struct krt_proto *) P;
|
||||
|
||||
if (shutting_down)
|
||||
if (config->shutdown)
|
||||
return;
|
||||
if (!(net->n.flags & KRF_INSTALLED))
|
||||
old = NULL;
|
||||
|
||||
@@ -210,7 +210,7 @@ read_config(void)
|
||||
else
|
||||
die("Unable to open configuration file %s: %m", config_name);
|
||||
}
|
||||
config_commit(conf, RECONFIG_HARD);
|
||||
config_commit(conf, RECONFIG_HARD, 0);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -228,19 +228,17 @@ async_config(void)
|
||||
config_free(conf);
|
||||
}
|
||||
else
|
||||
config_commit(conf, RECONFIG_HARD);
|
||||
config_commit(conf, RECONFIG_HARD, 0);
|
||||
}
|
||||
|
||||
void
|
||||
cmd_reconfig(char *name, int type)
|
||||
static struct config *
|
||||
cmd_read_config(char *name)
|
||||
{
|
||||
struct config *conf;
|
||||
|
||||
if (cli_access_restricted())
|
||||
return;
|
||||
|
||||
if (!name)
|
||||
name = config_name;
|
||||
|
||||
cli_msg(-2, "Reading configuration from %s", name);
|
||||
if (!unix_read_config(&conf, name))
|
||||
{
|
||||
@@ -249,26 +247,96 @@ cmd_reconfig(char *name, int type)
|
||||
else
|
||||
cli_msg(8002, "%s: %m", name);
|
||||
config_free(conf);
|
||||
conf = NULL;
|
||||
}
|
||||
else
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
void
|
||||
cmd_check_config(char *name)
|
||||
{
|
||||
struct config *conf = cmd_read_config(name);
|
||||
if (!conf)
|
||||
return;
|
||||
|
||||
cli_msg(20, "Configuration OK");
|
||||
config_free(conf);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_reconfig_msg(int r)
|
||||
{
|
||||
switch (r)
|
||||
{
|
||||
switch (config_commit(conf, type))
|
||||
{
|
||||
case CONF_DONE:
|
||||
cli_msg(3, "Reconfigured.");
|
||||
break;
|
||||
case CONF_PROGRESS:
|
||||
cli_msg(4, "Reconfiguration in progress.");
|
||||
break;
|
||||
case CONF_SHUTDOWN:
|
||||
cli_msg(6, "Reconfiguration ignored, shutting down.");
|
||||
break;
|
||||
default:
|
||||
cli_msg(5, "Reconfiguration already in progress, queueing new config");
|
||||
}
|
||||
case CONF_DONE: cli_msg( 3, "Reconfigured"); break;
|
||||
case CONF_PROGRESS: cli_msg( 4, "Reconfiguration in progress"); break;
|
||||
case CONF_QUEUED: cli_msg( 5, "Reconfiguration already in progress, queueing new config"); break;
|
||||
case CONF_UNQUEUED: cli_msg(17, "Reconfiguration already in progress, removing queued config"); break;
|
||||
case CONF_CONFIRM: cli_msg(18, "Reconfiguration confirmed"); break;
|
||||
case CONF_SHUTDOWN: cli_msg( 6, "Reconfiguration ignored, shutting down"); break;
|
||||
case CONF_NOTHING: cli_msg(19, "Nothing to do"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hack for scheduled undo notification */
|
||||
cli *cmd_reconfig_stored_cli;
|
||||
|
||||
void
|
||||
cmd_reconfig_undo_notify(void)
|
||||
{
|
||||
if (cmd_reconfig_stored_cli)
|
||||
{
|
||||
cli *c = cmd_reconfig_stored_cli;
|
||||
cli_printf(c, CLI_ASYNC_CODE, "Config timeout expired, starting undo");
|
||||
cli_write_trigger(c);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cmd_reconfig(char *name, int type, int timeout)
|
||||
{
|
||||
if (cli_access_restricted())
|
||||
return;
|
||||
|
||||
struct config *conf = cmd_read_config(name);
|
||||
if (!conf)
|
||||
return;
|
||||
|
||||
int r = config_commit(conf, type, timeout);
|
||||
|
||||
if ((r >= 0) && (timeout > 0))
|
||||
{
|
||||
cmd_reconfig_stored_cli = this_cli;
|
||||
cli_msg(-22, "Undo scheduled in %d s", timeout);
|
||||
}
|
||||
|
||||
cmd_reconfig_msg(r);
|
||||
}
|
||||
|
||||
void
|
||||
cmd_reconfig_confirm(void)
|
||||
{
|
||||
if (cli_access_restricted())
|
||||
return;
|
||||
|
||||
int r = config_confirm();
|
||||
cmd_reconfig_msg(r);
|
||||
}
|
||||
|
||||
void
|
||||
cmd_reconfig_undo(void)
|
||||
{
|
||||
if (cli_access_restricted())
|
||||
return;
|
||||
|
||||
cli_msg(-21, "Undo requested");
|
||||
|
||||
int r = config_undo();
|
||||
cmd_reconfig_msg(r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Command-Line Interface
|
||||
*/
|
||||
@@ -623,6 +691,7 @@ main(int argc, char **argv)
|
||||
rt_init();
|
||||
if_init();
|
||||
roa_init();
|
||||
config_init();
|
||||
|
||||
uid_t use_uid = get_uid(use_user);
|
||||
gid_t use_gid = get_gid(use_group);
|
||||
|
||||
@@ -32,6 +32,7 @@ void tm_dump_all(void);
|
||||
|
||||
extern bird_clock_t now; /* Relative, monotonic time in seconds */
|
||||
extern bird_clock_t now_real; /* Time in seconds since fixed known epoch */
|
||||
extern bird_clock_t boot_time;
|
||||
|
||||
static inline bird_clock_t
|
||||
tm_remains(timer *t)
|
||||
|
||||
@@ -19,9 +19,14 @@ extern char *bird_name;
|
||||
void async_config(void);
|
||||
void async_dump(void);
|
||||
void async_shutdown(void);
|
||||
void cmd_reconfig(char *name, int type);
|
||||
void cmd_check_config(char *name);
|
||||
void cmd_reconfig(char *name, int type, int timeout);
|
||||
void cmd_reconfig_confirm(void);
|
||||
void cmd_reconfig_undo(void);
|
||||
void cmd_shutdown(void);
|
||||
|
||||
#define UNIX_DEFAULT_CONFIGURE_TIMEOUT 300
|
||||
|
||||
/* io.c */
|
||||
|
||||
volatile int async_config_flag;
|
||||
|
||||
Reference in New Issue
Block a user