diff --git a/CHANGELOG.md b/CHANGELOG.md index 82ba6372..588c5e10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -94,6 +94,7 @@ * For backward compatibility, define CLICON_CLI_MODEL_TREENAME_PATCH in clixon_custom.h ### Minor changes +* Added new clixon-lib yang module for internal netconf protocol. Currently only extends the standard with a debug RPC. * Added three-valued return values for several validate functions where -1 is fatal error, 0 is validation failed and 1 is validation OK. * This includes: `xmldb_put`, `xml_yang_validate_all`, `xml_yang_validate_add`, `xml_yang_validate_rpc`, `api_path2xml`, `api_path2xpath` * Added new xml functions for specific types: `xml_child_nr_notype`, `xml_child_nr_notype`, `xml_child_i_type`, `xml_find_type`. diff --git a/apps/backend/backend_main.c b/apps/backend/backend_main.c index 8e05c175..6fbb8750 100644 --- a/apps/backend/backend_main.c +++ b/apps/backend/backend_main.c @@ -805,6 +805,9 @@ main(int argc, if ((str = clicon_yang_main_dir(h)) != NULL) if (yang_spec_load_dir(h, str, yspec) < 0) goto done; + /* Load clixon lib yang module */ + if (yang_spec_parse_module(h, "clixon-lib", NULL, yspec) < 0) + goto done; /* Load yang module library, RFC7895 */ if (yang_modules_init(h) < 0) goto done; diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index e6d7925a..ce994fee 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -446,6 +446,9 @@ main(int argc, char **argv) if (yang_spec_load_dir(h, str, yspec) < 0) goto done; } + /* Load clixon lib yang module */ + if (yang_spec_parse_module(h, "clixon-lib", NULL, yspec) < 0) + goto done; /* Load yang module library, RFC7895 */ if (yang_modules_init(h) < 0) diff --git a/apps/netconf/netconf_main.c b/apps/netconf/netconf_main.c index e60a5d08..eadbcc1b 100644 --- a/apps/netconf/netconf_main.c +++ b/apps/netconf/netconf_main.c @@ -468,7 +468,9 @@ main(int argc, if (yang_spec_load_dir(h, str, yspec) < 0) goto done; } - + /* Load clixon lib yang module */ + if (yang_spec_parse_module(h, "clixon-lib", NULL, yspec) < 0) + goto done; /* Load yang module library, RFC7895 */ if (yang_modules_init(h) < 0) goto done; diff --git a/apps/restconf/restconf_main.c b/apps/restconf/restconf_main.c index e6234884..0819c7cb 100644 --- a/apps/restconf/restconf_main.c +++ b/apps/restconf/restconf_main.c @@ -645,7 +645,9 @@ main(int argc, if (yang_spec_load_dir(h, str, yspec) < 0) goto done; } - + /* Load clixon lib yang module */ + if (yang_spec_parse_module(h, "clixon-lib", NULL, yspec) < 0) + goto done; /* Load yang module library, RFC7895 */ if (yang_modules_init(h) < 0) goto done; diff --git a/apps/restconf/restconf_methods.c b/apps/restconf/restconf_methods.c index 8f3cb4a5..58980589 100644 --- a/apps/restconf/restconf_methods.c +++ b/apps/restconf/restconf_methods.c @@ -1132,27 +1132,23 @@ api_operations_get(clicon_handle h, if (use_xml) cprintf(cbx, ""); else - cprintf(cbx, "{\"operations\": "); + cprintf(cbx, "{\"operations\": {"); ymod = NULL; + i = 0; while ((ymod = yn_each((yang_node*)yspec, ymod)) != NULL) { namespace = yang_find_mynamespace(ymod); - yc = NULL; i=0; + yc = NULL; while ((yc = yn_each((yang_node*)ymod, yc)) != NULL) { if (yc->ys_keyword != Y_RPC) continue; if (use_xml) cprintf(cbx, "<%s xmlns=\"%s\"/>", yc->ys_argument, namespace); else{ - if (i==0) - cprintf(cbx, "{"); - if (i) + if (i++) cprintf(cbx, ","); cprintf(cbx, "\"%s:%s\": null", ymod->ys_argument, yc->ys_argument); } - i++; } - if (!use_xml && i) - cprintf(cbx, "}"); } if (use_xml) cprintf(cbx, ""); diff --git a/example/example.yang b/example/example.yang index 749b10ff..f5e82063 100644 --- a/example/example.yang +++ b/example/example.yang @@ -128,13 +128,4 @@ module example { } } } - rpc debug { - description "Set debug level of backend. XXX should be in clixon-config"; - input { - leaf level { - type uint32; - } - } - } - } diff --git a/lib/src/clixon_proto_client.c b/lib/src/clixon_proto_client.c index 0dbb76d1..b454b608 100644 --- a/lib/src/clixon_proto_client.c +++ b/lib/src/clixon_proto_client.c @@ -827,7 +827,7 @@ clicon_rpc_debug(clicon_handle h, username = clicon_username_get(h); /* XXX: hardcoded example yang, should be clixon-config!!! */ - if ((msg = clicon_msg_encode("%d", username?username:"", level)) == NULL) + if ((msg = clicon_msg_encode("%d", username?username:"", level)) == NULL) goto done; if (clicon_rpc_msg(h, msg, &xret, NULL) < 0) goto done; diff --git a/test/test_install.sh b/test/test_install.sh index 032bba4a..09867c42 100755 --- a/test/test_install.sh +++ b/test/test_install.sh @@ -12,19 +12,23 @@ if [ $? -ne 0 ]; then err fi -new "Check installed files" +new "Check installed files /usr" if [ ! -d $dir/usr ]; then err $dir/usr fi +new "Check installed files /www-data" if [ ! -d $dir/www-data ]; then err $dir/www-data fi +new "Check installed files clixon-config" if [ ! -f $dir/usr/local/share/clixon/clixon-config* ]; then err $dir/usr/local/share/clixon/clixon-config* fi +new "Check installed files libclixon.so" if [ ! -h $dir/usr/local/lib/libclixon.so ]; then err $dir/usr/local/lib/libclixon.so fi +new "Check installed files libclixon_backend.so" if [ ! -h $dir/usr/local/lib/libclixon_backend.so ]; then err $dir/usr/local/lib/libclixon_backend.so fi diff --git a/test/test_restconf.sh b/test/test_restconf.sh index e7451d0a..2a1fd961 100755 --- a/test/test_restconf.sh +++ b/test/test_restconf.sh @@ -118,12 +118,12 @@ expecteq "$(curl -s -H 'Accept: application/yang-data+xml' -G http://localhost/r # Should be alphabetically ordered new2 "restconf get restconf/operations. RFC8040 3.3.2 (json)" -expecteq "$(curl -sG http://localhost/restconf/operations)" '{"operations": {"example:empty": null,"example:client-rpc": null}{"ietf-routing:fib-route": null,"ietf-routing:route-count": null}} +expecteq "$(curl -sG http://localhost/restconf/operations)" '{"operations": {"example:empty": null,"example:client-rpc": null,"ietf-routing:fib-route": null,"ietf-routing:route-count": null,"clixon-lib:debug": null} ' new "restconf get restconf/operations. RFC8040 3.3.2 (xml)" ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/operations) -expect='' +expect='' match=`echo $ret | grep -EZo "$expect"` if [ -z "$match" ]; then err "$expect" "$ret" diff --git a/yang/Makefile.in b/yang/Makefile.in index fb32b74d..a1d0be57 100644 --- a/yang/Makefile.in +++ b/yang/Makefile.in @@ -41,10 +41,12 @@ datarootdir = @datarootdir@ CLIXON_DATADIR = @CLIXON_DATADIR@ YANGSPECS = clixon-config@2018-10-21.yang +YANGSPECS += clixon-lib@2019-01-02.yang YANGSPECS += ietf-netconf@2011-06-01.yang YANGSPECS += ietf-netconf-acm@2018-02-14.yang YANGSPECS += ietf-inet-types@2013-07-15.yang YANGSPECS += ietf-yang-types@2013-07-15.yang +YANGSPECS += ietf-restconf@2017-01-26.yang YANGSPECS += ietf-restconf-monitoring@2017-01-26.yang YANGSPECS += ietf-netconf-notification@2008-07-01.yang YANGSPECS += ietf-yang-library@2016-06-21.yang diff --git a/yang/clixon-config@2018-10-21.yang b/yang/clixon-config@2018-10-21.yang index efa777e3..a9ad7414 100644 --- a/yang/clixon-config@2018-10-21.yang +++ b/yang/clixon-config@2018-10-21.yang @@ -1,6 +1,6 @@ module clixon-config { yang-version 1.1; - namespace "http://clicon.org"; + namespace "http://clicon.org/config"; prefix cc; organization @@ -455,12 +455,4 @@ module clixon-config { } } - rpc debug { - description "Set debug level of backend."; - input { - leaf level { - type uint32; - } - } - } } diff --git a/yang/clixon-lib@2019-01-02.yang b/yang/clixon-lib@2019-01-02.yang new file mode 100644 index 00000000..1e26187b --- /dev/null +++ b/yang/clixon-lib@2019-01-02.yang @@ -0,0 +1,55 @@ +module clixon-lib { + yang-version 1.1; + namespace "http://clicon.org/lib"; + prefix cl; + + organization + "Clicon / Clixon"; + + contact + "Olof Hagsand "; + + description + "Clixon Netconf extensions for communication between clients and backend. + + ***** BEGIN LICENSE BLOCK ***** + Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren + + 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 *****"; + + revision 2019-01-02 { + description + "Released in Clixon 3.9"; + } + rpc debug { + description "Set debug level of backend."; + input { + leaf level { + type uint32; + } + } + } +} diff --git a/yang/ietf-restconf@2017-01-26.yang b/yang/ietf-restconf@2017-01-26.yang new file mode 100644 index 00000000..249006af --- /dev/null +++ b/yang/ietf-restconf@2017-01-26.yang @@ -0,0 +1,279 @@ +module ietf-restconf { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-restconf"; + prefix "rc"; + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG Web: + WG List: + + Author: Andy Bierman + + + Author: Martin Bjorklund + + + Author: Kent Watsen + "; + + description + "This module contains conceptual YANG specifications + for basic RESTCONF media type definitions used in + RESTCONF protocol messages. + + Note that the YANG definitions within this module do not + represent configuration data of any kind. + The 'restconf-media-type' YANG extension statement + provides a normative syntax for XML and JSON + message-encoding purposes. + + Copyright (c) 2017 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8040; see + the RFC itself for full legal notices."; + + revision 2017-01-26 { + description + "Initial revision."; + reference + "RFC 8040: RESTCONF Protocol."; + } + + extension yang-data { + argument name { + yin-element true; + } + description + "This extension is used to specify a YANG data template that + represents conceptual data defined in YANG. It is + intended to describe hierarchical data independent of + protocol context or specific message-encoding format. + Data definition statements within a yang-data extension + specify the generic syntax for the specific YANG data + template, whose name is the argument of the 'yang-data' + extension statement. + + Note that this extension does not define a media type. + A specification using this extension MUST specify the + message-encoding rules, including the content media type. + + The mandatory 'name' parameter value identifies the YANG + data template that is being defined. It contains the + template name. + + This extension is ignored unless it appears as a top-level + statement. It MUST contain data definition statements + that result in exactly one container data node definition. + An instance of a YANG data template can thus be translated + into an XML instance document, whose top-level element + corresponds to the top-level container. + + The module name and namespace values for the YANG module using + the extension statement are assigned to instance document data + conforming to the data definition statements within + this extension. + + The substatements of this extension MUST follow the + 'data-def-stmt' rule in the YANG ABNF. + + The XPath document root is the extension statement itself, + such that the child nodes of the document root are + represented by the data-def-stmt substatements within + this extension. This conceptual document is the context + for the following YANG statements: + + - must-stmt + - when-stmt + - path-stmt + - min-elements-stmt + - max-elements-stmt + - mandatory-stmt + - unique-stmt + - ordered-by + - instance-identifier data type + + The following data-def-stmt substatements are constrained + when used within a 'yang-data' extension statement. + + - The list-stmt is not required to have a key-stmt defined. + - The if-feature-stmt is ignored if present. + - The config-stmt is ignored if present. + - The available identity values for any 'identityref' + leaf or leaf-list nodes are limited to the module + containing this extension statement and the modules + imported into that module. + "; + } + + rc:yang-data yang-errors { + uses errors; + } + + rc:yang-data yang-api { + uses restconf; + } + + grouping errors { + description + "A grouping that contains a YANG container + representing the syntax and semantics of a + YANG Patch error report within a response message."; + + container errors { + description + "Represents an error report returned by the server if + a request results in an error."; + + list error { + description + "An entry containing information about one + specific error that occurred while processing + a RESTCONF request."; + reference + "RFC 6241, Section 4.3."; + + leaf error-type { + type enumeration { + enum transport { + description + "The transport layer."; + } + enum rpc { + description + "The rpc or notification layer."; + } + enum protocol { + description + "The protocol operation layer."; + } + enum application { + description + "The server application layer."; + } + } + mandatory true; + description + "The protocol layer where the error occurred."; + } + + leaf error-tag { + type string; + mandatory true; + description + "The enumerated error-tag."; + } + + leaf error-app-tag { + type string; + description + "The application-specific error-tag."; + } + + leaf error-path { + type instance-identifier; + description + "The YANG instance identifier associated + with the error node."; + } + + leaf error-message { + type string; + description + "A message describing the error."; + } + + anydata error-info { + description + "This anydata value MUST represent a container with + zero or more data nodes representing additional + error information."; + } + } + } + } + + grouping restconf { + description + "Conceptual grouping representing the RESTCONF + root resource."; + + container restconf { + description + "Conceptual container representing the RESTCONF + root resource."; + container data { + description + "Container representing the datastore resource. + Represents the conceptual root of all state data + and configuration data supported by the server. + The child nodes of this container can be any data + resources that are defined as top-level data nodes + from the YANG modules advertised by the server in + the 'ietf-yang-library' module."; + } + + container operations { + description + "Container for all operation resources. + + Each resource is represented as an empty leaf with the + name of the RPC operation from the YANG 'rpc' statement. + + For example, the 'system-restart' RPC operation defined + in the 'ietf-system' module would be represented as + an empty leaf in the 'ietf-system' namespace. This is + a conceptual leaf and will not actually be found in + the module: + + module ietf-system { + leaf system-reset { + type empty; + } + } + + To invoke the 'system-restart' RPC operation: + + POST /restconf/operations/ietf-system:system-restart + + To discover the RPC operations supported by the server: + + GET /restconf/operations + + In XML, the YANG module namespace identifies the module: + + + + In JSON, the YANG module name identifies the module: + + { 'ietf-system:system-restart' : [null] } + "; + } + + leaf yang-library-version { + type string { + pattern '\d{4}-\d{2}-\d{2}'; + } + config false; + mandatory true; + description + "Identifies the revision date of the 'ietf-yang-library' + module that is implemented by this RESTCONF server. + Indicates the year, month, and day in YYYY-MM-DD + numeric format."; + } + } + } + +}