diff options
| -rw-r--r-- | lib/northbound.c | 6 | ||||
| -rw-r--r-- | lib/northbound_cli.c | 14 | ||||
| -rw-r--r-- | lib/northbound_sysrepo.c | 2 | ||||
| -rw-r--r-- | lib/yang.c | 17 | ||||
| -rw-r--r-- | lib/yang.h | 21 | ||||
| -rw-r--r-- | lib/yang_translator.c | 9 | ||||
| -rw-r--r-- | lib/yang_wrappers.c | 6 | ||||
| -rw-r--r-- | tests/topotests/lib/topogen.py | 7 | ||||
| -rw-r--r-- | tests/topotests/lib/topotest.py | 2 | ||||
| -rw-r--r-- | tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py | 12 |
10 files changed, 76 insertions, 20 deletions
diff --git a/lib/northbound.c b/lib/northbound.c index 307cf0fb49..775f6ff92f 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -167,7 +167,7 @@ struct nb_node *nb_node_find(const char *path) * Use libyang to find the schema node associated to the path and get * the northbound node from there (snode private pointer). */ - snode = lys_find_path(ly_native_ctx, NULL, path, 0); + snode = yang_find_snode(ly_native_ctx, path, 0); if (!snode) return NULL; @@ -2129,8 +2129,8 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator, * all YANG lists (if any). */ - LY_ERR err = lyd_new_path(NULL, ly_native_ctx, xpath, NULL, - LYD_NEW_PATH_UPDATE, &dnode); + LY_ERR err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, 0, + LYD_NEW_PATH_UPDATE, NULL, &dnode); if (err || !dnode) { const char *errmsg = err ? ly_errmsg(ly_native_ctx) : "node not found"; diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c index 5cf5f93b43..c5582fc21c 100644 --- a/lib/northbound_cli.c +++ b/lib/northbound_cli.c @@ -1434,6 +1434,7 @@ DEFPY (show_yang_operational_data, struct lyd_node *dnode; char *strp; uint32_t print_options = LYD_PRINT_WITHSIBLINGS; + int ret; if (xml) format = LYD_XML; @@ -1454,10 +1455,15 @@ DEFPY (show_yang_operational_data, /* Obtain data. */ dnode = yang_dnode_new(ly_ctx, false); - if (nb_oper_data_iterate(xpath, translator, 0, nb_cli_oper_data_cb, - dnode) - != NB_OK) { - vty_out(vty, "%% Failed to fetch operational data.\n"); + ret = nb_oper_data_iterate(xpath, translator, 0, nb_cli_oper_data_cb, + dnode); + if (ret != NB_OK) { + if (format == LYD_JSON) + vty_out(vty, "{}\n"); + else { + /* embed ly_last_errmsg() when we get newer libyang */ + vty_out(vty, "<!-- Not found -->\n"); + } yang_dnode_free(dnode); return CMD_WARNING; } diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c index 86105d2e77..7fd4af8356 100644 --- a/lib/northbound_sysrepo.c +++ b/lib/northbound_sysrepo.c @@ -357,7 +357,7 @@ static int frr_sr_state_data_iter_cb(const struct lysc_node *snode, ly_errno = 0; ly_errno = lyd_new_path(NULL, ly_native_ctx, data->xpath, data->value, 0, &dnode); - if (!dnode && ly_errno) { + if (ly_errno) { flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed", __func__); yang_data_free(data); diff --git a/lib/yang.c b/lib/yang.c index 70a3251ab3..4dd8654217 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -250,6 +250,23 @@ void yang_snode_get_path(const struct lysc_node *snode, } } +struct lysc_node *yang_find_snode(struct ly_ctx *ly_ctx, const char *xpath, + uint32_t options) +{ + struct lysc_node *snode; + struct ly_set *set; + LY_ERR err; + + err = lys_find_xpath(ly_native_ctx, NULL, xpath, options, &set); + if (err || !set->count) + return NULL; + + snode = set->snodes[0]; + ly_set_free(set, NULL); + + return snode; +} + struct lysc_node *yang_snode_real_parent(const struct lysc_node *snode) { struct lysc_node *parent = snode->parent; diff --git a/lib/yang.h b/lib/yang.h index 654c246f0d..37369c09bf 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -210,6 +210,27 @@ extern void yang_snode_get_path(const struct lysc_node *snode, enum yang_path_type type, char *xpath, size_t xpath_len); + +/* + * Find libyang schema node for the given xpath. Uses `lys_find_xpath`, + * returning only the first of a set of nodes -- normally there should only + * be one. + * + * ly_ctx + * libyang context to operate on. + * + * xpath + * XPath expression (absolute or relative) to find the schema node for. + * + * options + * Libyang findxpathoptions value (see lys_find_xpath). + * + * Returns: + * The libyang schema node if found, or NULL if not found. + */ +extern struct lysc_node *yang_find_snode(struct ly_ctx *ly_ctx, + const char *xpath, uint32_t options); + /* * Find first parent schema node which is a presence-container or a list * (non-presence containers are ignored). diff --git a/lib/yang_translator.c b/lib/yang_translator.c index de668230ab..eae7577a0d 100644 --- a/lib/yang_translator.c +++ b/lib/yang_translator.c @@ -235,8 +235,8 @@ struct yang_translator *yang_translator_load(const char *path) xpath_custom = yang_dnode_get_string(set->dnodes[i], "./custom"); - snode_custom = lys_find_path(translator->ly_ctx, NULL, - xpath_custom, 0); + snode_custom = + yang_find_snode(translator->ly_ctx, xpath_custom, 0); if (!snode_custom) { flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD, "%s: unknown data path: %s", __func__, @@ -247,8 +247,7 @@ struct yang_translator *yang_translator_load(const char *path) xpath_native = yang_dnode_get_string(set->dnodes[i], "./native"); - snode_native = - lys_find_path(ly_native_ctx, NULL, xpath_native, 0); + snode_native = yang_find_snode(ly_native_ctx, xpath_native, 0); if (!snode_native) { flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD, "%s: unknown data path: %s", __func__, @@ -315,7 +314,7 @@ yang_translate_xpath(const struct yang_translator *translator, int dir, else ly_ctx = ly_native_ctx; - snode = lys_find_path(ly_ctx, NULL, xpath, 0); + snode = yang_find_snode(ly_ctx, xpath, 0); if (!snode) { flog_warn(EC_LIB_YANG_TRANSLATION_ERROR, "%s: unknown data path: %s", __func__, xpath); diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c index 509c4dd856..dc049a374a 100644 --- a/lib/yang_wrappers.c +++ b/lib/yang_wrappers.c @@ -89,7 +89,7 @@ static const char *yang_get_default_value(const char *xpath) const struct lysc_node *snode; const char *value; - snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); + snode = yang_find_snode(ly_native_ctx, xpath, 0); if (snode == NULL) { flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, "%s: unknown data path: %s", __func__, xpath); @@ -206,7 +206,7 @@ int yang_str2enum(const char *xpath, const char *value) const struct lysc_type_enum *type; const struct lysc_type_bitenum_item *enums; - snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); + snode = yang_find_snode(ly_native_ctx, xpath, 0); if (snode == NULL) { flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, "%s: unknown data path: %s", __func__, xpath); @@ -241,7 +241,7 @@ struct yang_data *yang_data_new_enum(const char *xpath, int value) const struct lysc_type_enum *type; const struct lysc_type_bitenum_item *enums; - snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); + snode = yang_find_snode(ly_native_ctx, xpath, 0); if (snode == NULL) { flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, "%s: unknown data path: %s", __func__, xpath); diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py index f5b3ad06d9..d505317e4e 100644 --- a/tests/topotests/lib/topogen.py +++ b/tests/topotests/lib/topogen.py @@ -33,6 +33,7 @@ import os import platform import pwd import re +import shlex import subprocess import sys from collections import OrderedDict @@ -946,9 +947,11 @@ class TopoRouter(TopoGear): if daemon is not None: dparam += "-d {}".format(daemon) - vtysh_command = 'vtysh {} -c "{}" 2>/dev/null'.format(dparam, command) + vtysh_command = "vtysh {} -c {} 2>/dev/null".format( + dparam, shlex.quote(command) + ) - self.logger.debug('vtysh command => "{}"'.format(command)) + self.logger.debug("vtysh command => {}".format(shlex.quote(command))) output = self.run(vtysh_command) dbgout = output.strip() diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index 86a7f2000f..ef04d59e29 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -1840,6 +1840,8 @@ class Router(Node): logger.info( "%s: %s %s launched in gdb window", self, self.routertype, daemon ) + # Need better check for daemons running. + time.sleep(5) else: if daemon != "snmpd": cmdopt += " -d " diff --git a/tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py b/tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py index b0ba146984..acc0aea9e8 100644 --- a/tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py +++ b/tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py @@ -52,10 +52,18 @@ def test_rip_allow_ecmp(): r1 = tgen.gears["r1"] def _show_rip_routes(): - output = json.loads( - r1.vtysh_cmd("show yang operational-data /frr-ripd:ripd ripd") + xpath = ( + "/frr-ripd:ripd/instance[vrf='default']" + "/state/routes/route[prefix='10.10.10.1/32']" ) try: + output = json.loads( + r1.vtysh_cmd(f"show yang operational-data {xpath} ripd") + ) + except Exception: + return False + + try: output = output["frr-ripd:ripd"]["instance"][0]["state"]["routes"] except KeyError: return False |
