diff --git a/docker/main/startsystem_fcgi.sh b/docker/main/startsystem_fcgi.sh index da597818..2f4ebe83 100755 --- a/docker/main/startsystem_fcgi.sh +++ b/docker/main/startsystem_fcgi.sh @@ -96,6 +96,7 @@ EOF # Patch to override YANG_INSTALLDIRS cat <> /usr/local/bin/test/config.sh YANG_INSTALLDIR=/usr/local/share/clixon +OPENCONFIG=/usr/local/share/openconfig EOF # Patch yang syntax errors diff --git a/docker/main/startsystem_native.sh b/docker/main/startsystem_native.sh index 255cc3b8..72287a90 100755 --- a/docker/main/startsystem_native.sh +++ b/docker/main/startsystem_native.sh @@ -64,6 +64,7 @@ EOF # Patch to override YANG_INSTALLDIRS cat <> /usr/local/bin/test/config.sh YANG_INSTALLDIR=/usr/local/share/clixon +OPENCONFIG=/usr/local/share/openconfig EOF # Patch yang syntax errors diff --git a/test/test_perf_restconf.sh b/test/test_perf_restconf.sh index 1c9d73da..2ad291e4 100755 --- a/test/test_perf_restconf.sh +++ b/test/test_perf_restconf.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash -# Scaling/ performance tests -# CLI/Netconf/Restconf +# Scaling/ performance tests for non-ssl RESTCONF # Lists (and leaf-lists) # Add, get and delete entries -# Override default to use http/1.1 +# Override default to use http/1.1, comment to use https/2 HAVE_LIBNGHTTP2=false +RCPROTO=http # Magic line must be first in script (see README.md) s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi @@ -127,7 +127,6 @@ expectpart "$(time -p ls)" 0 new "restconf write large config" expectpart "$(time -p curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+xml" $RCPROTO://localhost/restconf/data -d @$fdataxml )" 0 "HTTP/$HVER 201" -exit new "Check running-db contents" curl $CURLOPTS -X GET -H "Accept: application/yang-data+xml" $RCPROTO://localhost/restconf/data?content=config > $foutput @@ -261,6 +260,8 @@ rm -rf $dir # Set by restconf_config unset RESTCONFIG +unset HAVE_LIBNGHTTP2 +unset RCPROTO # unset conditional parameters unset format diff --git a/test/test_perf_restconf_ssl.sh b/test/test_perf_restconf_ssl.sh new file mode 100755 index 00000000..ed8e23c3 --- /dev/null +++ b/test/test_perf_restconf_ssl.sh @@ -0,0 +1,300 @@ +#!/usr/bin/env bash +# Scaling/ performance tests for ssl RESTCONF +# Lists (and leaf-lists) +# Add, get and delete entries + +# Override default to use http/1.1, comment to use https/2 +#HAVE_LIBNGHTTP2=false +#RCPROTO=http + +# Magic line must be first in script (see README.md) +s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi + +# Skip if other than native +if [ "${WITH_RESTCONF}" != "native" ]; then + if [ "$s" = $0 ]; then exit 0; else return 0; fi # skip +fi + +# Which format to use as datastore format internally +: ${format:=xml} + +# Number of list/leaf-list entries in file +: ${perfnr:=20000} + +# Number of requests made get/put +: ${perfreq:=10} + +# time function (this is a mess to get right on freebsd/linux) +# -f %e gives elapsed wall clock time but is not available on all systems +# so we use time -p for POSIX compliance and awk to get wall clock time +# Note sometimes time -p is used and sometimes $TIMEFN, cant get it to work same everywhere +: ${TIMEFN:=time -p} # portability: 2>&1 | awk '/real/ {print $2}' +if ! $TIMEFN true; then err "A working time function" "'$TIMEFN' does not work"; fi + +APPNAME=example + +cfg=$dir/scaling-conf.xml +fyang=$dir/scaling.yang +fdataxml=$dir/config.xml # dataxml +ftest=$dir/test.xml +fconfig=$dir/large.xml +fconfig2=$dir/large2.xml # leaf-list +foutput=$dir/output.xml +foutput2=$dir/output2.xml + +cat < $fyang +module scaling{ + yang-version 1.1; + namespace "urn:example:clixon"; + prefix ex; + container x { + list y { + key "a"; + leaf a { + type int32; + } + leaf b { + type int32; + } + } + leaf-list c { + type string; + } + } +} +EOF + +# Create server certs +certdir=$dir/certs +srvkey=$certdir/srv_key.pem +srvcert=$certdir/srv_cert.pem +cakey=$certdir/ca_key.pem # needed? +cacert=$certdir/ca_cert.pem +test -d $certdir || mkdir $certdir +# Create server certs and CA +cacerts $cakey $cacert +servercerts $cakey $cacert $srvkey $srvcert + +RESTCONFIG=$(cat < + true + none + $srvcert + $srvkey + $cakey + false + default
0.0.0.0
80false
+ default
0.0.0.0
443true
+ +EOF +) + +cat < $cfg + + $cfg + clixon-restconf:allow-auth-none + $dir + ${YANG_INSTALLDIR} + $fyang + /usr/local/var/$APPNAME/$APPNAME.sock + /usr/local/var/example/$APPNAME.pidfile + $dir + false + $format + example + /usr/local/lib/example/cli + /usr/local/lib/example/clispec + 0 + ietf-netconf:startup + $RESTCONFIG + +EOF + +new "test params: -f $cfg" +if [ $BE -ne 0 ]; then + new "kill old backend" + sudo clixon_backend -zf $cfg + if [ $? -ne 0 ]; then + err + fi + + new "start backend -s init -f $cfg -- -s" + start_backend -s init -f $cfg -- -s +fi + +new "waiting" +wait_backend + +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 + +# Check this later with committed data +new "generate config with $perfnr list entries" +echo -n "" > $fdataxml +for (( i=0; i<$perfnr; i++ )); do + echo -n "$i$i" >> $fdataxml +done +echo -n "" >> $fdataxml # No CR + +echo -n "$DEFAULTHELLO" > $fconfig +cat $fdataxml >> $fconfig +echo "]]>]]>" >> $fconfig + +# Now take large config file and write it via netconf to candidate +new "test time exists" +expectpart "$(time -p ls)" 0 + +new "restconf write large config" +expectpart "$(time -p curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+xml" $RCPROTO://localhost/restconf/data -d @$fdataxml )" 0 "HTTP/$HVER 201" + +new "Check running-db contents" +curl $CURLOPTS -X GET -H "Accept: application/yang-data+xml" $RCPROTO://localhost/restconf/data?content=config > $foutput +r=$? +if [ $r -ne 0 ]; then + err1 "retval 0" $r +fi + +# Remove Content-Length line (depends on size) +# Note: do not use sed -i since it is not portable between gnu and bsd +sed '/Content-Length:/d' $foutput > $foutput2 && mv $foutput2 $foutput +sed '/content-length:/d' $foutput > $foutput2 && mv $foutput2 $foutput +# Remove (nginx) web-server specific lines +sed '/Server:/d' $foutput > $foutput2 && mv $foutput2 $foutput +sed '/Date:/d' $foutput > $foutput2 && mv $foutput2 $foutput +sed '/Transfer-Encoding:/d' $foutput > $foutput2 && mv $foutput2 $foutput +sed '/Connection:/d' $foutput > $foutput2 && mv $foutput2 $foutput + +# Create a file to compare with +if ${HAVE_LIBNGHTTP2}; then + if [ ${HAVE_HTTP1} -a ${RCPROTO} = http ]; then + # Add 101 switch protocols for http 1->2 upgrade + echo "HTTP/1.1 101 Switching Protocols " > $ftest + echo "Upgrade: h2c " >> $ftest + echo " " >> $ftest + echo "HTTP/$HVER 200 " >> $ftest + else + echo "HTTP/$HVER 200 " > $ftest + fi +else + echo "HTTP/$HVER 200 OK " > $ftest +fi +echo "Content-Type: application/yang-data+xml " >> $ftest +echo "Cache-Control: no-cache " >> $ftest +echo " ">> $ftest +echo -n "">> $ftest +cat $fdataxml >> $ftest +echo " " >> $ftest + +ret=$(diff -i $ftest $foutput) +if [ $? -ne 0 ]; then + echo "diff -i $ftest $foutput" + err1 "Matching running-db with $fdataxml" +fi + +# RESTCONF get +new "restconf get $perfreq small config 1 key index" +{ time -p for (( i=0; i<$perfreq; i++ )); do + rnd=$(( ( RANDOM % $perfnr ) )) + curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/scaling:x/y=$rnd > /dev/null +done } 2>&1 | awk '/real/ {print $2}' + +# RESTCONF put +# Reference: +# i686 format=xml perfnr=10000/100 time: 38/29s 20190425 WITH/OUT startup copying +# i686 format=tree perfnr=10000/100 time: 72/64s 20190425 WITH/OUT startup copying +new "restconf add $perfreq small config" +{ time -p for (( i=0; i<$perfreq; i++ )); do + rnd=$(( ( RANDOM % $perfnr ) )) + curl $CURLOPTS -X PUT $RCPROTO://localhost/restconf/data/scaling:x/y=$rnd -d '{"scaling:y":{"a":"'$rnd'","b":"'$rnd'"}}' +done } 2>&1 | awk '/real/ {print $2}' + +new "restconf get large config" +# XXX for some reason cannot expand $TIMEFN next two tests, need keep variable? +$TIMEFN curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data 2>&1 > /dev/null | awk '/real/ {print $2}' + +# Delete entries (last since entries are removed from db) +# netconf +new "cli delete $perfreq small config" +{ time -p for (( i=0; i<$perfreq; i++ )); do + rnd=$(( ( RANDOM % $perfnr ) )) + $clixon_cli -1 -f $cfg delete x y $rnd +done } 2>&1 | awk '/real/ {print $2}' + +#new "netconf discard-changes" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" + +# XXX This takes time +# 18.69 without startup feature +# 21.98 with startup +{ time -p for (( i=0; i<$perfreq; i++ )); do + rnd=$(( ( RANDOM % $perfnr ) )) + curl $CURLOPTS -X DELETE $RCPROTO://localhost/restconf/data/scaling:x/y=$rnd +done > /dev/null; } 2>&1 | awk '/real/ {print $2}' + +# Now do leaf-lists istead of leafs + +#new "generate leaf-list config" +echo -n "$DEFAULTHELLOreplace" > $fconfig2 +for (( i=0; i<$perfnr; i++ )); do + echo -n "$i" >> $fconfig2 +done +echo "]]>]]>" >> $fconfig2 + +new "netconf replace large list-leaf config" +expecteof_file "time -p $clixon_netconf -qf $cfg" 0 "$fconfig2" "^]]>]]>$" 2>&1 | awk '/real/ {print $2}' + +new "netconf commit large leaf-list config" +expecteof "time -p $clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" 2>&1 | awk '/real/ {print $2}' + +new "netconf add $perfreq small leaf-list config" +{ time -p for (( i=0; i<$perfreq; i++ )); do + rnd=$(( ( RANDOM % $perfnr ) )) + echo "$DEFAULTHELLO$rnd]]>]]>" +done | $clixon_netconf -qf $cfg > /dev/null; } 2>&1 | awk '/real/ {print $2}' + +new "netconf add small leaf-list config" +expecteof "time -p $clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOx]]>]]>" "^]]>]]>$" 2>&1 | awk '/real/ {print $2}' + +new "netconf commit small leaf-list config" +expecteof "time -p $clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" 2>&1 | awk '/real/ {print $2}' + +new "netconf get large leaf-list config" +expecteof "time -p $clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^01" 2>&1 | awk '/real/ {print $2}' + +if [ $RC -ne 0 ]; then + new "Kill restconf daemon" + stop_restconf +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 +rm -rf $dir + +# Set by restconf_config +unset RESTCONFIG +unset HAVE_LIBNGHTTP2 +unset RCPROTO + +# unset conditional parameters +unset format +unset perfnr +unset perfreq +unset ret + +new "endtest" +endtest diff --git a/test/test_restconf_err.sh b/test/test_restconf_err.sh index 7d7d002c..8871b7b7 100755 --- a/test/test_restconf_err.sh +++ b/test/test_restconf_err.sh @@ -213,7 +213,7 @@ elif [ -n "$(type nc 2> /dev/null)" ]; then else netcat= fi -if [ -n "$netcat" ]; then +if [ -n "$netcat" -a "${WITH_RESTCONF}" != "fcgi" ]; then # new "restconf try fuzz crash" # expectpart "$(${netcat} 127.0.0.1 80 < ~/tmp/crashes/id:000000,sig:06,src:000493+000365,op:splice,rep:8)" 0 "HTTP/$HVER 400"