#!/usr/bin/env bash # Restconf native using socket network namespace (netns) support # Listen to a default and a separate netns # Init running with a=42 # Get the config from default and netns namespace with/without SSL # Write b=99 in netns and read from default # Also a failed usecase is failed bind in other namespace causes two processes/zombie # 1. Configure one valid and one invalid address in other dataplane # 2. Two restconf processes, one may be zombie # 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 # Skip if valgrind restconf (actually valgrind version < 3.16 27 May 2020) if [ $valgrindtest -eq 3 ]; then if [ "$s" = $0 ]; then exit 0; else return 0; fi # skip fi # Check if ip netns is implemented (Alpine does not have it) ip netns 2> /dev/null if [ $? -ne 0 ]; then echo "...ip netns does not work" if [ "$s" = $0 ]; then exit 0; else return 0; fi # skip fi APPNAME=example cfg=$dir/conf.xml startupdb=$dir/startup_db netns=clixonnetns veth=veth0 vethpeer=veth1 vaddr=10.23.1.1 # address in netns vaddr2=10.23.10.1 # Used as invalid RESTCONFDBG=$DBG # 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 $RESTCONFDBG default
127.0.0.1
80 false
$netns
0.0.0.0
80 false
$netns
0.0.0.0
443 true
" EOF ) cat < $cfg $cfg ietf-netconf:startup clixon-restconf:allow-auth-none /usr/local/share/clixon $IETFRFC clixon-example /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/backend example_backend.so$ /usr/local/lib/$APPNAME/restconf /usr/local/lib/$APPNAME/cli $APPNAME /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/var/$APPNAME/$APPNAME.pidfile $dir true $RESTCONFIG EOF new "Create netns: $netns" sudo ip netns delete $netns # Create netns sudo ip netns add $netns if [ -z "$(ip netns list | grep $netns)" ]; then err "$netns" "$netns does not exist" fi new "Create veth pair: $veth and $vethpeer" sudo ip link delete $veth 2> /dev/null sudo ip link delete $vethpeer 2> /dev/null sudo ip link add $veth type veth peer name $vethpeer if [ -z "$(ip netns show $veth)" ]; then err "$veth" "$veth does not exist" fi if [ -z "$(ip netns show $vethpeer)" ]; then err "$veth" "$vethpeer does not exist" fi new "Move $vethpeer to netns $netns" sudo ip link set $vethpeer netns $netns if [ -z "$( sudo ip netns exec $netns ip link show $vethpeer)" ]; then err "$veth" "$vethpeer does not exist" fi new "Assign address $vaddr on $veth in netns $netns" sudo ip netns exec $netns ip addr add $vaddr/24 dev $vethpeer sudo ip netns exec $netns ip link set dev $vethpeer up sudo ip netns exec $netns ip link set dev lo up #sudo ip netns exec $netns ping $vaddr #----------------- new "test params: -f $cfg" if [ $BE -ne 0 ]; then new "kill old backend" sudo clixon_backend -z -f $cfg if [ $? -ne 0 ]; then err fi new "start backend -s init -f $cfg" start_backend -s init -f $cfg fi new "wait backend" 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 http # force to http on host ns new "add sample config w netconf" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOa42
]]>]]>" "^]]>]]>$" new "netconf commit" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" # NOTE http/1.1 new "restconf http get config on default netns" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' http://127.0.0.1/restconf/data/clixon-example:table)" 0 "HTTP/1.1 200" 'a42
' new "restconf http get config on addr:$vaddr in netns:$netns" expectpart "$(sudo ip netns exec $netns curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' https://$vaddr/restconf/data/clixon-example:table)" 0 "HTTP/$HVER 200" 'a42
' new "restconf https/SSL get config on addr:$vaddr in netns:$netns" expectpart "$(sudo ip netns exec $netns curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' https://$vaddr/restconf/data/clixon-example:table)" 0 "HTTP/$HVER 200" 'a42
' new "restconf https/SSL put table b" expectpart "$(sudo ip netns exec $netns curl $CURLOPTS -X POST -H 'Content-Type: application/yang-data+xml' -d 'b99' https://$vaddr/restconf/data/clixon-example:table)" 0 "HTTP/$HVER 201" # NOTE http/1.1 new "restconf http get table b on default ns" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' http://127.0.0.1/restconf/data/clixon-example:table/parameter=b)" 0 "HTTP/1.1 200" 'b99' # Negative new "restconf get config on wrong port in netns:$netns" expectpart "$(sudo ip netns exec $netns curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://$vaddr:8888/restconf/data/clixon-example:table 2> /dev/null)" 7 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 #----------------------------------------- RESTCONFIG=$(cat < true $RESTCONFDBG none false default
127.0.0.1
80 false
$netns
$vaddr
80 false
$netns
$vaddr2
80 false
EOF ) cat < $cfg $cfg ietf-netconf:startup clixon-restconf:allow-auth-none /usr/local/share/clixon $IETFRFC clixon-example /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/backend example_backend.so$ /usr/local/lib/$APPNAME/restconf /usr/local/lib/$APPNAME/cli $APPNAME /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/var/$APPNAME/$APPNAME.pidfile $dir true $RESTCONFIG EOF new "Failed usecase. Fail to bind in other namespace causes two processes/zombie" new "kill old restconf" stop_restconf_pre new "test params: -f $cfg" if [ $BE -ne 0 ]; then new "kill old backend" sudo clixon_backend -z -f $cfg if [ $? -ne 0 ]; then err fi new "start backend -s init -f $cfg" start_backend -s init -f $cfg fi new "wait backend" 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 http # force to http on host ns sleep $DEMSLEEP new "Check zombies" retx=$(ps aux| grep clixon | grep defunc | grep -v grep) if [ -n "$retx" ]; then err "No zombie process" "$retx" 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 sudo ip link delete $veth sudo ip netns delete $netns new "endtest" endtest rm -rf $dir