Very large commit for upcoming 4.4 release
Major New features
* New and updated search functions using xpath, api-path and instance-id
* New search functions using api-path and instance_id:
* C search functions: `clixon_find_instance_id()` and `clixon_find_api_path()`
* Binary search optimization in lists for indexed leafs in all three formats.
* This improves search performance to O(logN) which is drastical improvements for large lists.
* You can also register explicit indexes for making binary search (not only list keys)
* For more info, see docs at [paths](https://clixon-docs.readthedocs.io/en/latest/paths.html) and
[search](https://clixon-docs.readthedocs.io/en/latest/xml.html#searching-in-xml)
API changes on existing features (you may need to change your code)
* On failed validation of leafrefs, error message changed from: `No such leaf` to `No leaf <name> matching path <path>`.
* CLI Error message (clicon_rpc_generate_error()) changed when backend returns netconf error to be more descriptive:
* Original: `Config error: Validate failed. Edit and try again or discard changes: Invalid argument`
* New (example): `Netconf error: application operation-failed Identityref validation failed, undefined not derived from acl-base . Validate failed. Edit and try again or discard changes"
Minor changes
* Test framework
* Added `-- -S <file>` command-line to main example to be able to return any state to main example.
* Added `test/cicd` test scripts for running on a set of other hosts
* C-code restructuring
* clixon_yang.c partitioned and moved code into clixon_yang_parse_lib.c and clixon_yang_module.c and move back some code from clixon_yang_type.c.
* partly to reduce size, but most important to limit code that accesses internal yang structures, only clixon_yang.c does this now.
This commit is contained in:
parent
e8ae628d06
commit
19e21be0bc
132 changed files with 6241 additions and 2332 deletions
|
|
@ -2,7 +2,8 @@
|
|||
*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
|
||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||
Copyright (C) 2017-2020 Olof Hagsand
|
||||
|
||||
This file is part of CLIXON.
|
||||
|
||||
|
|
@ -47,6 +48,7 @@
|
|||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
/* clicon */
|
||||
|
|
@ -71,6 +73,11 @@ static int _reset = 0;
|
|||
*/
|
||||
static int _state = 0;
|
||||
|
||||
/*! File where state XML is read from, if _state is true
|
||||
* Primarily for testing
|
||||
*/
|
||||
static char *_state_file = NULL;
|
||||
|
||||
/*! Variable to control upgrade callbacks.
|
||||
* If set, call test-case for upgrading ietf-interfaces, otherwise call
|
||||
* auto-upgrade
|
||||
|
|
@ -307,55 +314,67 @@ example_statedata(clicon_handle h,
|
|||
cvec *nsc1 = NULL;
|
||||
cvec *nsc2 = NULL;
|
||||
yang_stmt *yspec = NULL;
|
||||
int fd;
|
||||
|
||||
if (!_state)
|
||||
goto ok;
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
|
||||
/* Example of statedata, in this case merging state data with
|
||||
* state information. In this case adding dummy interface operation state
|
||||
* to configured interfaces.
|
||||
* Get config according to xpath */
|
||||
if ((nsc1 = xml_nsctx_init(NULL, "urn:ietf:params:xml:ns:yang:ietf-interfaces")) == NULL)
|
||||
goto done;
|
||||
if (xmldb_get0(h, "running", nsc1, "/interfaces/interface/name", 1, &xt, NULL) < 0)
|
||||
goto done;
|
||||
if (xpath_vec(xt, nsc1, "/interfaces/interface/name", &xvec, &xlen) < 0)
|
||||
goto done;
|
||||
if (xlen){
|
||||
cprintf(cb, "<interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\">");
|
||||
for (i=0; i<xlen; i++){
|
||||
name = xml_body(xvec[i]);
|
||||
cprintf(cb, "<interface xmlns:ex=\"urn:example:clixon\"><name>%s</name><type>ex:eth</type><oper-status>up</oper-status>", name);
|
||||
cprintf(cb, "<ex:my-status><ex:int>42</ex:int><ex:str>foo</ex:str></ex:my-status>");
|
||||
cprintf(cb, "</interface>");
|
||||
/* If -S is set, then read state data from file, otherwise construct it programmatically */
|
||||
if (_state_file){
|
||||
if ((fd = open(_state_file, O_RDONLY)) < 0){
|
||||
clicon_err(OE_UNIX, errno, "open(%s)", _state_file);
|
||||
goto done;
|
||||
}
|
||||
cprintf(cb, "</interfaces>");
|
||||
if (xml_parse_string(cbuf_get(cb), NULL, &xstate) < 0)
|
||||
if (xml_parse_file(fd, NULL, yspec, &xstate) < 0)
|
||||
goto done;
|
||||
}
|
||||
/* State in test_yang.sh , test_restconf.sh and test_order.sh */
|
||||
if (yang_find_module_by_namespace(yspec, "urn:example:clixon") != NULL){
|
||||
if (xml_parse_string("<state xmlns=\"urn:example:clixon\">"
|
||||
"<op>42</op>"
|
||||
"<op>41</op>"
|
||||
"<op>43</op>" /* should not be ordered */
|
||||
"</state>", NULL, &xstate) < 0)
|
||||
goto done; /* For the case when urn:example:clixon is not loaded */
|
||||
}
|
||||
/* Event state from RFC8040 Appendix B.3.1
|
||||
* Note: (1) order is by-system so is different,
|
||||
* (2) event-count is XOR on name, so is not 42 and 4
|
||||
*/
|
||||
if (yang_find_module_by_namespace(yspec, "urn:example:events") != NULL){
|
||||
cbuf_reset(cb);
|
||||
cprintf(cb, "<events xmlns=\"urn:example:events\">");
|
||||
cprintf(cb, "<event><name>interface-down</name><event-count>90</event-count></event>");
|
||||
cprintf(cb, "<event><name>interface-up</name><event-count>77</event-count></event>");
|
||||
cprintf(cb, "</events>");
|
||||
if (xml_parse_string(cbuf_get(cb), NULL, &xstate) < 0)
|
||||
goto done;
|
||||
}
|
||||
else {
|
||||
/* Example of statedata, in this case merging state data with
|
||||
* state information. In this case adding dummy interface operation state
|
||||
* to configured interfaces.
|
||||
* Get config according to xpath */
|
||||
if ((nsc1 = xml_nsctx_init(NULL, "urn:ietf:params:xml:ns:yang:ietf-interfaces")) == NULL)
|
||||
goto done;
|
||||
if (xmldb_get0(h, "running", nsc1, "/interfaces/interface/name", 1, &xt, NULL) < 0)
|
||||
goto done;
|
||||
if (xpath_vec(xt, nsc1, "/interfaces/interface/name", &xvec, &xlen) < 0)
|
||||
goto done;
|
||||
if (xlen){
|
||||
cprintf(cb, "<interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\">");
|
||||
for (i=0; i<xlen; i++){
|
||||
name = xml_body(xvec[i]);
|
||||
cprintf(cb, "<interface xmlns:ex=\"urn:example:clixon\"><name>%s</name><type>ex:eth</type><oper-status>up</oper-status>", name);
|
||||
cprintf(cb, "<ex:my-status><ex:int>42</ex:int><ex:str>foo</ex:str></ex:my-status>");
|
||||
cprintf(cb, "</interface>");
|
||||
}
|
||||
cprintf(cb, "</interfaces>");
|
||||
if (xml_parse_string(cbuf_get(cb), NULL, &xstate) < 0)
|
||||
goto done;
|
||||
}
|
||||
/* State in test_yang.sh , test_restconf.sh and test_order.sh */
|
||||
if (yang_find_module_by_namespace(yspec, "urn:example:clixon") != NULL){
|
||||
if (xml_parse_string("<state xmlns=\"urn:example:clixon\">"
|
||||
"<op>42</op>"
|
||||
"<op>41</op>"
|
||||
"<op>43</op>" /* should not be ordered */
|
||||
"</state>", NULL, &xstate) < 0)
|
||||
goto done; /* For the case when urn:example:clixon is not loaded */
|
||||
}
|
||||
/* Event state from RFC8040 Appendix B.3.1
|
||||
* Note: (1) order is by-system so is different,
|
||||
* (2) event-count is XOR on name, so is not 42 and 4
|
||||
*/
|
||||
if (yang_find_module_by_namespace(yspec, "urn:example:events") != NULL){
|
||||
cbuf_reset(cb);
|
||||
cprintf(cb, "<events xmlns=\"urn:example:events\">");
|
||||
cprintf(cb, "<event><name>interface-down</name><event-count>90</event-count></event>");
|
||||
cprintf(cb, "<event><name>interface-up</name><event-count>77</event-count></event>");
|
||||
cprintf(cb, "</events>");
|
||||
if (xml_parse_string(cbuf_get(cb), NULL, &xstate) < 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
|
|
@ -709,7 +728,7 @@ clixon_plugin_init(clicon_handle h)
|
|||
goto done;
|
||||
opterr = 0;
|
||||
optind = 1;
|
||||
while ((c = getopt(argc, argv, "rsut:")) != -1)
|
||||
while ((c = getopt(argc, argv, "rsS:ut")) != -1)
|
||||
switch (c) {
|
||||
case 'r':
|
||||
_reset = 1;
|
||||
|
|
@ -717,6 +736,9 @@ clixon_plugin_init(clicon_handle h)
|
|||
case 's':
|
||||
_state = 1;
|
||||
break;
|
||||
case 'S': /* state file */
|
||||
_state_file = optarg;
|
||||
break;
|
||||
case 'u':
|
||||
_upgrade = 1;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,36 @@
|
|||
# Common CLI syntax for both server and PMNode operatio mode
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
#
|
||||
# Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||
# Copyright (C) 2017-2020 Olof Hagsand
|
||||
#
|
||||
# This file is part of CLIXON
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# the GNU General Public License Version 3 or later (the "GPL"),
|
||||
# in which case the provisions of the GPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of the GPL, and not to allow others to
|
||||
# use your version of this file under the terms of Apache License version 2,
|
||||
# indicate your decision by deleting the provisions above and replace them with
|
||||
# the notice and other provisions required by the GPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the Apache License version 2 or the GPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# Clixon example specification
|
||||
CLICON_MODE="example";
|
||||
CLICON_PROMPT="%U@%H> ";
|
||||
CLICON_PLUGIN="example_cli";
|
||||
|
|
@ -37,8 +69,8 @@ show("Show a particular state of the system"){
|
|||
xml("Show comparison in xml"), compare_dbs((int32)0);
|
||||
text("Show comparison in text"), compare_dbs((int32)1);
|
||||
}
|
||||
state("Show configuration and state"), cli_show_config_state("running", "text", "/"){
|
||||
xml("Show configuration and state as XML"), cli_show_config_state("candidate", "xml", "/");{
|
||||
state("Show configuration and state"), cli_show_config_state("running", "text", "/");{
|
||||
xml("Show configuration and state as XML"), cli_show_config_state("running", "xml", "/");{
|
||||
@datamodel, cli_show_auto_state("running", "xml");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue