#!/usr/bin/env bash # Starting clixon with outdated (or not) modules. # It is a test of handling modstate, identifying invalid startups # and entering failsafe # No active upgrading of an outdated db is made # This relies on storing RFC7895 YANG Module Library modules-state info # in the datastore (or XML files?) # The test is made with three Yang models A, B and C as follows: # Yang module A has revisions "0814-01-28" and "2019-01-01" # Yang module B has only revision "2019-01-01" # Yang module C has only revision "2019-01-01" # The system is started YANG modules: # A revision "2019-01-01" # B revision "2019-01-01" # The (startup) configuration XML file has: # A revision "0814-01-28"; # B revision "2019-01-01" # C revision "2019-01-01" # Which means the following: # A has an obsolete version # containing a0 which has been removed, and a1 which is OK # B has a compatible version # C is not present in the system # 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 fyangA0=$dir/A@0814-01-28.yang fyangA1=$dir/A@2019-01-01.yang fyangB=$dir/B@2019-01-01.yang # Yang module A revision "0814-01-28" # Note that this Yang model will exist in the DIR but will not be loaded # by the system. Just here for reference cat < $fyangA0 module A{ prefix a; revision 0814-01-28; namespace "urn:example:a"; leaf a0{ type string; } leaf a1{ type string; } } EOF # Yang module A revision "2019-01-01" cat < $fyangA1 module A{ prefix a; revision 2019-01-01; revision 0814-01-28; namespace "urn:example:a"; /* leaf a0 has been removed */ leaf a1{ description "exists in both versions"; type string; } leaf a2{ description "has been added"; type string; } } EOF # Yang module B revision "2019-01-01" cat < $fyangB module B{ prefix b; revision 2019-01-01; namespace "urn:example:b"; leaf b{ type string; } } EOF # Yang module C revision "2019-01-01" (note not written to yang dir) cat < /dev/null module C{ prefix c; revision 2019-01-01; namespace "urn:example:c"; leaf c{ type string; } } EOF # Create configuration cat < $cfg $cfg ietf-netconf:startup /usr/local/share/clixon $dir /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/lib/example/backend /usr/local/var/$APPNAME/$APPNAME.pidfile $dir true /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli $APPNAME EOF # Create failsafe db cat < $dir/failsafe_db <${DATASTORE_TOP}> always work EOF # Create compatible startup db # startup config XML with following cat < $dir/compat-valid.xml <${DATASTORE_TOP}> 42 A 2019-01-01 urn:example:a B 2019-01-01 urn:example:b always work other text EOF # Create compatible startup db # startup config XML with following cat < $dir/compat-invalid.xml <${DATASTORE_TOP}> 42 A 2019-01-01 urn:example:a B 2019-01-01 urn:example:b old version always work other text bla bla EOF # Create non-compat valid startup db # startup config XML with following (A obsolete, B OK, C lacking) # But XML is OK cat < $dir/non-compat-valid.xml <${DATASTORE_TOP}> 42 A 0814-01-28 urn:example:a B 2019-01-01 urn:example:b C 2019-01-01 urn:example:c always work other text EOF # Create non-compat startup db # startup config XML with following (A obsolete, B OK, C lacking) cat < $dir/non-compat-invalid.xml <${DATASTORE_TOP}> 42 A 0814-01-28 urn:example:a B 2019-01-01 urn:example:b C 2019-01-01 urn:example:c old version always work other text bla bla EOF # Compatible startup with syntax errors cat < $dir/compat-err.xml <${DATASTORE_TOP}> 42 A 2019-01-01 urn:example:a B 2019-01-01 urn:example:b <always work other text EOF #! Start system in given mode and check database contents # Before script is called populate running_db and startup_db # @param[in] modstate Boolean: Tag datastores with RFC 7895 YANG Module Library # @param[in] mode Startup mode: init, none, running, or startup # @param[in] exprun Expected content of running-db # @param[in] expstart Check startup database or not if "" runtest(){ modstate=$1 mode=$2 exprun=$3 expstart=$4 new "test params: -f $cfg" # Bring your own backend if [ $BE -ne 0 ]; then # kill old backend (if any) new "kill old backend" sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi new "start backend -s $mode -f $cfg -o \"CLICON_XMLDB_MODSTATE=$modstate\"" start_backend -s $mode -f $cfg -o "CLICON_XMLDB_MODSTATE=$modstate" new "waiting" wait_backend else new "Restart backend as eg follows: -Ff $cfg -s $mode -o \"CLICON_XMLDB_MODSTATE=$modstate\" ($BETIMEOUT s)" # sleep $BETIMEOUT fi new "Check running db content" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^$exprun]]>]]>$" # If given check startup db XML if [ -n "$expstart" ]; then new "Check startup db content" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^$expstart]]>]]>$" fi if [ $BE -ne 0 ]; then 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 } # Compatible == all yang modules match # runtest # This is really just that modstate is stripped from candidate and running if modstate is off new "1. Run without CLICON_XMLDB_MODSTATE ensure no modstate in datastore" (cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases (cd $dir; cp compat-valid.xml startup_db) runtest false startup 'always workother text' 'always workother text' new "Verify no modstate in running" expect="modules-state" ret=$(sudo grep $expect $dir/running_db) if [ -n "$ret" ]; then err "did not expect $expect" "$ret" fi new "2. Load compatible valid startup (all OK)" # This is really just that modstate is used in candidate and running if modstate is on (cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases (cd $dir; cp compat-valid.xml startup_db) runtest true startup 'always workother text' 'always workother text' new "Verify modstate in running" expect="modules-state" ret=$(sudo grep $expect $dir/running_db) if [ -z "$ret" ]; then err "Expected $expect" "$ret" fi new "3. Load compatible running valid running (rest of tests are startup)" # Just test that a valid db survives start from running (cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases (cd $dir; cp compat-valid.xml running_db) runtest true running 'always workother text' '' #'always workother text' new "4. Load non-compat valid startup" # Just test that a valid db survives start from running (cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases (cd $dir; cp non-compat-valid.xml startup_db) runtest true startup 'always workother text' 'always workother text' new "5. Load non-compat invalid startup. Enter failsafe, startup invalid." # A test that if a non-valid startup is encountered, validation fails and failsafe is entered (cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases (cd $dir; cp non-compat-invalid.xml startup_db) runtest true startup 'always work' 'old versionalways workother textbla bla' # sorted #runtest true startup 'always work' 'old versionbla blaalways workother text' # unsorted new "6. Load non-compat invalid running. Enter failsafe, startup invalid." (cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases (cd $dir; cp non-compat-invalid.xml running_db) (cd $dir; cp non-compat-valid.xml startup_db) # XXX tmp runtest true running 'always work' '' #'old versionalways workother textbla bla' new "7. Load compatible invalid startup." (cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases (cd $dir; cp compat-invalid.xml startup_db) runtest true startup 'always work' 'old versionalways workother textbla bla' # sorted #runtest true startup 'always work' 'old versionbla blaalways workother text' # unsorted # This testcase contains an error/exception of the clixon xml parser, and # I cant track down the memory leakage. if [ $valgrindtest -ne 2 ]; then new "8. Load non-compat startup. Syntax fail, enter failsafe, startup invalid" (cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases (cd $dir; cp compat-err.xml startup_db) runtest true startup 'always work' 'applicationoperation-failederrorread registry' fi # valgrindtest rm -rf $dir new "endtest" endtest