From c0ad3da700b5df7e4482399930c40576689128a9 Mon Sep 17 00:00:00 2001 From: ajaychhabria Date: Mon, 17 Apr 2017 23:45:23 +0000 Subject: [PATCH] CallHome Tests First draft. Change-Id: I5fae3a5dfff79ff61657bf02933f1f9933b47329 Signed-off-by: ajaychhabria --- csit/libraries/NetconfCallHome.robot | 82 +++++++++++++++++ csit/suites/netconf/callhome/callhome.robot | 64 ++++++++++++++ csit/testplans/netconf-callhome.txt | 2 + .../netconf/callhome/credentials_set.sh | 88 +++++++++++++++++++ .../netconf/callhome/datastore-server.xml | 52 +++++++++++ .../netconf/callhome/docker-compose.yaml | 17 ++++ .../netconf/callhome/whitelist_add.sh | 46 ++++++++++ 7 files changed, 351 insertions(+) create mode 100644 csit/libraries/NetconfCallHome.robot create mode 100644 csit/suites/netconf/callhome/callhome.robot create mode 100644 csit/testplans/netconf-callhome.txt create mode 100755 csit/variables/netconf/callhome/credentials_set.sh create mode 100644 csit/variables/netconf/callhome/datastore-server.xml create mode 100644 csit/variables/netconf/callhome/docker-compose.yaml create mode 100755 csit/variables/netconf/callhome/whitelist_add.sh diff --git a/csit/libraries/NetconfCallHome.robot b/csit/libraries/NetconfCallHome.robot new file mode 100644 index 0000000000..a5d120a362 --- /dev/null +++ b/csit/libraries/NetconfCallHome.robot @@ -0,0 +1,82 @@ +*** Settings *** +Library SSHLibrary +Library RequestsLibrary +Resource SSHKeywords.robot +Resource ../variables/Variables.robot + +*** Variables *** +${mount_point_url} /restconf/operational/network-topology:network-topology/topology/topology-netconf/ +${device_status} /restconf/operational/odl-netconf-callhome-server:netconf-callhome-server +${whitelist} /restconf/config/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices +${substring1} "netconf-node-topology:connection-status":"connected" +${substring2} "node-id":"netopeer" +${substring3} "netconf-node-topology:available-capabilities" + +*** Keywords *** +Check Device status + [Arguments] ${status} ${id}=netopeer + [Documentation] Checks the operational device status. + @{expectedValues} Create List "unique-id":"${id}" "callhome-status:device-status":"${status}" + Run Keyword If '${status}'=='FAILED_NOT_ALLOWED' or '${status}'=='FAILED_AUTH_FAILURE' Remove Values From List ${expectedValues} "unique-id":"${id}" + Utils.Check For Elements At URI ${device_status} ${expectedValues} + +Get Netopeer Ready + [Documentation] Pulls the netopeer image from the docker repository. Points ODL(CallHome Server) IP in the files used by netopeer(CallHome Client). + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker pull sdnhub/netopeer return_stdout=True return_stderr=True + ... return_rc=True + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker images return_stdout=True return_stderr=True + ... return_rc=True + Reset Docker Compose Configuration + +Reset Docker Compose Configuration + [Documentation] Resets the docker compose configurations. + SSHLibrary.Put File ${CURDIR}/../variables/netconf/callhome/docker-compose.yaml . + SSHLibrary.Put File ${CURDIR}/../variables/netconf/callhome/datastore-server.xml . + SSHLibrary.Execute_Command sed -i -e 's/ODL_SYSTEM_IP/${ODL_SYSTEM_IP}/g' docker-compose.yaml + SSHLibrary.Execute_Command sed -i -e 's/ODL_SYSTEM_IP/${ODL_SYSTEM_IP}/g' datastore-server.xml + +Get Environment Ready + [Documentation] Get the scripts ready to set credentials and control whitelist maintained by the CallHome server. + SSHLibrary.Put File ${CURDIR}/../variables/netconf/callhome/whitelist_add.sh . + SSHLibrary.Put File ${CURDIR}/../variables/netconf/callhome/credentials_set.sh . + SSHLibrary.Execute_Command chmod +x whitelist_add.sh + SSHLibrary.Execute_Command chmod +x credentials_set.sh + SSHLibrary.Execute_Command sed -i -e 's/ODL_SYSTEM_IP/${ODL_SYSTEM_IP}/g' credentials_set.sh + SSHLibrary.Execute_Command sed -i -e 's/ODL_SYSTEM_IP/${ODL_SYSTEM_IP}/g' whitelist_add.sh + +Install Docker Compose on tools system + [Documentation] Install docker-compose on tools system. + ${netopeer_conn_id} = SSHKeywords.Open_Connection_To_Tools_System + Builtin.Set Suite Variable ${netopeer_conn_id} + SSHLibrary.Write sudo curl -L "https://github.com/docker/compose/releases/download/1.11.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose + ${output}= Wait Until Keyword Succeeds 30s 2s SSHLibrary.Read_Until_Prompt + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command sudo chmod +x /usr/local/bin/docker-compose return_stdout=True return_stderr=True + ... return_rc=True + +Uninstall Docker Compose on tools system + [Documentation] Uninstall docker-compose on tools system + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command pip uninstall docker-compose return_stdout=True return_stderr=True + ... return_rc=True + +Suite Teardown + [Documentation] Tearing down the setup. + Uninstall Docker Compose on tools system + RequestsLibrary.Delete_All_Sessions + SSHLibrary.Close_All_Connections + +Test Teardown + [Documentation] Tears down the docker running netopeer and deletes entry from the whitelist. + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker-compose down return_stdout=True return_stderr=True + ... return_rc=True + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker ps -a return_stdout=True return_stderr=True + ... return_rc=True + ${resp} = RequestsLibrary.Delete_Request session ${whitelist} + +Suite Setup + [Documentation] Get the suite ready for callhome test cases. + RequestsLibrary.Create_Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} auth=${AUTH} + Install Docker Compose on tools system + Get Environment Ready + Get Netopeer Ready + ${netconf_mount_expected_values} Create list ${substring1} ${substring2} ${substring3} + Set Suite Variable ${netconf_mount_expected_values} diff --git a/csit/suites/netconf/callhome/callhome.robot b/csit/suites/netconf/callhome/callhome.robot new file mode 100644 index 0000000000..113f9549e4 --- /dev/null +++ b/csit/suites/netconf/callhome/callhome.robot @@ -0,0 +1,64 @@ +*** Settings *** +Documentation Test suite to verify callhome functionality where the Call Home Server(CONTROLLER) is provisioned with device +... certificates when docker-compose is invoked. Every test case does a SED operation to search and replace words +... to cover the happy path and negative scenarios. +Suite Setup Suite Setup +Suite Teardown Suite Teardown +Test Setup Reset Docker Compose Configuration +Test Teardown Test Teardown +Resource ../../../libraries/NetconfCallHome.robot + +*** Test Cases *** +CallHome with Incorrect global Credentials + [Documentation] Incorrect global credentials should result to mount failure. FAILED_AUTH_FAILURE should be the device status. + SSHLibrary.Execute_Command sed -i -e 's/global root/global incorrect/g' docker-compose.yaml + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker-compose up -d return_stdout=True return_stderr=True + ... return_rc=True + Wait Until Keyword Succeeds 30s 2s NetconfCallHome.Check Device Status FAILED_AUTH_FAILURE + Wait Until Keyword Succeeds 30s 2s Run Keyword And Expect Error * Utils.Check For Elements At URI ${mount_point_url} + ... ${netconf_mount_expected_values} + +CallHome with Incorrect per-device Credentials + [Documentation] Incorrect per-device credentials should result to mount failure. FAILED_AUTH_FAILURE should be the device status. + SSHLibrary.Execute_Command sed -i -e 's/global root/per-device netopeer incorrect/g' docker-compose.yaml + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker-compose up -d return_stdout=True return_stderr=True + ... return_rc=True + Wait Until Keyword Succeeds 30s 2s NetconfCallHome.Check Device Status FAILED_AUTH_FAILURE + Wait Until Keyword Succeeds 30s 2s Run Keyword And Expect Error * Utils.Check For Elements At URI ${mount_point_url} + ... ${netconf_mount_expected_values} + +CallHome with Incorrect Node-id + [Documentation] CallHome from device that does not have an entry in per-device credential with result to mount point failure. + SSHLibrary.Execute_Command sed -i -e 's/global/per-device incorrect_hostname/g' docker-compose.yaml return_rc=True + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker-compose up -d return_stdout=True return_stderr=True + ... return_rc=True + Wait Until Keyword Succeeds 30s 2s NetconfCallHome.Check Device Status DISCONNECTED + Wait Until Keyword Succeeds 30s 2s Run Keyword And Expect Error * Utils.Check For Elements At URI ${mount_point_url} + ... ${netconf_mount_expected_values} + +CallHome with Rogue Devices + [Documentation] A Rogue Device will fail to callhome and wont be able to mount because the keys are not added in whitelist. + ... FAILED_NOT_ALLOWED should be the device status. + SSHLibrary.Execute_Command sed -i -e 's,\/root\/whitelist_add.sh \$\$\{HOSTNAME\}\;,,g' docker-compose.yaml + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker-compose up -d return_stdout=True return_stderr=True + ... return_rc=True + Wait Until Keyword Succeeds 30s 2s NetconfCallHome.Check Device Status FAILED_NOT_ALLOWED + Wait Until Keyword Succeeds 30s 2s Run Keyword And Expect Error * Utils.Check For Elements At URI ${mount_point_url} + ... ${netconf_mount_expected_values} + +Successful CallHome with correct global credentials + [Documentation] Device being in whitelist of the Call Home server along with correct global credentials will result to successful mount. + ... CONNECTED should be the device status. + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker-compose up -d return_stdout=True return_stderr=True + ... return_rc=True + Wait Until Keyword Succeeds 30s 2s NetconfCallHome.Check Device Status CONNECTED + Wait Until Keyword Succeeds 30s 2s Utils.Check For Elements At URI ${mount_point_url} ${netconf_mount_expected_values} + +Successful CallHome with correct per-device credentials + [Documentation] Device being in whitelist of the Call Home server along with correct per-device credentials will result to successful mount. + ... CONNECTED should be the device status. + SSHLibrary.Execute_Command sed -i -e 's/global/per-device netopeer/g' docker-compose.yaml + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker-compose up -d return_stdout=True return_stderr=True + ... return_rc=True + Wait Until Keyword Succeeds 30s 2s NetconfCallHome.Check Device Status CONNECTED + Wait Until Keyword Succeeds 30s 2s Utils.Check For Elements At URI ${mount_point_url} ${netconf_mount_expected_values} diff --git a/csit/testplans/netconf-callhome.txt b/csit/testplans/netconf-callhome.txt new file mode 100644 index 0000000000..5d37af0fcf --- /dev/null +++ b/csit/testplans/netconf-callhome.txt @@ -0,0 +1,2 @@ +# Place the suites in run order: +integration/test/csit/suites/netconf/callhome diff --git a/csit/variables/netconf/callhome/credentials_set.sh b/csit/variables/netconf/callhome/credentials_set.sh new file mode 100755 index 0000000000..fd80f2021f --- /dev/null +++ b/csit/variables/netconf/callhome/credentials_set.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +# This script is called within the docker-compose to provision the controller with either +# the global or per-device credentials. + +stderr() { echo "$@" 1>&2; } + +[ $# -eq 0 ] && { stderr "Usage: $0 ( -global | -per-device id ) username password(s)"; exit 1; } + +: ${1?"Usage: $0 -global | -per-device"} + +option=${1}; + +if [[ "${option}" == "-per-device" ]]; then + : ${2?"Usage: $0 Device Id"} + : ${3?"Usage: $0 Device Username"} + : ${4?"Usage: $0 Device Password"} + devid=${2} + user=${3} + shift; shift; shift + pwds="$@" +elif [[ "${option}" == "-global" ]]; then + : ${2?"Usage: $0 Global Username"} + : ${3?"Usage: $0 Global Password"} + devid="" + user=${2} + shift; shift + pwds="$@" +else + stderr "$0: must supply -global or -per-device command line argument for global password changes, not '${option}''" + exit 1 +fi + +pwdsjson="" + +for pwd in $pwds; do + if [[ ! -z "$pwdsjson" ]]; then + pwdsjson+="," + fi + pwdsjson+="'$pwd'" +done + +set -e +controller=ODL_SYSTEM_IP +port=8181 +basicauth="YWRtaW46YWRtaW4=" + +baseurl="http://${controller}:${port}/restconf/config/odl-netconf-callhome-server:netconf-callhome-server" + +if [[ "${option}" == "-global" ]]; then + url="${baseurl}/global/credentials" +else + url="${baseurl}/allowed-devices/device/${devid}/credentials" +fi + +set +e +read -r -d '' payload << EOM +{ + "credentials": { + "username": "${user}", + "passwords": [${pwdsjson}] + } +} +EOM +set -e + +payload=$(echo "${payload}" | tr '\n' ' ' | tr -s " ") + +echo "PUT of user (${user}) and pwd (${pwd})" +res=$(curl -s -X PUT \ + -H "Authorization: Basic ${basicauth}" \ + -H "Content-Type: application/json" \ + -H "Cache-Control: no-cache" \ + --data "${payload}" \ + ${url}) + +if [[ $res == *"error-message"* ]]; then + stderr "$0: ${res}" + exit 1 +fi + +echo "Getting user/pwd ..." + +res=$(curl -s -X GET \ + -H "Authorization: Basic ${basicauth}" \ + -H "Cache-Control: no-cache" \ + ${url}) +echo ${res} diff --git a/csit/variables/netconf/callhome/datastore-server.xml b/csit/variables/netconf/callhome/datastore-server.xml new file mode 100644 index 0000000000..8762a29148 --- /dev/null +++ b/csit/variables/netconf/callhome/datastore-server.xml @@ -0,0 +1,52 @@ + + + + + + + + + test + + +
ODL_SYSTEM_IP
+ 6666 +
+
+ + + localhost + + +
+
+
+
+
+
+ + + + + + + test + + +
ODL_SYSTEM_IP
+ 6666 +
+
+ + + localhost + + +
+
+
+
+
+
+ +
diff --git a/csit/variables/netconf/callhome/docker-compose.yaml b/csit/variables/netconf/callhome/docker-compose.yaml new file mode 100644 index 0000000000..6eb1e78c07 --- /dev/null +++ b/csit/variables/netconf/callhome/docker-compose.yaml @@ -0,0 +1,17 @@ +# Controller needs to be provisoned with the unique-id of the device(netopeer) and public key. +# The way this is done with docker compose is: +# 1. A new docker instance is spawned and public key is generated. +# 2. We create new pair of keys to ensure it is different than the snapshot of the image. +# 3. Execute script to send REST to provision netopeer unique-id + public key + credentials in controller. +# 4. Start netopeer. + +netopeer: + image: sdnhub/netopeer + hostname: netopeer + command: sh -c "apt-get update;apt-get install curl --force-yes -y;echo -e 'y/n' | ssh-keygen -q -N '' -f /etc/ssh/ssh_host_rsa_key;/root/whitelist_add.sh $${HOSTNAME};/root/credentials_set.sh -global root root;/root/netopeer/server/netopeer-server -v 3" + environment: + - controller_ip=ODL_SYSTEM_IP + volumes: + - ./datastore-server.xml:/usr/local/etc/netopeer/cfgnetopeer/datastore-server.xml + - ./whitelist_add.sh:/root/whitelist_add.sh + - ./credentials_set.sh:/root/credentials_set.sh diff --git a/csit/variables/netconf/callhome/whitelist_add.sh b/csit/variables/netconf/callhome/whitelist_add.sh new file mode 100755 index 0000000000..ef569aaea3 --- /dev/null +++ b/csit/variables/netconf/callhome/whitelist_add.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# This script is called within the docker-compose to get the public RSA key of the +# device(callhome client) and provision the controller. + +set -e + +key3="$(cat /etc/ssh/ssh_host_rsa_key.pub)" +parts=($key3) +hostkey=${parts[1]} +id=$1 +controller=ODL_SYSTEM_IP +echo "Adding key for ${id} to ${controller}" +echo "Found host key: ${hostkey}" + +port=8181 +basicauth="YWRtaW46YWRtaW4=" + +set +e +read -r -d '' payload << EOM +{ + "device": [ + { + "ssh-host-key": "${hostkey}", + "unique-id": "${id}" + } + ] +} +EOM +set -e + +payload=$(echo "${payload}" | tr '\n' ' ' | tr -s " ") + +url="http://${controller}:${port}/restconf/config/odl-netconf-callhome-server:netconf-callhome-server/allowed-devices" + +echo "POST to whitelist" +res=$(curl -s -X POST -H "Authorization: Basic ${basicauth}" \ + -H "Content-Type: application/json" \ + -H "Cache-Control: no-cache" \ + -H "Postman-Token: 656d7e0d-2f48-5135-3569-06b2a27a709d" \ + --data "${payload}" \ + ${url}) +echo $res +if [[ $res == *"data-exists"* ]]; then + echo "Whitelist already has that entry." +fi -- 2.36.6