forked from Mirror/frr
Merge pull request #15272 from LabNConsulting/chopps/mgmtd-notif-test
tests: add mgmtd backend notification test
This commit is contained in:
commit
e24f43e64e
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <zebra.h>
|
#include <zebra.h>
|
||||||
#include <lib/version.h>
|
#include <lib/version.h>
|
||||||
|
#include "darr.h"
|
||||||
#include "libfrr.h"
|
#include "libfrr.h"
|
||||||
#include "mgmt_be_client.h"
|
#include "mgmt_be_client.h"
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@
|
||||||
/* Local Prototypes */
|
/* Local Prototypes */
|
||||||
/* ---------------- */
|
/* ---------------- */
|
||||||
|
|
||||||
static void ripd_notification(struct mgmt_be_client *client, uintptr_t usr_data,
|
static void async_notification(struct mgmt_be_client *client, uintptr_t usr_data,
|
||||||
struct mgmt_be_client_notification_cb *this,
|
struct mgmt_be_client_notification_cb *this,
|
||||||
const char *notif_data);
|
const char *notif_data);
|
||||||
|
|
||||||
|
@ -42,7 +43,16 @@ struct zebra_privs_t __privs = {
|
||||||
.cap_num_i = 0,
|
.cap_num_i = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct option longopts[] = {{0}};
|
#define OPTION_LISTEN 2000
|
||||||
|
#define OPTION_NOTIF_COUNT 2001
|
||||||
|
#define OPTION_TIMEOUT 2002
|
||||||
|
const struct option longopts[] = {
|
||||||
|
{ "listen", no_argument, NULL, OPTION_LISTEN },
|
||||||
|
{ "notif-count", required_argument, NULL, OPTION_NOTIF_COUNT },
|
||||||
|
{ "timeout", required_argument, NULL, OPTION_TIMEOUT },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Master of threads. */
|
/* Master of threads. */
|
||||||
struct event_loop *master;
|
struct event_loop *master;
|
||||||
|
@ -85,17 +95,13 @@ FRR_DAEMON_INFO(mgmtd_testc, MGMTD_TESTC,
|
||||||
);
|
);
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
struct mgmt_be_client_notification_cb __notify_cbs[] = { {
|
struct mgmt_be_client_notification_cb *__notify_cbs;
|
||||||
.xpath = "frr-ripd",
|
|
||||||
.format = LYD_JSON,
|
|
||||||
.callback = ripd_notification,
|
|
||||||
} };
|
|
||||||
|
|
||||||
struct mgmt_be_client_cbs __client_cbs = {
|
struct mgmt_be_client_cbs __client_cbs = {};
|
||||||
.notify_cbs = __notify_cbs,
|
struct event *event_timeout;
|
||||||
.nnotify_cbs = array_size(__notify_cbs),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
int o_notif_count = 1;
|
||||||
|
int o_timeout;
|
||||||
|
|
||||||
/* --------- */
|
/* --------- */
|
||||||
/* Functions */
|
/* Functions */
|
||||||
|
@ -107,22 +113,43 @@ static void sigusr1(void)
|
||||||
zlog_rotate();
|
zlog_rotate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void quit(int exit_code)
|
||||||
|
{
|
||||||
|
EVENT_OFF(event_timeout);
|
||||||
|
frr_fini();
|
||||||
|
darr_free(__client_cbs.notify_cbs);
|
||||||
|
exit(exit_code);
|
||||||
|
}
|
||||||
|
|
||||||
static void sigint(void)
|
static void sigint(void)
|
||||||
{
|
{
|
||||||
zlog_notice("Terminating on signal");
|
zlog_notice("Terminating on signal");
|
||||||
frr_fini();
|
quit(0);
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ripd_notification(struct mgmt_be_client *client, uintptr_t usr_data,
|
static void timeout(struct event *event)
|
||||||
|
{
|
||||||
|
zlog_notice("Timeout, exiting");
|
||||||
|
quit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void async_notification(struct mgmt_be_client *client, uintptr_t usr_data,
|
||||||
struct mgmt_be_client_notification_cb *this,
|
struct mgmt_be_client_notification_cb *this,
|
||||||
const char *notif_data)
|
const char *notif_data)
|
||||||
{
|
{
|
||||||
zlog_notice("Received RIPd notification");
|
zlog_notice("Received YANG notification");
|
||||||
|
|
||||||
|
printf("%s\n", notif_data);
|
||||||
|
|
||||||
|
if (o_notif_count && !--o_notif_count)
|
||||||
|
quit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
int f_listen = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
frr_preinit(&mgmtd_testc_di, argc, argv);
|
frr_preinit(&mgmtd_testc_di, argc, argv);
|
||||||
frr_opt_add("", longopts, "");
|
frr_opt_add("", longopts, "");
|
||||||
|
|
||||||
|
@ -135,6 +162,15 @@ int main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
case OPTION_LISTEN:
|
||||||
|
f_listen = 1;
|
||||||
|
break;
|
||||||
|
case OPTION_NOTIF_COUNT:
|
||||||
|
o_notif_count = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case OPTION_TIMEOUT:
|
||||||
|
o_timeout = atoi(optarg);
|
||||||
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -144,10 +180,38 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
master = frr_init();
|
master = frr_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup notification listen
|
||||||
|
*/
|
||||||
|
argv += optind;
|
||||||
|
argc -= optind;
|
||||||
|
if (!argc && f_listen) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Must specify at least one notification xpath to listen to\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (argc && f_listen) {
|
||||||
|
struct mgmt_be_client_notification_cb *cb;
|
||||||
|
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
zlog_notice("Listen on xpath: %s", argv[i]);
|
||||||
|
cb = darr_append(__notify_cbs);
|
||||||
|
cb->xpath = argv[i];
|
||||||
|
cb->format = LYD_JSON;
|
||||||
|
cb->callback = async_notification;
|
||||||
|
}
|
||||||
|
__client_cbs.notify_cbs = __notify_cbs;
|
||||||
|
__client_cbs.nnotify_cbs = darr_len(__notify_cbs);
|
||||||
|
}
|
||||||
|
|
||||||
mgmt_be_client = mgmt_be_client_create("mgmtd-testc", &__client_cbs, 0,
|
mgmt_be_client = mgmt_be_client_create("mgmtd-testc", &__client_cbs, 0,
|
||||||
master);
|
master);
|
||||||
|
|
||||||
frr_config_fork();
|
frr_config_fork();
|
||||||
|
|
||||||
|
if (o_timeout)
|
||||||
|
event_add_timer(master, timeout, NULL, o_timeout, &event_timeout);
|
||||||
|
|
||||||
frr_run(master);
|
frr_run(master);
|
||||||
|
|
||||||
/* Reached. */
|
/* Reached. */
|
||||||
|
|
|
@ -43,7 +43,7 @@ def tgen(request):
|
||||||
tgen.stop_topology()
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
|
||||||
def test_oper_simple(tgen):
|
def test_frontend_notification(tgen):
|
||||||
if tgen.routers_have_failure():
|
if tgen.routers_have_failure():
|
||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
@ -57,9 +57,46 @@ def test_oper_simple(tgen):
|
||||||
if rc:
|
if rc:
|
||||||
pytest.skip("No protoc or present cannot run test")
|
pytest.skip("No protoc or present cannot run test")
|
||||||
|
|
||||||
|
# The first notifications is a frr-ripd:authentication-type-failure
|
||||||
|
# So we filter to avoid that, all the rest are frr-ripd:authentication-failure
|
||||||
|
# making our test deterministic
|
||||||
|
output = r1.cmd_raises(
|
||||||
|
fe_client_path + " --listen frr-ripd:authentication-failure"
|
||||||
|
)
|
||||||
|
jsout = json.loads(output)
|
||||||
|
|
||||||
|
expected = {"frr-ripd:authentication-failure": {"interface-name": "r1-eth0"}}
|
||||||
|
result = json_cmp(jsout, expected)
|
||||||
|
assert result is None
|
||||||
|
|
||||||
output = r1.cmd_raises(fe_client_path + " --listen")
|
output = r1.cmd_raises(fe_client_path + " --listen")
|
||||||
jsout = json.loads(output)
|
jsout = json.loads(output)
|
||||||
|
|
||||||
expected = {"frr-ripd:authentication-type-failure": {"interface-name": "r1-eth0"}}
|
expected = {"frr-ripd:authentication-failure": {"interface-name": "r1-eth0"}}
|
||||||
|
result = json_cmp(jsout, expected)
|
||||||
|
assert result is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_backend_notification(tgen):
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
r1 = tgen.gears["r1"].net
|
||||||
|
|
||||||
|
check_kernel_32(r1, "11.11.11.11", 1, "")
|
||||||
|
|
||||||
|
be_client_path = "/usr/lib/frr/mgmtd_testc"
|
||||||
|
rc, _, _ = r1.cmd_status(be_client_path + " --help")
|
||||||
|
|
||||||
|
if rc:
|
||||||
|
pytest.skip("No mgmtd_testc")
|
||||||
|
|
||||||
|
output = r1.cmd_raises(
|
||||||
|
be_client_path + " --timeout 20 --log file:mgmt_testc.log --listen frr-ripd"
|
||||||
|
)
|
||||||
|
|
||||||
|
jsout = json.loads(output)
|
||||||
|
|
||||||
|
expected = {"frr-ripd:authentication-failure": {"interface-name": "r1-eth0"}}
|
||||||
result = json_cmp(jsout, expected)
|
result = json_cmp(jsout, expected)
|
||||||
assert result is None
|
assert result is None
|
||||||
|
|
Loading…
Reference in a new issue