#!/usr/bin/env bash # Test of the IETF rfc6243: With-defaults Capability for NETCONF # # Test cases below follows the RFC. # # Magic line must be first in script (see README.md) s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi APPNAME=example cfg=$dir/conf_yang.xml fyang=$dir/example-default.yang fstate=$dir/state.xml RESTCONFIG=$(restconf_config none false) cat < $cfg $cfg ietf-netconf:startup 42 ${YANG_INSTALLDIR} $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/backend example_backend.so$ /usr/local/lib/$APPNAME/netconf /usr/local/lib/$APPNAME/cli $APPNAME $dir/$APPNAME.sock /usr/local/var/$APPNAME/$APPNAME.pidfile false $dir false $IETFRFC clixon-restconf:allow-auth-none $RESTCONFIG EOF # A.1. Example YANG Module # The following YANG module defines an example interfaces table to # demonstrate how the parameter behaves for a specific # data model. cat < $fyang module example { namespace "http://example.com/ns/interfaces"; prefix exam; typedef status-type { description "Interface status"; type enumeration { enum ok; enum 'waking up'; enum 'not feeling so good'; enum 'better check it out'; enum 'better call for help'; } default ok; } container interfaces { description "Example interfaces group"; list interface { description "Example interface entry"; key name; leaf name { description "The administrative name of the interface. This is an identifier that is only unique within the scope of this list, and only within a specific server."; type string { length "1 .. max"; } } leaf mtu { description "The maximum transmission unit (MTU) value assigned to this interface."; type uint32; default 1500; } leaf status { description "The current status of this interface."; type status-type; config false; } } } } EOF # A.2. Example Data Set EXAMPLENS="xmlns=\"http://example.com/ns/interfaces\"" XML="\ eth08192\ eth1\ eth29000\ eth31500\ " cat < $fstate eth2not feeling so good eth3waking up EOF db=startup if [ $db = startup ]; then sudo echo "<${DATASTORE_TOP}>$XML" > $dir/startup_db fi if [ $BE -ne 0 ]; then # Bring your own backend new "kill old backend" sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi new "start backend -s $db -f $cfg -- -sS $fstate" start_backend -s $db -f $cfg -- -sS $fstate fi new "wait backend" wait_backend # permission kludges new "chmod datastores" sudo chmod 666 $dir/running_db if [ $? -ne 0 ]; then err1 "chmod $dir/running_db" fi sudo chmod 666 $dir/startup_db if [ $? -ne 0 ]; then err1 "chmod $dir/startup_db" fi new "Checking startup unchanged" ret=$(diff $dir/startup_db <(echo "<${DATASTORE_TOP}>$XML")) if [ $? -ne 0 ]; then err "<${DATASTORE_TOP}>$XML" "$ret" fi new "Checking running unchanged" ret=$(diff $dir/running_db <(echo -n "<${DATASTORE_TOP}>$XML")) if [ $? -ne 0 ]; then err "<${DATASTORE_TOP}>$XML" "$ret" fi if [ $RC -ne 0 ]; then new "kill old restconf daemon" stop_restconf_pre new "start restconf daemon" start_restconf -f $cfg fi new "wait restconf" wait_restconf new "rfc4243 4.3. Capability Identifier" expecteof "$clixon_netconf -ef $cfg" 0 "$DEFAULTHELLO" \ "urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&also-supported=report-all,trim,report-all-tagged" new "rfc6243 3.1. 'report-all' Retrieval Mode" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "\ report-all" \ "" \ "\ eth08192ok\ eth11500ok\ eth29000not feeling so good\ eth31500waking up\ " new "rfc6243 3.2. 'trim' Retrieval Mode" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "\ trim" \ "" \ "\ eth08192\ eth1\ eth29000not feeling so good\ eth3waking up\ " new "rfc6243 3.3. 'explicit' Retrieval Mode" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "\ explicit" \ "" \ "\ eth08192ok\ eth1ok\ eth29000not feeling so good\ eth31500waking up\ " new "rfc6243 3.4. 'report-all-tagged' Retrieval Mode" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "\ report-all-tagged" \ "" \ "\ eth08192ok\ eth11500ok\ eth29000not feeling so good\ eth31500waking up\ " new "rfc6243 2.3.1. 'explicit' Basic Mode Retrieval" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "" "" \ "\ eth08192ok\ eth11500ok\ eth29000not feeling so good\ eth31500waking up\ " "" new "rfc6243 2.3.3. 'explicit' and Behavior (part 1): create explicit node" # A valid 'create' operation attribute for a data node that has # been set by a client to its schema default value MUST fail with a # 'data-exists' error-tag. # (test: try to create mtu=3000 on interface eth3) expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "\ \ eth33000\ none " "" \ "\ application\ data-exists\ error\ Data already exists; cannot create new resource\ " # nothing to commit here, but just to verify expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" # verify no change expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "" "" \ "\ eth08192ok\ eth11500ok\ eth29000not feeling so good\ eth31500waking up\ " "" new "rfc6243 2.3.3. 'explicit' and Behavior (part 2): create default node" # A valid 'create' operation attribute for a # data node that has been set by the server to its schema default value # MUST succeed. # (test: set mtu=3000 on interface eth1) expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "\ \ eth13000\ none " \ "" \ "" # commit change expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" # verify that the mtu value has changed expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "" "" \ "\ eth08192ok\ eth13000ok\ eth29000not feeling so good\ eth31500waking up\ " "" new "rfc6243 2.3.3. 'explicit' and Behavior (part 3): delete explicit node" # A valid 'delete' operation attribute for a data node # that has been set by a client to its schema default value MUST # succeed. # (test: try to delete mtu on interface eth1) expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "\ \ eth1\ none" \ "" \ "" # commit delete expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" # check thet the default mtu vale has been restored expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "" "" \ "\ eth08192ok\ eth11500ok\ eth29000not feeling so good\ eth31500waking up\ " "" new "rfc6243 2.3.3. 'explicit' and Behavior (part 4): delete default node" # A valid 'delete' operation attribute for a data node that # has been set by the server to its schema default value MUST fail with # a 'data-missing' error-tag. #(test: try to delete default mtu on interface eth1) expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "\ \ eth11500\ none" \ "" \ "\ application\ data-missing\ error\ Data does not exist; cannot delete resource\ " # nothing to commit expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" # verify that the configuration has not changed expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "" "" \ "\ eth08192ok\ eth11500ok\ eth29000not feeling so good\ eth31500waking up\ " "" new "rfc8040 4.3. RESTCONF GET" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces)" \ 0 \ "HTTP/$HVER 200" \ "Content-Type: application/yang-data+json" \ "Cache-Control: no-cache" \ '{"example:interfaces":{"interface":\[{"name":"eth0","mtu":8192,"status":"ok"},{"name":"eth1","mtu":1500,"status":"ok"},{"name":"eth2","mtu":9000,"status":"not feeling so good"},{"name":"eth3","mtu":1500,"status":"waking up"}\]}}' expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:interfaces)" \ 0 \ "HTTP/$HVER 200" \ "Content-Type: application/yang-data+xml" \ "Cache-Control: no-cache" \ 'eth08192oketh11500oketh29000not feeling so goodeth31500waking up' new "rfc8040 B.3.9. RESTCONF with-defaults parameter = report-all" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=report-all)" \ 0 \ "HTTP/$HVER 200" \ "Content-Type: application/yang-data+json" \ "Cache-Control: no-cache" \ '{"example:interface":\[{"name":"eth1","mtu":1500,"status":"ok"}\]}' expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=report-all)" \ 0 \ "HTTP/$HVER 200" \ "Content-Type: application/yang-data+xml" \ "Cache-Control: no-cache" \ 'eth11500ok' new "rfc8040 B.3.9. RESTONF with-defaults parameter = explicit" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=explicit)" \ 0 \ "HTTP/$HVER 200" \ "Content-Type: application/yang-data+json" \ "Cache-Control: no-cache" \ '{"example:interface":\[{"name":"eth1","status":"ok"}\]}' expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=explicit)" \ 0 \ "HTTP/$HVER 200" \ "Content-Type: application/yang-data+xml" \ "Cache-Control: no-cache" \ 'eth1ok' new "rfc8040 B.3.9. RESTONF with-defaults parameter = trim" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth3?with-defaults=trim)" \ 0 \ "HTTP/$HVER 200" \ "Content-Type: application/yang-data+json" \ "Cache-Control: no-cache" \ '{"example:interface":\[{"name":"eth3","status":"waking up"}\]}' expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth3?with-defaults=trim)" \ 0 \ "HTTP/$HVER 200" \ "Content-Type: application/yang-data+xml" \ "Cache-Control: no-cache" \ 'eth3waking up' new "rfc8040 B.3.9. RESTCONF with-defaults parameter = report-all-tagged" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=report-all-tagged)" \ 0 \ "HTTP/$HVER 200" \ "Content-Type: application/yang-data+json" \ "Cache-Control: no-cache" \ '{"example:interface":\[{"name":"eth1","mtu":1500,"status":"ok"}\]}' expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=report-all-tagged)" \ 0 \ "HTTP/$HVER 200" \ "Content-Type: application/yang-data+xml" \ "Cache-Control: no-cache" \ 'eth11500ok' if [ $RC -ne 0 ]; then new "Kill restconf daemon" stop_restconf fi if [ $BE -ne 0 ]; then # Bring your own backend new "Kill backend" # Check if premature kill pid=$(pgrep -u root -f clixon_backend) if [ -z "$pid" ]; then err "backend already dead" fi # kill backend stop_backend -f $cfg fi rm -rf $dir unset ret new "endtest" endtest