mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 12:25:02 +00:00
Merge pull request #13763 from LabNConsulting/mgmtd/simplify
fix 'exit' bug in config file processing, et al.
This commit is contained in:
commit
e0db9a05bd
@ -21,7 +21,7 @@
|
|||||||
#include "lib/mgmt_be_client_clippy.c"
|
#include "lib/mgmt_be_client_clippy.c"
|
||||||
|
|
||||||
#define MGMTD_BE_CLIENT_DBG(fmt, ...) \
|
#define MGMTD_BE_CLIENT_DBG(fmt, ...) \
|
||||||
DEBUGD(&mgmt_dbg_be_client, "BE-CLIENT: %s:" fmt, __func__, \
|
DEBUGD(&mgmt_dbg_be_client, "BE-CLIENT: %s: " fmt, __func__, \
|
||||||
##__VA_ARGS__)
|
##__VA_ARGS__)
|
||||||
#define MGMTD_BE_CLIENT_ERR(fmt, ...) \
|
#define MGMTD_BE_CLIENT_ERR(fmt, ...) \
|
||||||
zlog_err("BE-CLIENT: %s: ERROR: " fmt, __func__, ##__VA_ARGS__)
|
zlog_err("BE-CLIENT: %s: ERROR: " fmt, __func__, ##__VA_ARGS__)
|
||||||
|
@ -124,18 +124,15 @@ static int mgmt_fe_send_session_req(struct mgmt_fe_client *client,
|
|||||||
{
|
{
|
||||||
Mgmtd__FeMessage fe_msg;
|
Mgmtd__FeMessage fe_msg;
|
||||||
Mgmtd__FeSessionReq sess_req;
|
Mgmtd__FeSessionReq sess_req;
|
||||||
bool scok;
|
|
||||||
|
|
||||||
mgmtd__fe_session_req__init(&sess_req);
|
mgmtd__fe_session_req__init(&sess_req);
|
||||||
sess_req.create = create;
|
sess_req.create = create;
|
||||||
if (create) {
|
if (create) {
|
||||||
sess_req.id_case = MGMTD__FE_SESSION_REQ__ID_CLIENT_CONN_ID;
|
sess_req.id_case = MGMTD__FE_SESSION_REQ__ID_CLIENT_CONN_ID;
|
||||||
sess_req.client_conn_id = session->client_id;
|
sess_req.client_conn_id = session->client_id;
|
||||||
scok = true;
|
|
||||||
} else {
|
} else {
|
||||||
sess_req.id_case = MGMTD__FE_SESSION_REQ__ID_SESSION_ID;
|
sess_req.id_case = MGMTD__FE_SESSION_REQ__ID_SESSION_ID;
|
||||||
sess_req.session_id = session->session_id;
|
sess_req.session_id = session->session_id;
|
||||||
scok = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mgmtd__fe_message__init(&fe_msg);
|
mgmtd__fe_message__init(&fe_msg);
|
||||||
@ -146,7 +143,7 @@ static int mgmt_fe_send_session_req(struct mgmt_fe_client *client,
|
|||||||
"Sending SESSION_REQ %s message for client-id %" PRIu64,
|
"Sending SESSION_REQ %s message for client-id %" PRIu64,
|
||||||
create ? "create" : "destroy", session->client_id);
|
create ? "create" : "destroy", session->client_id);
|
||||||
|
|
||||||
return mgmt_fe_client_send_msg(client, &fe_msg, scok);
|
return mgmt_fe_client_send_msg(client, &fe_msg, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mgmt_fe_send_lockds_req(struct mgmt_fe_client *client, uint64_t session_id,
|
int mgmt_fe_send_lockds_req(struct mgmt_fe_client *client, uint64_t session_id,
|
||||||
|
@ -120,7 +120,7 @@ struct mgmt_fe_client_cbs {
|
|||||||
extern struct debug mgmt_dbg_fe_client;
|
extern struct debug mgmt_dbg_fe_client;
|
||||||
|
|
||||||
#define MGMTD_FE_CLIENT_DBG(fmt, ...) \
|
#define MGMTD_FE_CLIENT_DBG(fmt, ...) \
|
||||||
DEBUGD(&mgmt_dbg_fe_client, "FE-CLIENT: %s:" fmt, __func__, \
|
DEBUGD(&mgmt_dbg_fe_client, "FE-CLIENT: %s: " fmt, __func__, \
|
||||||
##__VA_ARGS__)
|
##__VA_ARGS__)
|
||||||
#define MGMTD_FE_CLIENT_ERR(fmt, ...) \
|
#define MGMTD_FE_CLIENT_ERR(fmt, ...) \
|
||||||
zlog_err("FE-CLIENT: %s: ERROR: " fmt, __func__, ##__VA_ARGS__)
|
zlog_err("FE-CLIENT: %s: ERROR: " fmt, __func__, ##__VA_ARGS__)
|
||||||
|
12
lib/vty.c
12
lib/vty.c
@ -2423,6 +2423,14 @@ void vty_close(struct vty *vty)
|
|||||||
|
|
||||||
vty->status = VTY_CLOSE;
|
vty->status = VTY_CLOSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we reach here with pending config to commit we will be losing it
|
||||||
|
* so warn the user.
|
||||||
|
*/
|
||||||
|
if (vty->mgmt_num_pending_setcfg)
|
||||||
|
MGMTD_FE_CLIENT_ERR(
|
||||||
|
"vty closed, uncommitted config will be lost.");
|
||||||
|
|
||||||
if (mgmt_fe_client && vty->mgmt_session_id) {
|
if (mgmt_fe_client && vty->mgmt_session_id) {
|
||||||
MGMTD_FE_CLIENT_DBG("closing vty session");
|
MGMTD_FE_CLIENT_DBG("closing vty session");
|
||||||
mgmt_fe_destroy_client_session(mgmt_fe_client,
|
mgmt_fe_destroy_client_session(mgmt_fe_client,
|
||||||
@ -3445,7 +3453,9 @@ static void vty_mgmt_session_notify(struct mgmt_fe_client *client,
|
|||||||
vty->mgmt_session_id = session_id;
|
vty->mgmt_session_id = session_id;
|
||||||
} else {
|
} else {
|
||||||
vty->mgmt_session_id = 0;
|
vty->mgmt_session_id = 0;
|
||||||
vty_close(vty);
|
/* We may come here by way of vty_close() and short-circuits */
|
||||||
|
if (vty->status != VTY_CLOSE)
|
||||||
|
vty_close(vty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include "mgmtd/mgmt_be_adapter.h"
|
#include "mgmtd/mgmt_be_adapter.h"
|
||||||
|
|
||||||
#define MGMTD_BE_ADAPTER_DBG(fmt, ...) \
|
#define MGMTD_BE_ADAPTER_DBG(fmt, ...) \
|
||||||
DEBUGD(&mgmt_debug_be, "BE-ADAPTER: %s:" fmt, __func__, ##__VA_ARGS__)
|
DEBUGD(&mgmt_debug_be, "BE-ADAPTER: %s: " fmt, __func__, ##__VA_ARGS__)
|
||||||
#define MGMTD_BE_ADAPTER_ERR(fmt, ...) \
|
#define MGMTD_BE_ADAPTER_ERR(fmt, ...) \
|
||||||
zlog_err("BE-ADAPTER: %s: ERROR: " fmt, __func__, ##__VA_ARGS__)
|
zlog_err("BE-ADAPTER: %s: ERROR: " fmt, __func__, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include "libyang/libyang.h"
|
#include "libyang/libyang.h"
|
||||||
|
|
||||||
#define MGMTD_DS_DBG(fmt, ...) \
|
#define MGMTD_DS_DBG(fmt, ...) \
|
||||||
DEBUGD(&mgmt_debug_ds, "%s:" fmt, __func__, ##__VA_ARGS__)
|
DEBUGD(&mgmt_debug_ds, "DS: %s: " fmt, __func__, ##__VA_ARGS__)
|
||||||
#define MGMTD_DS_ERR(fmt, ...) \
|
#define MGMTD_DS_ERR(fmt, ...) \
|
||||||
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
|
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include "mgmtd/mgmt_fe_adapter.h"
|
#include "mgmtd/mgmt_fe_adapter.h"
|
||||||
|
|
||||||
#define MGMTD_FE_ADAPTER_DBG(fmt, ...) \
|
#define MGMTD_FE_ADAPTER_DBG(fmt, ...) \
|
||||||
DEBUGD(&mgmt_debug_fe, "FE-ADAPTER: %s:" fmt, __func__, ##__VA_ARGS__)
|
DEBUGD(&mgmt_debug_fe, "FE-ADAPTER: %s: " fmt, __func__, ##__VA_ARGS__)
|
||||||
#define MGMTD_FE_ADAPTER_ERR(fmt, ...) \
|
#define MGMTD_FE_ADAPTER_ERR(fmt, ...) \
|
||||||
zlog_err("FE-ADAPTER: %s: ERROR: " fmt, __func__, ##__VA_ARGS__)
|
zlog_err("FE-ADAPTER: %s: ERROR: " fmt, __func__, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include "mgmtd/mgmt_txn.h"
|
#include "mgmtd/mgmt_txn.h"
|
||||||
|
|
||||||
#define MGMTD_TXN_DBG(fmt, ...) \
|
#define MGMTD_TXN_DBG(fmt, ...) \
|
||||||
DEBUGD(&mgmt_debug_txn, "%s:" fmt, __func__, ##__VA_ARGS__)
|
DEBUGD(&mgmt_debug_txn, "TXN: %s: " fmt, __func__, ##__VA_ARGS__)
|
||||||
#define MGMTD_TXN_ERR(fmt, ...) \
|
#define MGMTD_TXN_ERR(fmt, ...) \
|
||||||
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
|
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
|
||||||
|
|
||||||
@ -2618,26 +2618,6 @@ int mgmt_txn_notify_be_cfg_apply_reply(uint64_t txn_id, bool success,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mgmt_txn_send_commit_config_reply(uint64_t txn_id,
|
|
||||||
enum mgmt_result result,
|
|
||||||
const char *error_if_any)
|
|
||||||
{
|
|
||||||
struct mgmt_txn_ctx *txn;
|
|
||||||
|
|
||||||
txn = mgmt_txn_id2ctx(txn_id);
|
|
||||||
if (!txn)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!txn->commit_cfg_req) {
|
|
||||||
MGMTD_TXN_ERR("NO commit in-progress txn-id: %" PRIu64
|
|
||||||
" session-id: %" PRIu64,
|
|
||||||
txn->txn_id, txn->session_id);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mgmt_txn_send_commit_cfg_reply(txn, result, error_if_any);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mgmt_txn_send_get_config_req(uint64_t txn_id, uint64_t req_id,
|
int mgmt_txn_send_get_config_req(uint64_t txn_id, uint64_t req_id,
|
||||||
Mgmtd__DatastoreId ds_id,
|
Mgmtd__DatastoreId ds_id,
|
||||||
struct mgmt_ds_ctx *ds_ctx,
|
struct mgmt_ds_ctx *ds_ctx,
|
||||||
|
@ -176,10 +176,6 @@ extern int mgmt_txn_send_commit_config_req(uint64_t txn_id, uint64_t req_id,
|
|||||||
bool validate_only, bool abort,
|
bool validate_only, bool abort,
|
||||||
bool implicit);
|
bool implicit);
|
||||||
|
|
||||||
extern int mgmt_txn_send_commit_config_reply(uint64_t txn_id,
|
|
||||||
enum mgmt_result result,
|
|
||||||
const char *error_if_any);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send get-config request to be processed later in transaction.
|
* Send get-config request to be processed later in transaction.
|
||||||
*
|
*
|
||||||
|
@ -56,11 +56,11 @@ struct event_loop *master;
|
|||||||
struct mgmt_be_client *mgmt_be_client;
|
struct mgmt_be_client *mgmt_be_client;
|
||||||
|
|
||||||
static struct frr_daemon_info staticd_di;
|
static struct frr_daemon_info staticd_di;
|
||||||
|
|
||||||
/* SIGHUP handler. */
|
/* SIGHUP handler. */
|
||||||
static void sighup(void)
|
static void sighup(void)
|
||||||
{
|
{
|
||||||
zlog_info("SIGHUP received");
|
zlog_info("SIGHUP received and ignored");
|
||||||
vty_read_config(NULL, staticd_di.config_file, config_default);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SIGINT / SIGTERM handler. */
|
/* SIGINT / SIGTERM handler. */
|
||||||
|
6
tests/topotests/mgmt_config/r1/early-end-zebra.conf
Normal file
6
tests/topotests/mgmt_config/r1/early-end-zebra.conf
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
allow-external-route-update
|
||||||
|
end
|
||||||
|
ip multicast rpf-lookup-mode urib-only
|
||||||
|
end
|
||||||
|
ip table range 2 3
|
||||||
|
end
|
8
tests/topotests/mgmt_config/r1/early-end.conf
Normal file
8
tests/topotests/mgmt_config/r1/early-end.conf
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ip route 15.1.0.0/24 101.0.0.2
|
||||||
|
end
|
||||||
|
ip route 15.2.0.0/24 101.0.0.2
|
||||||
|
end
|
||||||
|
ip route 15.3.0.0/24 101.0.0.2
|
||||||
|
end
|
||||||
|
ip route 15.4.0.0/24 101.0.0.2
|
||||||
|
end
|
7
tests/topotests/mgmt_config/r1/early-end2-zebra.conf
Normal file
7
tests/topotests/mgmt_config/r1/early-end2-zebra.conf
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
conf t
|
||||||
|
allow-external-route-update
|
||||||
|
end
|
||||||
|
ip multicast rpf-lookup-mode urib-only
|
||||||
|
end
|
||||||
|
ip table range 2 3
|
||||||
|
end
|
9
tests/topotests/mgmt_config/r1/early-end2.conf
Normal file
9
tests/topotests/mgmt_config/r1/early-end2.conf
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
conf t
|
||||||
|
ip route 16.1.0.0/24 101.0.0.2
|
||||||
|
end
|
||||||
|
ip route 16.2.0.0/24 101.0.0.2
|
||||||
|
end
|
||||||
|
ip route 16.3.0.0/24 101.0.0.2
|
||||||
|
end
|
||||||
|
ip route 16.4.0.0/24 101.0.0.2
|
||||||
|
end
|
6
tests/topotests/mgmt_config/r1/early-exit-zebra.conf
Normal file
6
tests/topotests/mgmt_config/r1/early-exit-zebra.conf
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
allow-external-route-update
|
||||||
|
exit
|
||||||
|
ip multicast rpf-lookup-mode urib-only
|
||||||
|
exit
|
||||||
|
ip table range 2 3
|
||||||
|
exit
|
8
tests/topotests/mgmt_config/r1/early-exit.conf
Normal file
8
tests/topotests/mgmt_config/r1/early-exit.conf
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ip route 13.1.0.0/24 101.0.0.2
|
||||||
|
exit
|
||||||
|
ip route 13.2.0.0/24 101.0.0.2
|
||||||
|
exit
|
||||||
|
ip route 13.3.0.0/24 101.0.0.2
|
||||||
|
exit
|
||||||
|
ip route 13.4.0.0/24 101.0.0.2
|
||||||
|
exit
|
7
tests/topotests/mgmt_config/r1/early-exit2-zebra.conf
Normal file
7
tests/topotests/mgmt_config/r1/early-exit2-zebra.conf
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
conf t
|
||||||
|
allow-external-route-update
|
||||||
|
exit
|
||||||
|
ip multicast rpf-lookup-mode urib-only
|
||||||
|
exit
|
||||||
|
ip table range 2 3
|
||||||
|
exit
|
9
tests/topotests/mgmt_config/r1/early-exit2.conf
Normal file
9
tests/topotests/mgmt_config/r1/early-exit2.conf
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
conf t
|
||||||
|
ip route 14.1.0.0/24 101.0.0.2
|
||||||
|
exit
|
||||||
|
ip route 14.2.0.0/24 101.0.0.2
|
||||||
|
exit
|
||||||
|
ip route 14.3.0.0/24 101.0.0.2
|
||||||
|
exit
|
||||||
|
ip route 14.4.0.0/24 101.0.0.2
|
||||||
|
exit
|
11
tests/topotests/mgmt_config/r1/mgmtd.conf
Normal file
11
tests/topotests/mgmt_config/r1/mgmtd.conf
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
debug northbound notifications
|
||||||
|
debug northbound libyang
|
||||||
|
debug northbound events
|
||||||
|
debug northbound callbacks
|
||||||
|
debug mgmt backend datastore frontend transaction
|
||||||
|
debug mgmt client backend
|
||||||
|
debug mgmt client frontend
|
||||||
|
|
||||||
|
ip route 12.0.0.0/24 101.0.0.2
|
||||||
|
|
||||||
|
ipv6 route 2012::/48 2101::2
|
8
tests/topotests/mgmt_config/r1/normal-exit.conf
Normal file
8
tests/topotests/mgmt_config/r1/normal-exit.conf
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ip route 13.1.0.0/24 101.0.0.2
|
||||||
|
exit
|
||||||
|
ip route 13.2.0.0/24 101.0.0.2
|
||||||
|
exit
|
||||||
|
ip route 13.3.0.0/24 101.0.0.2
|
||||||
|
exit
|
||||||
|
ip route 13.4.0.0/24 101.0.0.2
|
||||||
|
exit
|
3
tests/topotests/mgmt_config/r1/one-exit-zebra.conf
Normal file
3
tests/topotests/mgmt_config/r1/one-exit-zebra.conf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
allow-external-route-update
|
||||||
|
exit
|
||||||
|
ip multicast rpf-lookup-mode urib-only
|
3
tests/topotests/mgmt_config/r1/one-exit.conf
Normal file
3
tests/topotests/mgmt_config/r1/one-exit.conf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
ip route 20.1.0.0/24 101.0.0.2
|
||||||
|
exit
|
||||||
|
ip route 20.2.0.0/24 101.0.0.2
|
4
tests/topotests/mgmt_config/r1/one-exit2-zebra.conf
Normal file
4
tests/topotests/mgmt_config/r1/one-exit2-zebra.conf
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
conf t
|
||||||
|
allow-external-route-update
|
||||||
|
exit
|
||||||
|
ip multicast rpf-lookup-mode urib-only
|
4
tests/topotests/mgmt_config/r1/one-exit2.conf
Normal file
4
tests/topotests/mgmt_config/r1/one-exit2.conf
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
conf t
|
||||||
|
ip route 21.1.0.0/24 101.0.0.2
|
||||||
|
exit
|
||||||
|
ip route 21.2.0.0/24 101.0.0.2
|
7
tests/topotests/mgmt_config/r1/zebra.conf
Normal file
7
tests/topotests/mgmt_config/r1/zebra.conf
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
log timestamp precision 6
|
||||||
|
log file frr-r1.log debug
|
||||||
|
|
||||||
|
interface r1-eth0
|
||||||
|
ip address 101.0.0.1/24
|
||||||
|
ipv6 address 2101::1/64
|
||||||
|
exit
|
385
tests/topotests/mgmt_config/test_config.py
Normal file
385
tests/topotests/mgmt_config/test_config.py
Normal file
@ -0,0 +1,385 @@
|
|||||||
|
# -*- coding: utf-8 eval: (blacken-mode 1) -*-
|
||||||
|
# SPDX-License-Identifier: ISC
|
||||||
|
#
|
||||||
|
# June 10 2023, Christian Hopps <chopps@labn.net>
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023, LabN Consulting, L.L.C.
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
Test mgmtd parsing of configs.
|
||||||
|
|
||||||
|
So:
|
||||||
|
|
||||||
|
MGMTD matches zebra:
|
||||||
|
|
||||||
|
one exit file: ONE: vty -f file
|
||||||
|
one exit redir: ONE: vty < file
|
||||||
|
early exit file: ONE: vty -f file
|
||||||
|
early exit redir: ONE: vty < file
|
||||||
|
early end file: ALL: vty -f file
|
||||||
|
early end redir: ONE: vty < file
|
||||||
|
|
||||||
|
Raw tests:
|
||||||
|
|
||||||
|
FAILED mgmt_config/test_config.py::test_mgmtd_one_exit_file - AssertionError: vtysh < didn't work after exit
|
||||||
|
FAILED mgmt_config/test_config.py::test_mgmtd_one_exit_redir - AssertionError: vtysh < didn't work after exit
|
||||||
|
FAILED mgmt_config/test_config.py::test_mgmtd_early_exit_file - AssertionError: vtysh -f didn't work after 1 exit
|
||||||
|
FAILED mgmt_config/test_config.py::test_mgmtd_early_exit_redir - AssertionError: vtysh < didn't work after 1 exits
|
||||||
|
FAILED mgmt_config/test_config.py::test_mgmtd_early_end_redir - AssertionError: vtysh < didn't work after 1 end
|
||||||
|
|
||||||
|
FAILED mgmt_config/test_config.py::test_zebra_one_exit_file - AssertionError: zebra second conf missing
|
||||||
|
FAILED mgmt_config/test_config.py::test_zebra_one_exit_redir - AssertionError: zebra second conf missing
|
||||||
|
FAILED mgmt_config/test_config.py::test_zebra_early_exit_file - AssertionError: zebra second conf missing
|
||||||
|
FAILED mgmt_config/test_config.py::test_zebra_early_exit_redir - AssertionError: zebra second conf missing
|
||||||
|
FAILED mgmt_config/test_config.py::test_zebra_early_end_redir - AssertionError: zebra second conf missing
|
||||||
|
|
||||||
|
Before fixed:
|
||||||
|
|
||||||
|
one exit file: NONE: vty -f file
|
||||||
|
early exit file: NONE: vty -f file
|
||||||
|
|
||||||
|
FAILED mgmt_config/test_config.py::test_mgmtd_one_exit_file - AssertionError: vtysh -f didn't work before exit
|
||||||
|
FAILED mgmt_config/test_config.py::test_mgmtd_one_exit_redir - AssertionError: vtysh < didn't work after exit
|
||||||
|
FAILED mgmt_config/test_config.py::test_mgmtd_early_exit_file - AssertionError: vtysh -f didn't work before exit
|
||||||
|
FAILED mgmt_config/test_config.py::test_mgmtd_early_exit_redir - AssertionError: vtysh < didn't work after 1 exits
|
||||||
|
FAILED mgmt_config/test_config.py::test_mgmtd_early_end_redir - AssertionError: vtysh < didn't work after 1 end
|
||||||
|
|
||||||
|
FAILED mgmt_config/test_config.py::test_zebra_one_exit_file - AssertionError: zebra second conf missing
|
||||||
|
FAILED mgmt_config/test_config.py::test_zebra_one_exit_redir - AssertionError: zebra second conf missing
|
||||||
|
FAILED mgmt_config/test_config.py::test_zebra_early_exit_file - AssertionError: zebra second conf missing
|
||||||
|
FAILED mgmt_config/test_config.py::test_zebra_early_exit_redir - AssertionError: zebra second conf missing
|
||||||
|
FAILED mgmt_config/test_config.py::test_zebra_early_end_redir - AssertionError: zebra second conf missing
|
||||||
|
|
||||||
|
"""
|
||||||
|
import ipaddress
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from lib.common_config import retry, step
|
||||||
|
from lib.topogen import Topogen, TopoRouter
|
||||||
|
|
||||||
|
# pytestmark = [pytest.mark.staticd, pytest.mark.mgmtd]
|
||||||
|
pytestmark = [pytest.mark.staticd]
|
||||||
|
|
||||||
|
|
||||||
|
@retry(retry_timeout=1, initial_wait=0.1)
|
||||||
|
def check_kernel(r1, prefix, expected=True):
|
||||||
|
net = ipaddress.ip_network(prefix)
|
||||||
|
if net.version == 6:
|
||||||
|
kernel = r1.cmd_nostatus("ip -6 route show", warn=not expected)
|
||||||
|
else:
|
||||||
|
kernel = r1.cmd_nostatus("ip -4 route show", warn=not expected)
|
||||||
|
|
||||||
|
logging.debug("checking kernel routing table:\n%0.1920s", kernel)
|
||||||
|
route = f"{str(net)}(?: nhid [0-9]+)?.*proto (static|196)"
|
||||||
|
m = re.search(route, kernel)
|
||||||
|
if expected and not m:
|
||||||
|
return f"Failed to find \n'{route}'\n in \n'{kernel:.1920}'"
|
||||||
|
elif not expected and m:
|
||||||
|
return f"Failed found \n'{route}'\n in \n'{kernel:.1920}'"
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def tgen(request):
|
||||||
|
"Setup/Teardown the environment and provide tgen argument to tests"
|
||||||
|
|
||||||
|
topodef = {"s1": ("r1",)}
|
||||||
|
|
||||||
|
tgen = Topogen(topodef, request.module.__name__)
|
||||||
|
tgen.start_topology()
|
||||||
|
|
||||||
|
# configure mgmtd using current mgmtd config file
|
||||||
|
tgen.gears["r1"].load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
|
||||||
|
tgen.gears["r1"].load_config(TopoRouter.RD_MGMTD)
|
||||||
|
|
||||||
|
tgen.start_router()
|
||||||
|
yield tgen
|
||||||
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
|
||||||
|
def save_log_snippet(logfile, content, savepath=None):
|
||||||
|
os.sync()
|
||||||
|
os.sync()
|
||||||
|
os.sync()
|
||||||
|
|
||||||
|
with open(logfile, encoding="utf-8") as f:
|
||||||
|
buf = f.read()
|
||||||
|
assert content == buf[: len(content)]
|
||||||
|
newcontent = buf[len(content) :]
|
||||||
|
|
||||||
|
if savepath:
|
||||||
|
with open(savepath, "w", encoding="utf-8") as f:
|
||||||
|
f.write(newcontent)
|
||||||
|
|
||||||
|
return buf
|
||||||
|
|
||||||
|
|
||||||
|
def mapname(lname):
|
||||||
|
return lname.replace(".conf", "") + "-log.txt"
|
||||||
|
|
||||||
|
|
||||||
|
logbuf = ""
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def r1(tgen):
|
||||||
|
return tgen.gears["r1"].net
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def confdir():
|
||||||
|
return Path(os.environ["PYTEST_TOPOTEST_SCRIPTDIR"]) / "r1"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def tempdir(r1):
|
||||||
|
return Path(r1.rundir)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def logpath(tempdir):
|
||||||
|
return tempdir / "mgmtd.log"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True, scope="function")
|
||||||
|
def cleanup_config(r1, tempdir, logpath):
|
||||||
|
global logbuf
|
||||||
|
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, "/dev/null")
|
||||||
|
|
||||||
|
yield
|
||||||
|
|
||||||
|
r1.cmd_nostatus("vtysh -c 'conf t' -c 'no allow-external-route-update'")
|
||||||
|
r1.cmd_nostatus("vtysh -c 'conf t' -c 'no ip multicast rpf-lookup-mode urib-only'")
|
||||||
|
r1.cmd_nostatus("vtysh -c 'conf t' -c 'no ip table range 2 3'")
|
||||||
|
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, "/dev/null")
|
||||||
|
|
||||||
|
|
||||||
|
def test_staticd_startup(r1):
|
||||||
|
r1.cmd_nostatus(
|
||||||
|
"vtysh -c 'debug mgmt client frontend' "
|
||||||
|
"-c 'debug mgmt client backend' "
|
||||||
|
"-c 'debug mgmt backend frontend datastore transaction'"
|
||||||
|
)
|
||||||
|
step("Verifying routes are present on r1")
|
||||||
|
result = check_kernel(r1, "12.0.0.0/24", retry_timeout=3.0)
|
||||||
|
assert result is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_mgmtd_one_exit_file(r1, confdir, tempdir, logpath):
|
||||||
|
global logbuf
|
||||||
|
|
||||||
|
conf = "one-exit.conf"
|
||||||
|
step(f"load {conf} file with vtysh -f ")
|
||||||
|
output = r1.cmd_nostatus(f"vtysh -f {confdir / conf}")
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf))
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
result1 = check_kernel(r1, "20.1.0.0/24")
|
||||||
|
result2 = check_kernel(r1, "20.2.0.0/24")
|
||||||
|
|
||||||
|
assert result1 is None, "vtysh -f didn't work before exit"
|
||||||
|
assert result2 is not None, "vtysh < worked after exit, unexpected"
|
||||||
|
|
||||||
|
|
||||||
|
def test_mgmtd_one_exit_redir(r1, confdir, tempdir, logpath):
|
||||||
|
global logbuf
|
||||||
|
|
||||||
|
conf = "one-exit2.conf"
|
||||||
|
step(f"Redirect {conf} file into vtysh")
|
||||||
|
output = r1.cmd_nostatus(f"vtysh < {confdir / conf}")
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf))
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
result1 = check_kernel(r1, "21.1.0.0/24")
|
||||||
|
result2 = check_kernel(r1, "21.2.0.0/24")
|
||||||
|
|
||||||
|
assert result1 is None, "vtysh < didn't work before exit"
|
||||||
|
assert result2 is not None, "vtysh < worked after exit, unexpected"
|
||||||
|
|
||||||
|
|
||||||
|
def test_mgmtd_early_exit_file(r1, confdir, tempdir, logpath):
|
||||||
|
global logbuf
|
||||||
|
|
||||||
|
conf = "early-exit.conf"
|
||||||
|
step(f"load {conf} file with vtysh -f ")
|
||||||
|
output = r1.cmd_nostatus(f"vtysh -f {confdir / conf}")
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf))
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
result1 = check_kernel(r1, "13.1.0.0/24")
|
||||||
|
result2 = check_kernel(r1, "13.2.0.0/24")
|
||||||
|
result3 = check_kernel(r1, "13.3.0.0/24")
|
||||||
|
|
||||||
|
assert result1 is None, "vtysh -f didn't work before exit"
|
||||||
|
assert result2 is not None, "vtysh -f worked after 1 exit, unexpected"
|
||||||
|
assert result3 is not None, "vtysh -f worked after 2 exit, unexpected"
|
||||||
|
|
||||||
|
|
||||||
|
def test_mgmtd_early_exit_redir(r1, confdir, tempdir, logpath):
|
||||||
|
global logbuf
|
||||||
|
|
||||||
|
conf = "early-exit2.conf"
|
||||||
|
step(f"Redirect {conf} file into vtysh")
|
||||||
|
output = r1.cmd_nostatus(f"vtysh < {confdir / conf}")
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf))
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
result1 = check_kernel(r1, "14.1.0.0/24")
|
||||||
|
result2 = check_kernel(r1, "14.2.0.0/24")
|
||||||
|
result3 = check_kernel(r1, "14.3.0.0/24")
|
||||||
|
|
||||||
|
assert result1 is None, "vtysh < didn't work before exit"
|
||||||
|
assert result2 is not None, "vtysh < worked after 1 exits, unexpected"
|
||||||
|
assert result3 is not None, "vtysh < worked after 2 exits, unexpected"
|
||||||
|
|
||||||
|
|
||||||
|
def test_mgmtd_early_end_file(r1, confdir, tempdir, logpath):
|
||||||
|
global logbuf
|
||||||
|
|
||||||
|
conf = "early-end.conf"
|
||||||
|
step(f"load {conf} file with vtysh -f ")
|
||||||
|
output = r1.cmd_nostatus(f"vtysh -f {confdir / conf}")
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf))
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
result1 = check_kernel(r1, "15.1.0.0/24")
|
||||||
|
result2 = check_kernel(r1, "15.2.0.0/24")
|
||||||
|
result3 = check_kernel(r1, "15.3.0.0/24")
|
||||||
|
|
||||||
|
assert result1 is None, "vtysh -f didn't work before end"
|
||||||
|
assert result2 is None, "vtysh -f didn't work after 1 end"
|
||||||
|
assert result3 is None, "vtysh -f didn't work after 2 ends"
|
||||||
|
|
||||||
|
|
||||||
|
def test_mgmtd_early_end_redir(r1, confdir, tempdir, logpath):
|
||||||
|
global logbuf
|
||||||
|
|
||||||
|
conf = "early-end2.conf"
|
||||||
|
step(f"Redirect {conf} file into vtysh")
|
||||||
|
output = r1.cmd_nostatus(f"vtysh < {confdir / conf}")
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf))
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
result1 = check_kernel(r1, "16.1.0.0/24")
|
||||||
|
result2 = check_kernel(r1, "16.2.0.0/24")
|
||||||
|
result3 = check_kernel(r1, "16.3.0.0/24")
|
||||||
|
|
||||||
|
assert result1 is None, "vtysh < didn't work before end"
|
||||||
|
assert result2 is not None, "vtysh < worked after 1 end, unexpected"
|
||||||
|
assert result3 is not None, "vtysh < worked after 2 end, unexpected"
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Zebra
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
def test_zebra_one_exit_file(r1, confdir, tempdir, logpath):
|
||||||
|
global logbuf
|
||||||
|
|
||||||
|
conf = "one-exit-zebra.conf"
|
||||||
|
step(f"load {conf} file with vtysh -f ")
|
||||||
|
output = r1.cmd_nostatus(f"vtysh -f {confdir / conf}")
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf))
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
showrun = r1.cmd_nostatus("vtysh -c 'show running'")
|
||||||
|
assert "allow-external-route-update" in showrun, "zebra conf missing"
|
||||||
|
assert (
|
||||||
|
"ip multicast rpf-lookup-mode urib-only" not in showrun
|
||||||
|
), "zebra second conf present, unexpected"
|
||||||
|
|
||||||
|
|
||||||
|
def test_zebra_one_exit_redir(r1, confdir, tempdir, logpath):
|
||||||
|
global logbuf
|
||||||
|
|
||||||
|
conf = "one-exit2-zebra.conf"
|
||||||
|
step(f"Redirect {conf} file into vtysh")
|
||||||
|
output = r1.cmd_nostatus(f"vtysh < {confdir / conf}")
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf))
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
showrun = r1.cmd_nostatus("vtysh -c 'show running'")
|
||||||
|
|
||||||
|
assert "allow-external-route-update" in showrun, "zebra conf missing"
|
||||||
|
assert (
|
||||||
|
"ip multicast rpf-lookup-mode urib-only" not in showrun
|
||||||
|
), "zebra second conf present, unexpected"
|
||||||
|
|
||||||
|
|
||||||
|
def test_zebra_early_exit_file(r1, confdir, tempdir, logpath):
|
||||||
|
global logbuf
|
||||||
|
|
||||||
|
conf = "early-exit-zebra.conf"
|
||||||
|
step(f"load {conf} file with vtysh -f ")
|
||||||
|
output = r1.cmd_nostatus(f"vtysh -f {confdir / conf}")
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf))
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
showrun = r1.cmd_nostatus("vtysh -c 'show running'")
|
||||||
|
|
||||||
|
assert "allow-external-route-update" in showrun, "zebra conf missing"
|
||||||
|
assert (
|
||||||
|
"ip multicast rpf-lookup-mode urib-only" not in showrun
|
||||||
|
), "zebra second conf present, unexpected"
|
||||||
|
assert "ip table range 2 3" not in showrun, "zebra third conf present, unexpected"
|
||||||
|
|
||||||
|
|
||||||
|
def test_zebra_early_exit_redir(r1, confdir, tempdir, logpath):
|
||||||
|
global logbuf
|
||||||
|
|
||||||
|
conf = "early-exit2-zebra.conf"
|
||||||
|
step(f"Redirect {conf} file into vtysh")
|
||||||
|
output = r1.cmd_nostatus(f"vtysh < {confdir / conf}")
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf))
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
showrun = r1.cmd_nostatus("vtysh -c 'show running'")
|
||||||
|
|
||||||
|
assert "allow-external-route-update" in showrun, "zebra conf missing"
|
||||||
|
assert (
|
||||||
|
"ip multicast rpf-lookup-mode urib-only" not in showrun
|
||||||
|
), "zebra second conf present, unexpected"
|
||||||
|
assert "ip table range 2 3" not in showrun, "zebra third conf present, unexpected"
|
||||||
|
|
||||||
|
|
||||||
|
def test_zebra_early_end_file(r1, confdir, tempdir, logpath):
|
||||||
|
global logbuf
|
||||||
|
|
||||||
|
conf = "early-end-zebra.conf"
|
||||||
|
step(f"load {conf} file with vtysh -f ")
|
||||||
|
output = r1.cmd_nostatus(f"vtysh -f {confdir / conf}")
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf))
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
showrun = r1.cmd_nostatus("vtysh -c 'show running'")
|
||||||
|
|
||||||
|
assert "allow-external-route-update" in showrun, "zebra conf missing"
|
||||||
|
assert (
|
||||||
|
"ip multicast rpf-lookup-mode urib-only" in showrun
|
||||||
|
), "zebra second conf missing"
|
||||||
|
assert "ip table range 2 3" in showrun, "zebra third missing"
|
||||||
|
|
||||||
|
|
||||||
|
def test_zebra_early_end_redir(r1, confdir, tempdir, logpath):
|
||||||
|
global logbuf
|
||||||
|
|
||||||
|
conf = "early-end2-zebra.conf"
|
||||||
|
step(f"Redirect {conf} file into vtysh")
|
||||||
|
output = r1.cmd_nostatus(f"vtysh < {confdir / conf}")
|
||||||
|
logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf))
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
showrun = r1.cmd_nostatus("vtysh -c 'show running'")
|
||||||
|
|
||||||
|
assert "allow-external-route-update" in showrun, "zebra conf missing"
|
||||||
|
assert (
|
||||||
|
"ip multicast rpf-lookup-mode urib-only" not in showrun
|
||||||
|
), "zebra second conf present, unexpected"
|
||||||
|
assert "ip table range 2 3" not in showrun, "zebra third conf present, unexpected"
|
@ -880,6 +880,13 @@ int vtysh_config_from_file(struct vty *vty, FILE *fp)
|
|||||||
if (strmatch(vty_buf_trimmed, "end"))
|
if (strmatch(vty_buf_trimmed, "end"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (strmatch(vty_buf_trimmed, "exit") &&
|
||||||
|
vty->node == CONFIG_NODE) {
|
||||||
|
fprintf(stderr, "line %d: Warning[%d]...: %s\n", lineno,
|
||||||
|
vty->node, "early exit from config file");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ret = command_config_read_one_line(vty, &cmd, lineno, 1);
|
ret = command_config_read_one_line(vty, &cmd, lineno, 1);
|
||||||
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
|
Loading…
Reference in New Issue
Block a user