From a96c1608fbe75392943549bf790f37411cc43841 Mon Sep 17 00:00:00 2001 From: Sangwook Ha Date: Fri, 9 Sep 2022 16:43:51 -0700 Subject: [PATCH] Update Robot Framework format - step 1 Robotidy has stricter formatting rules for line width, alignment, section ordering & spacing, etc. Update the format of Robot Framework files in the following directory with Robotidy: - csit/libraries JIRA: INTTEST-132 Change-Id: I5c7300e322b7069bac36a8b6ca3273e6f9186d25 Signed-off-by: Sangwook Ha --- csit/libraries/AAA/DockerKeystone.robot | 151 ++- csit/libraries/AAAKeywords.robot | 66 +- csit/libraries/BGPSpeaker.robot | 83 +- csit/libraries/BGPcliKeywords.robot | 55 +- csit/libraries/BackupRestoreKeywords.robot | 117 +- csit/libraries/BgpOperations.robot | 279 ++-- csit/libraries/BierTeResource.robot | 63 +- csit/libraries/BulkomaticKeywords.robot | 116 +- csit/libraries/CarPeople.robot | 55 +- csit/libraries/ChangeCounter.robot | 62 +- csit/libraries/CheckJVMResource.robot | 64 +- csit/libraries/ClusterAdmin.robot | 108 +- csit/libraries/ClusterManagement.robot | 858 ++++++++---- csit/libraries/ClusterOpenFlow.robot | 350 +++-- csit/libraries/ClusterOvsdb.robot | 255 +++- csit/libraries/Coe.robot | 167 ++- csit/libraries/CompareStream.robot | 295 ++-- csit/libraries/DIDMKeywords.robot | 58 +- csit/libraries/DaeximKeywords.robot | 172 ++- csit/libraries/DataModels.robot | 29 +- csit/libraries/DatastoreCRUD.robot | 65 +- csit/libraries/DevstackUtils.robot | 69 +- csit/libraries/ExaBgpLib.robot | 59 +- csit/libraries/FailFast.robot | 41 +- csit/libraries/FlowLib.robot | 306 +++-- csit/libraries/GBP/AssertionUtils.robot | 76 +- csit/libraries/GBP/ConnUtils.robot | 17 +- csit/libraries/GBP/DockerUtils.robot | 107 +- csit/libraries/GBP/OpenFlowUtils.robot | 198 +-- csit/libraries/GBP/RestconfUtils.robot | 162 +-- csit/libraries/GUIKeywords.robot | 134 +- csit/libraries/GbpSxp.robot | 117 +- csit/libraries/Genius.robot | 270 ++-- csit/libraries/GoBgpLib.robot | 62 +- csit/libraries/IoTDM/IoTDMKeywords.robot | 14 +- csit/libraries/IoTDM/IoTDMResources.robot | 92 +- csit/libraries/IoTDM/iotdm_sanity_tests.robot | 47 +- csit/libraries/JsonrpcKeywords.robot | 39 +- csit/libraries/KarafKeywords.robot | 373 +++-- csit/libraries/KillPythonTool.robot | 41 +- csit/libraries/L2GatewayOperations.robot | 176 ++- csit/libraries/LISPFlowMapping.robot | 39 +- csit/libraries/LISPFlowMapping__Lithium.robot | 22 +- csit/libraries/LiveMigration.robot | 35 +- csit/libraries/MdsalLowlevel.robot | 301 ++-- csit/libraries/MininetKeywords.robot | 159 ++- csit/libraries/NetconfCallHome.robot | 194 ++- csit/libraries/NetconfKeywords.robot | 201 ++- csit/libraries/NettyReplication.robot | 69 +- csit/libraries/NexusKeywords.robot | 364 +++-- csit/libraries/ODLMicroKeywords.robot | 60 +- csit/libraries/ODLTools.robot | 38 +- csit/libraries/OVSDB.robot | 376 +++-- csit/libraries/OcpAgentKeywords.robot | 45 +- csit/libraries/OpenStackOperations.robot | 1205 +++++++++++------ csit/libraries/OvsManager.robot | 208 +-- csit/libraries/PacketcableVersion.robot | 6 +- csit/libraries/PcepOperations.robot | 66 +- csit/libraries/PrefixCounting.robot | 93 +- csit/libraries/RemoteBash.robot | 56 +- csit/libraries/RestPerfClient.robot | 74 +- csit/libraries/Restconf.robot | 45 +- csit/libraries/SFC/DockerSfc.robot | 94 +- csit/libraries/SFC/SfcKeywords.robot | 63 +- csit/libraries/SSHKeywords.robot | 273 ++-- csit/libraries/SXP/FilteringResources.robot | 8 +- csit/libraries/ScalarClosures.robot | 77 +- csit/libraries/SetupUtils.robot | 57 +- csit/libraries/ShardStability.robot | 100 +- csit/libraries/SubStrings.robot | 7 +- csit/libraries/SwitchUtils.robot | 163 ++- csit/libraries/SxpBindingOriginsLib.robot | 59 +- csit/libraries/SxpClusterLib.robot | 229 +++- csit/libraries/SxpLib.robot | 260 ++-- csit/libraries/Tcpdump.robot | 55 +- csit/libraries/Tempest.robot | 117 +- csit/libraries/TemplatedRequests.robot | 931 +++++++++---- csit/libraries/ToolsSystem.robot | 17 +- csit/libraries/TopoprocessingKeywords.robot | 536 +++++--- csit/libraries/TsdrUtils.robot | 401 +++--- csit/libraries/UnimgrKeywords.robot | 33 +- csit/libraries/UscUtils.robot | 49 +- csit/libraries/Utils.robot | 401 +++--- csit/libraries/VpnOperations.robot | 281 ++-- csit/libraries/VtnMaKeywords.robot | 449 +++--- csit/libraries/WaitForFailure.robot | 69 +- csit/libraries/WaitUtils.robot | 331 +++-- csit/libraries/WorkflowsL2switch.robot | 131 +- csit/libraries/WorkflowsOpenFlow.robot | 391 ++++-- csit/libraries/YangCollection.robot | 786 +++++++---- csit/libraries/YangmanKeywords.robot | 387 ++++-- csit/libraries/controller/CsCommon.robot | 136 +- csit/libraries/controller/DdbCommons.robot | 521 +++++-- csit/libraries/controller/DnbCommons.robot | 71 +- csit/libraries/controller/DrbCommons.robot | 179 ++- .../libraries/distribution/StreamDistro.robot | 25 +- 96 files changed, 11248 insertions(+), 5963 deletions(-) diff --git a/csit/libraries/AAA/DockerKeystone.robot b/csit/libraries/AAA/DockerKeystone.robot index 7f9189556d..00ed18cb82 100644 --- a/csit/libraries/AAA/DockerKeystone.robot +++ b/csit/libraries/AAA/DockerKeystone.robot @@ -1,138 +1,181 @@ *** Settings *** -Documentation DockerKeystone library. This library is useful to deal with Openstack Keystone service which provides API client authentication. +Documentation DockerKeystone library. This library is useful to deal with Openstack Keystone service which provides API client authentication. ... -... It consists of three main groups of keywords: +... It consists of three main groups of keywords: ... -... - Start/Stop keystone node in SYSTEM TOOLS VM: -... - Run Docker Keystone -... - Destroy Docker Keystone -... - Check Keystone Log File For String +... - Start/Stop keystone node in SYSTEM TOOLS VM: +... - Run Docker Keystone +... - Destroy Docker Keystone +... - Check Keystone Log File For String ... -... - Provision keystone node: -... - Create Keystone session -... - Get Keystone Token -... - Create Keystone Domain -... - Create Keystone User in a Domain -... - Set Domain To False -... - Get Admin Role Id -... - Grant Admin Role -... - Delete Keystone Domain +... - Provision keystone node: +... - Create Keystone session +... - Get Keystone Token +... - Create Keystone Domain +... - Create Keystone User in a Domain +... - Set Domain To False +... - Get Admin Role Id +... - Grant Admin Role +... - Delete Keystone Domain ... -... - Provision ODL node for secure communication with Keystone node: -... - Set Keystone Certificate into ODL -Library SSHLibrary -Library RequestsLibrary +... - Provision ODL node for secure communication with Keystone node: +... - Set Keystone Certificate into ODL + +Library SSHLibrary +Library RequestsLibrary -*** Variables *** *** Keywords *** Get Keystone Token - [Arguments] ${TOOLS_SYSTEM_NAME} ${CREATE_TOKEN_FILE} [Documentation] Get Keystone token for a particular user and domain + [Arguments] ${TOOLS_SYSTEM_NAME} ${CREATE_TOKEN_FILE} Set Suite Variable ${CREATE_TOKEN_URI} /v3/auth/tokens/ ${body} OperatingSystem.Get File ${CREATE_TOKEN_FILE} Log ${HEADERS} - ${resp}= RequestsLibrary.Post Request session_keystone ${CREATE_TOKEN_URI} data=${body} headers=${HEADERS} allow_redirects=${true} + ${resp} RequestsLibrary.Post Request + ... session_keystone + ... ${CREATE_TOKEN_URI} + ... data=${body} + ... headers=${HEADERS} + ... allow_redirects=${true} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} ${token} Get From Dictionary ${resp.headers} x-subject-token - [Return] ${token} + RETURN ${token} Create Keystone session - [Arguments] ${TOOLS_SYSTEM_NAME} [Documentation] Create a https session with Keystone for provisioning new domains, users, projects ... + [Arguments] ${TOOLS_SYSTEM_NAME} Log ${HEADERS} - Create Session session_keystone https://${TOOLS_SYSTEM_NAME}:35357 auth=${AUTH_ADMIN_SDN} headers=${HEADERS} debug=3 + Create Session + ... session_keystone + ... https://${TOOLS_SYSTEM_NAME}:35357 + ... auth=${AUTH_ADMIN_SDN} + ... headers=${HEADERS} + ... debug=3 Create Keystone Domain - [Arguments] ${HEADERS} ${CREATE_DOMAIN_FILE} [Documentation] Provision a domain in Keystone + [Arguments] ${HEADERS} ${CREATE_DOMAIN_FILE} Set Suite Variable ${CREATE_DOMAIN_URI} /v3/domains/ ${body} OperatingSystem.Get File ${CREATE_DOMAIN_FILE} - ${resp} RequestsLibrary.Post Request session_keystone ${CREATE_DOMAIN_URI} data=${body} headers=${HEADERS} + ${resp} RequestsLibrary.Post Request + ... session_keystone + ... ${CREATE_DOMAIN_URI} + ... data=${body} + ... headers=${HEADERS} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} ${domain_id} Convert To String ${resp.json()['domain']['id']} - [Return] ${domain_id} + RETURN ${domain_id} Create Keystone User in a Domain - [Arguments] ${HEADERS} ${CREATE_USERS_FILE} [Documentation] Provision an user associated to a domain in \ Keystone + [Arguments] ${HEADERS} ${CREATE_USERS_FILE} Set Suite Variable ${CREATE_USERS_URI} /v3/users/ ${body} OperatingSystem.Get File ${CREATE_USERS_FILE} - ${resp} RequestsLibrary.Post Request session_keystone ${CREATE_USERS_URI} data=${body} headers=${HEADERS} + ${resp} RequestsLibrary.Post Request + ... session_keystone + ... ${CREATE_USERS_URI} + ... data=${body} + ... headers=${HEADERS} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} ${user_id} Convert To String ${resp.json()['user']['id']} - [Return] ${user_id} + RETURN ${user_id} Grant Admin Role - [Arguments] ${domain} ${user} ${roleid} ${HEADERS} [Documentation] Grant a role to an user in a domain in \ Keystone + [Arguments] ${domain} ${user} ${roleid} ${HEADERS} Set Suite Variable ${GRANT_ADMIN_ROLE_URI} /v3/domains/${domain}/users/${user}/roles/${roleid} ${resp} RequestsLibrary.Put Request session_keystone ${GRANT_ADMIN_ROLE_URI} headers=${HEADERS} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Get Admin Role Id - [Arguments] ${HEADERS} [Documentation] Get admin role id from Keystone + [Arguments] ${HEADERS} Set Suite Variable ${GET_ADMIN_ROLE_URI} /v3/roles?name=admin - ${resp}= RequestsLibrary.Get Request session_keystone ${GET_ADMIN_ROLE_URI} headers=${HEADERS} + ${resp} RequestsLibrary.Get Request session_keystone ${GET_ADMIN_ROLE_URI} headers=${HEADERS} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} ${admin_role_id} Convert To String ${resp.json()['roles'][0]['id']} Log ${admin_role_id} - [Return] ${admin_role_id} + RETURN ${admin_role_id} Run Docker Keystone [Documentation] Run Keystone in a docker container hosted in the SYSTEM TOOL server and define "CSC_user" and "CSC_user_no_admin" users, the former with "admin" role and the latter with "user" role ${output} SSHLibrary.Open_Connection ${TOOLS_SYSTEM_IP} timeout=20s SSHKeywords.Flexible_Controller_Login SSHLibrary.Put File ${CURDIR}/../../suites/aaa/keystone/start_keystone.sh - ${output}= SSHLibrary.Execute Command ./start_keystone.sh + ${output} SSHLibrary.Execute Command ./start_keystone.sh Log ${output} - ${output}= SSHLibrary.Execute Command docker ps --all + ${output} SSHLibrary.Execute Command docker ps --all Log ${output} Wait Until Keyword Succeeds 10x 15 Check Keystone Log File For String GET - SSHLibrary.Execute Command docker exec -t keystone bash -c "source openrc;openstack user create --password cscuser CSC_user;openstack user set --project admin CSC_user;openstack role add --project admin --user CSC_user admin;openstack role add --domain default --user CSC_user admin;openstack user list" - SSHLibrary.Execute Command docker exec -t keystone bash -c "source openrc;openstack user create --password cscusernoadmin CSC_user_no_admin;openstack user set --project admin CSC_user_no_admin;openstack role add --project admin --user CSC_user_no_admin user;openstack role add --domain default --user CSC_user_no_admin user" - [Return] ${output} + SSHLibrary.Execute Command + ... docker exec -t keystone bash -c "source openrc;openstack user create --password cscuser CSC_user;openstack user set --project admin CSC_user;openstack role add --project admin --user CSC_user admin;openstack role add --domain default --user CSC_user admin;openstack user list" + SSHLibrary.Execute Command + ... docker exec -t keystone bash -c "source openrc;openstack user create --password cscusernoadmin CSC_user_no_admin;openstack user set --project admin CSC_user_no_admin;openstack role add --project admin --user CSC_user_no_admin user;openstack role add --domain default --user CSC_user_no_admin user" + RETURN ${output} Destroy Docker Keystone [Documentation] Destroy keystone container and remove mysql database - ${output} SSHLibrary.Execute Command docker stop keystone;docker rm keystone return_stdout=True return_stderr=True return_rc=True - ${output} SSHLibrary.Execute Command sudo rm -rf /var/lib/mysql/ return_stdout=True return_stderr=True return_rc=True - [Return] ${output} + ${output} SSHLibrary.Execute Command + ... docker stop keystone;docker rm keystone + ... return_stdout=True + ... return_stderr=True + ... return_rc=True + ${output} SSHLibrary.Execute Command + ... sudo rm -rf /var/lib/mysql/ + ... return_stdout=True + ... return_stderr=True + ... return_rc=True + RETURN ${output} Set Domain To False - [Arguments] ${domain} ${HEADERS} [Documentation] Disable domain in keystone + [Arguments] ${domain} ${HEADERS} Set Suite Variable ${PATCH_DOMAIN_URI} /v3/domains/${domain} Set Suite Variable ${PATCH_DOMAIN_FILE} ${CURDIR}/../../variables/aaa/patch-domain.json ${body} OperatingSystem.Get File ${PATCH_DOMAIN_FILE} - ${resp} RequestsLibrary.Patch Request session_keystone ${PATCH_DOMAIN_URI} data=${body} headers=${HEADERS} + ${resp} RequestsLibrary.Patch Request + ... session_keystone + ... ${PATCH_DOMAIN_URI} + ... data=${body} + ... headers=${HEADERS} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Delete Keystone Domain - [Arguments] ${domain} ${HEADERS} [Documentation] Delete domain in \ Keystone + [Arguments] ${domain} ${HEADERS} Set Suite Variable ${DELETE_DOMAIN_URI} /v3/domains/${domain} ${resp} RequestsLibrary.Delete Request session_keystone ${DELETE_DOMAIN_URI} headers=${HEADERS} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Set Keystone Certificate into ODL - [Arguments] ${PUT_KEYSTONE_CERT_FILE} ${TOOLS_SYSTEM_NAME} [Documentation] Install Keystone Certificate into ODL + [Arguments] ${PUT_KEYSTONE_CERT_FILE} ${TOOLS_SYSTEM_NAME} SSHLibrary.Get File ${USER_HOME}${/}keystone_cert.pem ${USER_HOME}${/}key_cert.pem - ${keystone_certificate} ${rc} SSHLibrary.Execute Command cat keystone_cert.pem|grep -v CERTIFICATE|tr -d '\n' return_stdout=True return_stderr=False return_rc=True + ${keystone_certificate} ${rc} SSHLibrary.Execute Command + ... cat keystone_cert.pem|grep -v CERTIFICATE|tr -d '\n' + ... return_stdout=True + ... return_stderr=False + ... return_rc=True Create Session session_admin http://${ODL_SYSTEM_IP}:${RESTCONFPORT} auth=${AUTH} headers=${HEADERS} Set Suite Variable ${PUT_CERTIFICATE_URI} /restconf/operations/aaa-cert-rpc:setNodeCertifcate - ${normalized_file}= OperatingSystem.Normalize Path ${PUT_KEYSTONE_CERT_FILE} - ${output} OperatingSystem.Run sed -i 's#\"node-cert\".*#\"node-cert\"\: \"${keystone_certificate}\",#g' ${PUT_KEYSTONE_CERT_FILE} - ${output} OperatingSystem.Run sed -i 's#\"node-alias\".*#\"node-alias\"\: \"${TOOLS_SYSTEM_NAME}\"#g' ${PUT_KEYSTONE_CERT_FILE} + ${normalized_file} OperatingSystem.Normalize Path ${PUT_KEYSTONE_CERT_FILE} + ${output} OperatingSystem.Run + ... sed -i 's#\"node-cert\".*#\"node-cert\"\: \"${keystone_certificate}\",#g' ${PUT_KEYSTONE_CERT_FILE} + ${output} OperatingSystem.Run + ... sed -i 's#\"node-alias\".*#\"node-alias\"\: \"${TOOLS_SYSTEM_NAME}\"#g' ${PUT_KEYSTONE_CERT_FILE} ${body_cert} OperatingSystem.Get File ${PUT_KEYSTONE_CERT_FILE} - ${resp} RequestsLibrary.Post Request session_admin ${PUT_CERTIFICATE_URI} data=${body_cert} headers=${HEADERS} + ${resp} RequestsLibrary.Post Request + ... session_admin + ... ${PUT_CERTIFICATE_URI} + ... data=${body_cert} + ... headers=${HEADERS} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Check Keystone Log File For String - [Arguments] ${string} [Documentation] Check provided log exists in /var/log/nginx-access.log - ${output} SSHLibrary.Execute Command docker exec -t keystone bash -c "grep ${string} /var/log/nginx-access.log" + [Arguments] ${string} + ${output} SSHLibrary.Execute Command + ... docker exec -t keystone bash -c "grep ${string} /var/log/nginx-access.log" Log ${output} BuiltIn.Should Contain ${output} ${string} diff --git a/csit/libraries/AAAKeywords.robot b/csit/libraries/AAAKeywords.robot index daa5d20307..9735f5b2c4 100644 --- a/csit/libraries/AAAKeywords.robot +++ b/csit/libraries/AAAKeywords.robot @@ -1,35 +1,47 @@ *** Settings *** -Library RequestsLibrary -Resource ../variables/Variables.robot +Library RequestsLibrary +Resource ../variables/Variables.robot + *** Variables *** -${WORKSPACE} /tmp -${AUTHN_CFG_FILE} ${WORKSPACE}/${BUNDLEFOLDER}/etc/org.opendaylight.aaa.authn.cfg +${WORKSPACE} /tmp +${AUTHN_CFG_FILE} ${WORKSPACE}/${BUNDLEFOLDER}/etc/org.opendaylight.aaa.authn.cfg + *** Keywords *** AAA Login - [Arguments] ${controller_ip} ${auth_data} [Documentation] Makes a POST REST call to the AUTH_TOKEN_API with the given auth_data and returns the response + [Arguments] ${controller_ip} ${auth_data} Create Session ODL_SESSION http://${controller_ip}:8181 ${headers}= Create Dictionary Content-Type=application/x-www-form-urlencoded - ${resp}= RequestsLibrary.POST Request ODL_SESSION ${AUTH_TOKEN_API} data=${auth_data} headers=${headers} + ${resp}= RequestsLibrary.POST Request + ... ODL_SESSION + ... ${AUTH_TOKEN_API} + ... data=${auth_data} + ... headers=${headers} Delete All Sessions - [Return] ${resp} + RETURN ${resp} Create Auth Data - [Arguments] ${user}=${USER} ${password}=${PWD} ${scope}=${SCOPE} ${client_id}=${EMPTY} ${client_secret}=${EMPTY} [Documentation] returns a string in the direct authentacation format (e.g., grant_type=password&username=admin&password=admin). ... It can also be passed scope, client_id and client_secret arguments for the case of client specific authorization + [Arguments] ${user}=${USER} ${password}=${PWD} ${scope}=${SCOPE} ${client_id}=${EMPTY} ${client_secret}=${EMPTY} ${data}= Set Variable grant_type=password&username=${user}&password=${password}&scope=${scope} - ${data}= Run Keyword If "${client_id}" != "${EMPTY}" Set Variable ${data}&client_id=${client_id} - ... ELSE Set Variable ${data} - ${data}= Run Keyword If "${client_secret}" != "${EMPTY}" Set Variable ${data}&client_secret=${client_secret} - ... ELSE Set Variable ${data} - [Return] ${data} + IF "${client_id}" != "${EMPTY}" + ${data}= Set Variable ${data}&client_id=${client_id} + ELSE + ${data}= Set Variable ${data} + END + IF "${client_secret}" != "${EMPTY}" + ${data}= Set Variable ${data}&client_secret=${client_secret} + ELSE + ${data}= Set Variable ${data} + END + RETURN ${data} Disable Authentication On Controller - [Arguments] ${controller_ip} [Documentation] Will disable token based authentication. Currently, that is done with a config file change + [Arguments] ${controller_ip} SSHLibrary.Open Connection ${controller_ip} Login With Public Key ${ODL_SYSTEM_USER} ${USER_HOME}/.ssh/${SSH_KEY} any ${cmd}= Set Variable sed -i 's/^authEnabled=.*$/authEnabled=false/g' ${AUTHN_CFG_FILE} @@ -37,8 +49,8 @@ Disable Authentication On Controller SSHLibrary.Close Connection Enable Authentication On Controller - [Arguments] ${controller_ip} [Documentation] Will enable token based authentication. Currently, that is done with a config file change + [Arguments] ${controller_ip} SSHLibrary.Open Connection ${controller_ip} Login With Public Key ${ODL_SYSTEM_USER} ${USER_HOME}/.ssh/${SSH_KEY} any ${cmd}= Set Variable sed -i 's/^authEnabled=.*$/authEnabled=true/g' ${AUTHN_CFG_FILE} @@ -46,42 +58,46 @@ Enable Authentication On Controller SSHLibrary.Close Connection Get Auth Token - [Arguments] ${user}=${USER} ${password}=${PWD} ${scope}=${SCOPE} ${client_id}=${EMPTY} ${client_secret}=${EMPTY} [Documentation] Wrapper used to login to controller and retrieve an auth token. Optional argumented available for client based credentials. + [Arguments] ${user}=${USER} ${password}=${PWD} ${scope}=${SCOPE} ${client_id}=${EMPTY} ${client_secret}=${EMPTY} ${auth_data}= Create Auth Data ${USER} ${PWD} ${scope} ${client_id} ${client_secret} ${resp}= AAA Login ${ODL_SYSTEM_IP} ${auth_data} Should Be Equal As Strings ${resp.status_code} 201 - ${auth_token} = Extract Value From Content ${resp.text} 'access_token' - [Return] ${auth_token} + ${auth_token}= Extract Value From Content ${resp.text} 'access_token' + RETURN ${auth_token} Revoke Auth Token - [Arguments] ${token} [Documentation] Requests the given token be revoked via POST to ${REVOKE_TOKEN_API} + [Arguments] ${token} ${headers}= Create Dictionary Content-Type=application/x-www-form-urlencoded - ${resp}= RequestsLibrary.POST Request ODL_SESSION ${REVOKE_TOKEN_API} data=${token} headers=${headers} + ${resp}= RequestsLibrary.POST Request + ... ODL_SESSION + ... ${REVOKE_TOKEN_API} + ... data=${token} + ... headers=${headers} Should Be Equal As Strings ${resp.status_code} 204 Validate Token Format - [Arguments] ${token} [Documentation] Validates the given string is in the proper "token" format + [Arguments] ${token} Should Match Regexp ${token} [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} Get User From IDM DB - [Arguments] ${user_id}=${EMPTY} [Documentation] Will return user information. If no user id is passed, it will retrieve all users in DB + [Arguments] ${user_id}=${EMPTY} Create Session httpbin http://${ODL_SYSTEM_IP}:${RESTPORT} ${headers}= Create Dictionary Content-Type=application/x-www-form-urlencoded ${resp}= RequestsLibrary.GET Request httpbin ${idmurl}/users/${user_id} headers=${headers} Should Be Equal As Strings ${resp.status_code} 200 Log ${resp.text} - [Return] ${resp} + RETURN ${resp} Create User - [Arguments] ${user_data} [Documentation] Will return user information. If no user id is passed, it will retrieve all users in DB + [Arguments] ${user_data} Create Session httpbin http://${ODL_SYSTEM_IP}:${RESTPORT} ${headers}= Create Dictionary Content-Type=application/json ${resp}= RequestsLibrary.POST Request httpbin ${idmurl}/users headers=${headers} data=${user_data} Should Be Equal As Strings ${resp.status_code} 201 Log ${resp.text} - [Return] ${resp} + RETURN ${resp} diff --git a/csit/libraries/BGPSpeaker.robot b/csit/libraries/BGPSpeaker.robot index ef2cfa5f1a..d8e284d56a 100644 --- a/csit/libraries/BGPSpeaker.robot +++ b/csit/libraries/BGPSpeaker.robot @@ -1,68 +1,77 @@ *** Settings *** -Documentation Robot keyword library (Resource) for handling the BGP speaker Python utilities. +Documentation Robot keyword library (Resource) for handling the BGP speaker Python utilities. ... -... Copyright (c) 2015,2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2015,2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... This library assumes that a SSH connection exists (and is switched to) -... to a Linux machine (usualy TOOLS_SYSTEM) where the Python BGP speaker should be run. -... It also assumes that the current working directory on that connection is the -... directory where the speaker tool was deployed as there are no paths to neither -... the play.py nor the log files in the commands. +... This library assumes that a SSH connection exists (and is switched to) +... to a Linux machine (usualy TOOLS_SYSTEM) where the Python BGP speaker should be run. +... It also assumes that the current working directory on that connection is the +... directory where the speaker tool was deployed as there are no paths to neither +... the play.py nor the log files in the commands. ... -... Aside BGP Speaker utility, there is also BGP Manager starting utilities in parallel. -... For purpose of dumping logs and killing, Manager behaves the same as Speaker. +... Aside BGP Speaker utility, there is also BGP Manager starting utilities in parallel. +... For purpose of dumping logs and killing, Manager behaves the same as Speaker. ... -... TODO: RemoteBash.robot contains logic which could be reused here. +... TODO: RemoteBash.robot contains logic which could be reused here. ... -... TODO: Update the following TODOs, as SSHKeywords.robot was introduced. -... TODO: The Utils.robot library has a "Run Command On Remote System" if we didn't -... want to make the assumption that an SSH connection was already open. -... alternative TODO: Explain that it is not worth to perform separate SSH logins. -Library SSHLibrary -Library RequestsLibrary -Resource RemoteBash.robot -Resource ../variables/Variables.robot +... TODO: Update the following TODOs, as SSHKeywords.robot was introduced. +... TODO: The Utils.robot library has a "Run Command On Remote System" if we didn't +... want to make the assumption that an SSH connection was already open. +... alternative TODO: Explain that it is not worth to perform separate SSH logins. + +Library SSHLibrary +Library RequestsLibrary +Resource RemoteBash.robot +Resource ../variables/Variables.robot + *** Variables *** -${BGPSpeaker__OUTPUT_LOG} play.py.out +${BGPSpeaker__OUTPUT_LOG} play.py.out + *** Keywords *** Start_BGP_Speaker - [Arguments] ${arguments} [Documentation] Start the BGP speaker python utility. Redirect its error output to a log file ... so it can be dumped into the logs later, when stopping it. This also avoids polluting the ... output seen by "Read Until Prompt" with false propmpts so it won't stop prematurely ... leading to a spurious test failure, messy log content or other misbehavior. - ${command} = BuiltIn.Set_Variable python3 play.py ${arguments} &> ${BGPSpeaker__OUTPUT_LOG} + [Arguments] ${arguments} + ${command}= BuiltIn.Set_Variable python3 play.py ${arguments} &> ${BGPSpeaker__OUTPUT_LOG} BuiltIn.Log ${command} - ${output} = SSHLibrary.Write ${command} + ${output}= SSHLibrary.Write ${command} Start_BGP_Speaker_And_Verify_Connected - [Arguments] ${arguments} ${session} ${speaker_ip}=${TOOLS_SYSTEM_IP} ${connected}=${True} [Documentation] Start the BGP speaker python utility, and verifies it's connection. ... We can change connected variable to false to verify Speaker did not connect. + [Arguments] ${arguments} ${session} ${speaker_ip}=${TOOLS_SYSTEM_IP} ${connected}=${True} Start_BGP_Speaker ${arguments} - ${message} BuiltIn.Wait_Until_Keyword_Succeeds 5x 2s Verify_BGP_Speaker_Connection ${session} ${speaker_ip} + ${message}= BuiltIn.Wait_Until_Keyword_Succeeds + ... 5x + ... 2s + ... Verify_BGP_Speaker_Connection + ... ${session} + ... ${speaker_ip} ... ${connected} - [Return] ${message} + RETURN ${message} Verify_BGP_Speaker_Connection - [Arguments] ${session} ${ip} ${connected}=${True} [Documentation] Verifies peer's presence in bgp rib. - ${exp_status_code} BuiltIn.Set_Variable_If ${connected} ${200} ${404} - ${url}= BuiltIn.Set_Variable ${REST_API}/bgp-rib:bgp-rib/rib=example-bgp-rib/peer=bgp:%2F%2F${ip}?content=nonconfig - ${response} RequestsLibrary.Get_Request ${session} ${url} + [Arguments] ${session} ${ip} ${connected}=${True} + ${exp_status_code}= BuiltIn.Set_Variable_If ${connected} ${200} ${404} + ${url}= BuiltIn.Set_Variable + ... ${REST_API}/bgp-rib:bgp-rib/rib=example-bgp-rib/peer=bgp:%2F%2F${ip}?content=nonconfig + ${response}= RequestsLibrary.Get_Request ${session} ${url} BuiltIn.Should_Be_Equal_As_Numbers ${exp_status_code} ${response.status_code} - [Return] ${response.content} + RETURN ${response.content} Start_BGP_Manager - [Arguments] ${arguments} [Documentation] Start the BGP manager python utility. Redirect its error output to a log file. + [Arguments] ${arguments} ${command}= BuiltIn.Set_Variable python3 play.py ${arguments} &> ${BGPSpeaker__OUTPUT_LOG} BuiltIn.Log ${command} ${output}= SSHLibrary.Write ${command} @@ -72,7 +81,7 @@ Dump_BGP_Speaker_Logs ... This needs to be called if your suite detects play.py crashing and bypasses ... Kill_BGP_Speaker in that case otherwise the output of play.py (which most ... likely contains clues about why it crashed) will be lost. - ${output_log} = SSHLibrary.Execute_Command cat ${BGPSpeaker__OUTPUT_LOG} + ${output_log}= SSHLibrary.Execute_Command cat ${BGPSpeaker__OUTPUT_LOG} BuiltIn.Log ${output_log} Kill_BGP_Speaker @@ -80,10 +89,10 @@ Kill_BGP_Speaker ... Also dump the logs with the output the program produced. ... This keyword is also suitable for stopping BGP manager. RemoteBash.Write_Bare_Ctrl_C - ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error SSHLibrary.Read_Until_Prompt + ${status} ${message}= BuiltIn.Run_Keyword_And_Ignore_Error SSHLibrary.Read_Until_Prompt Dump_BGP_Speaker_Logs # TODO: When Propagate_Failure is moved to better Resource, use it instead of the following. - BuiltIn.Return_From_Keyword_If '${status}' == 'PASS' + IF '${status}' == 'PASS' RETURN BuiltIn.Log ${message} BuiltIn.Fail The prompt was not seen within timeout period. diff --git a/csit/libraries/BGPcliKeywords.robot b/csit/libraries/BGPcliKeywords.robot index d8e797f037..8739d34261 100644 --- a/csit/libraries/BGPcliKeywords.robot +++ b/csit/libraries/BGPcliKeywords.robot @@ -1,34 +1,36 @@ *** Settings *** -Documentation Robot keyword library (Resource) for handling the BGP speaker CLI tools +Documentation Robot keyword library (Resource) for handling the BGP speaker CLI tools ... -... Copyright (c) 2015,2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2015,2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... -... This library contains keywords to handle command line tools in BGP Application -... for handling shell connections. +... This library contains keywords to handle command line tools in BGP Application +... for handling shell connections. ... -... TODO: RemoteBash.robot contains logic which could be reused here. -Library SSHLibrary timeout=10s -Library RequestsLibrary -Resource ../variables/Variables.robot -Resource RemoteBash.robot -Resource NexusKeywords.robot +... TODO: RemoteBash.robot contains logic which could be reused here. + +Library SSHLibrary timeout=10s +Library RequestsLibrary +Resource ../variables/Variables.robot +Resource RemoteBash.robot +Resource NexusKeywords.robot + *** Keywords *** Start_Console_Tool - [Arguments] ${command} ${tool_opt} [Documentation] Start the tool ${command} ${tool_opt} - ${start_cmd} BuiltIn.Set_Variable ${command} ${tool_opt} + [Arguments] ${command} ${tool_opt} + ${start_cmd}= BuiltIn.Set_Variable ${command} ${tool_opt} BuiltIn.Log ${start_cmd} ${output}= SSHLibrary.Write ${start_cmd} BuiltIn.Log ${output} Start_Java_Tool_And_Verify_Connection [Arguments] ${command} ${until_phrase} - ${start_cmd} NexusKeywords.Compose_Full_Java_Command ${command} + ${start_cmd}= NexusKeywords.Compose_Full_Java_Command ${command} BuiltIn.Log ${start_cmd} SSHLibrary.Set_Client_Configuration timeout=30s SSHLibrary.Write ${start_cmd} @@ -36,8 +38,8 @@ Start_Java_Tool_And_Verify_Connection BuiltIn.Log ${output} Wait_Until_Console_Tool_Finish - [Arguments] ${timeout} [Documentation] Wait ${timeout} for the tool exit. + [Arguments] ${timeout} BuiltIn.Wait Until Keyword Succeeds ${timeout} 1s SSHLibrary.Read Until Prompt Stop_Console_Tool @@ -56,8 +58,11 @@ Stop_Console_Tool_And_Wait_Until_Prompt Read_And_Fail_If_Prompt_Is_Seen [Documentation] Try to read SSH to see prompt, but expect to see no prompt within SSHLibrary's timeout. - ${passed}= BuiltIn.Run_Keyword_And_Return_Status BuiltIn.Run_Keyword_And_Expect_Error No match found for '${ODL_SYSTEM_PROMPT}' in *. Read_Text_Before_Prompt - BuiltIn.Return_From_Keyword_If ${passed} + ${passed}= BuiltIn.Run_Keyword_And_Return_Status + ... BuiltIn.Run_Keyword_And_Expect_Error + ... No match found for '${ODL_SYSTEM_PROMPT}' in *. + ... Read_Text_Before_Prompt + IF ${passed} RETURN BGPSpeaker.Dump_BGP_Speaker_Logs Builtin.Fail The prompt was seen but it was not expected yet @@ -68,29 +73,29 @@ Read_Text_Before_Prompt BuiltIn.Log ${text} Store_File_To_Workspace - [Arguments] ${source_file_name} ${target_file_name} [Documentation] Store the ${source_file_name} to the workspace as ${target_file_name}. + [Arguments] ${source_file_name} ${target_file_name} ${output_log}= SSHLibrary.Execute_Command cat ${source_file_name} BuiltIn.Log ${output_log} Create File ${target_file_name} ${output_log} Check_File_For_Word_Count - [Arguments] ${file_name} ${word} ${expected_count} [Documentation] Count ${word} in ${file_name}. Expect ${expected_count} occurence(s) + [Arguments] ${file_name} ${word} ${expected_count} ${output_log}= SSHLibrary.Execute_Command grep -o '${word}' ${file_name} | wc -l BuiltIn.Log ${output_log} BuiltIn.Should_Be_Equal_As_Strings ${output_log} ${expected_count} Count_Key_Value_Pairs - [Arguments] ${file_name} ${keyword} ${value}='' [Documentation] Check file for ${keyword} or ${keyword} ${value} pair and returns number of occurences + [Arguments] ${file_name} ${keyword} ${value}='' ${output_log}= SSHLibrary.Execute_Command grep '${keyword}' ${file_name} | grep -c ${value} ${count}= Convert To Integer ${output_log} - [Return] ${count} + RETURN ${count} Check_File_For_Occurence - [Arguments] ${file_name} ${keyword} ${value}='' [Documentation] Check file for ${keyword} or ${keyword} ${value} pair and returns number of occurences + [Arguments] ${file_name} ${keyword} ${value}='' ${output_log}= SSHLibrary.Execute_Command grep '${keyword}' ${file_name} | grep -c ${value} ${count}= Convert To Integer ${output_log} - [Return] ${count} + RETURN ${count} diff --git a/csit/libraries/BackupRestoreKeywords.robot b/csit/libraries/BackupRestoreKeywords.robot index b2ac0f91a0..5b9345f387 100644 --- a/csit/libraries/BackupRestoreKeywords.robot +++ b/csit/libraries/BackupRestoreKeywords.robot @@ -1,56 +1,87 @@ *** Settings *** -Library OperatingSystem -Library SSHLibrary -Library Collections -Library RequestsLibrary -Library backuprestore/JsonDiffTool.py -Resource ClusterManagement.robot -Resource ../variables/daexim/DaeximVariables.robot -Resource DaeximKeywords.robot -Resource ../variables/backuprestore/BackupRestoreVariables.robot -Resource ../variables/Variables.robot -Resource Utils.robot +Library OperatingSystem +Library SSHLibrary +Library Collections +Library RequestsLibrary +Library backuprestore/JsonDiffTool.py +Resource ClusterManagement.robot +Resource ../variables/daexim/DaeximVariables.robot +Resource DaeximKeywords.robot +Resource ../variables/backuprestore/BackupRestoreVariables.robot +Resource ../variables/Variables.robot +Resource Utils.robot + *** Keywords *** Set Global Variable If It Does Not Exist - [Arguments] ${name} ${value} [Documentation] Checks whether a given variable has been defined. If it does not, sets the passed value to that global variable - ${status} ${message} = Run Keyword And Ignore Error Variable Should Exist ${name} - Run Keyword If "${status}" == "FAIL" Set Global Variable ${name} ${value} + [Arguments] ${name} ${value} + ${status} ${message}= Run Keyword And Ignore Error Variable Should Exist ${name} + IF "${status}" == "FAIL" Set Global Variable ${name} ${value} Perform Export - [Arguments] ${controller_index} [Documentation] schedule a basic export/backup, waiting for completion [Tags] create backup + [Arguments] ${controller_index} DaeximKeywords.Schedule Export ${controller_index} DaeximKeywords.Verify Export Status ${EXPORT_SCHEDULED_STATUS} ${controller_index} - Builtin.Wait Until Keyword Succeeds 10 sec 5 sec DaeximKeywords.Verify Export Status ${EXPORT_COMPLETE_STATUS} ${controller_index} + Builtin.Wait Until Keyword Succeeds + ... 10 sec + ... 5 sec + ... DaeximKeywords.Verify Export Status + ... ${EXPORT_COMPLETE_STATUS} + ... ${controller_index} DaeximKeywords.Verify Export Files ${controller_index} ConditionalBackupRestoreCheck - [Arguments] ${exclusionsConfigBefore}=${EMPTY} ${exclusionsConfigAfter}=${EMPTY} ${exclusionsOperationalBefore}=${EMPTY} ${exclusionsOperationalAfter}=${EMPTY} ${odlControllerIndex}=${FIRST_CONTROLLER_INDEX} [Documentation] When enabled, performs a datastore export, then a backup, then a restore, then an export. The check is considered to be failed when exports before and after are different (two different json path files can be passed in order to filter certain subtrees from the export files before / after the export) + [Arguments] ${exclusionsConfigBefore}=${EMPTY} ${exclusionsConfigAfter}=${EMPTY} ${exclusionsOperationalBefore}=${EMPTY} ${exclusionsOperationalAfter}=${EMPTY} ${odlControllerIndex}=${FIRST_CONTROLLER_INDEX} Set Global Variable If It Does Not Exist \${BR_TESTING_ENABLED} FALSE - Return From Keyword If '${BR_TESTING_ENABLED}'!='true' - BackupRestoreCheck ${exclusionsConfigBefore} ${exclusionsConfigAfter} ${exclusionsOperationalBefore} ${exclusionsOperationalAfter} ${odlControllerIndex} + IF '${BR_TESTING_ENABLED}'!='true' RETURN + BackupRestoreCheck + ... ${exclusionsConfigBefore} + ... ${exclusionsConfigAfter} + ... ${exclusionsOperationalBefore} + ... ${exclusionsOperationalAfter} + ... ${odlControllerIndex} BackupRestoreCheck - [Arguments] ${exclusionsConfigBefore}=${EMPTY} ${exclusionsConfigAfter}=${EMPTY} ${exclusionsOperationalBefore}=${EMPTY} ${exclusionsOperationalAfter}=${EMPTY} ${odlControllerIndex}=${FIRST_CONTROLLER_INDEX} [Documentation] When enabled, performs a datastore export, then a backup, then a restore, then an export. The check is considered to be failed when exports before and after are different (two different json path files can be passed in order to filter certain subtrees from the export files before / after the export) + [Arguments] ${exclusionsConfigBefore}=${EMPTY} ${exclusionsConfigAfter}=${EMPTY} ${exclusionsOperationalBefore}=${EMPTY} ${exclusionsOperationalAfter}=${EMPTY} ${odlControllerIndex}=${FIRST_CONTROLLER_INDEX} Log Performing backup-restore check ${ARG_CONFIG_BEFORE}= Set Variable ' ' ${ARG_CONFIG_AFTER}= Set Variable ' ' ${ARG_OPER_BEFORE}= Set Variable ' ' ${ARG_OPER_AFTER}= Set Variable ' ' - ${ARG_CONFIG_BEFORE}= Run Keyword If '${exclusionsConfigBefore}'!='${EMPTY}' '${exclusionsConfigBefore}' - ${ARG_CONFIG_AFTER}= Run Keyword If '${exclusionsConfigAfter}'!='${EMPTY}' '${exclusionsConfigAfter}' - ${ARG_OPER_BEFORE}= Run Keyword If '${exclusionsOperationalBefore}'!='${EMPTY}' Normalize Path ${CURDIR}/${exclusionsOperationalBefore} - ${ARG_OPER_AFTER}= Run Keyword If '${exclusionsOperationalAfter}'!='${EMPTY}' Normalize Path ${CURDIR}/${exclusionsOperationalAfter} - ${controller_index} Builtin.Convert To Integer ${odlControllerIndex} + IF '${exclusionsConfigBefore}'!='${EMPTY}' + ${ARG_CONFIG_BEFORE}= '${exclusionsConfigBefore}' + ELSE + ${ARG_CONFIG_BEFORE}= Set Variable ${None} + END + IF '${exclusionsConfigAfter}'!='${EMPTY}' + ${ARG_CONFIG_AFTER}= '${exclusionsConfigAfter}' + ELSE + ${ARG_CONFIG_AFTER}= Set Variable ${None} + END + IF '${exclusionsOperationalBefore}'!='${EMPTY}' + ${ARG_OPER_BEFORE}= Normalize Path ${CURDIR}/${exclusionsOperationalBefore} + ELSE + ${ARG_OPER_BEFORE}= Set Variable ${None} + END + IF '${exclusionsOperationalAfter}'!='${EMPTY}' + ${ARG_OPER_AFTER}= Normalize Path ${CURDIR}/${exclusionsOperationalAfter} + ELSE + ${ARG_OPER_AFTER}= Set Variable ${None} + END + ${controller_index}= Builtin.Convert To Integer ${odlControllerIndex} Perform Export ${controller_index} - ${host} ClusterManagement.Resolve IP Address For Member ${controller_index} - ${directory_exist} Builtin.Run Keyword And Return Status OperatingSystem.Directory Should Exist ${EXP_DIR}/${RELATIVE_BEFORE_BACKUP_DIR} - Builtin.Run Keyword If ${directory_exist} Cleanup Directory ${EXP_DIR}/${RELATIVE_BEFORE_BACKUP_DIR} + ${host}= ClusterManagement.Resolve IP Address For Member ${controller_index} + ${directory_exist}= Builtin.Run Keyword And Return Status + ... OperatingSystem.Directory Should Exist + ... ${EXP_DIR}/${RELATIVE_BEFORE_BACKUP_DIR} + IF ${directory_exist} + Cleanup Directory ${EXP_DIR}/${RELATIVE_BEFORE_BACKUP_DIR} + END Copy Export Directory To Test VM ${host} OperatingSystem.Move Directory ${EXP_DIR}${host} ${EXP_DIR}/${RELATIVE_BEFORE_BACKUP_DIR} # @@ -59,11 +90,29 @@ BackupRestoreCheck Log doing the second export! Perform Export ${controller_index} Copy Export Directory To Test VM ${host} - ${directory_exist} Builtin.Run Keyword And Return Status OperatingSystem.Directory Should Exist ${EXP_DIR}/${RELATIVE_AFTER_RESTORE_DIR} - Builtin.Run Keyword If ${directory_exist} Cleanup Directory ${EXP_DIR}/${RELATIVE_AFTER_RESTORE_DIR} + ${directory_exist}= Builtin.Run Keyword And Return Status + ... OperatingSystem.Directory Should Exist + ... ${EXP_DIR}/${RELATIVE_AFTER_RESTORE_DIR} + IF ${directory_exist} + Cleanup Directory ${EXP_DIR}/${RELATIVE_AFTER_RESTORE_DIR} + END OperatingSystem.Move Directory ${EXP_DIR}${host} ${EXP_DIR}/${RELATIVE_AFTER_RESTORE_DIR} log "Performing comparison" - ${differencesConfigDatastore}= Json Diff Check Keyword ${EXP_DIR}/${RELATIVE_BEFORE_BACKUP_DIR}/${EXP_DATA_FILE} ${EXP_DIR}/${RELATIVE_AFTER_RESTORE_DIR}/${EXP_DATA_FILE} ${ARG_CONFIG_BEFORE} ${ARG_CONFIG_AFTER} - ${differencesOperationalDatastore}= Json Diff Check Keyword ${EXP_DIR}/${RELATIVE_BEFORE_BACKUP_DIR}/${EXP_OPER_FILE} ${EXP_DIR}/${RELATIVE_AFTER_RESTORE_DIR}/${EXP_OPER_FILE} ${ARG_OPER_BEFORE} ${ARG_OPER_AFTER} - Should Be Equal '0' '${differencesConfigDatastore}' Error: Diferences found in the config DS before backup / after restore - Should Be Equal '0' '${differencesOperationalDatastore}' Error: Diferences found in the config DS before backup / after restore + ${differencesConfigDatastore}= Json Diff Check Keyword + ... ${EXP_DIR}/${RELATIVE_BEFORE_BACKUP_DIR}/${EXP_DATA_FILE} + ... ${EXP_DIR}/${RELATIVE_AFTER_RESTORE_DIR}/${EXP_DATA_FILE} + ... ${ARG_CONFIG_BEFORE} + ... ${ARG_CONFIG_AFTER} + ${differencesOperationalDatastore}= Json Diff Check Keyword + ... ${EXP_DIR}/${RELATIVE_BEFORE_BACKUP_DIR}/${EXP_OPER_FILE} + ... ${EXP_DIR}/${RELATIVE_AFTER_RESTORE_DIR}/${EXP_OPER_FILE} + ... ${ARG_OPER_BEFORE} + ... ${ARG_OPER_AFTER} + Should Be Equal + ... '0' + ... '${differencesConfigDatastore}' + ... Error: Diferences found in the config DS before backup / after restore + Should Be Equal + ... '0' + ... '${differencesOperationalDatastore}' + ... Error: Diferences found in the config DS before backup / after restore diff --git a/csit/libraries/BgpOperations.robot b/csit/libraries/BgpOperations.robot index 62d3290b39..9937c33afe 100644 --- a/csit/libraries/BgpOperations.robot +++ b/csit/libraries/BgpOperations.robot @@ -1,35 +1,38 @@ *** Settings *** -Documentation This library contains keywords related to the BGP functionality. -Library SSHLibrary -Library String -Library BgpRpcClient.py ${TOOLS_SYSTEM_IP} -Resource ../variables/Variables.robot -Resource CompareStream.robot -Resource Utils.robot -Resource KillPythonTool.robot -Resource TemplatedRequests.robot +Documentation This library contains keywords related to the BGP functionality. + +Library SSHLibrary +Library String +Library BgpRpcClient.py ${TOOLS_SYSTEM_IP} +Resource ../variables/Variables.robot +Resource CompareStream.robot +Resource Utils.robot +Resource KillPythonTool.robot +Resource TemplatedRequests.robot + *** Variables *** -${BGP_BMP_DIR} ${CURDIR}/../variables/bgpfunctional/bmp_basic/filled_structure -${BGP_BMP_FEAT_DIR} ${CURDIR}/../variables/bgpfunctional/bmp_basic/empty_structure -${BGP_RIB_URI} bgp-rib:bgp-rib/rib=example-bgp-rib -${BGP_TOPOLOGY_URI} ${TOPOLOGY_URL}=example-ipv4-topology -${VAR_BASE_BGP} ${CURDIR}/../variables/bgpfunctional -${RIB_NAME} example-bgp-rib -${OLD_AS_PATH} \n"as-path": {}, -${NEW_AS_PATH} ${EMPTY} -&{APP_PEER} IP=${ODL_SYSTEM_IP} BGP_RIB=${RIB_NAME} -${NEW_IPV4_ROUTES_LINE} ${EMPTY} -${OLD_IPV4_ROUTES_LINE} \n"bgp-inet:ipv4-routes": {}, +${BGP_BMP_DIR} ${CURDIR}/../variables/bgpfunctional/bmp_basic/filled_structure +${BGP_BMP_FEAT_DIR} ${CURDIR}/../variables/bgpfunctional/bmp_basic/empty_structure +${BGP_RIB_URI} bgp-rib:bgp-rib/rib=example-bgp-rib +${BGP_TOPOLOGY_URI} ${TOPOLOGY_URL}=example-ipv4-topology +${VAR_BASE_BGP} ${CURDIR}/../variables/bgpfunctional +${RIB_NAME} example-bgp-rib +${OLD_AS_PATH} \n"as-path": {}, +${NEW_AS_PATH} ${EMPTY} +&{APP_PEER} IP=${ODL_SYSTEM_IP} BGP_RIB=${RIB_NAME} +${NEW_IPV4_ROUTES_LINE} ${EMPTY} +${OLD_IPV4_ROUTES_LINE} \n"bgp-inet:ipv4-routes": {}, ${BGP_CONFIG_SERVER_CMD} bgp-connect -h ${ODL_SYSTEM_IP} -p 7644 add -${VPNV4_ADDR_FAMILY} vpnv4 -${DISPLAY_VPN4_ALL} show-bgp --cmd "ip bgp ${VPNV4_ADDR_FAMILY} all" +${VPNV4_ADDR_FAMILY} vpnv4 +${DISPLAY_VPN4_ALL} show-bgp --cmd "ip bgp ${VPNV4_ADDR_FAMILY} all" + *** Keywords *** Start Quagga Processes On ODL - [Arguments] ${odl_ip} [Documentation] To start the zrpcd processes on ODL VM - ${conn_id}= Open_Connection_To_ODL_System ip_address=${odl_ip} + [Arguments] ${odl_ip} + ${conn_id} = Open_Connection_To_ODL_System ip_address=${odl_ip} Switch Connection ${conn_id} Write Commands Until Expected Prompt cd /opt/quagga/etc/ ${DEFAULT_LINUX_PROMPT_STRICT} Write Commands Until Expected Prompt sudo cp zebra.conf.sample zebra.conf ${DEFAULT_LINUX_PROMPT_STRICT} @@ -39,16 +42,16 @@ Start Quagga Processes On ODL Close Connection Restart BGP Processes On ODL - [Arguments] ${odl_ip} [Documentation] To restart the bgpd , qthriftd processes on ODL VM + [Arguments] ${odl_ip} ${conn_id} = Open_Connection_To_ODL_System ip_address=${odl_ip} Switch Connection ${conn_id} Write Commands Until Expected Prompt sudo pkill -f bgpd ${DEFAULT_LINUX_PROMPT_STRICT} Start Quagga Processes On ODL ${odl_ip} Start Quagga Processes On DCGW - [Arguments] ${dcgw_ip} [Documentation] To start the zrpcd, bgpd,and zebra processes on DCGW + [Arguments] ${dcgw_ip} ${dcgw_conn_id} = Open_Connection_To_Tools_System ip_address=${dcgw_ip} Switch Connection ${dcgw_conn_id} Write Commands Until Expected Prompt cd /opt/quagga/etc/ ${DEFAULT_LINUX_PROMPT_STRICT} @@ -67,22 +70,22 @@ Start Quagga Processes On DCGW Write Commands Until Expected Prompt netstat -nap | grep 7644 ${DEFAULT_LINUX_PROMPT_STRICT} Restart BGP Processes On DCGW - [Arguments] ${dcgw_ip} [Documentation] To Restart the zrpcd, bgpd and zebra processes on DCGW + [Arguments] ${dcgw_ip} ${dcgw_conn_id} = Open_Connection_To_Tools_System ip_address=${dcgw_ip} Switch Connection ${dcgw_conn_id} Write Commands Until Expected Prompt sudo pkill -f bgpd ${DEFAULT_LINUX_PROMPT_STRICT} Start Quagga Processes On DCGW ${dcgw_ip} Stop BGP Processes On Node - [Arguments] ${node_ip} [Documentation] To stop the bgpd , qthriftd processes on specific node given by user. + [Arguments] ${node_ip} Utils.Run Command On Remote System ${node_ip} sudo pkill -f bgpd Utils.Run Command On Remote System ${node_ip} sudo pkill -f zrpcd Show Quagga Configuration On ODL - [Arguments] ${odl_ip} ${rd} [Documentation] Show quagga config from ODL + [Arguments] ${odl_ip} ${rd} Create Quagga Telnet Session ${odl_ip} bgpd sdncbgpc Execute Command On Quagga Telnet Session show running-config Execute Command On Quagga Telnet Session show bgp neighbors @@ -91,9 +94,9 @@ Show Quagga Configuration On ODL Close Connection Create Quagga Telnet Session - [Arguments] ${ip} ${user} ${password} [Documentation] Create telnet session for Quagga - ${conn_id}= Open_Connection_To_Tools_System ip_address=${ip} + [Arguments] ${ip} ${user} ${password} + ${conn_id} = Open_Connection_To_Tools_System ip_address=${ip} Switch Connection ${conn_id} ${output} = Write telnet localhost ${user} ${output} = Read Until Password: @@ -103,17 +106,17 @@ Create Quagga Telnet Session ${output} = Read Execute Command On Quagga Telnet Session - [Arguments] ${command} [Documentation] Execute command on Quagga telnet session(session should exist) and returns the output. + [Arguments] ${command} SSHLibrary.Write ${command} ${output} = SSHLibrary.Read Log ${output} - [Return] ${output} + RETURN ${output} Configure BGP And Add Neighbor On DCGW + [Documentation] Configure BGP and add neighbor on the dcgw [Arguments] ${dcgw_ip} ${as_id} ${router_id} ${neighbor_ip} ${vrf_name} ${rd} ... ${loopback_ip} - [Documentation] Configure BGP and add neighbor on the dcgw Create Quagga Telnet Session ${dcgw_ip} bgpd sdncbgpc Execute Command On Quagga Telnet Session configure terminal Execute Command On Quagga Telnet Session router bgp ${as_id} @@ -134,8 +137,8 @@ Configure BGP And Add Neighbor On DCGW Execute Command On Quagga Telnet Session exit Add Loopback Interface On DCGW - [Arguments] ${dcgw_ip} ${loopback_name} ${loopback_ip} ${user}=zebra ${password}=zebra [Documentation] Add loopback interface on DCGW + [Arguments] ${dcgw_ip} ${loopback_name} ${loopback_ip} ${user}=zebra ${password}=zebra Create Quagga Telnet Session ${dcgw_ip} ${user} ${password} Execute Command On Quagga Telnet Session enable Execute Command On Quagga Telnet Session ${password} @@ -148,26 +151,26 @@ Add Loopback Interface On DCGW Execute Command On Quagga Telnet Session exit Execute Show Command On Quagga - [Arguments] ${dcgw_ip} ${cmd} ${user}=bgpd ${password}=sdncbgpc [Documentation] Execute command on quagga and returns the ouput. + [Arguments] ${dcgw_ip} ${cmd} ${user}=bgpd ${password}=sdncbgpc Create Quagga Telnet Session ${dcgw_ip} ${user} ${password} ${output} = Execute Command On Quagga Telnet Session ${cmd} Log ${output} Execute Command On quagga Telnet Session exit - [Return] ${output} + RETURN ${output} Verify BGP Neighbor Status On Quagga - [Arguments] ${dcgw_ip} ${neighbor_ip} [Documentation] Verify bgp neighbor status on quagga + [Arguments] ${dcgw_ip} ${neighbor_ip} ${output} = Execute Show Command On quagga ${dcgw_ip} show bgp neighbors ${neighbor_ip} Log ${output} Should Contain ${output} BGP state = Established Setup BGP Peering On ODL - [Arguments] ${odl_ip} ${as_id} ${nbr_ip} [Documentation] Setup BGP peering between ODL and given neighbor IP. ... Configuring and starting BGP on ODL node with given AS number ... Adding and verifying BGP neighbor + [Arguments] ${odl_ip} ${as_id} ${nbr_ip} KarafKeywords.Issue Command On Karaf Console ${BGP_CONFIG_SERVER_CMD} BgpOperations.Create BGP Configuration On ODL localas=${as_id} routerid=${odl_ip} BgpOperations.AddNeighbor To BGP Configuration On ODL remoteas=${as_id} neighborAddr=${nbr_ip} @@ -175,17 +178,23 @@ Setup BGP Peering On ODL BuiltIn.Should Contain ${output} ${nbr_ip} Setup BGP Peering On DCGW - [Arguments] ${dcgw_ip} ${as_id} ${nbr_ip} ${vrf_name} ${rd} ${loopback_ip} [Documentation] Setup BGP peering between DCGW and given neighbor IP. ... Configuring,adding neighbor on DCGW node and verifying BGP neighbor. - BgpOperations.Configure BGP And Add Neighbor On DCGW ${dcgw_ip} ${as_id} ${dcgw_ip} ${nbr_ip} ${vrf_name} ${rd} + [Arguments] ${dcgw_ip} ${as_id} ${nbr_ip} ${vrf_name} ${rd} ${loopback_ip} + BgpOperations.Configure BGP And Add Neighbor On DCGW + ... ${dcgw_ip} + ... ${as_id} + ... ${dcgw_ip} + ... ${nbr_ip} + ... ${vrf_name} + ... ${rd} ... ${loopback_ip} ${output} = BgpOperations.Execute Show Command On Quagga ${dcgw_ip} ${RUN_CONFIG} BuiltIn.Should Contain ${output} ${nbr_ip} Verify Routes On Quagga - [Arguments] ${dcgw_ip} ${rd} ${ip_list} [Documentation] Verify routes on quagga + [Arguments] ${dcgw_ip} ${rd} ${ip_list} ${output} = Execute Show Command On quagga ${dcgw_ip} show ip bgp vrf ${rd} Log ${output} FOR ${ip} IN @{ip_list} @@ -193,19 +202,19 @@ Verify Routes On Quagga END Delete BGP Config On Quagga - [Arguments] ${dcgw_ip} ${bgp_id} ${user}=bgpd ${password}=sdncbgpc [Documentation] Delete BGP Config on Quagga + [Arguments] ${dcgw_ip} ${bgp_id} ${user}=bgpd ${password}=sdncbgpc Create Quagga Telnet Session ${dcgw_ip} ${user} ${password} Execute Command On Quagga Telnet Session configure terminal Execute Command On Quagga Telnet Session no router bgp ${bgp_id} Execute Command On Quagga Telnet Session end ${output} = Execute Command On Quagga Telnet Session show running-config Execute Command On Quagga Telnet Session exit - [Return] ${output} + RETURN ${output} Create L3VPN on DCGW - [Arguments] ${dcgw_ip} ${as_id} ${vpn_name} ${rd} [Documentation] Creating L3VPN on DCGW + [Arguments] ${dcgw_ip} ${as_id} ${vpn_name} ${rd} BgpOperations.Create Quagga Telnet Session ${dcgw_ip} bgpd sdncbgpc BgpOperations.Execute Command On Quagga Telnet Session configure terminal BgpOperations.Execute Command On Quagga Telnet Session router bgp ${as_id} @@ -216,8 +225,8 @@ Create L3VPN on DCGW BgpOperations.Execute Command On Quagga Telnet Session end Delete L3VPN on DCGW - [Arguments] ${dcgw_ip} ${as_id} @{vpns} [Documentation] Deleting L3VPN on DCGW + [Arguments] ${dcgw_ip} ${as_id} @{vpns} BgpOperations.Create Quagga Telnet Session ${dcgw_ip} bgpd sdncbgpc BgpOperations.Execute Command On Quagga Telnet Session configure terminal BgpOperations.Execute Command On Quagga Telnet Session router bgp ${as_id} @@ -227,15 +236,15 @@ Delete L3VPN on DCGW BgpOperations.Execute Command On Quagga Telnet Session end Verify L3VPN On DCGW - [Arguments] ${dcgw_ip} ${vpn_name} ${rd} [Documentation] Verify L3VPN vrf name and rd value on DCGW + [Arguments] ${dcgw_ip} ${vpn_name} ${rd} ${output} = BgpOperations.Execute Show Command On Quagga ${dcgw_ip} show running-config BuiltIn.Should Contain ${output} vrf ${vpn_name} BuiltIn.Should Contain ${output} rd ${rd} Add Routes On DCGW - [Arguments] ${dcgw_ip} ${rd} ${network_ip} ${label} [Documentation] Add routes on DCGW + [Arguments] ${dcgw_ip} ${rd} ${network_ip} ${label} BgpOperations.Create Quagga Telnet Session ${dcgw_ip} bgpd sdncbgpc BgpOperations.Execute Command On Quagga Telnet Session configure terminal BgpOperations.Execute Command On Quagga Telnet Session router bgp ${AS_ID} @@ -244,47 +253,64 @@ Add Routes On DCGW BgpOperations.Execute Command On Quagga Telnet Session end Create BGP Configuration On ODL - [Arguments] &{Kwargs} [Documentation] Associate the created L3VPN to a network-id received as dictionary argument - TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE_BGP}/create_bgp mapping=${Kwargs} session=session + [Arguments] &{Kwargs} + TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE_BGP}/create_bgp + ... mapping=${Kwargs} + ... session=session AddNeighbor To BGP Configuration On ODL - [Arguments] &{Kwargs} [Documentation] Associate the created L3VPN to a network-id received as dictionary argument - CompareStream.Run_Keyword_If_Less_Than_Magnesium TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE_BGP}/addNeighbor_bgp mapping=${Kwargs} session=session - CompareStream.Run_Keyword_If_At_Least_Magnesium TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE_BGP}/addNeighborsContainer_bgp mapping=${Kwargs} session=session + [Arguments] &{Kwargs} + CompareStream.Run_Keyword_If_Less_Than_Magnesium + ... TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE_BGP}/addNeighbor_bgp + ... mapping=${Kwargs} + ... session=session + CompareStream.Run_Keyword_If_At_Least_Magnesium + ... TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE_BGP}/addNeighborsContainer_bgp + ... mapping=${Kwargs} + ... session=session Get BGP Configuration On ODL - [Arguments] ${odl_session} [Documentation] Get bgp configuration + [Arguments] ${odl_session} ${resp} = RequestsLibrary.Get Request ${odl_session} ${CONFIG_API}/ebgp:bgp/ Log ${resp.text} - [Return] ${resp.text} + RETURN ${resp.text} Delete BGP Configuration On ODL - [Arguments] ${odl_session} [Documentation] Delete BGP + [Arguments] ${odl_session} ${resp} = RequestsLibrary.Delete Request ${odl_session} ${CONFIG_API}/ebgp:bgp/ Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 - [Return] ${resp.text} + RETURN ${resp.text} Create External Tunnel Endpoint Configuration - [Arguments] &{Kwargs} [Documentation] Create Tunnel End point - TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE_BGP}/create_etep mapping=${Kwargs} session=session + [Arguments] &{Kwargs} + TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE_BGP}/create_etep + ... mapping=${Kwargs} + ... session=session Delete External Tunnel Endpoint Configuration - [Arguments] &{Kwargs} [Documentation] Delete Tunnel End point - TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE_BGP}/delete_etep mapping=${Kwargs} session=session + [Arguments] &{Kwargs} + TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE_BGP}/delete_etep + ... mapping=${Kwargs} + ... session=session Get External Tunnel Endpoint Configuration - [Arguments] ${ip} [Documentation] Get bgp configuration + [Arguments] ${ip} ${resp} = RequestsLibrary.Get Request session ${CONFIG_API}/itm:dc-gateway-ip-list/dc-gateway-ip/${ip}/ Log ${resp.text} - [Return] ${resp.text} + RETURN ${resp.text} Teardown_Everything [Documentation] Create and Log the diff between expected and actual responses, make sure Python tool was killed. @@ -294,51 +320,65 @@ Teardown_Everything SSHLibrary.Close_All_Connections Check_Example_Bgp_Rib_Content - [Arguments] ${session} ${substr} ${error_message}=${JSONKEYSTR} not found, but expected. [Documentation] Check the example-bgp-rib content for string - ${response}= RequestsLibrary.Get Request ${session} ${REST_API}/${BGP_RIB_URI}?content=nonconfig + [Arguments] ${session} ${substr} ${error_message}=${JSONKEYSTR} not found, but expected. + ${response} = RequestsLibrary.Get Request ${session} ${REST_API}/${BGP_RIB_URI}?content=nonconfig BuiltIn.Log ${response.status_code} BuiltIn.Log ${response.text} BuiltIn.Should_Contain ${response.text} ${substr} ${error_message} values=False Check_Example_Bgp_Rib_Does_Not_Contain - [Arguments] ${session} ${substr} ${error_message}=${JSONKEYSTR} found, but not expected. [Documentation] Check the example-bgp-rib does not contain the string - ${response}= RequestsLibrary.Get Request ${session} ${REST_API}/${BGP_RIB_URI}?content=nonconfig + [Arguments] ${session} ${substr} ${error_message}=${JSONKEYSTR} found, but not expected. + ${response} = RequestsLibrary.Get Request ${session} ${REST_API}/${BGP_RIB_URI}?content=nonconfig BuiltIn.Log ${response.status_code} BuiltIn.Log ${response.text} BuiltIn.Should_Not_Contain ${response.text} ${substr} ${error_message} values=False Check_Example_IPv4_Topology_Content - [Arguments] ${session} ${string_to_check}=${EMPTY} [Documentation] Check the example-ipv4-topology content for string - ${response}= RequestsLibrary.Get Request ${session} ${REST_API}/${BGP_TOPOLOGY_URI}?content=nonconfig + [Arguments] ${session} ${string_to_check}=${EMPTY} + ${response} = RequestsLibrary.Get Request ${session} ${REST_API}/${BGP_TOPOLOGY_URI}?content=nonconfig BuiltIn.Log ${response.status_code} BuiltIn.Log ${response.text} BuiltIn.Should_Contain ${response.text} ${string_to_check} Check_Example_IPv4_Topology_Does_Not_Contain - [Arguments] ${session} ${string_to_check} [Documentation] Check the example-ipv4-topology does not contain the string - ${response}= RequestsLibrary.Get Request ${session} ${REST_API}/${BGP_TOPOLOGY_URI}?content=nonconfig + [Arguments] ${session} ${string_to_check} + ${response} = RequestsLibrary.Get Request ${session} ${REST_API}/${BGP_TOPOLOGY_URI}?content=nonconfig BuiltIn.Log ${response.status_code} BuiltIn.Log ${response.text} BuiltIn.Should_Not_Contain ${response.text} ${string_to_check} Bmp_Monitor_Precondition - [Arguments] ${session} [Documentation] Verify example-bmp-monitor presence in bmp-monitors - &{mapping} BuiltIn.Create_Dictionary TOOL_IP=${TOOLS_SYSTEM_IP} - BuiltIn.Wait_Until_Keyword_Succeeds 6x 10s TemplatedRequests.Get_As_Json_Templated folder=${BGP_BMP_FEAT_DIR} mapping=${mapping} verify=True + [Arguments] ${session} + &{mapping} = BuiltIn.Create_Dictionary TOOL_IP=${TOOLS_SYSTEM_IP} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 6x + ... 10s + ... TemplatedRequests.Get_As_Json_Templated + ... folder=${BGP_BMP_FEAT_DIR} + ... mapping=${mapping} + ... verify=True ... session=${session} Bmp_Monitor_Postcondition - [Arguments] ${session} [Documentation] Verifies if example-bmp-monitor data contains one peer. - ${routes_line} = CompareStream.Set_Variable_If_At_Least_Neon ${NEW_IPV4_ROUTES_LINE} ${OLD_IPV4_ROUTES_LINE} - &{mapping} BuiltIn.Create_Dictionary TOOL_IP=${TOOLS_SYSTEM_IP} ROUTES_LINE=${routes_line} - ${output} BuiltIn.Wait_Until_Keyword_Succeeds 10x 5s TemplatedRequests.Get_As_Json_Templated folder=${BGP_BMP_DIR} mapping=${mapping} - ... session=${session} verify=True + [Arguments] ${session} + ${routes_line} = CompareStream.Set_Variable_If_At_Least_Neon + ... ${NEW_IPV4_ROUTES_LINE} + ... ${OLD_IPV4_ROUTES_LINE} + &{mapping} = BuiltIn.Create_Dictionary TOOL_IP=${TOOLS_SYSTEM_IP} ROUTES_LINE=${routes_line} + ${output} = BuiltIn.Wait_Until_Keyword_Succeeds + ... 10x + ... 5s + ... TemplatedRequests.Get_As_Json_Templated + ... folder=${BGP_BMP_DIR} + ... mapping=${mapping} + ... session=${session} + ... verify=True BuiltIn.Log ${output} Odl_To_Play_Template @@ -347,34 +387,64 @@ Odl_To_Play_Template ${announce_hex} = String.Remove_String ${announce_hex} \n ${withdraw_hex} = OperatingSystem.Get_File ${dir}/${totest}/withdraw_${totest}.hex ${withdraw_hex} = String.Remove_String ${withdraw_hex} \n - BuiltIn.Run_Keyword_If '${remove}' == 'True' BgpRpcClient.play_clean + IF '${remove}' == 'True' BgpRpcClient.play_clean TemplatedRequests.Post_As_Xml_Templated ${dir}/${totest}/app mapping=${APP_PEER} session=${CONFIG_SESSION} - ${update} BuiltIn.Wait_Until_Keyword_Succeeds 3x 2s Get_Update_Message + ${update} = BuiltIn.Wait_Until_Keyword_Succeeds 3x 2s Get_Update_Message Verify_Two_Hex_Messages_Are_Equal ${update} ${announce_hex} BgpRpcClient.play_clean Remove_Configured_Routes ${totest} ${dir} - ${update} BuiltIn.Wait_Until_Keyword_Succeeds 3x 2s Get_Update_Message + ${update} = BuiltIn.Wait_Until_Keyword_Succeeds 3x 2s Get_Update_Message Verify_Two_Hex_Messages_Are_Equal ${update} ${withdraw_hex} [Teardown] Remove_Configured_Routes ${totest} ${dir} Play_To_Odl_Template [Arguments] ${totest} ${dir} ${ipv}=ipv4 ${as_path} = CompareStream.Set_Variable_If_At_Least_Neon ${NEW_AS_PATH} ${OLD_AS_PATH} - &{adj_rib_in} BuiltIn.Create_Dictionary PATH=peer\=bgp:%2F%2F${TOOLS_SYSTEM_IP}/adj-rib-in BGP_RIB=${RIB_NAME} AS_PATH=${as_path} - &{effective_rib_in} BuiltIn.Create_Dictionary PATH=peer\=bgp:%2F%2F${TOOLS_SYSTEM_IP}/effective-rib-in BGP_RIB=${RIB_NAME} AS_PATH=${as_path} - &{loc_rib} BuiltIn.Create_Dictionary PATH=loc-rib BGP_RIB=${RIB_NAME} AS_PATH=${as_path} + &{adj_rib_in} = BuiltIn.Create_Dictionary + ... PATH=peer\=bgp:%2F%2F${TOOLS_SYSTEM_IP}/adj-rib-in + ... BGP_RIB=${RIB_NAME} + ... AS_PATH=${as_path} + &{effective_rib_in} = BuiltIn.Create_Dictionary + ... PATH=peer\=bgp:%2F%2F${TOOLS_SYSTEM_IP}/effective-rib-in + ... BGP_RIB=${RIB_NAME} + ... AS_PATH=${as_path} + &{loc_rib} = BuiltIn.Create_Dictionary PATH=loc-rib BGP_RIB=${RIB_NAME} AS_PATH=${as_path} ${announce_hex} = OperatingSystem.Get_File ${dir}/${totest}/announce_${totest}.hex ${withdraw_hex} = OperatingSystem.Get_File ${dir}/${totest}/withdraw_${totest}.hex BgpRpcClient.play_clean BgpRpcClient.play_send ${announce_hex} - BuiltIn.Wait_Until_Keyword_Succeeds 3x 2s TemplatedRequests.Get_As_Json_Templated ${dir}/${totest}/rib mapping=${adj_rib_in} session=${CONFIG_SESSION} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 3x + ... 2s + ... TemplatedRequests.Get_As_Json_Templated + ... ${dir}/${totest}/rib + ... mapping=${adj_rib_in} + ... session=${CONFIG_SESSION} ... verify=True - BuiltIn.Wait_Until_Keyword_Succeeds 3x 2s TemplatedRequests.Get_As_Json_Templated ${dir}/${totest}/rib mapping=${effective_rib_in} session=${CONFIG_SESSION} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 3x + ... 2s + ... TemplatedRequests.Get_As_Json_Templated + ... ${dir}/${totest}/rib + ... mapping=${effective_rib_in} + ... session=${CONFIG_SESSION} ... verify=True - BuiltIn.Wait_Until_Keyword_Succeeds 3x 2s TemplatedRequests.Get_As_Json_Templated ${dir}/${totest}/rib mapping=${loc_rib} session=${CONFIG_SESSION} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 3x + ... 2s + ... TemplatedRequests.Get_As_Json_Templated + ... ${dir}/${totest}/rib + ... mapping=${loc_rib} + ... session=${CONFIG_SESSION} ... verify=True BgpRpcClient.play_send ${withdraw_hex} - BuiltIn.Wait_Until_Keyword_Succeeds 3x 2s TemplatedRequests.Get_As_Json_Templated ${dir}/empty_routes/${ipv} mapping=${loc_rib} session=${CONFIG_SESSION} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 3x + ... 2s + ... TemplatedRequests.Get_As_Json_Templated + ... ${dir}/empty_routes/${ipv} + ... mapping=${loc_rib} + ... session=${CONFIG_SESSION} ... verify=True [Teardown] BgpRpcClient.play_send ${withdraw_hex} @@ -384,25 +454,35 @@ Play_To_Odl_Non_Removal_Template BgpRpcClient.play_clean BgpRpcClient.play_send ${announce_hex} ${as_path} = CompareStream.Set_Variable_If_At_Least_Neon ${NEW_AS_PATH} ${OLD_AS_PATH} - &{loc_rib} BuiltIn.Create_Dictionary PATH=loc-rib BGP_RIB=${RIB_NAME} AS_PATH=${as_path} - BuiltIn.Wait_Until_Keyword_Succeeds 3x 2s TemplatedRequests.Get_As_Json_Templated ${dir}/${totest}/rib mapping=${loc_rib} session=${CONFIG_SESSION} + &{loc_rib} = BuiltIn.Create_Dictionary PATH=loc-rib BGP_RIB=${RIB_NAME} AS_PATH=${as_path} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 3x + ... 2s + ... TemplatedRequests.Get_As_Json_Templated + ... ${dir}/${totest}/rib + ... mapping=${loc_rib} + ... session=${CONFIG_SESSION} ... verify=True Get_Update_Message [Documentation] Returns hex update message. ${update} = BgpRpcClient.play_get BuiltIn.Should_Not_Be_Equal ${update} ${Empty} - [Return] ${update} + RETURN ${update} Remove_Configured_Routes - [Arguments] ${totest} ${dir} [Documentation] Removes the route if present. - BuiltIn.Run_Keyword_And_Ignore_Error TemplatedRequests.Delete_Templated ${dir}/${totest}/app mapping=${APP_PEER} session=${CONFIG_SESSION} + [Arguments] ${totest} ${dir} + BuiltIn.Run_Keyword_And_Ignore_Error + ... TemplatedRequests.Delete_Templated + ... ${dir}/${totest}/app + ... mapping=${APP_PEER} + ... session=${CONFIG_SESSION} Verify_Two_Hex_Messages_Are_Equal - [Arguments] ${hex_1} ${hex_2} [Documentation] Verifies two hex messages are equal even in case, their arguments are misplaced. ... Compares length of the hex messages and sums hex messages arguments as integers and compares results. + [Arguments] ${hex_1} ${hex_2} ${len_1} = BuiltIn.Get_Length ${hex_1} ${len_2} = BuiltIn.Get_Length ${hex_2} BuiltIn.Should_Be_Equal ${len_1} ${len_2} @@ -411,10 +491,13 @@ Verify_Two_Hex_Messages_Are_Equal BuiltIn.Should_Be_Equal ${sum_1} ${sum_2} Check BGP VPNv4 Nbr On ODL - [Arguments] ${dcgw_count} ${flag}=True ${start}=${START_VALUE} [Documentation] Check all BGP VPNv4 neighbor on ODL + [Arguments] ${dcgw_count} ${flag}=True ${start}=${START_VALUE} ${output} = KarafKeywords.Issue Command On Karaf Console ${DISPLAY_VPN4_ALL} FOR ${index} IN RANGE ${start} ${dcgw_count} - BuiltIn.Run Keyword If ${flag}==True BuiltIn.Should Contain ${output} ${DCGW_IP_LIST[${index}]} - ... ELSE BuiltIn.Should Not Contain ${output} ${DCGW_IP_LIST[${index}]} + IF ${flag}==True + BuiltIn.Should Contain ${output} ${DCGW_IP_LIST[${index}]} + ELSE + BuiltIn.Should Not Contain ${output} ${DCGW_IP_LIST[${index}]} + END END diff --git a/csit/libraries/BierTeResource.robot b/csit/libraries/BierTeResource.robot index 79b0683390..b0fee30643 100644 --- a/csit/libraries/BierTeResource.robot +++ b/csit/libraries/BierTeResource.robot @@ -1,22 +1,25 @@ *** Settings *** -Documentation Robot keyword library (Resource) for BIER information configuration and verification Python utilities. +Documentation Robot keyword library (Resource) for BIER information configuration and verification Python utilities. ... -... Copyright (c) 2016-2017 Zte, Inc. and others. All rights reserved. +... Copyright (c) 2016-2017 Zte, Inc. and others. All rights reserved. ... -... This resource contains some keywords which complete four main functions: -... Send corresponding request to datastore, -... Construct BIER information, -... Verity Configuration success or not and its result, -... Delete BIER configuration and close all session. -Resource TemplatedRequests.robot -Library SSHLibrary +... This resource contains some keywords which complete four main functions: +... Send corresponding request to datastore, +... Construct BIER information, +... Verity Configuration success or not and its result, +... Delete BIER configuration and close all session. + +Resource TemplatedRequests.robot +Library SSHLibrary + *** Variables *** -${BIER_TE_VAR_FOLDER} ${CURDIR}/../variables/bier -@{NETCONF_PORT_LIST} 17830 17831 17832 17833 17834 -${TESTTOOL_PATH} /root -${TESTTOOL_VERSION} netconf-testtool-1.3.0-SNAPSHOT-executable.jar -${TESTTOOL_SCHEME} ./yang_ietf_bier +${BIER_TE_VAR_FOLDER} ${CURDIR}/../variables/bier +@{NETCONF_PORT_LIST} 17830 17831 17832 17833 17834 +${TESTTOOL_PATH} /root +${TESTTOOL_VERSION} netconf-testtool-1.3.0-SNAPSHOT-executable.jar +${TESTTOOL_SCHEME} ./yang_ietf_bier + *** Keywords *** Init All @@ -26,24 +29,42 @@ Init All Init Bier Topology [Documentation] Init the configuration datastore defined by the YANG module bier-network-topology. - ${resp} TemplatedRequests.Put_As_Json_Templated ${BIER_TE_VAR_FOLDER}/bier_init_all/bier_init_biertopology {} session + ${resp} TemplatedRequests.Put_As_Json_Templated + ... ${BIER_TE_VAR_FOLDER}/bier_init_all/bier_init_biertopology + ... {} + ... session Init Channel [Documentation] Init the configuration datastore defined by the YANG module bier-network-channel. - ${resp} TemplatedRequests.Put_As_Json_Templated ${BIER_TE_VAR_FOLDER}/bier_init_all/bier_init_channel {} session + ${resp} TemplatedRequests.Put_As_Json_Templated + ... ${BIER_TE_VAR_FOLDER}/bier_init_all/bier_init_channel + ... {} + ... session Node Online [Documentation] Verify the Keyword Init Bier Topology has been successfully executed by query and verify the nodes in the datastore. - ${resp} TemplatedRequests.Post_As_Json_Templated ${BIER_TE_VAR_FOLDER}/bier_node_configuration/query_node {} session True + ${resp} TemplatedRequests.Post_As_Json_Templated + ... ${BIER_TE_VAR_FOLDER}/bier_node_configuration/query_node + ... {} + ... session + ... True Second Layer Loop - [Arguments] ${node-id} ${tp-id-list} ${bp-list} ${length} [Documentation] The keyword is used for the second layer of loop TC5_Configure Te Node. + [Arguments] ${node-id} ${tp-id-list} ${bp-list} ${length} FOR ${j} IN RANGE ${length} ${tp-id} Get From List ${tp-id-list} ${j} ${bp} Get From List ${bp-list} ${j} - ${mapping} Create Dictionary TOPOLOGYID=${TOPOLOGY_ID} NODEID=${node-id} DOMAINID=${DOMAIN_ID_LIST[0]} SUBDOMAINID=${SUBDOMAIN_ID_LIST[0]} - ... TPID=${tp-id} BP=${bp} - ${resp} TemplatedRequests.Post_As_Json_Templated ${BIER_TE_VAR_FOLDER}/bier_node_configuration/configure_te_node ${mapping} session + ${mapping} Create Dictionary + ... TOPOLOGYID=${TOPOLOGY_ID} + ... NODEID=${node-id} + ... DOMAINID=${DOMAIN_ID_LIST[0]} + ... SUBDOMAINID=${SUBDOMAIN_ID_LIST[0]} + ... TPID=${tp-id} + ... BP=${bp} + ${resp} TemplatedRequests.Post_As_Json_Templated + ... ${BIER_TE_VAR_FOLDER}/bier_node_configuration/configure_te_node + ... ${mapping} + ... session Verify_Response_As_Json_Templated ${resp} ${BIER_TE_VAR_FOLDER}/common success_response END diff --git a/csit/libraries/BulkomaticKeywords.robot b/csit/libraries/BulkomaticKeywords.robot index 6b37c65d4d..302c913fa5 100644 --- a/csit/libraries/BulkomaticKeywords.robot +++ b/csit/libraries/BulkomaticKeywords.robot @@ -1,22 +1,28 @@ *** Settings *** -Documentation Bulkomatic Keyword library contains keywords for performing bulkomatic operations -... with a single bulkomatic API we can trigger bulk flows in config datastore which eventually populates switches and operational datastore -... So far this library is only to be used by MD-SAL clustering and OpenFlowplugin clustering test as it is very specific for these tests -Resource Utils.robot -Variables ../variables/Variables.py +Documentation Bulkomatic Keyword library contains keywords for performing bulkomatic operations +... with a single bulkomatic API we can trigger bulk flows in config datastore which eventually populates switches and operational datastore +... So far this library is only to be used by MD-SAL clustering and OpenFlowplugin clustering test as it is very specific for these tests + +Resource Utils.robot +Variables ../variables/Variables.py + *** Variables *** ${ADD_BULK_CONFIG_NODES_API} /rests/operations/sal-bulk-flow:flow-test ${GET_BULK_CONFIG_NODES_API} /rests/operations/sal-bulk-flow:read-flow-test -${ADD_TABLE_NODEs_API} /rests/operations/sal-bulk-flow:table-test -${jolokia_write_op_status} /jolokia/read/org.opendaylight.openflowplugin.applications.bulk.o.matic:type=FlowCounter/WriteOpStatus -${jolokia_read_op_status} /jolokia/read/org.opendaylight.openflowplugin.applications.bulk.o.matic:type=FlowCounter/ReadOpStatus -${jolokia_flow_count_status} /jolokia/read/org.opendaylight.openflowplugin.applications.bulk.o.matic:type=FlowCounter/FlowCount +${ADD_TABLE_NODEs_API} /rests/operations/sal-bulk-flow:table-test +${jolokia_write_op_status} +... /jolokia/read/org.opendaylight.openflowplugin.applications.bulk.o.matic:type=FlowCounter/WriteOpStatus +${jolokia_read_op_status} +... /jolokia/read/org.opendaylight.openflowplugin.applications.bulk.o.matic:type=FlowCounter/ReadOpStatus +${jolokia_flow_count_status} +... /jolokia/read/org.opendaylight.openflowplugin.applications.bulk.o.matic:type=FlowCounter/FlowCount + *** Keywords *** Operation Status Check - [Arguments] ${op_status_uri} ${controller_index} [Documentation] Checks to see if read or write operation is successfull in controller node. + [Arguments] ${op_status_uri} ${controller_index} ${data}= ClusterManagement.Get From Member ${op_status_uri} ${controller_index} ${json}= To Json ${data} ${value}= Get From Dictionary ${json} value @@ -25,71 +31,93 @@ Operation Status Check Should Start With ${value} ${two} Wait Until Write Finishes - [Arguments] ${controller_index} ${timeout} [Documentation] Wait Until Write operation status is OK in member ${controller_index}. - Wait Until Keyword Succeeds ${timeout} 1s BulkomaticKeywords.Operation Status Check ${jolokia_write_op_status} ${controller_index} + [Arguments] ${controller_index} ${timeout} + Wait Until Keyword Succeeds + ... ${timeout} + ... 1s + ... BulkomaticKeywords.Operation Status Check + ... ${jolokia_write_op_status} + ... ${controller_index} Wait Until Read Finishes - [Arguments] ${controller_index} ${timeout} [Documentation] Wait Until Read operation status is OK in member ${controller_index}. - Wait Until Keyword Succeeds ${timeout} 1s BulkomaticKeywords.Operation Status Check ${jolokia_read_op_status} ${controller_index} + [Arguments] ${controller_index} ${timeout} + Wait Until Keyword Succeeds + ... ${timeout} + ... 1s + ... BulkomaticKeywords.Operation Status Check + ... ${jolokia_read_op_status} + ... ${controller_index} Add Bulk Flow - [Arguments] ${json_body_add} ${controller_index} [Documentation] Add Bulk Flow in member ${controller_index} according to \${json_body_add}. - ${resp} ClusterManagement.Post As Json To Member ${ADD_BULK_CONFIG_NODES_API} ${json_body_add} ${controller_index} + [Arguments] ${json_body_add} ${controller_index} + ${resp}= ClusterManagement.Post As Json To Member + ... ${ADD_BULK_CONFIG_NODES_API} + ... ${json_body_add} + ... ${controller_index} Add Table Flow - [Arguments] ${json_body_add} ${controller_index} [Documentation] Add Table in member ${controller_index} according to \${json_body_add}. - ${resp} ClusterManagement.Post As Json To Member ${ADD_TABLE_NODEs_API} ${json_body_add} ${controller_index} + [Arguments] ${json_body_add} ${controller_index} + ${resp}= ClusterManagement.Post As Json To Member + ... ${ADD_TABLE_NODEs_API} + ... ${json_body_add} + ... ${controller_index} Delete Bulk Flow - [Arguments] ${json_body_del} ${controller_index} [Documentation] Delete Bulk Flow in member ${controller_index} according to \${json_body_del}. - ${resp} ClusterManagement.Post As Json To Member ${ADD_BULK_CONFIG_NODES_API} ${json_body_del} ${controller_index} + [Arguments] ${json_body_del} ${controller_index} + ${resp}= ClusterManagement.Post As Json To Member + ... ${ADD_BULK_CONFIG_NODES_API} + ... ${json_body_del} + ... ${controller_index} Get Bulk Flow - [Arguments] ${json_body_get} ${controller_index} [Documentation] Get Bulk Flow in member ${controller_index} according to \${json_body_get}. - ${resp} ClusterManagement.Post As Json To Member ${GET_BULK_CONFIG_NODES_API} ${json_body_get} ${controller_index} + [Arguments] ${json_body_get} ${controller_index} + ${resp}= ClusterManagement.Post As Json To Member + ... ${GET_BULK_CONFIG_NODES_API} + ... ${json_body_get} + ... ${controller_index} Get Bulk Flow Count - [Arguments] ${controller_index} [Documentation] Get Flow count in member ${controller_index}. New Flow Count is available after Get Bulk Flow operation. + [Arguments] ${controller_index} ${data}= ClusterManagement.Get From Member ${jolokia_flow_count_status} ${controller_index} - [Return] ${data} + RETURN ${data} Verify Flow Count - [Arguments] ${flow_count} ${controller_index} [Documentation] Verify Flow Count in member ${controller_index} matches ${flow_count}. + [Arguments] ${flow_count} ${controller_index} ${data}= Get Bulk Flow Count ${controller_index} ${json}= To Json ${data} ${value}= Get From Dictionary ${json} value Should Be Equal As Strings ${value} ${flow_count} Add Bulk Flow In Node - [Arguments] ${json_body_add} ${controller_index} ${timeout} [Documentation] Add Bulk Flow in member ${controller_index} and wait until operation is completed. + [Arguments] ${json_body_add} ${controller_index} ${timeout} Add Bulk Flow ${json_body_add} ${controller_index} Wait Until Write Finishes ${controller_index} ${timeout} Add Table In Node - [Arguments] ${json_body_add} ${controller_index} ${timeout} [Documentation] Add Table Flow in member ${controller_index} and wait until operation is completed. + [Arguments] ${json_body_add} ${controller_index} ${timeout} Add Table Flow ${json_body_add} ${controller_index} Wait Until Write Finishes ${controller_index} ${timeout} Delete Bulk Flow In Node - [Arguments] ${json_body_del} ${controller_index} ${timeout} [Documentation] Delete Bulk Flow in member ${controller_index} and wait until operation is completed. + [Arguments] ${json_body_del} ${controller_index} ${timeout} Delete Bulk Flow ${json_body_del} ${controller_index} Wait Until Write Finishes ${controller_index} ${timeout} Get Bulk Flow And Verify Count In Cluster - [Arguments] ${json_body_get} ${timeout} ${flow_count} ${controller_index_list}=${EMPTY} [Documentation] Get Bulk Flow and Verify Flow Count in ${controller_index_list} matches ${flow_count}. - ${index_list} = ClusterManagement.List Indices Or All given_list=${controller_index_list} + [Arguments] ${json_body_get} ${timeout} ${flow_count} ${controller_index_list}=${EMPTY} + ${index_list}= ClusterManagement.List Indices Or All given_list=${controller_index_list} FOR ${index} IN @{index_list} Get Bulk Flow ${json_body_get} ${index} END @@ -101,46 +129,46 @@ Get Bulk Flow And Verify Count In Cluster END Set DPN And Flow Count In Json Add - [Arguments] ${json_config} ${dpn_count} ${flows_count} [Documentation] Set new DPN count and flows count per DPN in the Bulkomatic Add json file. + [Arguments] ${json_config} ${dpn_count} ${flows_count} ${body}= OperatingSystem.Get File ${CURDIR}/../variables/openflowplugin/${json_config} ${get_string}= Set Variable "sal-bulk-flow:dpn-count" : "1" ${put_string}= Set Variable "sal-bulk-flow:dpn-count" : "${dpn_count}" - ${str} Replace String Using Regexp ${body} ${get_string} ${put_string} + ${str}= Replace String Using Regexp ${body} ${get_string} ${put_string} ${get_string}= Set Variable "sal-bulk-flow:flows-per-dpn" : "1000" ${put_string}= Set Variable "sal-bulk-flow:flows-per-dpn" : "${flows_count}" - ${json_body_add} Replace String Using Regexp ${str} ${get_string} ${put_string} + ${json_body_add}= Replace String Using Regexp ${str} ${get_string} ${put_string} ${get_string}= Set Variable "sal-bulk-flow:batch-size" : "1" ${put_string}= Set Variable "sal-bulk-flow:batch-size" : "${flows_count}" - ${json_body_add} Replace String Using Regexp ${json_body_add} ${get_string} ${put_string} + ${json_body_add}= Replace String Using Regexp ${json_body_add} ${get_string} ${put_string} Log ${json_body_add} - [Return] ${json_body_add} + RETURN ${json_body_add} Set DPN And Flow Count In Json Get - [Arguments] ${json_config} ${dpn_count} ${flows_count} [Documentation] Set new DPN count and flows count per DPN in the Bulkomatic Get json file. + [Arguments] ${json_config} ${dpn_count} ${flows_count} ${body}= OperatingSystem.Get File ${CURDIR}/../variables/openflowplugin/${json_config} ${get_string}= Set Variable "sal-bulk-flow:dpn-count" : "1" ${put_string}= Set Variable "sal-bulk-flow:dpn-count" : "${dpn_count}" - ${str} Replace String Using Regexp ${body} ${get_string} ${put_string} + ${str}= Replace String Using Regexp ${body} ${get_string} ${put_string} ${get_string}= Set Variable "sal-bulk-flow:flows-per-dpn" : "1000" ${put_string}= Set Variable "sal-bulk-flow:flows-per-dpn" : "${flows_count}" - ${json_body_get} Replace String Using Regexp ${str} ${get_string} ${put_string} + ${json_body_get}= Replace String Using Regexp ${str} ${get_string} ${put_string} Log ${json_body_get} - [Return] ${json_body_get} + RETURN ${json_body_get} Set DPN And Flow Count In Json Del - [Arguments] ${json_config} ${dpn_count} ${flows_count} [Documentation] Set new DPN count and flows count per DPN in the Bulkomatic Del json file. + [Arguments] ${json_config} ${dpn_count} ${flows_count} ${body}= OperatingSystem.Get File ${CURDIR}/../variables/openflowplugin/${json_config} ${get_string}= Set Variable "sal-bulk-flow:dpn-count" : "1" ${put_string}= Set Variable "sal-bulk-flow:dpn-count" : "${dpn_count}" - ${str} Replace String Using Regexp ${body} ${get_string} ${put_string} + ${str}= Replace String Using Regexp ${body} ${get_string} ${put_string} ${get_string}= Set Variable "sal-bulk-flow:flows-per-dpn" : "1000" ${put_string}= Set Variable "sal-bulk-flow:flows-per-dpn" : "${flows_count}" - ${json_body_del} Replace String Using Regexp ${str} ${get_string} ${put_string} + ${json_body_del}= Replace String Using Regexp ${str} ${get_string} ${put_string} ${get_string}= Set Variable "sal-bulk-flow:batch-size" : "1" ${put_string}= Set Variable "sal-bulk-flow:batch-size" : "${flows_count}" - ${json_body_del} Replace String Using Regexp ${json_body_del} ${get_string} ${put_string} + ${json_body_del}= Replace String Using Regexp ${json_body_del} ${get_string} ${put_string} Log ${json_body_del} - [Return] ${json_body_del} + RETURN ${json_body_del} diff --git a/csit/libraries/CarPeople.robot b/csit/libraries/CarPeople.robot index 2a61689e1f..da88abfc39 100644 --- a/csit/libraries/CarPeople.robot +++ b/csit/libraries/CarPeople.robot @@ -1,54 +1,68 @@ *** Settings *** -Documentation Resource housing Keywords common to tests which interact with car/people models. +Documentation Resource housing Keywords common to tests which interact with car/people models. ... -... Copyright (c) 2016-2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2016-2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... This resource is tightly coupled with "crud" cluster suite, -... as it is not straightforward to allow ${VAR_DIR} customization. -Resource ${CURDIR}/TemplatedRequests.robot +... This resource is tightly coupled with "crud" cluster suite, +... as it is not straightforward to allow ${VAR_DIR} customization. + +Resource ${CURDIR}/TemplatedRequests.robot + *** Variables *** -${VAR_DIR} ${CURDIR}/../../../variables/carpeople/crud +${VAR_DIR} ${CURDIR}/../../../variables/carpeople/crud + *** Keywords *** Add_Several_People - [Arguments] ${session} ${iterations} ${iter_start}=1 [Documentation] Simple loop for issuing add-person RPCs to session, one by one. ... People need to be added via RPC, otherwise buy-car routed RPC will not find registered path. ... See javadocs in RpcProviderRegistry.java + [Arguments] ${session} ${iterations} ${iter_start}=1 FOR ${i} IN RANGE ${iter_start} ${iter_start}+${iterations} - TemplatedRequests.Post_As_Json_Templated folder=${VAR_DIR}/add-person mapping={"i": "${i}"} session=${session} + TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_DIR}/add-person + ... mapping={"i": "${i}"} + ... session=${session} END Buy_Several_Cars - [Arguments] ${session} ${iterations} ${iter_start}=1 ${registration_delay}=20s [Documentation] Simple loop for issuing buy-car RPCs to session, one by one. ... This needs to be a separate Keyword mostly just because nested FOR loops are not allowed. ... Actual fact of buying one car is done by inner Keyword. + [Arguments] ${session} ${iterations} ${iter_start}=1 ${registration_delay}=20s FOR ${iter} IN RANGE ${iter_start} ${iter_start}+${iterations} Buy_Single_Car session=${session} iteration=${iter} registration_delay=${registration_delay} END Buy_Single_Car - [Arguments] ${session} ${iteration}=1 ${registration_delay}=20s [Documentation] Each buy-car RPC is routed, which means there is a delay between ... the time add-car RPC is executed and the time member in question registers the route. ... To distinguish functional bugs from performance ones, this Keyword waits up to 20 seconds ... while retrying buy-car requests. - BuiltIn.Wait_Until_Keyword_Succeeds ${registration_delay} 1s TemplatedRequests.Post_As_Json_Templated folder=${VAR_DIR}/buy-car mapping={"i": "${iteration}"} session=${session} + [Arguments] ${session} ${iteration}=1 ${registration_delay}=20s + BuiltIn.Wait_Until_Keyword_Succeeds + ... ${registration_delay} + ... 1s + ... TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_DIR}/buy-car + ... mapping={"i": "${iteration}"} + ... session=${session} Set_Variables_For_Shard - [Arguments] ${shard_name} ${shard_type}=config [Documentation] Get leader and followers for given shard name and ... set several suite variables related to member indices and sessions. ... ClusterManagement Resource is assumed to be initialized. ... TODO: car-people shard name causes dash in variable names. Should we convert to underscores? - ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=${shard_name} shard_type=${shard_type} + [Arguments] ${shard_name} ${shard_type}=config + ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=${shard_name} + ... shard_type=${shard_type} BuiltIn.Set_Suite_Variable \${${shard_name}_leader_index} ${leader} BuiltIn.Set_Suite_Variable \${${shard_name}_follower_indices} ${follower_list} ${first_follower_index} = Collections.Get_From_List ${follower_list} 0 @@ -65,7 +79,6 @@ Set_Variables_For_Shard BuiltIn.Set_Suite_Variable \${${shard_name}_first_follower_session} ${first_follower_session} Set_Tmp_Variables_For_Shard_For_Nodes - [Arguments] ${member_index_list} ${shard_name}=car ${shard_type}=config [Documentation] Get current leader and followers for given shard. Can be used for less nodes than full odl configuration. ... Variable names do not contain neither node nor shard names, so the variables are only suitable for temporary use, as indicated by Tmp in the keyword name. ... This keyword sets the following suite variables: @@ -74,7 +87,11 @@ Set_Tmp_Variables_For_Shard_For_Nodes ... ${new_first_follower_session} - http session for the first follower node ... ${new_leader_index} - index of the shard leader ... ${new_followers_list} - list of followers indexes - ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=${shard_name} shard_type=${shard_type} member_index_list=${member_index_list} + [Arguments] ${member_index_list} ${shard_name}=car ${shard_type}=config + ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=${shard_name} + ... shard_type=${shard_type} + ... member_index_list=${member_index_list} BuiltIn.Set_Suite_Variable \${new_leader_index} ${leader} BuiltIn.Set_Suite_Variable \${new_followers_list} ${follower_list} ${leader_session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${leader} @@ -87,4 +104,4 @@ Set_Tmp_Variables_For_Shard_For_Nodes BuiltIn.Set_Suite_Variable \${new_follower_sessions} ${sessions} ${first_follower_session} = Collections.Get_From_List ${sessions} 0 BuiltIn.Set_Suite_Variable \${new_first_follower_session} ${first_follower_session} - BuiltIn.Return_From_Keyword ${leader} ${follower_list} + RETURN ${leader} ${follower_list} diff --git a/csit/libraries/ChangeCounter.robot b/csit/libraries/ChangeCounter.robot index ceba89a743..60f6ba38fb 100644 --- a/csit/libraries/ChangeCounter.robot +++ b/csit/libraries/ChangeCounter.robot @@ -1,24 +1,27 @@ *** Settings *** -Documentation Robot keyword library (Resource) for common handling of data change counter. +Documentation Robot keyword library (Resource) for common handling of data change counter. ... -... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... This resource creates a "default" session using TemplatedRequests.Create_Default_Session -... which points to (an analogue of) http://${ODL_SYSTEM_IP}:${RESTCONFPORT} -Library RequestsLibrary -Resource ${CURDIR}/CompareStream.robot -Resource ${CURDIR}/ScalarClosures.robot -Resource ${CURDIR}/TemplatedRequests.robot -Resource ${CURDIR}/WaitUtils.robot +... This resource creates a "default" session using TemplatedRequests.Create_Default_Session +... which points to (an analogue of) http://${ODL_SYSTEM_IP}:${RESTCONFPORT} + +Library RequestsLibrary +Resource ${CURDIR}/CompareStream.robot +Resource ${CURDIR}/ScalarClosures.robot +Resource ${CURDIR}/TemplatedRequests.robot +Resource ${CURDIR}/WaitUtils.robot + *** Variables *** -${CHANGE_COUNTER_TEMPLATE_FOLDER} ${CURDIR}/../variables/bgpuser -${CC_DATA_CHANGE_COUNTER_URL} ${REST_API}/data-change-counter:data-change-counter?content=nonconfig +${CHANGE_COUNTER_TEMPLATE_FOLDER} ${CURDIR}/../variables/bgpuser +${CC_DATA_CHANGE_COUNTER_URL} ${REST_API}/data-change-counter:data-change-counter?content=nonconfig + *** Keywords *** CC_Setup @@ -29,27 +32,38 @@ CC_Setup BuiltIn.Set_Suite_Variable ${ChangeCounter__getter} ${counter} Get_Change_Count - [Arguments] ${session}=operational [Documentation] GET data change request, assert status 200, return the value. + [Arguments] ${session}=operational ${response} = RequestsLibrary.Get_Request ${session} ${CC_DATA_CHANGE_COUNTER_URL} - BuiltIn.Should_Be_Equal ${response.status_code} ${200} Got status: ${response.status_code} and message: ${response.text} + BuiltIn.Should_Be_Equal + ... ${response.status_code} + ... ${200} + ... Got status: ${response.status_code} and message: ${response.text} # CompareStream.Set_Variable_If_At_Least_Else cannot be used direcly, because ${response.text}["data-change-counter"]["count"] would be # evaluated before the stream comparison and it causes failures BuiltIn.Log ${response.text} - ${count} = BuiltIn.Evaluate json.loads('${response.text}')["data-change-counter:data-change-counter"]["counter"][0]["count"] modules=json - [Return] ${count} + ${count} = BuiltIn.Evaluate + ... json.loads('${response.text}')["data-change-counter:data-change-counter"]["counter"][0]["count"] + ... modules=json + RETURN ${count} Reconfigure_Topology_Name - [Arguments] ${topology_name}=example-linkstate-topology [Documentation] Configure data change counter to count transactions affecting ... ${topology_name} instead of previously configured topology name. - &{mapping} Create Dictionary DEVICE_NAME=${DEVICE_NAME} TOPOLOGY_NAME=${topology_name} + [Arguments] ${topology_name}=example-linkstate-topology + &{mapping} = Create Dictionary DEVICE_NAME=${DEVICE_NAME} TOPOLOGY_NAME=${topology_name} TemplatedRequests.Put_As_Xml_Templated ${CHANGE_COUNTER_TEMPLATE_FOLDER}${/}change_counter mapping=${mapping} Wait_For_Change_Count_To_Become_Stable - [Arguments] ${timeout}=60s ${period}=1s ${repetitions}=4 ${count_to_overcome}=-1 [Documentation] Each ${period} get count. After ${repetitions} of constant value above ${count_to_overcome} within ${timeout}, Return validator output. Fail early on getter error. - ${validator} = WaitUtils.Create_Limiting_Stability_Safe_Stateful_Validator_From_Value_To_Overcome maximum_invalid=${count_to_overcome} - ${result} = WaitUtils.Wait_For_Getter_Error_Or_Safe_Stateful_Validator_Consecutive_Success timeout=${timeout} period=${period} count=${repetitions} getter=${ChangeCounter__getter} safe_validator=${validator} + [Arguments] ${timeout}=60s ${period}=1s ${repetitions}=4 ${count_to_overcome}=-1 + ${validator} = WaitUtils.Create_Limiting_Stability_Safe_Stateful_Validator_From_Value_To_Overcome + ... maximum_invalid=${count_to_overcome} + ${result} = WaitUtils.Wait_For_Getter_Error_Or_Safe_Stateful_Validator_Consecutive_Success + ... timeout=${timeout} + ... period=${period} + ... count=${repetitions} + ... getter=${ChangeCounter__getter} + ... safe_validator=${validator} ... initial_state=${count_to_overcome} - [Return] ${result} + RETURN ${result} diff --git a/csit/libraries/CheckJVMResource.robot b/csit/libraries/CheckJVMResource.robot index 07d24a5e06..792dce3114 100644 --- a/csit/libraries/CheckJVMResource.robot +++ b/csit/libraries/CheckJVMResource.robot @@ -1,52 +1,74 @@ *** Settings *** -Documentation Robot keyword library for Monitoring JVM resources -Library ${CURDIR}/Appenders/ElasticsearchAppender.py -Variables ${CURDIR}/../variables/Variables.py +Documentation Robot keyword library for Monitoring JVM resources + +Library ${CURDIR}/Appenders/ElasticsearchAppender.py +Variables ${CURDIR}/../variables/Variables.py + *** Keywords *** Get JVM Memory - [Arguments] ${controller-ip}=${ODL_SYSTEM_IP} ${elastic-port}=${ELASTICPORT} [Documentation] Return latest jvm Memory object + [Arguments] ${controller-ip}=${ODL_SYSTEM_IP} ${elastic-port}=${ELASTICPORT} ${session} ElasticsearchAppender.Get_Connection ${controller-ip} ${elastic-port} - ${value}= ElasticsearchAppender.Get Jvm Memory ${session} + ${value} ElasticsearchAppender.Get Jvm Memory ${session} Log ${value} - [Return] ${value} + RETURN ${value} Get JVM Threading - [Arguments] ${controller-ip}=${ODL_SYSTEM_IP} ${elastic-port}=${ELASTICPORT} [Documentation] Return latest jvm Threading object + [Arguments] ${controller-ip}=${ODL_SYSTEM_IP} ${elastic-port}=${ELASTICPORT} ${session} ElasticsearchAppender.Get_Connection ${controller-ip} ${elastic-port} - ${value}= ElasticsearchAppender.Get Jvm Threading ${session} + ${value} ElasticsearchAppender.Get Jvm Threading ${session} Log ${value} - [Return] ${value} + RETURN ${value} Get JVM Classloading - [Arguments] ${controller-ip}=${ODL_SYSTEM_IP} ${elastic-port}=${ELASTICPORT} [Documentation] Return latest jvm Classloading object + [Arguments] ${controller-ip}=${ODL_SYSTEM_IP} ${elastic-port}=${ELASTICPORT} ${session} ElasticsearchAppender.Get_Connection ${controller-ip} ${elastic-port} - ${value}= ElasticsearchAppender.Get Jvm Classloading ${session} + ${value} ElasticsearchAppender.Get Jvm Classloading ${session} Log ${value} - [Return] ${value} + RETURN ${value} Get JVM Operatingsystem - [Arguments] ${controller-ip}=${ODL_SYSTEM_IP} ${elastic-port}=${ELASTICPORT} [Documentation] Return latest jvm Operatingsystem object + [Arguments] ${controller-ip}=${ODL_SYSTEM_IP} ${elastic-port}=${ELASTICPORT} ${session} ElasticsearchAppender.Get_Connection ${controller-ip} ${elastic-port} - ${value}= ElasticsearchAppender.Get Jvm Operatingsystem ${session} + ${value} ElasticsearchAppender.Get Jvm Operatingsystem ${session} Log ${value} - [Return] ${value} + RETURN ${value} Create JVM Plots - [Arguments] ${controllers_number}=${NUM_ODL_SYSTEM} ${elastic-port}=${ELASTICPORT} [Documentation] Draw Resource usage plot using plot_points method. + [Arguments] ${controllers_number}=${NUM_ODL_SYSTEM} ${elastic-port}=${ELASTICPORT} FOR ${index} IN RANGE 1 ${controllers_number}+1 - ${controller-ip}= Builtin.Set Variable ${ODL_SYSTEM_${index}_IP} + ${controller-ip} Builtin.Set Variable ${ODL_SYSTEM_${index}_IP} Log ${controller-ip} ${session} ElasticsearchAppender.Get_Connection ${controller-ip} ${elastic-port} Log ${session} - ElasticsearchAppender.Plot Points ${session} JVM Threads threadcount_${index}.png 'Threading' 'ThreadCount' - ElasticsearchAppender.Plot Points ${session} JVM Heap Memory heapmemory_${index}.png 'Memory' 'HeapMemoryUsage' + ElasticsearchAppender.Plot Points + ... ${session} + ... JVM Threads + ... threadcount_${index}.png + ... 'Threading' + ... 'ThreadCount' + ElasticsearchAppender.Plot Points + ... ${session} + ... JVM Heap Memory + ... heapmemory_${index}.png + ... 'Memory' + ... 'HeapMemoryUsage' ... 'used' - ElasticsearchAppender.Plot Points ${session} JVM Loaded Classes class_count_${index}.png 'ClassLoading' 'TotalLoadedClassCount' - ElasticsearchAppender.Plot Points ${session} JVM CPU Usage cpu_usage_${index}.png 'OperatingSystem' 'ProcessCpuLoad' + ElasticsearchAppender.Plot Points + ... ${session} + ... JVM Loaded Classes + ... class_count_${index}.png + ... 'ClassLoading' + ... 'TotalLoadedClassCount' + ElasticsearchAppender.Plot Points + ... ${session} + ... JVM CPU Usage + ... cpu_usage_${index}.png + ... 'OperatingSystem' + ... 'ProcessCpuLoad' END diff --git a/csit/libraries/ClusterAdmin.robot b/csit/libraries/ClusterAdmin.robot index 19d55e529a..e5bd1eaab2 100644 --- a/csit/libraries/ClusterAdmin.robot +++ b/csit/libraries/ClusterAdmin.robot @@ -1,77 +1,107 @@ *** Settings *** -Documentation Keywords wrapping controller's cluster-admin yang model rpcs. +Documentation Keywords wrapping controller's cluster-admin yang model rpcs. ... -... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html -Library XML -Resource ${CURDIR}/ClusterManagement.robot -Resource ${CURDIR}/TemplatedRequests.robot +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html + +Library XML +Resource ${CURDIR}/ClusterManagement.robot +Resource ${CURDIR}/TemplatedRequests.robot + *** Variables *** -${CLUSTERADMIN_RPC_DIR} ${CURDIR}/../variables/mdsal/clusteradmin -${ADD_PREFIX_SHARD_REPLICA_DIR} ${CLUSTERADMIN_RPC_DIR}/add_prefix_shard_replica -${ADD_SHARD_REPLICA_DIR} ${CLUSTERADMIN_RPC_DIR}/add_shard_replica -${MAKE_LEADER_LOCAL_DIR} ${CLUSTERADMIN_RPC_DIR}/make_leader_local -${REMOVE_PREFIX_SHARD_REPLICA_DIR} ${CLUSTERADMIN_RPC_DIR}/remove_prefix_shard_replica -${REMOVE_SHARD_REPLICA_DIR} ${CLUSTERADMIN_RPC_DIR}/remove_shard_replica -${GET_SHARD_ROLE_DIR} ${CLUSTERADMIN_RPC_DIR}/get_shard_role -${GET_PREFIX_SHARD_ROLE_DIR} ${CLUSTERADMIN_RPC_DIR}/get_prefix_shard_role +${CLUSTERADMIN_RPC_DIR} ${CURDIR}/../variables/mdsal/clusteradmin +${ADD_PREFIX_SHARD_REPLICA_DIR} ${CLUSTERADMIN_RPC_DIR}/add_prefix_shard_replica +${ADD_SHARD_REPLICA_DIR} ${CLUSTERADMIN_RPC_DIR}/add_shard_replica +${MAKE_LEADER_LOCAL_DIR} ${CLUSTERADMIN_RPC_DIR}/make_leader_local +${REMOVE_PREFIX_SHARD_REPLICA_DIR} ${CLUSTERADMIN_RPC_DIR}/remove_prefix_shard_replica +${REMOVE_SHARD_REPLICA_DIR} ${CLUSTERADMIN_RPC_DIR}/remove_shard_replica +${GET_SHARD_ROLE_DIR} ${CLUSTERADMIN_RPC_DIR}/get_shard_role +${GET_PREFIX_SHARD_ROLE_DIR} ${CLUSTERADMIN_RPC_DIR}/get_prefix_shard_role + *** Keywords *** Make_Leader_Local - [Arguments] ${member_index} ${shard_name} ${shard_type} [Documentation] Makes the node to be a shard leader by invoking make-leader-local rpc. + [Arguments] ${member_index} ${shard_name} ${shard_type} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary SHARD_NAME=${shard_name} SHARD_TYPE=${shard_type} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${MAKE_LEADER_LOCAL_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary SHARD_NAME=${shard_name} SHARD_TYPE=${shard_type} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${MAKE_LEADER_LOCAL_DIR} + ... mapping=${mapping} + ... session=${session} Add_Prefix_Shard_Replica - [Arguments] ${member_index} ${shard_prefix} ${ds_type} [Documentation] Add prefix shard replica to given member by invoking add-prefix-shard-replica rpc. + [Arguments] ${member_index} ${shard_prefix} ${ds_type} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary SHARD_PREFIX=${shard_prefix} DATA_STORE_TYPE=${ds_type} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${ADD_PREFIX_SHARD_REPLICA_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary SHARD_PREFIX=${shard_prefix} DATA_STORE_TYPE=${ds_type} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${ADD_PREFIX_SHARD_REPLICA_DIR} + ... mapping=${mapping} + ... session=${session} Remove_Prefix_Shard_Replica - [Arguments] ${member_index} ${shard_prefix} ${member_name} ${ds_type} [Documentation] Remove prefix shard replica from the given member by invoking remove-prefix-shard-replica rpc. + [Arguments] ${member_index} ${shard_prefix} ${member_name} ${ds_type} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary SHARD_PREFIX=${shard_prefix} MEMBER_NAME=${member_name} DATA_STORE_TYPE=${ds_type} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${REMOVE_PREFIX_SHARD_REPLICA_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary + ... SHARD_PREFIX=${shard_prefix} + ... MEMBER_NAME=${member_name} + ... DATA_STORE_TYPE=${ds_type} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${REMOVE_PREFIX_SHARD_REPLICA_DIR} + ... mapping=${mapping} + ... session=${session} Add_Shard_Replica - [Arguments] ${member_index} ${shard_name} ${ds_type} [Documentation] Add shard replica to given member by invoking add-shard-replica rpc. + [Arguments] ${member_index} ${shard_name} ${ds_type} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary SHARD_NAME=${shard_name} DATA_STORE_TYPE=${ds_type} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${ADD_SHARD_REPLICA_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary SHARD_NAME=${shard_name} DATA_STORE_TYPE=${ds_type} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${ADD_SHARD_REPLICA_DIR} + ... mapping=${mapping} + ... session=${session} Remove_Shard_Replica - [Arguments] ${member_index} ${shard_name} ${member_name} ${ds_type} [Documentation] Remove shard replica from the given member by invoking remove-shard-replica rpc. + [Arguments] ${member_index} ${shard_name} ${member_name} ${ds_type} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary SHARD_NAME=${shard_name} MEMBER_NAME=${member_name} DATA_STORE_TYPE=${ds_type} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${REMOVE_SHARD_REPLICA_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary + ... SHARD_NAME=${shard_name} + ... MEMBER_NAME=${member_name} + ... DATA_STORE_TYPE=${ds_type} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${REMOVE_SHARD_REPLICA_DIR} + ... mapping=${mapping} + ... session=${session} Get_Shard_Role - [Arguments] ${member_index} ${shard_name} ${ds_type} [Documentation] Get shard member role. + [Arguments] ${member_index} ${shard_name} ${ds_type} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary SHARD_NAME=${shard_name} DATA_STORE_TYPE=${ds_type} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${GET_SHARD_ROLE_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary SHARD_NAME=${shard_name} DATA_STORE_TYPE=${ds_type} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${GET_SHARD_ROLE_DIR} + ... mapping=${mapping} + ... session=${session} ${xml} = XML.Parse_Xml ${text} ${role} = XML.Get_Element_Text ${xml} xpath=role - BuiltIn.Return_From_Keyword ${role} + RETURN ${role} Get_Prefix_Shard_Role - [Arguments] ${member_index} ${shard_prefix} ${ds_type} [Documentation] Get prefix shard member role. + [Arguments] ${member_index} ${shard_prefix} ${ds_type} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary SHARD_PREFIX=${shard_prefix} DATA_STORE_TYPE=${ds_type} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${GET_PREFIX_SHARD_ROLE_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary SHARD_PREFIX=${shard_prefix} DATA_STORE_TYPE=${ds_type} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${GET_PREFIX_SHARD_ROLE_DIR} + ... mapping=${mapping} + ... session=${session} ${xml} = XML.Parse_Xml ${text} ${role} = XML.Get_Element_Text ${xml} xpath=role - BuiltIn.Return_From_Keyword ${role} + RETURN ${role} diff --git a/csit/libraries/ClusterManagement.robot b/csit/libraries/ClusterManagement.robot index e5ac43f38f..c624b10b8f 100644 --- a/csit/libraries/ClusterManagement.robot +++ b/csit/libraries/ClusterManagement.robot @@ -1,134 +1,180 @@ *** Settings *** -Documentation Resource housing Keywords common to several suites for cluster functional testing. +Documentation Resource housing Keywords common to several suites for cluster functional testing. ... -... Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. -... Copyright (c) 2016 Brocade Communications Systems, Inc. and others. All rights reserved. +... Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2016 Brocade Communications Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... This resource holds private state (in suite variables), -... which is generated once at Setup with ClusterManagement_Setup KW. -... The state includes member indexes, IP addresses and Http (RequestsLibrary) sessions. -... Cluster Keywords normally use member index, member list or nothing (all members) as argument. +... This resource holds private state (in suite variables), +... which is generated once at Setup with ClusterManagement_Setup KW. +... The state includes member indexes, IP addresses and Http (RequestsLibrary) sessions. +... Cluster Keywords normally use member index, member list or nothing (all members) as argument. ... -... All index lists returned should be sorted numerically, fix if not. +... All index lists returned should be sorted numerically, fix if not. ... -... Requirements: -... odl-jolokia is assumed to be installed. +... Requirements: +... odl-jolokia is assumed to be installed. ... -... Keywords are ordered as follows: -... - Cluster Setup -... - Shard state, leader and followers -... - Entity Owner, candidates and successors -... - Kill, Stop and Start Member -... - Isolate and Rejoin Member -... - Run Commands On Member -... - REST requests and checks on Members +... Keywords are ordered as follows: +... - Cluster Setup +... - Shard state, leader and followers +... - Entity Owner, candidates and successors +... - Kill, Stop and Start Member +... - Isolate and Rejoin Member +... - Run Commands On Member +... - REST requests and checks on Members ... -... TODO: Unify capitalization of Leaders and Followers. -Library RequestsLibrary # for Create_Session and To_Json -Library Collections -Library String -Library ClusterEntities.py -Resource ${CURDIR}/CompareStream.robot -Resource ${CURDIR}/KarafKeywords.robot -Resource ${CURDIR}/SSHKeywords.robot -Resource ${CURDIR}/TemplatedRequests.robot # for Get_As_Json_From_Uri -Resource ${CURDIR}/Utils.robot # for Run_Command_On_Controller -Resource ../variables/Variables.robot +... TODO: Unify capitalization of Leaders and Followers. + +Library RequestsLibrary # for Create_Session and To_Json +Library Collections +Library String +Library ClusterEntities.py +Resource ${CURDIR}/CompareStream.robot +Resource ${CURDIR}/KarafKeywords.robot +Resource ${CURDIR}/SSHKeywords.robot +Resource ${CURDIR}/TemplatedRequests.robot # for Get_As_Json_From_Uri +Resource ${CURDIR}/Utils.robot # for Run_Command_On_Controller +Resource ../variables/Variables.robot + *** Variables *** -${RESTCONF_URI} rests -${GC_LOG_PATH} ${KARAF_HOME}/data/log -${JAVA_HOME} ${EMPTY} # releng/builder scripts should provide correct value -${JOLOKIA_CONF_SHARD_MANAGER_URI} jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore -${JOLOKIA_OPER_SHARD_MANAGER_URI} jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-operational,type=DistributedOperationalDatastore -${JOLOKIA_CONFIG_LOCAL_SHARDS_URI} jolokia/read/org.opendaylight.controller:type=DistributedConfigDatastore,Category=ShardManager,name=shard-manager-config/LocalShards -${JOLOKIA_OPER_LOCAL_SHARDS_URI} jolokia/read/org.opendaylight.controller:type=DistributedOperationalDatastore,Category=ShardManager,name=shard-manager-operational/LocalShards -${JOLOKIA_READ_URI} jolokia/read/org.opendaylight.controller +${RESTCONF_URI} rests +${GC_LOG_PATH} ${KARAF_HOME}/data/log +${JAVA_HOME} ${EMPTY} # releng/builder scripts should provide correct value +${JOLOKIA_CONF_SHARD_MANAGER_URI} +... jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore +${JOLOKIA_OPER_SHARD_MANAGER_URI} +... jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-operational,type=DistributedOperationalDatastore +${JOLOKIA_CONFIG_LOCAL_SHARDS_URI} +... jolokia/read/org.opendaylight.controller:type=DistributedConfigDatastore,Category=ShardManager,name=shard-manager-config/LocalShards +${JOLOKIA_OPER_LOCAL_SHARDS_URI} +... jolokia/read/org.opendaylight.controller:type=DistributedOperationalDatastore,Category=ShardManager,name=shard-manager-operational/LocalShards +${JOLOKIA_READ_URI} jolokia/read/org.opendaylight.controller # Bug 9044 workaround: delete etc/host.key before restart. -@{ODL_DEFAULT_DATA_PATHS} tmp/ data/ cache/ snapshots/ journal/ segmented-journal/ etc/opendaylight/current/ etc/host.key -${RESTCONF_MODULES_DIR} ${CURDIR}/../variables/restconf/modules -${SINGLETON_NETCONF_DEVICE_ID_PREFIX} KeyedInstanceIdentifier{targetType=interface org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node, path=[org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology, org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology[key=TopologyKey{_topologyId=Uri{_value=topology-netconf}}], org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node[key=NodeKey{_nodeId=Uri{_value= -${SINGLETON_NETCONF_DEVICE_ID_SUFFIX} }}]]} -${SINGLETON_BGPCEP_DEVICE_ID_SUFFIX} -service-group -&{SINGLETON_DEVICE_ID_PREFIX} bgpcep=${EMPTY} netconf=${SINGLETON_NETCONF_DEVICE_ID_PREFIX} openflow=${EMPTY} sxp=${EMPTY} -&{SINGLETON_DEVICE_ID_SUFFIX} bgpcep=${SINGLETON_BGPCEP_DEVICE_ID_SUFFIX} netconf=${SINGLETON_NETCONF_DEVICE_ID_SUFFIX} openflow=${EMPTY} sxp=${EMPTY} -${SINGLETON_ELECTION_ENTITY_TYPE} org.opendaylight.mdsal.ServiceEntityType -${SINGLETON_CHANGE_OWNERSHIP_ENTITY_TYPE} org.opendaylight.mdsal.AsyncServiceCloseEntityType -${NODE_ROLE_INDEX_START} 1 -${NODE_START_COMMAND} ${KARAF_HOME}/bin/start -${NODE_STOP_COMMAND} ${KARAF_HOME}/bin/stop -${NODE_KARAF_COUNT_COMMAND} ps axf | grep org.apache.karaf | grep -v grep | wc -l -${NODE_KILL_COMMAND} ps axf | grep org.apache.karaf | grep -v grep | awk '{print \"kill -9 \" $1}' | sh -${NODE_FREEZE_COMMAND} ps axf | grep org.apache.karaf | grep -v grep | awk '{print \"kill -STOP \" $1}' | sh -${NODE_UNFREEZE_COMMAND} ps axf | grep org.apache.karaf | grep -v grep | awk '{print \"kill -CONT \" $1}' | sh +@{ODL_DEFAULT_DATA_PATHS} +... tmp/ +... data/ +... cache/ +... snapshots/ +... journal/ +... segmented-journal/ +... etc/opendaylight/current/ +... etc/host.key +${RESTCONF_MODULES_DIR} ${CURDIR}/../variables/restconf/modules +${SINGLETON_NETCONF_DEVICE_ID_PREFIX} +... KeyedInstanceIdentifier{targetType=interface org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node, path=[org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology, org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology[key=TopologyKey{_topologyId=Uri{_value=topology-netconf}}], org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node[key=NodeKey{_nodeId=Uri{_value= +${SINGLETON_NETCONF_DEVICE_ID_SUFFIX} }}]]} +${SINGLETON_BGPCEP_DEVICE_ID_SUFFIX} -service-group +&{SINGLETON_DEVICE_ID_PREFIX} +... bgpcep=${EMPTY} +... netconf=${SINGLETON_NETCONF_DEVICE_ID_PREFIX} +... openflow=${EMPTY} +... sxp=${EMPTY} +&{SINGLETON_DEVICE_ID_SUFFIX} +... bgpcep=${SINGLETON_BGPCEP_DEVICE_ID_SUFFIX} +... netconf=${SINGLETON_NETCONF_DEVICE_ID_SUFFIX} +... openflow=${EMPTY} +... sxp=${EMPTY} +${SINGLETON_ELECTION_ENTITY_TYPE} org.opendaylight.mdsal.ServiceEntityType +${SINGLETON_CHANGE_OWNERSHIP_ENTITY_TYPE} org.opendaylight.mdsal.AsyncServiceCloseEntityType +${NODE_ROLE_INDEX_START} 1 +${NODE_START_COMMAND} ${KARAF_HOME}/bin/start +${NODE_STOP_COMMAND} ${KARAF_HOME}/bin/stop +${NODE_KARAF_COUNT_COMMAND} ps axf | grep org.apache.karaf | grep -v grep | wc -l +${NODE_KILL_COMMAND} +... ps axf | grep org.apache.karaf | grep -v grep | awk '{print \"kill -9 \" $1}' | sh +${NODE_FREEZE_COMMAND} +... ps axf | grep org.apache.karaf | grep -v grep | awk '{print \"kill -STOP \" $1}' | sh +${NODE_UNFREEZE_COMMAND} +... ps axf | grep org.apache.karaf | grep -v grep | awk '{print \"kill -CONT \" $1}' | sh + *** Keywords *** ClusterManagement_Setup - [Arguments] ${http_timeout}=${DEFAULT_TIMEOUT_HTTP} ${http_retries}=0 [Documentation] Detect repeated call, or detect number of members and initialize derived suite variables. ... Http sessions are created with parameters to not waste time when ODL is no accepting connections properly. + [Arguments] ${http_timeout}=${DEFAULT_TIMEOUT_HTTP} ${http_retries}=0 # Avoid multiple initialization by several downstream libraries. ${already_done} = BuiltIn.Get_Variable_Value \${ClusterManagement__has_setup_run} False - BuiltIn.Return_From_Keyword_If ${already_done} + IF ${already_done} RETURN BuiltIn.Set_Suite_Variable \${ClusterManagement__has_setup_run} True ${cluster_size} = BuiltIn.Get_Variable_Value \${NUM_ODL_SYSTEM} 1 - ${status} ${possibly_int_of_members} = BuiltIn.Run_Keyword_And_Ignore_Error BuiltIn.Convert_To_Integer ${cluster_size} + ${status} ${possibly_int_of_members} = BuiltIn.Run_Keyword_And_Ignore_Error + ... BuiltIn.Convert_To_Integer + ... ${cluster_size} ${int_of_members} = BuiltIn.Set_Variable_If '${status}' != 'PASS' ${1} ${possibly_int_of_members} - ClusterManagement__Compute_Derived_Variables int_of_members=${int_of_members} http_timeout=${http_timeout} http_retries=${http_retries} + ClusterManagement__Compute_Derived_Variables + ... int_of_members=${int_of_members} + ... http_timeout=${http_timeout} + ... http_retries=${http_retries} Check_Cluster_Is_In_Sync - [Arguments] ${member_index_list}=${EMPTY} [Documentation] Fail if no-sync is detected on a member from list (or any). + [Arguments] ${member_index_list}=${EMPTY} ${index_list} = List_Indices_Or_All given_list=${member_index_list} FOR ${index} IN @{index_list} # usually: 1, 2, 3. ${status} = Get_Sync_Status_Of_Member member_index=${index} - BuiltIn.Continue_For_Loop_If 'True' == '${status}' + IF 'True' == '${status}' CONTINUE BuiltIn.Fail Index ${index} has incorrect status: ${status} END Get_Sync_Status_Of_Member - [Arguments] ${member_index} [Documentation] Obtain IP, two GETs from jolokia URIs, return combined sync status as string. + [Arguments] ${member_index} ${session} = Resolve_Http_Session_For_Member member_index=${member_index} - ${conf_text} = TemplatedRequests.Get_As_Json_From_Uri uri=${JOLOKIA_CONF_SHARD_MANAGER_URI} session=${session} + ${conf_text} = TemplatedRequests.Get_As_Json_From_Uri + ... uri=${JOLOKIA_CONF_SHARD_MANAGER_URI} + ... session=${session} ${conf_status} = ClusterManagement__Parse_Sync_Status shard_manager_text=${conf_text} - BuiltIn.Return_From_Keyword_If 'False' == ${conf_status} False - ${oper_text} = TemplatedRequests.Get_As_Json_From_Uri uri=${JOLOKIA_OPER_SHARD_MANAGER_URI} session=${session} + IF 'False' == ${conf_status} RETURN False + ${oper_text} = TemplatedRequests.Get_As_Json_From_Uri + ... uri=${JOLOKIA_OPER_SHARD_MANAGER_URI} + ... session=${session} ${oper_status} = ClusterManagement__Parse_Sync_Status shard_manager_text=${oper_text} - [Return] ${oper_status} + RETURN ${oper_status} Verify_Leader_Exists_For_Each_Shard - [Arguments] ${shard_name_list} ${shard_type}=operational ${member_index_list}=${EMPTY} ${verify_restconf}=True [Documentation] For each shard name, call Get_Leader_And_Followers_For_Shard. ... Not much logic there, but single Keyword is useful when using BuiltIn.Wait_Until_Keyword_Succeeds. + [Arguments] ${shard_name_list} ${shard_type}=operational ${member_index_list}=${EMPTY} ${verify_restconf}=True FOR ${shard_name} IN @{shard_name_list} - Get_Leader_And_Followers_For_Shard shard_name=${shard_name} shard_type=${shard_type} validate=True member_index_list=${member_index_list} verify_restconf=${verify_restconf} + Get_Leader_And_Followers_For_Shard + ... shard_name=${shard_name} + ... shard_type=${shard_type} + ... validate=True + ... member_index_list=${member_index_list} + ... verify_restconf=${verify_restconf} END Get_Leader_And_Followers_For_Shard - [Arguments] ${shard_name}=default ${shard_type}=operational ${validate}=True ${member_index_list}=${EMPTY} ${verify_restconf}=True ${http_timeout}=${EMPTY} [Documentation] Get role lists, validate there is one leader, return the leader and list of followers. ... Optionally, issue GET to a simple restconf URL to make sure subsequent operations will not encounter 503. - ${leader_list} ${follower_list} = Get_State_Info_For_Shard shard_name=${shard_name} shard_type=${shard_type} validate=True member_index_list=${member_index_list} - ... verify_restconf=${verify_restconf} http_timeout=${http_timeout} + [Arguments] ${shard_name}=default ${shard_type}=operational ${validate}=True ${member_index_list}=${EMPTY} ${verify_restconf}=True ${http_timeout}=${EMPTY} + ${leader_list} ${follower_list} = Get_State_Info_For_Shard + ... shard_name=${shard_name} + ... shard_type=${shard_type} + ... validate=True + ... member_index_list=${member_index_list} + ... verify_restconf=${verify_restconf} + ... http_timeout=${http_timeout} ${leader_count} = BuiltIn.Get_Length ${leader_list} - BuiltIn.Run_Keyword_If ${leader_count} < 1 BuiltIn.Fail No leader found. + IF ${leader_count} < 1 BuiltIn.Fail No leader found. BuiltIn.Length_Should_Be ${leader_list} ${1} Too many Leaders. ${leader} = Collections.Get_From_List ${leader_list} 0 - [Return] ${leader} ${follower_list} + RETURN ${leader} ${follower_list} Get_State_Info_For_Shard - [Arguments] ${shard_name}=default ${shard_type}=operational ${validate}=False ${member_index_list}=${EMPTY} ${verify_restconf}=False ${http_timeout}=${EMPTY} [Documentation] Return lists of Leader and Follower member indices from a given member index list ... (or from the full list if empty). If \${shard_type} is not 'config', 'operational' is assumed. ... If \${validate}, Fail if raft state is not Leader or Follower (for example on Candidate). ... The biggest difference from Get_Leader_And_Followers_For_Shard ... is that no check on number of Leaders is performed. + [Arguments] ${shard_name}=default ${shard_type}=operational ${validate}=False ${member_index_list}=${EMPTY} ${verify_restconf}=False ${http_timeout}=${EMPTY} ${index_list} = List_Indices_Or_All given_list=${member_index_list} Collections.Sort_List ${index_list} # to guarantee return values are also sorted lists # TODO: Support alternative capitalization of 'config'? @@ -136,58 +182,91 @@ Get_State_Info_For_Shard ${leader_list} = BuiltIn.Create_List ${follower_list} = BuiltIn.Create_List FOR ${index} IN @{index_list} # usually: 1, 2, 3. - ${raft_state} = Get_Raft_State_Of_Shard_At_Member shard_name=${shard_name} shard_type=${ds_type} member_index=${index} verify_restconf=${verify_restconf} + ${raft_state} = Get_Raft_State_Of_Shard_At_Member + ... shard_name=${shard_name} + ... shard_type=${ds_type} + ... member_index=${index} + ... verify_restconf=${verify_restconf} ... http_timeout=${http_timeout} - BuiltIn.Run_Keyword_If 'Follower' == '${raft_state}' Collections.Append_To_List ${follower_list} ${index} - ... ELSE IF 'Leader' == '${raft_state}' Collections.Append_To_List ${leader_list} ${index} - ... ELSE IF ${validate} BuiltIn.Fail Unrecognized Raft state: ${raft_state} + IF 'Follower' == '${raft_state}' + Collections.Append_To_List ${follower_list} ${index} + ELSE IF 'Leader' == '${raft_state}' + Collections.Append_To_List ${leader_list} ${index} + ELSE IF ${validate} + BuiltIn.Fail Unrecognized Raft state: ${raft_state} + END END - [Return] ${leader_list} ${follower_list} + RETURN ${leader_list} ${follower_list} Get_Raft_State_Of_Shard_At_Member - [Arguments] ${shard_name} ${shard_type} ${member_index} ${verify_restconf}=False ${http_timeout}=${EMPTY} [Documentation] Send request to Jolokia on indexed member, return extracted Raft status. ... Optionally, check restconf works. - ${raft_state} = Get_Raft_Property_From_Shard_Member RaftState ${shard_name} ${shard_type} ${member_index} verify_restconf=${verify_restconf} + [Arguments] ${shard_name} ${shard_type} ${member_index} ${verify_restconf}=False ${http_timeout}=${EMPTY} + ${raft_state} = Get_Raft_Property_From_Shard_Member + ... RaftState + ... ${shard_name} + ... ${shard_type} + ... ${member_index} + ... verify_restconf=${verify_restconf} ... http_timeout=${http_timeout} - [Return] ${raft_state} + RETURN ${raft_state} Get_Raft_State_Of_Shard_Of_All_Member_Nodes - [Arguments] ${shard_name}=default ${shard_type}=config ${member_index_list}=${EMPTY} [Documentation] Get raft state of shard of all member nodes + [Arguments] ${shard_name}=default ${shard_type}=config ${member_index_list}=${EMPTY} ${index_list} = List_Indices_Or_All given_list=${member_index_list} Collections.Sort_List ${index_list} FOR ${index} IN @{index_list} - ClusterManagement.Get Raft State Of Shard At Member shard_name=${shard_name} shard_type=${shard_type} member_index=${index} + ClusterManagement.Get Raft State Of Shard At Member + ... shard_name=${shard_name} + ... shard_type=${shard_type} + ... member_index=${index} END Get_Raft_Property_From_Shard_Member - [Arguments] ${property} ${shard_name} ${shard_type} ${member_index} ${verify_restconf}=False ${http_timeout}=${EMPTY} [Documentation] Send request to Jolokia on indexed member, return extracted Raft property. ... Optionally, check restconf works. + [Arguments] ${property} ${shard_name} ${shard_type} ${member_index} ${verify_restconf}=False ${http_timeout}=${EMPTY} ${session} = Resolve_Http_Session_For_Member member_index=${member_index} # TODO: Does the used URI tend to generate large data which floods log.html? - BuiltIn.Run_Keyword_If ${verify_restconf} TemplatedRequests.Get_As_Json_Templated session=${session} folder=${RESTCONF_MODULES_DIR} verify=False http_timeout=${http_timeout} + IF ${verify_restconf} + TemplatedRequests.Get_As_Json_Templated + ... session=${session} + ... folder=${RESTCONF_MODULES_DIR} + ... verify=False + ... http_timeout=${http_timeout} + END ${type_class} = Resolve_Shard_Type_Class shard_type=${shard_type} ${cluster_index} = Evaluate ${member_index}+${NODE_ROLE_INDEX_START}-1 - ${uri} = BuiltIn.Set_Variable ${JOLOKIA_READ_URI}:Category=Shards,name=member-${cluster_index}-shard-${shard_name}-${shard_type},type=${type_class} - ${data_text} = TemplatedRequests.Get_As_Json_From_Uri uri=${uri} session=${session} http_timeout=${http_timeout} + ${uri} = BuiltIn.Set_Variable + ... ${JOLOKIA_READ_URI}:Category=Shards,name=member-${cluster_index}-shard-${shard_name}-${shard_type},type=${type_class} + ${data_text} = TemplatedRequests.Get_As_Json_From_Uri + ... uri=${uri} + ... session=${session} + ... http_timeout=${http_timeout} ${data_object} = RequestsLibrary.To_Json ${data_text} ${value} = Collections.Get_From_Dictionary ${data_object} value ${raft_property} = Collections.Get_From_Dictionary ${value} ${property} - [Return] ${raft_property} + RETURN ${raft_property} Verify_Shard_Leader_Elected - [Arguments] ${shard_name} ${shard_type} ${new_elected} ${old_leader} ${member_index_list}=${EMPTY} ${verify_restconf}=True [Documentation] Verify new leader was elected or remained the same. Bool paramter ${new_elected} indicates if ... new leader is elected or should remained the same as ${old_leader} - ${leader} ${followers}= Get_Leader_And_Followers_For_Shard shard_name=${shard_name} shard_type=${shard_type} member_index_list=${member_index_list} verify_restconf=${verify_restconf} - BuiltIn.Run_Keyword_If ${new_elected} BuiltIn.Should_Not_Be_Equal_As_Numbers ${old_leader} ${leader} - BuiltIn.Run_Keyword_If not ${new_elected} BuiltIn.Should_Be_Equal_As_numbers ${old_leader} ${leader} - BuiltIn.Return_From_Keyword ${leader} ${followers} + [Arguments] ${shard_name} ${shard_type} ${new_elected} ${old_leader} ${member_index_list}=${EMPTY} ${verify_restconf}=True + ${leader} ${followers} = Get_Leader_And_Followers_For_Shard + ... shard_name=${shard_name} + ... shard_type=${shard_type} + ... member_index_list=${member_index_list} + ... verify_restconf=${verify_restconf} + IF ${new_elected} + BuiltIn.Should_Not_Be_Equal_As_Numbers ${old_leader} ${leader} + END + IF not ${new_elected} + BuiltIn.Should_Be_Equal_As_numbers ${old_leader} ${leader} + END + RETURN ${leader} ${followers} Verify_Owner_And_Successors_For_Device - [Arguments] ${device_name} ${device_type} ${member_index} ${candidate_list}=${EMPTY} ${after_stop}=False [Documentation] Returns the owner and successors for the SB device ${device_name} of type ${device_type}. Request is sent to member ${member_index}. ... For Boron and beyond, candidates are not removed on node down or isolation, ... so this keyword expects candidates to be all members from Boron on. @@ -195,43 +274,65 @@ Verify_Owner_And_Successors_For_Device ... ${candidate_list} minus owner is returned as ${successor list}. ... Users can still use Get_Owner_And_Successors_For_Device if they are interested in downed candidates, ... or for testing heterogeneous clusters. + [Arguments] ${device_name} ${device_type} ${member_index} ${candidate_list}=${EMPTY} ${after_stop}=False ${index_list} = List_Indices_Or_All given_list=${candidate_list} - ${owner} ${successor_list} = Get_Owner_And_Successors_For_Device device_name=${device_name} device_type=${device_type} member_index=${member_index} - Collections.List_Should_Contain_Value ${index_list} ${owner} Owner ${owner} is not in candidate list ${index_list} + ${owner} ${successor_list} = Get_Owner_And_Successors_For_Device + ... device_name=${device_name} + ... device_type=${device_type} + ... member_index=${member_index} + Collections.List_Should_Contain_Value + ... ${index_list} + ... ${owner} + ... Owner ${owner} is not in candidate list ${index_list} # In Beryllium or after stopping an instance, the removed instance does not show in the candidate list. - ${expected_candidate_list_origin} = BuiltIn.Set_Variable_If ${after_stop} ${index_list} ${ClusterManagement__member_index_list} + ${expected_candidate_list_origin} = BuiltIn.Set_Variable_If + ... ${after_stop} + ... ${index_list} + ... ${ClusterManagement__member_index_list} # We do not want to manipulate either origin list. ${expected_successor_list} = BuiltIn.Create_List @{expected_candidate_list_origin} Collections.Remove_Values_From_List ${expected_successor_list} ${owner} - Collections.Lists_Should_Be_Equal ${expected_successor_list} ${successor_list} Successor list ${successor_list} is not the came as expected ${expected_successor_list} + Collections.Lists_Should_Be_Equal + ... ${expected_successor_list} + ... ${successor_list} + ... Successor list ${successor_list} is not the came as expected ${expected_successor_list} # User expects the returned successor list to be the provided candidate list minus the owner. Collections.Remove_Values_From_List ${index_list} ${owner} - [Return] ${owner} ${index_list} + RETURN ${owner} ${index_list} Get_Owner_And_Successors_For_Device - [Arguments] ${device_name} ${device_type} ${member_index} ${http_timeout}=${EMPTY} [Documentation] Returns the owner and a list of successors for the SB device ${device_name} of type ${device_type}. Request is sent to member ${member_index}. ... Successors are those device candidates not elected as owner. The list of successors = (list of candidates) - (owner). ... The returned successor list is sorted numerically. ... Note that "candidate list" definition currently differs between Beryllium and Boron. ... Use Verify_Owner_And_Successors_For_Device if you want the older semantics (inaccessible nodes not present in the list). + [Arguments] ${device_name} ${device_type} ${member_index} ${http_timeout}=${EMPTY} # TODO: somewhere to introduce ${DEFAULT_RESTCONF_DATASTORE_TIMEOUT}. Value may depend on protocol (ask vs tell) and perhaps stream. - ${owner} ${candidate_list} = Get_Owner_And_Candidates_For_Device device_name=${device_name} device_type=${device_type} member_index=${member_index} http_timeout=${http_timeout} - ${successor_list} = BuiltIn.Create_List @{candidate_list} # Copy operation is not required, but new variable name requires a line anyway. + ${owner} ${candidate_list} = Get_Owner_And_Candidates_For_Device + ... device_name=${device_name} + ... device_type=${device_type} + ... member_index=${member_index} + ... http_timeout=${http_timeout} + # Copy operation is not required, but new variable name requires a line anyway. + ${successor_list} = BuiltIn.Create_List + ... @{candidate_list} Collections.Remove_Values_From_List ${successor_list} ${owner} - [Return] ${owner} ${successor_list} + RETURN ${owner} ${successor_list} Get_Owner_And_Candidates_For_Device_Rpc - [Arguments] ${device_name} ${device_type} ${member_index} ${http_timeout}=${EMPTY} [Documentation] Returns the owner and a list of candidates for the SB device ${device_name} of type ${device_type}. Request is sent to member ${member_index}. ... Candidates are all members that register to own a device, so the list of candiates includes the owner. ... The returned candidate list is sorted numerically. ... Note that "candidate list" definition currently differs between Beryllium and Boron. ... It is recommended to use Get_Owner_And_Successors_For_Device instead of this keyword, see documentation there. + [Arguments] ${device_name} ${device_type} ${member_index} ${http_timeout}=${EMPTY} BuiltIn.Comment TODO: Can this implementation be changed to call Get_Owner_And_Candidates_For_Type_And_Id? ${index} = BuiltIn.Convert_To_Integer ${member_index} ${ip} = Resolve_IP_Address_For_Member member_index=${index} - ${entity_type} = BuiltIn.Set_Variable_If '${device_type}' == 'netconf' netconf-node/${device_name} ${device_type} + ${entity_type} = BuiltIn.Set_Variable_If + ... '${device_type}' == 'netconf' + ... netconf-node/${device_name} + ... ${device_type} ${url} = BuiltIn.Catenate SEPARATOR= http:// ${ip} :8181/ ${RESTCONF_URI} ${entity_result} = ClusterEntities.Get_Entity ${url} ${entity_type} ${device_name} ${entity_candidates} = Collections.Get_From_Dictionary ${entity_result} candidates @@ -246,11 +347,11 @@ Get_Owner_And_Candidates_For_Device_Rpc Collections.Append_To_List ${candidate_list} ${candidate} END Collections.Sort_List ${candidate_list} - [Return] ${owner} ${candidate_list} + RETURN ${owner} ${candidate_list} Get_Owner_And_Candidates_For_Device_Singleton - [Arguments] ${device_name} ${device_type} ${member_index} ${http_timeout}=${EMPTY} [Documentation] Returns the owner and a list of candidates for the SB device ${device_name} of type ${device_type}. Request is sent to member ${member_index}. + [Arguments] ${device_name} ${device_type} ${member_index} ${http_timeout}=${EMPTY} # Normalize device type to the lowercase as in ${SINGLETON_DEVICE_ID_PREFIX} & ${SINGLETON_DEVICE_ID_SUFFIX} ${device_type} = String.Convert To Lower Case ${device_type} # Set device ID prefix @@ -266,49 +367,74 @@ Get_Owner_And_Candidates_For_Device_Singleton Log ${id} # Get election entity type results ${type} = BuiltIn.Set_Variable ${SINGLETON_ELECTION_ENTITY_TYPE} - ${owner_1} ${candidate_list_1} = Get_Owner_And_Candidates_For_Type_And_Id ${type} ${id} ${member_index} http_timeout=${http_timeout} + ${owner_1} ${candidate_list_1} = Get_Owner_And_Candidates_For_Type_And_Id + ... ${type} + ... ${id} + ... ${member_index} + ... http_timeout=${http_timeout} # Get change ownership entity type results ${type} = BuiltIn.Set_Variable ${SINGLETON_CHANGE_OWNERSHIP_ENTITY_TYPE} - ${owner_2} ${candidate_list_2} = Get_Owner_And_Candidates_For_Type_And_Id ${type} ${id} ${member_index} http_timeout=${http_timeout} + ${owner_2} ${candidate_list_2} = Get_Owner_And_Candidates_For_Type_And_Id + ... ${type} + ... ${id} + ... ${member_index} + ... http_timeout=${http_timeout} # Owners must be same, if not, there is still some election or change ownership in progress BuiltIn.Should_Be_Equal_As_Integers ${owner_1} ${owner_2} Owners for device ${device_name} are not same - [Return] ${owner_1} ${candidate_list_1} + RETURN ${owner_1} ${candidate_list_1} Get_Owner_And_Candidates_For_Device - [Arguments] ${device_name} ${device_type} ${member_index} ${http_timeout}=${EMPTY} [Documentation] Returns the owner and a list of candidates for the SB device ${device_name} of type ${device_type}. Request is sent to member ${member_index}. ... If parsing as singleton failed, kw try to parse data in old way (without singleton). ... Candidates are all members that register to own a device, so the list of candiates includes the owner. ... The returned candidate list is sorted numerically. ... Note that "candidate list" definition currently differs between Beryllium and Boron. ... It is recommended to use Get_Owner_And_Successors_For_Device instead of this keyword, see documentation there. + [Arguments] ${device_name} ${device_type} ${member_index} ${http_timeout}=${EMPTY} # Try singleton - ${status} ${results} = BuiltIn.Run_Keyword_And_Ignore_Error Get_Owner_And_Candidates_For_Device_Singleton device_name=${device_name} device_type=${device_type} member_index=${member_index} + ${status} ${results} = BuiltIn.Run_Keyword_And_Ignore_Error + ... Get_Owner_And_Candidates_For_Device_Singleton + ... device_name=${device_name} + ... device_type=${device_type} + ... member_index=${member_index} ... http_timeout=${http_timeout} - BuiltIn.Return_From_Keyword_If "${status}"=="PASS" ${results} + IF "${status}"=="PASS" RETURN ${results} # If singleton failed, try parsing in old way - ${status} ${results} = BuiltIn.Run_Keyword_And_Ignore_Error Get_Owner_And_Candidates_For_Device_Rpc device_name=${device_name} device_type=${device_type} member_index=${member_index} + ${status} ${results} = BuiltIn.Run_Keyword_And_Ignore_Error + ... Get_Owner_And_Candidates_For_Device_Rpc + ... device_name=${device_name} + ... device_type=${device_type} + ... member_index=${member_index} ... http_timeout=${http_timeout} # previous 3 lines (BuilIn.Return.., # If singleton..., ${status}....) could be deleted when old way will not be supported anymore - BuiltIn.Run_Keyword_If '${status}'=='FAIL' BuiltIn.Fail Could not parse owner and candidates for device ${device_name} - [Return] @{results} + IF '${status}'=='FAIL' + BuiltIn.Fail Could not parse owner and candidates for device ${device_name} + END + RETURN @{results} Check_Old_Owner_Stays_Elected_For_Device - [Arguments] ${device_name} ${device_type} ${old_owner} ${node_to_ask} ${http_timeout}=${EMPTY} [Documentation] Verify the owner remain the same as ${old_owner} - ${owner} ${candidates} = Get_Owner_And_Candidates_For_Device ${device_name} ${device_type} ${node_to_ask} http_timeout=${http_timeout} + [Arguments] ${device_name} ${device_type} ${old_owner} ${node_to_ask} ${http_timeout}=${EMPTY} + ${owner} ${candidates} = Get_Owner_And_Candidates_For_Device + ... ${device_name} + ... ${device_type} + ... ${node_to_ask} + ... http_timeout=${http_timeout} BuiltIn.Should_Be_Equal_As_numbers ${old_owner} ${owner} - BuiltIn.Return_From_Keyword ${owner} ${candidates} + RETURN ${owner} ${candidates} Check_New_Owner_Got_Elected_For_Device - [Arguments] ${device_name} ${device_type} ${old_owner} ${node_to_ask} ${http_timeout}=${EMPTY} [Documentation] Verify new owner was elected comparing to ${old_owner} - ${owner} ${candidates} = Get_Owner_And_Candidates_For_Device ${device_name} ${device_type} ${node_to_ask} http_timeout=${http_timeout} + [Arguments] ${device_name} ${device_type} ${old_owner} ${node_to_ask} ${http_timeout}=${EMPTY} + ${owner} ${candidates} = Get_Owner_And_Candidates_For_Device + ... ${device_name} + ... ${device_type} + ... ${node_to_ask} + ... http_timeout=${http_timeout} BuiltIn.Should_Not_Be_Equal_As_Numbers ${old_owner} ${owner} - BuiltIn.Return_From_Keyword ${owner} ${candidates} + RETURN ${owner} ${candidates} Get_Owner_And_Candidates_For_Type_And_Id - [Arguments] ${type} ${id} ${member_index} ${require_candidate_list}=${EMPTY} ${http_timeout}=${EMPTY} [Documentation] Returns the owner and a list of candidates for entity specified by ${type} and ${id} ... Request is sent to member ${member_index}. ... Candidates are all members that register to own a device, so the list of candiates includes the owner. @@ -316,131 +442,191 @@ Get_Owner_And_Candidates_For_Type_And_Id ... If ${require_candidate_list} is not \${EMPTY}, check whether the actual list of candidates matches. ... Note that differs from "given list" semantics used in other keywords, ... namely you cannot use \${EMPTY} to stand for "full list" in this keyword. + [Arguments] ${type} ${id} ${member_index} ${require_candidate_list}=${EMPTY} ${http_timeout}=${EMPTY} BuiltIn.Comment TODO: Find a way to unify and deduplicate code blocks in Get_Owner_And_Candidates_* keywords. - ${owner} ${candidates} = Get_Owner_And_Candidates_For_Device_Rpc ${id} ${type} ${member_index} http_timeout=${http_timeout} - [Return] ${owner} ${candidates} + ${owner} ${candidates} = Get_Owner_And_Candidates_For_Device_Rpc + ... ${id} + ... ${type} + ... ${member_index} + ... http_timeout=${http_timeout} + RETURN ${owner} ${candidates} Extract_Service_Entity_Type - [Arguments] ${data} [Documentation] Remove superfluous device data from Entity Owner printout. - ${clear_data} = String.Replace_String ${data} /odl-general-entity:entity[odl-general-entity:name=' ${EMPTY} + [Arguments] ${data} + ${clear_data} = String.Replace_String + ... ${data} + ... /odl-general-entity:entity[odl-general-entity:name=' + ... ${EMPTY} ${clear_data} = String.Replace_String ${clear_data} -service-group'] ${EMPTY} Log ${clear_data} - [Return] ${clear_data} + RETURN ${clear_data} Extract_OpenFlow_Device_Data - [Arguments] ${data} [Documentation] Remove superfluous OpenFlow device data from Entity Owner printout. + [Arguments] ${data} ${clear_data} = String.Replace_String ${data} org.opendaylight.mdsal.ServiceEntityType openflow - ${clear_data} = String.Replace_String ${clear_data} /odl-general-entity:entity[odl-general-entity:name=' ${EMPTY} - ${clear_data} = String.Replace_String ${clear_data} /general-entity:entity[general-entity:name=' ${EMPTY} + ${clear_data} = String.Replace_String + ... ${clear_data} + ... /odl-general-entity:entity[odl-general-entity:name=' + ... ${EMPTY} + ${clear_data} = String.Replace_String + ... ${clear_data} + ... /general-entity:entity[general-entity:name=' + ... ${EMPTY} ${clear_data} = String.Replace_String ${clear_data} '] ${EMPTY} Log ${clear_data} - [Return] ${clear_data} + RETURN ${clear_data} Extract_Ovsdb_Device_Data - [Arguments] ${data} [Documentation] Remove superfluous OVSDB device data from Entity Owner printout. - ${clear_data} = String.Replace_String ${data} /network-topology:network-topology/network-topology:topology[network-topology:topology-id='ovsdb:1']/network-topology:node[network-topology:node-id=' ${EMPTY} + [Arguments] ${data} + ${clear_data} = String.Replace_String + ... ${data} + ... /network-topology:network-topology/network-topology:topology[network-topology:topology-id='ovsdb:1']/network-topology:node[network-topology:node-id=' + ... ${EMPTY} ${clear_data} = String.Replace_String ${clear_data} '] ${EMPTY} Log ${clear_data} - [Return] ${clear_data} + RETURN ${clear_data} Kill_Single_Member - [Arguments] ${member} ${original_index_list}=${EMPTY} ${confirm}=True [Documentation] Convenience keyword that kills the specified member of the cluster. ... The KW will return a list of available members: \${updated index_list}=\${original_index_list}-\${member} + [Arguments] ${member} ${original_index_list}=${EMPTY} ${confirm}=True ${index_list} = ClusterManagement__Build_List ${member} ${member_ip} = Return_Member_IP ${member} KarafKeywords.Log_Message_To_Controller_Karaf Killing ODL${member} ${member_ip} ${updated_index_list} = Kill_Members_From_List_Or_All ${index_list} ${original_index_list} ${confirm} - [Return] ${updated_index_list} + RETURN ${updated_index_list} Kill_Members_From_List_Or_All - [Arguments] ${member_index_list}=${EMPTY} ${original_index_list}=${EMPTY} ${confirm}=True [Documentation] If the list is empty, kill all ODL instances. Otherwise, kill members based on \${kill_index_list} ... If \${confirm} is True, sleep 1 second and verify killed instances are not there anymore. ... The KW will return a list of available members: \${updated index_list}=\${original_index_list}-\${member_index_list} + [Arguments] ${member_index_list}=${EMPTY} ${original_index_list}=${EMPTY} ${confirm}=True ${kill_index_list} = List_Indices_Or_All given_list=${member_index_list} ${index_list} = List_Indices_Or_All given_list=${original_index_list} Run_Bash_Command_On_List_Or_All command=${NODE_KILL_COMMAND} member_index_list=${member_index_list} ${updated_index_list} = BuiltIn.Create_List @{index_list} Collections.Remove_Values_From_List ${updated_index_list} @{kill_index_list} - BuiltIn.Return_From_Keyword_If not ${confirm} ${updated_index_list} + IF not ${confirm} RETURN ${updated_index_list} # TODO: Convert to WUKS with configurable timeout if it turns out 1 second is not enough. - BuiltIn.Sleep 1s Kill -9 closes open files, which may take longer than ssh overhead, but not long enough to warrant WUKS. + BuiltIn.Sleep + ... 1s + ... Kill -9 closes open files, which may take longer than ssh overhead, but not long enough to warrant WUKS. FOR ${index} IN @{kill_index_list} Verify_Karaf_Is_Not_Running_On_Member member_index=${index} END Run_Bash_Command_On_List_Or_All command=netstat -pnatu | grep 2550 - [Return] ${updated_index_list} + RETURN ${updated_index_list} Stop_Single_Member - [Arguments] ${member} ${original_index_list}=${EMPTY} ${confirm}=True ${msg}=${EMPTY} [Documentation] Convenience keyword that stops the specified member of the cluster. ... The KW will return a list of available members: \${updated index_list}=\${original_index_list}-\${member} + [Arguments] ${member} ${original_index_list}=${EMPTY} ${confirm}=True ${msg}=${EMPTY} ${index_list} = ClusterManagement__Build_List ${member} ${member_ip} = Return_Member_IP ${member} - ${msg} = Builtin.Set Variable If "${msg}" == "${EMPTY}" Stopping ODL${member} ${member_ip} Stopping ODL${member} ${member_ip}, ${msg} + ${msg} = Builtin.Set Variable If + ... "${msg}" == "${EMPTY}" + ... Stopping ODL${member} ${member_ip} + ... Stopping ODL${member} ${member_ip}, ${msg} KarafKeywords.Log_Message_To_Controller_Karaf ${msg} ${updated_index_list} = Stop_Members_From_List_Or_All ${index_list} ${original_index_list} ${confirm} - [Return] ${updated_index_list} + RETURN ${updated_index_list} Stop_Members_From_List_Or_All - [Arguments] ${member_index_list}=${EMPTY} ${original_index_list}=${EMPTY} ${confirm}=True ${timeout}=360s [Documentation] If the list is empty, stops all ODL instances. Otherwise stop members based on \${stop_index_list} ... If \${confirm} is True, verify stopped instances are not there anymore. ... The KW will return a list of available members: \${updated index_list}=\${original_index_list}-\${member_index_list} + [Arguments] ${member_index_list}=${EMPTY} ${original_index_list}=${EMPTY} ${confirm}=True ${timeout}=360s ${stop_index_list} = List_Indices_Or_All given_list=${member_index_list} ${index_list} = List_Indices_Or_All given_list=${original_index_list} Run_Bash_Command_On_List_Or_All command=${NODE_STOP_COMMAND} member_index_list=${member_index_list} ${updated_index_list} = BuiltIn.Create_List @{index_list} Collections.Remove_Values_From_List ${updated_index_list} @{stop_index_list} - BuiltIn.Return_From_Keyword_If not ${confirm} ${updated_index_list} + IF not ${confirm} RETURN ${updated_index_list} FOR ${index} IN @{stop_index_list} - BuiltIn.Wait Until Keyword Succeeds ${timeout} 2s Verify_Karaf_Is_Not_Running_On_Member member_index=${index} + BuiltIn.Wait Until Keyword Succeeds + ... ${timeout} + ... 2s + ... Verify_Karaf_Is_Not_Running_On_Member + ... member_index=${index} END Run_Bash_Command_On_List_Or_All command=netstat -pnatu | grep 2550 - [Return] ${updated_index_list} + RETURN ${updated_index_list} Start_Single_Member + [Documentation] Convenience keyword that starts the specified member of the cluster. [Arguments] ${member} ${wait_for_sync}=True ${timeout}=300s ${msg}=${EMPTY} ${check_system_status}=False ${verify_restconf}=True ... ${service_list}=${EMPTY_LIST} - [Documentation] Convenience keyword that starts the specified member of the cluster. ${index_list} = ClusterManagement__Build_List ${member} ${member_ip} = Return_Member_IP ${member} - ${msg} = Builtin.Set Variable If "${msg}" == "${EMPTY}" Starting ODL${member} ${member_ip} Starting ODL${member} ${member_ip}, ${msg} + ${msg} = Builtin.Set Variable If + ... "${msg}" == "${EMPTY}" + ... Starting ODL${member} ${member_ip} + ... Starting ODL${member} ${member_ip}, ${msg} KarafKeywords.Log_Message_To_Controller_Karaf ${msg} - Start_Members_From_List_Or_All ${index_list} ${wait_for_sync} ${timeout} check_system_status=${check_system_status} verify_restconf=${verify_restconf} service_list=${service_list} + Start_Members_From_List_Or_All + ... ${index_list} + ... ${wait_for_sync} + ... ${timeout} + ... check_system_status=${check_system_status} + ... verify_restconf=${verify_restconf} + ... service_list=${service_list} Start_Members_From_List_Or_All - [Arguments] ${member_index_list}=${EMPTY} ${wait_for_sync}=True ${timeout}=360s ${karaf_home}=${EMPTY} ${export_java_home}=${EMPTY} ${gc_log_dir}=${EMPTY} - ... ${check_system_status}=False ${verify_restconf}=True ${service_list}=${EMPTY_LIST} [Documentation] If the list is empty, start all cluster members. Otherwise, start members based on present indices. ... If ${wait_for_sync}, wait for cluster sync on listed members. ... Optionally karaf_home can be overriden. Optionally specific JAVA_HOME is used for starting. ... Garbage collection is unconditionally logged to files. TODO: Make that reasonable conditional? - ${base_command} = BuiltIn.Set_Variable_If """${karaf_home}""" != "" ${karaf_home}/bin/start ${NODE_START_COMMAND} - ${command} = BuiltIn.Set_Variable_If """${export_java_home}""" != "" export JAVA_HOME="${export_java_home}"; ${base_command} ${base_command} + [Arguments] ${member_index_list}=${EMPTY} ${wait_for_sync}=True ${timeout}=360s ${karaf_home}=${EMPTY} ${export_java_home}=${EMPTY} ${gc_log_dir}=${EMPTY} + ... ${check_system_status}=False ${verify_restconf}=True ${service_list}=${EMPTY_LIST} + ${base_command} = BuiltIn.Set_Variable_If + ... """${karaf_home}""" != "" + ... ${karaf_home}/bin/start + ... ${NODE_START_COMMAND} + ${command} = BuiltIn.Set_Variable_If + ... """${export_java_home}""" != "" + ... export JAVA_HOME="${export_java_home}"; ${base_command} + ... ${base_command} ${epoch} = DateTime.Get_Current_Date time_zone=UTC result_format=epoch exclude_millis=False - ${gc_filepath} = BuiltIn.Set_Variable_If """${karaf_home}""" != "" ${karaf_home}/data/log/gc_${epoch}.log ${GC_LOG_PATH}/gc_${epoch}.log - ${gc_options} = BuiltIn.Set_Variable_If "docker" not in """${node_start_command}""" -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:${gc_filepath} ${EMPTY} + ${gc_filepath} = BuiltIn.Set_Variable_If + ... """${karaf_home}""" != "" + ... ${karaf_home}/data/log/gc_${epoch}.log + ... ${GC_LOG_PATH}/gc_${epoch}.log + ${gc_options} = BuiltIn.Set_Variable_If + ... "docker" not in """${node_start_command}""" + ... -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:${gc_filepath} + ... ${EMPTY} Run_Bash_Command_On_List_Or_All command=${command} ${gc_options} member_index_list=${member_index_list} - BuiltIn.Wait_Until_Keyword_Succeeds ${timeout} 10s Verify_Members_Are_Ready ${member_index_list} ${wait_for_sync} ${verify_restconf} - ... ${check_system_status} ${service_list} + BuiltIn.Wait_Until_Keyword_Succeeds + ... ${timeout} + ... 10s + ... Verify_Members_Are_Ready + ... ${member_index_list} + ... ${wait_for_sync} + ... ${verify_restconf} + ... ${check_system_status} + ... ${service_list} [Teardown] Run_Bash_Command_On_List_Or_All command=netstat -pnatu | grep 2550 Verify_Members_Are_Ready - [Arguments] ${member_index_list} ${verify_cluster_sync} ${verify_restconf} ${verify_system_status} ${service_list} [Documentation] Verifies the specified readiness conditions for the given listed members after startup. ... If ${verify_cluster_sync}, verifies the datastores have synced with the rest of the cluster. ... If ${verify_restconf}, verifies RESTCONF is available. ... If ${verify_system_status}, verifies the system services are OPERATIONAL. - BuiltIn.Run_Keyword_If ${verify_cluster_sync} Check_Cluster_Is_In_Sync ${member_index_list} - BuiltIn.Run_Keyword_If ${verify_restconf} Verify_Restconf_Is_Available ${member_index_list} + [Arguments] ${member_index_list} ${verify_cluster_sync} ${verify_restconf} ${verify_system_status} ${service_list} + IF ${verify_cluster_sync} + Check_Cluster_Is_In_Sync ${member_index_list} + END + IF ${verify_restconf} + Verify_Restconf_Is_Available ${member_index_list} + END # for backward compatibility, some consumers might not be passing @{service_list}, but since we can't set a list to a default # value, we need to check here if it's empty in order to skip the check which would throw an error - BuiltIn.Run_Keyword_If ${verify_system_status} and ("${service_list}" != "[[]]") ClusterManagement.Check Status Of Services Is OPERATIONAL @{service_list} + IF ${verify_system_status} and ("${service_list}" != "[[]]") + ClusterManagement.Check Status Of Services Is OPERATIONAL @{service_list} + END Verify_Restconf_Is_Available [Arguments] ${member_index_list} @@ -451,30 +637,30 @@ Verify_Restconf_Is_Available END Freeze_Single_Member - [Arguments] ${member} [Documentation] Convenience keyword that stops the specified member of the cluster by freezing the jvm. + [Arguments] ${member} ${index_list} = ClusterManagement__Build_List ${member} Freeze_Or_Unfreeze_Members_From_List_Or_All ${NODE_FREEZE_COMMAND} ${index_list} Unfreeze_Single_Member - [Arguments] ${member} ${wait_for_sync}=True ${timeout}=60s [Documentation] Convenience keyword that "continues" the specified member of the cluster by unfreezing the jvm. + [Arguments] ${member} ${wait_for_sync}=True ${timeout}=60s ${index_list} = ClusterManagement__Build_List ${member} Freeze_Or_Unfreeze_Members_From_List_Or_All ${NODE_UNFREEZE_COMMAND} ${index_list} BuiltIn.Wait_Until_Keyword_Succeeds ${timeout} 10s Check_Cluster_Is_In_Sync Freeze_Or_Unfreeze_Members_From_List_Or_All - [Arguments] ${command} ${member_index_list}=${EMPTY} [Documentation] If the list is empty, stops/runs all ODL instances. Otherwise stop/run members based on \${stop_index_list} ... For command parameter only ${NODE_FREEZE_COMMAND} and ${NODE_UNFREEZE_COMMAND} should be used + [Arguments] ${command} ${member_index_list}=${EMPTY} ${freeze_index_list} = List_Indices_Or_All given_list=${member_index_list} Run_Bash_Command_On_List_Or_All command=${command} member_index_list=${member_index_list} Clean_Journals_Data_And_Snapshots_On_List_Or_All - [Arguments] ${member_index_list}=${EMPTY} ${karaf_home}=${KARAF_HOME} [Documentation] Delete journal and snapshots directories on every node listed (or all). ... BEWARE: If only a subset of members is cleaned, this causes RetiredGenerationException in Carbon after the affected node re-start. ... See https://bugs.opendaylight.org/show_bug.cgi?id=8138 + [Arguments] ${member_index_list}=${EMPTY} ${karaf_home}=${KARAF_HOME} ${index_list} = List_Indices_Or_All given_list=${member_index_list} ${command} = Set Variable rm -rf "${karaf_home}/"*journal "${karaf_home}/snapshots" "${karaf_home}/data" FOR ${index} IN @{index_list} # usually: 1, 2, 3. @@ -482,53 +668,63 @@ Clean_Journals_Data_And_Snapshots_On_List_Or_All END Verify_Karaf_Is_Not_Running_On_Member - [Arguments] ${member_index} [Documentation] Fail if non-zero karaf instances are counted on member of given index. + [Arguments] ${member_index} ${count} = Count_Running_Karafs_On_Member member_index=${member_index} BuiltIn.Should_Be_Equal 0 ${count} Found running Karaf count: ${count} Verify_Single_Karaf_Is_Running_On_Member - [Arguments] ${member_index} [Documentation] Fail if number of karaf instances on member of given index is not one. + [Arguments] ${member_index} ${count} = Count_Running_Karafs_On_Member member_index=${member_index} BuiltIn.Should_Be_Equal 1 ${count} Wrong number of Karafs running: ${count} Count_Running_Karafs_On_Member - [Arguments] ${member_index} [Documentation] Remotely execute grep for karaf process, return count as string. + [Arguments] ${member_index} ${command} = BuiltIn.Set_Variable ${NODE_KARAF_COUNT_COMMAND} ${count} = Run_Bash_Command_On_Member command=${command} member_index=${member_index} - [Return] ${count} + RETURN ${count} Isolate_Member_From_List_Or_All - [Arguments] ${isolate_member_index} ${member_index_list}=${EMPTY} ${protocol}=all ${port}=${EMPTY} [Documentation] If the list is empty, isolate member from all ODL instances. Otherwise, isolate member based on present indices. ... The KW will return a list of available members: \${updated index_list}=\${member_index_list}-\${isolate_member_index} + [Arguments] ${isolate_member_index} ${member_index_list}=${EMPTY} ${protocol}=all ${port}=${EMPTY} ${index_list} = List_Indices_Or_All given_list=${member_index_list} - ${source} = Collections.Get_From_Dictionary ${ClusterManagement__index_to_ip_mapping} ${isolate_member_index} + ${source} = Collections.Get_From_Dictionary + ... ${ClusterManagement__index_to_ip_mapping} + ... ${isolate_member_index} ${dport} = BuiltIn.Set_Variable_If '${port}' != '${EMPTY}' --dport ${port} ${EMPTY} FOR ${index} IN @{index_list} ${destination} = Collections.Get_From_Dictionary ${ClusterManagement__index_to_ip_mapping} ${index} - ${command} = BuiltIn.Set_Variable sudo /sbin/iptables -I OUTPUT -p ${protocol} ${dport} --source ${source} --destination ${destination} -j DROP - BuiltIn.Run_Keyword_If "${index}" != "${isolate_member_index}" Run_Bash_Command_On_Member command=${command} member_index=${isolate_member_index} + ${command} = BuiltIn.Set_Variable + ... sudo /sbin/iptables -I OUTPUT -p ${protocol} ${dport} --source ${source} --destination ${destination} -j DROP + IF "${index}" != "${isolate_member_index}" + Run_Bash_Command_On_Member command=${command} member_index=${isolate_member_index} + END END ${command} = BuiltIn.Set_Variable sudo /sbin/iptables -L -n ${output} = Run_Bash_Command_On_Member command=${command} member_index=${isolate_member_index} BuiltIn.Log ${output} ${updated_index_list} = BuiltIn.Create_List @{index_list} Collections.Remove_Values_From_List ${updated_index_list} ${isolate_member_index} - [Return] ${updated_index_list} + RETURN ${updated_index_list} Rejoin_Member_From_List_Or_All - [Arguments] ${rejoin_member_index} ${member_index_list}=${EMPTY} ${protocol}=all ${port}=${EMPTY} ${timeout}=60s [Documentation] If the list is empty, rejoin member from all ODL instances. Otherwise, rejoin member based on present indices. + [Arguments] ${rejoin_member_index} ${member_index_list}=${EMPTY} ${protocol}=all ${port}=${EMPTY} ${timeout}=60s ${index_list} = List_Indices_Or_All given_list=${member_index_list} - ${source} = Collections.Get_From_Dictionary ${ClusterManagement__index_to_ip_mapping} ${rejoin_member_index} + ${source} = Collections.Get_From_Dictionary + ... ${ClusterManagement__index_to_ip_mapping} + ... ${rejoin_member_index} ${dport} = BuiltIn.Set_Variable_If '${port}' != '${EMPTY}' --dport ${port} ${EMPTY} FOR ${index} IN @{index_list} ${destination} = Collections.Get_From_Dictionary ${ClusterManagement__index_to_ip_mapping} ${index} - ${command} = BuiltIn.Set_Variable sudo /sbin/iptables -D OUTPUT -p ${protocol} ${dport} --source ${source} --destination ${destination} -j DROP - BuiltIn.Run_Keyword_If "${index}" != "${rejoin_member_index}" Run_Bash_Command_On_Member command=${command} member_index=${rejoin_member_index} + ${command} = BuiltIn.Set_Variable + ... sudo /sbin/iptables -D OUTPUT -p ${protocol} ${dport} --source ${source} --destination ${destination} -j DROP + IF "${index}" != "${rejoin_member_index}" + Run_Bash_Command_On_Member command=${command} member_index=${rejoin_member_index} + END END ${command} = BuiltIn.Set_Variable sudo /sbin/iptables -L -n ${output} = Run_Bash_Command_On_Member command=${command} member_index=${rejoin_member_index} @@ -536,36 +732,55 @@ Rejoin_Member_From_List_Or_All BuiltIn.Wait_Until_Keyword_Succeeds ${timeout} 10s Check_Cluster_Is_In_Sync Flush_Iptables_From_List_Or_All - [Arguments] ${member_index_list}=${EMPTY} [Documentation] If the list is empty, flush IPTables in all ODL instances. Otherwise, flush member based on present indices. + [Arguments] ${member_index_list}=${EMPTY} ${command} = BuiltIn.Set_Variable sudo iptables -v -F ${output} = Run_Bash_Command_On_List_Or_All command=${command} member_index_list=${member_index_list} Check_Bash_Command_On_List_Or_All - [Arguments] ${command} ${member_index_list}=${EMPTY} ${return_success_only}=False ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=True [Documentation] Cycle through indices (or all), run bash command on each, using temporary SSH session and restoring the previously active one. + [Arguments] ${command} ${member_index_list}=${EMPTY} ${return_success_only}=False ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=True ${index_list} = List_Indices_Or_All given_list=${member_index_list} FOR ${index} IN @{index_list} - Check_Bash_Command_On_Member command=${command} member_index=${index} return_success_only=${return_success_only} log_on_success=${log_on_success} log_on_failure=${log_on_failure} + Check_Bash_Command_On_Member + ... command=${command} + ... member_index=${index} + ... return_success_only=${return_success_only} + ... log_on_success=${log_on_success} + ... log_on_failure=${log_on_failure} ... stderr_must_be_empty=${stderr_must_be_empty} END Check_Bash_Command_On_Member - [Arguments] ${command} ${member_index} ${return_success_only}=False ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=True [Documentation] Open SSH session, call SSHKeywords.Execute_Command_Passes, close session, restore previously active session and return output. - BuiltIn.Run_Keyword_And_Return SSHKeywords.Run_Keyword_Preserve_Connection Check_Unsafely_Bash_Command_On_Member ${command} ${member_index} return_success_only=${return_success_only} log_on_success=${log_on_success} - ... log_on_failure=${log_on_failure} stderr_must_be_empty=${stderr_must_be_empty} + [Arguments] ${command} ${member_index} ${return_success_only}=False ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=True + BuiltIn.Run_Keyword_And_Return + ... SSHKeywords.Run_Keyword_Preserve_Connection + ... Check_Unsafely_Bash_Command_On_Member + ... ${command} + ... ${member_index} + ... return_success_only=${return_success_only} + ... log_on_success=${log_on_success} + ... log_on_failure=${log_on_failure} + ... stderr_must_be_empty=${stderr_must_be_empty} Check_Unsafely_Bash_Command_On_Member - [Arguments] ${command} ${member_index} ${return_success_only}=False ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=True [Documentation] Obtain Ip address, open session, call SSHKeywords.Execute_Command_Passes, close session and return output. This affects which SSH session is active. + [Arguments] ${command} ${member_index} ${return_success_only}=False ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=True ${member_ip} = Resolve_Ip_Address_For_Member ${member_index} - BuiltIn.Run_Keyword_And_Return SSHKeywords.Run_Unsafely_Keyword_Over_Temporary_Odl_Session ${member_ip} Execute_Command_Passes ${command} return_success_only=${return_success_only} log_on_success=${log_on_success} - ... log_on_failure=${log_on_failure} stderr_must_be_empty=${stderr_must_be_empty} + BuiltIn.Run_Keyword_And_Return + ... SSHKeywords.Run_Unsafely_Keyword_Over_Temporary_Odl_Session + ... ${member_ip} + ... Execute_Command_Passes + ... ${command} + ... return_success_only=${return_success_only} + ... log_on_success=${log_on_success} + ... log_on_failure=${log_on_failure} + ... stderr_must_be_empty=${stderr_must_be_empty} Run_Bash_Command_On_List_Or_All - [Arguments] ${command} ${member_index_list}=${EMPTY} [Documentation] Cycle through indices (or all), run command on each. + [Arguments] ${command} ${member_index_list}=${EMPTY} # TODO: Migrate callers to Check_Bash_Command_* ${index_list} = List_Indices_Or_All given_list=${member_index_list} FOR ${index} IN @{index_list} @@ -573,140 +788,204 @@ Run_Bash_Command_On_List_Or_All END Run_Bash_Command_On_Member - [Arguments] ${command} ${member_index} [Documentation] Obtain IP, call Utils and return output. This keeps previous ssh session active. + [Arguments] ${command} ${member_index} # TODO: Migrate callers to Check_Bash_Command_* - ${member_ip} = Collections.Get_From_Dictionary dictionary=${ClusterManagement__index_to_ip_mapping} key=${member_index} - ${output} = SSHKeywords.Run_Keyword_Preserve_Connection Utils.Run_Command_On_Controller ${member_ip} ${command} + ${member_ip} = Collections.Get_From_Dictionary + ... dictionary=${ClusterManagement__index_to_ip_mapping} + ... key=${member_index} + ${output} = SSHKeywords.Run_Keyword_Preserve_Connection + ... Utils.Run_Command_On_Controller + ... ${member_ip} + ... ${command} Log ${output} - [Return] ${output} + RETURN ${output} Run_Karaf_Command_On_List_Or_All - [Arguments] ${command} ${member_index_list}=${EMPTY} ${timeout}=10s [Documentation] Cycle through indices (or all), run karaf command on each. + [Arguments] ${command} ${member_index_list}=${EMPTY} ${timeout}=10s ${index_list} = List_Indices_Or_All given_list=${member_index_list} FOR ${index} IN @{index_list} - ${member_ip} = Collections.Get_From_Dictionary dictionary=${ClusterManagement__index_to_ip_mapping} key=${index} + ${member_ip} = Collections.Get_From_Dictionary + ... dictionary=${ClusterManagement__index_to_ip_mapping} + ... key=${index} KarafKeywords.Safe_Issue_Command_On_Karaf_Console ${command} ${member_ip} timeout=${timeout} END Run_Karaf_Command_On_Member - [Arguments] ${command} ${member_index} ${timeout}=10s [Documentation] Obtain IP address, call KarafKeywords and return output. This does not preserve active ssh session. ... This keyword is not used by Run_Karaf_Command_On_List_Or_All, but returned output may be useful. - ${member_ip} = Collections.Get_From_Dictionary dictionary=${ClusterManagement__index_to_ip_mapping} key=${member_index} - ${output} = KarafKeywords.Safe_Issue_Command_On_Karaf_Console ${command} controller=${member_ip} timeout=${timeout} - [Return] ${output} + [Arguments] ${command} ${member_index} ${timeout}=10s + ${member_ip} = Collections.Get_From_Dictionary + ... dictionary=${ClusterManagement__index_to_ip_mapping} + ... key=${member_index} + ${output} = KarafKeywords.Safe_Issue_Command_On_Karaf_Console + ... ${command} + ... controller=${member_ip} + ... timeout=${timeout} + RETURN ${output} Install_Feature_On_List_Or_All - [Arguments] ${feature_name} ${member_index_list}=${EMPTY} ${timeout}=60s [Documentation] Attempt installation on each member from list (or all). Then look for failures. + [Arguments] ${feature_name} ${member_index_list}=${EMPTY} ${timeout}=60s ${index_list} = List_Indices_Or_All given_list=${member_index_list} ${status_list} = BuiltIn.Create_List FOR ${index} IN @{index_list} - ${status} ${text} = BuiltIn.Run_Keyword_And_Ignore_Error Install_Feature_On_Member feature_name=${feature_name} member_index=${index} + ${status} ${text} = BuiltIn.Run_Keyword_And_Ignore_Error + ... Install_Feature_On_Member + ... feature_name=${feature_name} + ... member_index=${index} ... timeout=${timeout} BuiltIn.Log ${text} Collections.Append_To_List ${status_list} ${status} END FOR ${status} IN @{status_list} - BuiltIn.Run_Keyword_If "${status}" != "PASS" BuiltIn.Fail ${feature_name} installation failed, see log. + IF "${status}" != "PASS" + BuiltIn.Fail ${feature_name} installation failed, see log. + END END Install_Feature_On_Member - [Arguments] ${feature_name} ${member_index} ${timeout}=60s [Documentation] Run feature:install karaf command, fail if installation was not successful. Return output. - ${status} ${output} = BuiltIn.Run_Keyword_And_Ignore_Error Run_Karaf_Command_On_Member command=feature:install ${feature_name} member_index=${member_index} timeout=${timeout} - BuiltIn.Run_Keyword_If "${status}" != "PASS" BuiltIn.Fail Failed to install ${feature_name}: ${output} + [Arguments] ${feature_name} ${member_index} ${timeout}=60s + ${status} ${output} = BuiltIn.Run_Keyword_And_Ignore_Error + ... Run_Karaf_Command_On_Member + ... command=feature:install ${feature_name} + ... member_index=${member_index} + ... timeout=${timeout} + IF "${status}" != "PASS" + BuiltIn.Fail Failed to install ${feature_name}: ${output} + END BuiltIn.Should_Not_Contain ${output} Can't install Failed to install ${feature_name}: ${output} - [Return] ${output} + RETURN ${output} With_Ssh_To_List_Or_All_Run_Keyword - [Arguments] ${member_index_list} ${keyword_name} @{args} &{kwargs} [Documentation] For each index in given list (or all): activate SSH connection, run given Keyword, close active connection. Return None. ... Beware that in order to avoid "got positional argument after named arguments", first two arguments in the call should not be named. + [Arguments] ${member_index_list} ${keyword_name} @{args} &{kwargs} BuiltIn.Comment This keyword is experimental and there is high risk of being replaced by another approach. # TODO: For_Index_From_List_Or_All_Run_Keyword applied to With_Ssh_To_Member_Run_Keyword? # TODO: Imagine another keyword, using ScalarClosures and adding member index as first argument for each call. Worth it? ${index_list} = List_Indices_Or_All given_list=${member_index_list} FOR ${member_index} IN @{index_list} ${member_ip} = Resolve_IP_Address_For_Member ${member_index} - SSHKeywords.Run_Unsafely_Keyword_Over_Temporary_Odl_Session ${member_ip} ${keyword_name} @{args} &{kwargs} + SSHKeywords.Run_Unsafely_Keyword_Over_Temporary_Odl_Session + ... ${member_ip} + ... ${keyword_name} + ... @{args} + ... &{kwargs} END Safe_With_Ssh_To_List_Or_All_Run_Keyword - [Arguments] ${member_index_list} ${keyword_name} @{args} &{kwargs} [Documentation] Remember active ssh connection index, call With_Ssh_To_List_Or_All_Run_Keyword, return None. Restore the conection index on teardown. - SSHKeywords.Run_Keyword_Preserve_Connection With_Ssh_To_List_Or_All_Run_Keyword ${member_index_list} ${keyword_name} @{args} &{kwargs} + [Arguments] ${member_index_list} ${keyword_name} @{args} &{kwargs} + SSHKeywords.Run_Keyword_Preserve_Connection + ... With_Ssh_To_List_Or_All_Run_Keyword + ... ${member_index_list} + ... ${keyword_name} + ... @{args} + ... &{kwargs} Clean_Directories_On_List_Or_All - [Arguments] ${member_index_list}=${EMPTY} ${directory_list}=${EMPTY} ${karaf_home}=${KARAF_HOME} ${tmp_dir}=${EMPTY} [Documentation] Clear @{directory_list} or @{ODL_DEFAULT_DATA_PATHS} for members in given list or all. Return None. ... If \${tmp_dir} is nonempty, use that location to preserve data/log/. ... This is intended to return Karaf (offline) to the state it was upon the first boot. - ${path_list} = Builtin.Set Variable If "${directory_list}" == "${EMPTY}" ${ODL_DEFAULT_DATA_PATHS} ${directory_list} - BuiltIn.Run_Keyword_If """${tmp_dir}""" != "" Check_Bash_Command_On_List_Or_All mkdir -p '${tmp_dir}' && rm -vrf '${tmp_dir}/log' && mv -vf '${karaf_home}/data/log' '${tmp_dir}/' ${member_index_list} - Safe_With_Ssh_To_List_Or_All_Run_Keyword ${member_index_list} ClusterManagement__Clean_Directories ${path_list} ${karaf_home} - BuiltIn.Run_Keyword_If """${tmp_dir}""" != "" Check_Bash_Command_On_List_Or_All mkdir -p '${karaf_home}/data' && rm -vrf '${karaf_home}/log' && mv -vf '${tmp_dir}/log' '${karaf_home}/data/' ${member_index_list} + [Arguments] ${member_index_list}=${EMPTY} ${directory_list}=${EMPTY} ${karaf_home}=${KARAF_HOME} ${tmp_dir}=${EMPTY} + ${path_list} = Builtin.Set Variable If + ... "${directory_list}" == "${EMPTY}" + ... ${ODL_DEFAULT_DATA_PATHS} + ... ${directory_list} + IF """${tmp_dir}""" != "" + Check_Bash_Command_On_List_Or_All + ... mkdir -p '${tmp_dir}' && rm -vrf '${tmp_dir}/log' && mv -vf '${karaf_home}/data/log' '${tmp_dir}/' + ... ${member_index_list} + END + Safe_With_Ssh_To_List_Or_All_Run_Keyword + ... ${member_index_list} + ... ClusterManagement__Clean_Directories + ... ${path_list} + ... ${karaf_home} + IF """${tmp_dir}""" != "" + Check_Bash_Command_On_List_Or_All + ... mkdir -p '${karaf_home}/data' && rm -vrf '${karaf_home}/log' && mv -vf '${tmp_dir}/log' '${karaf_home}/data/' + ... ${member_index_list} + END Store_Karaf_Log_On_List_Or_All - [Arguments] ${member_index_list}=${EMPTY} ${dst_dir}=/tmp ${karaf_home}=${KARAF_HOME} [Documentation] Saves karaf.log to the ${dst_dir} for members in given list or all. Return None. - Safe_With_Ssh_To_List_Or_All_Run_Keyword ${member_index_list} SSHKeywords.Execute_Command_Should_Pass cp ${karaf_home}/data/log/karaf.log ${dst_dir} + [Arguments] ${member_index_list}=${EMPTY} ${dst_dir}=/tmp ${karaf_home}=${KARAF_HOME} + Safe_With_Ssh_To_List_Or_All_Run_Keyword + ... ${member_index_list} + ... SSHKeywords.Execute_Command_Should_Pass + ... cp ${karaf_home}/data/log/karaf.log ${dst_dir} Restore_Karaf_Log_On_List_Or_All - [Arguments] ${member_index_list}=${EMPTY} ${src_dir}=/tmp ${karaf_home}=${KARAF_HOME} [Documentation] Places stored karaf.log to the ${karaf_home}/data/log for members in given list or all. Return None. - Safe_With_Ssh_To_List_Or_All_Run_Keyword ${member_index_list} SSHKeywords.Execute_Command_Should_Pass cp ${src_dir}/karaf.log ${karaf_home}/data/log/ + [Arguments] ${member_index_list}=${EMPTY} ${src_dir}=/tmp ${karaf_home}=${KARAF_HOME} + Safe_With_Ssh_To_List_Or_All_Run_Keyword + ... ${member_index_list} + ... SSHKeywords.Execute_Command_Should_Pass + ... cp ${src_dir}/karaf.log ${karaf_home}/data/log/ ClusterManagement__Clean_Directories - [Arguments] ${relative_path_list} ${karaf_home} [Documentation] For each relative path, remove files with respect to ${karaf_home}. Return None. + [Arguments] ${relative_path_list} ${karaf_home} FOR ${relative_path} IN @{relative_path_list} SSHLibrary.Execute_Command rm -rf ${karaf_home}${/}${relative_path} END Put_As_Json_And_Check_Member_List_Or_All - [Arguments] ${uri} ${data} ${member_index} ${member_index_list}=${EMPTY} [Documentation] Send a PUT with the supplied uri ${uri} and body ${data} to member ${member_index}. ... Then check data is replicated in all or some members defined in ${member_index_list}. + [Arguments] ${uri} ${data} ${member_index} ${member_index_list}=${EMPTY} ${response_text} = Put_As_Json_To_Member uri=${uri} data=${data} member_index=${member_index} - Wait Until Keyword Succeeds 5s 1s Check_Json_Member_List_Or_All uri=${uri}?content=config expected_data=${data} member_index_list=${member_index_list} - [Return] ${response_text} + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... Check_Json_Member_List_Or_All + ... uri=${uri}?content=config + ... expected_data=${data} + ... member_index_list=${member_index_list} + RETURN ${response_text} Put_As_Json_To_Member - [Arguments] ${uri} ${data} ${member_index} [Documentation] Send a PUT with the supplied uri and data to member ${member_index}. + [Arguments] ${uri} ${data} ${member_index} ${session} = Resolve_Http_Session_For_Member member_index=${member_index} ${response_text} = TemplatedRequests.Put_As_Json_To_Uri uri=${uri} data=${data} session=${session} - [Return] ${response_text} + RETURN ${response_text} Post_As_Json_To_Member - [Arguments] ${uri} ${data} ${member_index} [Documentation] Send a POST with the supplied uri and data to member ${member_index}. + [Arguments] ${uri} ${data} ${member_index} ${session} = Resolve_Http_Session_For_Member member_index=${member_index} ${response_text} = TemplatedRequests.Post_As_Json_To_Uri uri=${uri} data=${data} session=${session} - [Return] ${response_text} + RETURN ${response_text} Delete_And_Check_Member_List_Or_All - [Arguments] ${uri} ${member_index} ${member_index_list}=${EMPTY} [Documentation] Send a DELETE with the supplied uri to the member ${member_index}. ... Then check the data is removed from all members in ${member_index_list}. + [Arguments] ${uri} ${member_index} ${member_index_list}=${EMPTY} ${response_text} = Delete_From_Member ${uri} ${member_index} - BuiltIn.Wait_Until_Keyword_Succeeds 5s 1s Check_No_Content_Member_List_Or_All uri=${uri} member_index_list=${member_index_list} - [Return] ${response_text} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 5s + ... 1s + ... Check_No_Content_Member_List_Or_All + ... uri=${uri} + ... member_index_list=${member_index_list} + RETURN ${response_text} Delete_From_Member - [Arguments] ${uri} ${member_index} [Documentation] Send a DELETE with the supplied uri to member ${member_index}. + [Arguments] ${uri} ${member_index} ${session} = Resolve_Http_Session_For_Member member_index=${member_index} ${response_text} = TemplatedRequests.Delete_From_Uri uri=${uri} session=${session} - [Return] ${response_text} + RETURN ${response_text} Check_Json_Member_List_Or_All - [Arguments] ${uri} ${expected_data} ${member_index_list}=${EMPTY} [Documentation] Send a GET with the supplied uri to all or some members defined in ${member_index_list}. ... Then check received data is = ${expected data}. + [Arguments] ${uri} ${expected_data} ${member_index_list}=${EMPTY} ${index_list} = List_Indices_Or_All given_list=${member_index_list} FOR ${index} IN @{index_list} ${data} = Get_From_Member uri=${uri} member_index=${index} @@ -714,9 +993,9 @@ Check_Json_Member_List_Or_All END Check_Item_Occurrence_Member_List_Or_All - [Arguments] ${uri} ${dictionary} ${member_index_list}=${EMPTY} [Documentation] Send a GET with the supplied uri to all or some members defined in ${member_index_list}. ... Then check received for occurrences of items expressed in a dictionary ${dictionary}. + [Arguments] ${uri} ${dictionary} ${member_index_list}=${EMPTY} ${index_list} = List_Indices_Or_All given_list=${member_index_list} FOR ${index} IN @{index_list} ${data} = Get_From_Member uri=${uri} member_index=${index} @@ -724,9 +1003,9 @@ Check_Item_Occurrence_Member_List_Or_All END Check_No_Content_Member_List_Or_All - [Arguments] ${uri} ${member_index_list}=${EMPTY} [Documentation] Send a GET with the supplied uri to all or some members defined in ${member_index_list}. ... Then check there is no content. + [Arguments] ${uri} ${member_index_list}=${EMPTY} ${index_list} = List_Indices_Or_All given_list=${member_index_list} FOR ${index} IN @{index_list} ${session} = Resolve_Http_Session_For_Member member_index=${index} @@ -734,85 +1013,100 @@ Check_No_Content_Member_List_Or_All END Get_From_Member - [Arguments] ${uri} ${member_index} ${access}=${ACCEPT_EMPTY} [Documentation] Send a GET with the supplied uri to member ${member_index}. + [Arguments] ${uri} ${member_index} ${access}=${ACCEPT_EMPTY} ${session} = Resolve_Http_Session_For_Member member_index=${member_index} ${response_text} = TemplatedRequests.Get_From_Uri uri=${uri} accept=${access} session=${session} - [Return] ${response_text} + RETURN ${response_text} Resolve_IP_Address_For_Member - [Arguments] ${member_index} [Documentation] Return node IP address of given index. - ${ip_address} = Collections.Get From Dictionary dictionary=${ClusterManagement__index_to_ip_mapping} key=${member_index} - [Return] ${ip_address} + [Arguments] ${member_index} + ${ip_address} = Collections.Get From Dictionary + ... dictionary=${ClusterManagement__index_to_ip_mapping} + ... key=${member_index} + RETURN ${ip_address} Resolve_IP_Address_For_Members - [Arguments] ${member_index_list} [Documentation] Return a list of IP address of given indexes. + [Arguments] ${member_index_list} ${member_ip_list} = BuiltIn.Create_List FOR ${index} IN @{member_index_list} - ${ip_address} = Collections.Get From Dictionary dictionary=${ClusterManagement__index_to_ip_mapping} key=${index} + ${ip_address} = Collections.Get From Dictionary + ... dictionary=${ClusterManagement__index_to_ip_mapping} + ... key=${index} Collections.Append_To_List ${member_ip_list} ${ip_address} END - [Return] ${member_ip_list} + RETURN ${member_ip_list} Resolve_Http_Session_For_Member - [Arguments] ${member_index} [Documentation] Return RequestsLibrary session alias pointing to node of given index. + [Arguments] ${member_index} ${session} = BuiltIn.Set_Variable ClusterManagement__session_${member_index} - [Return] ${session} + RETURN ${session} Resolve_Shard_Type_Class - [Arguments] ${shard_type} [Documentation] Simple lookup for class name corresponding to desired type. - BuiltIn.Run_Keyword_If '${shard_type}' == 'config' BuiltIn.Return_From_Keyword DistributedConfigDatastore - ... ELSE IF '${shard_type}' == 'operational' BuiltIn.Return_From_Keyword DistributedOperationalDatastore + [Arguments] ${shard_type} + IF '${shard_type}' == 'config' + RETURN DistributedConfigDatastore + ELSE IF '${shard_type}' == 'operational' + RETURN DistributedOperationalDatastore + END BuiltIn.Fail Unrecognized shard type: ${shard_type} ClusterManagement__Build_List [Arguments] ${member} ${member_int} = BuiltIn.Convert_To_Integer ${member} ${index_list} = BuiltIn.Create_List ${member_int} - [Return] ${index_list} + RETURN ${index_list} ClusterManagement__Parse_Sync_Status - [Arguments] ${shard_manager_text} [Documentation] Return sync status parsed out of given text. Called twice by Get_Sync_Status_Of_Member. + [Arguments] ${shard_manager_text} BuiltIn.Log ${shard_manager_text} ${manager_object} = RequestsLibrary.To_Json ${shard_manager_text} ${value_object} = Collections.Get_From_Dictionary dictionary=${manager_object} key=value ${sync_status} = Collections.Get_From_Dictionary dictionary=${value_object} key=SyncStatus - [Return] ${sync_status} + RETURN ${sync_status} List_All_Indices [Documentation] Create a new list of all indices. BuiltIn.Run_Keyword_And_Return List_Indices_Or_All List_Indices_Or_All - [Arguments] ${given_list}=${EMPTY} [Documentation] Utility to allow \${EMPTY} as default argument value, as the internal list is computed at runtime. ... This keyword always returns a (shallow) copy of given or default list, ... so operations with the returned list should not affect other lists. ... Also note that this keyword does not consider empty list to be \${EMPTY}. - ${return_list_reference} = BuiltIn.Set_Variable_If """${given_list}""" != "" ${given_list} ${ClusterManagement__member_index_list} + [Arguments] ${given_list}=${EMPTY} + ${return_list_reference} = BuiltIn.Set_Variable_If + ... """${given_list}""" != "" + ... ${given_list} + ... ${ClusterManagement__member_index_list} ${return_list_copy} = BuiltIn.Create_List @{return_list_reference} - [Return] ${return_list_copy} + RETURN ${return_list_copy} List_Indices_Minus_Member - [Arguments] ${member_index} ${member_index_list}=${EMPTY} [Documentation] Create a new list which contains indices from ${member_index_list} (or all) without ${member_index}. + [Arguments] ${member_index} ${member_index_list}=${EMPTY} ${index_list} = List_Indices_Or_All ${member_index_list} Collections.Remove Values From List ${index_list} ${member_index} - [Return] ${index_list} + RETURN ${index_list} ClusterManagement__Compute_Derived_Variables - [Arguments] ${int_of_members} ${http_timeout}=${DEFAULT_TIMEOUT_HTTP} ${http_retries}=0 [Documentation] Construct index list, session list and IP mapping, publish them as suite variables. + [Arguments] ${int_of_members} ${http_timeout}=${DEFAULT_TIMEOUT_HTTP} ${http_retries}=0 @{member_index_list} = BuiltIn.Create_List @{session_list} = BuiltIn.Create_List &{index_to_ip_mapping} = BuiltIn.Create_Dictionary FOR ${index} IN RANGE 1 ${int_of_members+1} - ClusterManagement__Include_Member_Index ${index} ${member_index_list} ${session_list} ${index_to_ip_mapping} http_timeout=${http_timeout} + ClusterManagement__Include_Member_Index + ... ${index} + ... ${member_index_list} + ... ${session_list} + ... ${index_to_ip_mapping} + ... http_timeout=${http_timeout} ... http_retries=${http_retries} END BuiltIn.Set_Suite_Variable \${ClusterManagement__member_index_list} ${member_index_list} @@ -820,50 +1114,66 @@ ClusterManagement__Compute_Derived_Variables BuiltIn.Set_Suite_Variable \${ClusterManagement__session_list} ${session_list} ClusterManagement__Include_Member_Index - [Arguments] ${index} ${member_index_list} ${session_list} ${index_to_ip_mapping} ${http_timeout}=${DEFAULT_TIMEOUT_HTTP} ${http_retries}=0 [Documentation] Add a corresponding item based on index into the last three arguments. ... Create the Http session whose alias is added to list. + [Arguments] ${index} ${member_index_list} ${session_list} ${index_to_ip_mapping} ${http_timeout}=${DEFAULT_TIMEOUT_HTTP} ${http_retries}=0 Collections.Append_To_List ${member_index_list} ${index} ${member_ip} = BuiltIn.Set_Variable ${ODL_SYSTEM_${index}_IP} # ${index} is int (not string) so "key=value" syntax does not work in the following line. Collections.Set_To_Dictionary ${index_to_ip_mapping} ${index} ${member_ip} # Http session, with ${AUTH}, without headers. ${session_alias} = Resolve_Http_Session_For_Member member_index=${index} - RequestsLibrary.Create_Session ${session_alias} http://${member_ip}:${RESTCONFPORT} auth=${AUTH} timeout=${http_timeout} max_retries=${http_retries} + RequestsLibrary.Create_Session + ... ${session_alias} + ... http://${member_ip}:${RESTCONFPORT} + ... auth=${AUTH} + ... timeout=${http_timeout} + ... max_retries=${http_retries} Collections.Append_To_List ${session_list} ${session_alias} Sync_Status_Should_Be_False - [Arguments] ${controller_index} [Documentation] Verify that cluster node is not in sync with others - ${status} Get_Sync_Status_Of_Member ${controller_index} + [Arguments] ${controller_index} + ${status} = Get_Sync_Status_Of_Member ${controller_index} BuiltIn.Should_Not_Be_True ${status} Sync_Status_Should_Be_True - [Arguments] ${controller_index} [Documentation] Verify that cluster node is in sync with others - ${status} Get_Sync_Status_Of_Member ${controller_index} + [Arguments] ${controller_index} + ${status} = Get_Sync_Status_Of_Member ${controller_index} BuiltIn.Should_Be_True ${status} Return_Member_IP - [Arguments] ${member_index} [Documentation] Return the IP address of the member given the member_index. + [Arguments] ${member_index} ${member_int} = BuiltIn.Convert_To_Integer ${member_index} - ${member_ip} = Collections.Get_From_Dictionary dictionary=${ClusterManagement__index_to_ip_mapping} key=${member_int} - [Return] ${member_ip} + ${member_ip} = Collections.Get_From_Dictionary + ... dictionary=${ClusterManagement__index_to_ip_mapping} + ... key=${member_int} + RETURN ${member_ip} Check Service Status - [Arguments] ${odl_ip} ${system_ready_state} ${service_state} @{service_list} [Documentation] Issues the karaf shell command showSvcStatus to verify the ready and service states are the same as the arguments passed - ${service_status_output} = BuiltIn.Run Keyword If ${NUM_ODL_SYSTEM} > 1 KarafKeywords.Issue_Command_On_Karaf_Console showSvcStatus -n ${odl_ip} ${odl_ip} ${KARAF_SHELL_PORT} - ... ELSE KarafKeywords.Issue_Command_On_Karaf_Console showSvcStatus ${odl_ip} ${KARAF_SHELL_PORT} + [Arguments] ${odl_ip} ${system_ready_state} ${service_state} @{service_list} + IF ${NUM_ODL_SYSTEM} > 1 + ${service_status_output} = KarafKeywords.Issue_Command_On_Karaf_Console + ... showSvcStatus -n ${odl_ip} + ... ${odl_ip} + ... ${KARAF_SHELL_PORT} + ELSE + ${service_status_output} = KarafKeywords.Issue_Command_On_Karaf_Console + ... showSvcStatus + ... ${odl_ip} + ... ${KARAF_SHELL_PORT} + END BuiltIn.Should Contain ${service_status_output} ${system_ready_state} FOR ${service} IN @{service_list} BuiltIn.Should Match Regexp ${service_status_output} ${service} +: ${service_state} END Check Status Of Services Is OPERATIONAL - [Arguments] @{service_list} [Documentation] This keyword will verify whether all the services are operational in all the ODL nodes + [Arguments] @{service_list} FOR ${i} IN RANGE ${NUM_ODL_SYSTEM} ClusterManagement.Check Service Status ${ODL_SYSTEM_${i+1}_IP} ACTIVE OPERATIONAL @{service_list} END diff --git a/csit/libraries/ClusterOpenFlow.robot b/csit/libraries/ClusterOpenFlow.robot index 1560495d07..0bc1a4a27e 100644 --- a/csit/libraries/ClusterOpenFlow.robot +++ b/csit/libraries/ClusterOpenFlow.robot @@ -1,165 +1,323 @@ *** Settings *** -Documentation Cluster OpenFlow library. So far this library is only to be used by OpenFlow cluster test as it is very specific for this test. -Library Collections -Library RequestsLibrary -Library ${CURDIR}/ScaleClient.py -Resource ClusterManagement.robot -Resource CompareStream.robot -Resource MininetKeywords.robot -Resource Utils.robot -Resource ../variables/openflowplugin/Variables.robot -Variables ../variables/Variables.py +Documentation Cluster OpenFlow library. So far this library is only to be used by OpenFlow cluster test as it is very specific for this test. + +Library Collections +Library RequestsLibrary +Library ${CURDIR}/ScaleClient.py +Resource ClusterManagement.robot +Resource CompareStream.robot +Resource MininetKeywords.robot +Resource Utils.robot +Resource ../variables/openflowplugin/Variables.robot +Variables ../variables/Variables.py + *** Variables *** -@{SHARD_OPER_LIST} inventory topology default entity-ownership -@{SHARD_CONF_LIST} inventory topology default -${config_table_0} ${RFC8040_NODES_API}/node=openflow%3A1/flow-node-inventory:table=0 -${operational_table_0} ${RFC8040_NODES_API}/node=openflow%3A1/flow-node-inventory:table=0?${RFC8040_OPERATIONAL_CONTENT} -${operational_port_1} ${RFC8040_NODES_API}/node=openflow%3A1/node-connector=openflow%3A1%3A1?${RFC8040_OPERATIONAL_CONTENT} +@{SHARD_OPER_LIST} inventory topology default entity-ownership +@{SHARD_CONF_LIST} inventory topology default +${config_table_0} ${RFC8040_NODES_API}/node=openflow%3A1/flow-node-inventory:table=0 +${operational_table_0} +... ${RFC8040_NODES_API}/node=openflow%3A1/flow-node-inventory:table=0?${RFC8040_OPERATIONAL_CONTENT} +${operational_port_1} +... ${RFC8040_NODES_API}/node=openflow%3A1/node-connector=openflow%3A1%3A1?${RFC8040_OPERATIONAL_CONTENT} + *** Keywords *** Get InventoryConfig Shard Status - [Arguments] ${controller_index_list}=${EMPTY} [Documentation] Check Status for Inventory Config shard in OpenFlow application. - ${inv_conf_leader} ${inv_conf_followers_list} Wait Until Keyword Succeeds 10s 1s ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=inventory - ... shard_type=config member_index_list=${controller_index_list} + [Arguments] ${controller_index_list}=${EMPTY} + ${inv_conf_leader} ${inv_conf_followers_list}= Wait Until Keyword Succeeds + ... 10s + ... 1s + ... ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=inventory + ... shard_type=config + ... member_index_list=${controller_index_list} Log config inventory Leader is ${inv_conf_leader} and followers are ${inv_conf_followers_list} - [Return] ${inv_conf_leader} ${inv_conf_followers_list} + RETURN ${inv_conf_leader} ${inv_conf_followers_list} Check OpenFlow Shards Status - [Arguments] ${controller_index_list}=${EMPTY} [Documentation] Check Status for all shards in OpenFlow application. - CompareStream.Run_Keyword_If_At_Least_Phosphorus Collections.Remove Values From List ${SHARD_OPER_LIST} entity-ownership + [Arguments] ${controller_index_list}=${EMPTY} + CompareStream.Run_Keyword_If_At_Least_Phosphorus + ... Collections.Remove Values From List + ... ${SHARD_OPER_LIST} + ... entity-ownership Log ${SHARD_OPER_LIST} - ClusterManagement.Verify_Leader_Exists_For_Each_Shard shard_name_list=${SHARD_OPER_LIST} shard_type=operational member_index_list=${controller_index_list} - ClusterManagement.Verify_Leader_Exists_For_Each_Shard shard_name_list=${SHARD_CONF_LIST} shard_type=config member_index_list=${controller_index_list} + ClusterManagement.Verify_Leader_Exists_For_Each_Shard + ... shard_name_list=${SHARD_OPER_LIST} + ... shard_type=operational + ... member_index_list=${controller_index_list} + ClusterManagement.Verify_Leader_Exists_For_Each_Shard + ... shard_name_list=${SHARD_CONF_LIST} + ... shard_type=config + ... member_index_list=${controller_index_list} Check OpenFlow Shards Status After Cluster Event - [Arguments] ${controller_index_list}=${EMPTY} [Documentation] Check Shards Status after some cluster event. - Wait Until Keyword Succeeds 90s 1s ClusterOpenFlow.Check OpenFlow Shards Status ${controller_index_list} + [Arguments] ${controller_index_list}=${EMPTY} + Wait Until Keyword Succeeds + ... 90s + ... 1s + ... ClusterOpenFlow.Check OpenFlow Shards Status + ... ${controller_index_list} Get OpenFlow Entity Owner Status For One Device - [Arguments] ${device} ${controller_index} ${controller_index_list}=${EMPTY} ${after_stop}=False [Documentation] Check Entity Owner Status and identify owner and successors for the device ${device}. Request is sent to controller ${controller_index}. - ${owner} ${successor_list} Wait Until Keyword Succeeds 30s 1s ClusterManagement.Verify_Owner_And_Successors_For_Device device_name=${device} - ... device_type=openflow member_index=${controller_index} candidate_list=${controller_index_list} after_stop=${after_stop} - [Return] ${owner} ${successor_list} + [Arguments] ${device} ${controller_index} ${controller_index_list}=${EMPTY} ${after_stop}=False + ${owner} ${successor_list}= Wait Until Keyword Succeeds + ... 30s + ... 1s + ... ClusterManagement.Verify_Owner_And_Successors_For_Device + ... device_name=${device} + ... device_type=openflow + ... member_index=${controller_index} + ... candidate_list=${controller_index_list} + ... after_stop=${after_stop} + RETURN ${owner} ${successor_list} Check OpenFlow Device Owner - [Arguments] ${device} ${controller_index} ${expected_owner} ${expected_candidate_list}=${EMPTY} [Documentation] Check owner and candidates for the device ${device}. Request is sent to controller ${controller_index}. - ${owner} ${successor_list} ClusterManagement.Verify_Owner_And_Successors_For_Device device_name=${device} device_type=openflow member_index=${controller_index} candidate_list=${expected_candidate_list} + [Arguments] ${device} ${controller_index} ${expected_owner} ${expected_candidate_list}=${EMPTY} + ${owner} ${successor_list}= ClusterManagement.Verify_Owner_And_Successors_For_Device + ... device_name=${device} + ... device_type=openflow + ... member_index=${controller_index} + ... candidate_list=${expected_candidate_list} Should Be Equal ${owner} ${expected_owner} Check OpenFlow Network Operational Information For Sample Topology - [Arguments] ${controller_index_list}=${EMPTY} [Documentation] Check devices in tree,2 are in operational inventory and topology in all instances in ${controller_index_list}. ... Inventory should show 1x node_id per device 1x node_id per connector. Topology should show 2x node_id per device + 3x node_id per connector ... + 5x node_id per link termination. TODO: A Keyword that can calculate this based on mininet topology. - ${dictionary} Create Dictionary openflow:1=4 openflow:2=5 openflow:3=5 - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_OPERATIONAL_NODES_API} dictionary=${dictionary} member_index_list=${controller_index_list} - ${dictionary} Create Dictionary openflow:1=21 openflow:2=19 openflow:3=19 - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_OPERATIONAL_TOPO_API} dictionary=${dictionary} member_index_list=${controller_index_list} + [Arguments] ${controller_index_list}=${EMPTY} + ${dictionary}= Create Dictionary openflow:1=4 openflow:2=5 openflow:3=5 + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_OPERATIONAL_NODES_API} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} + ${dictionary}= Create Dictionary openflow:1=21 openflow:2=19 openflow:3=19 + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_OPERATIONAL_TOPO_API} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} Check No OpenFlow Network Operational Information - [Arguments] ${controller_index_list}=${EMPTY} [Documentation] Check device is not in operational inventory or topology in all cluster instances in ${controller_index_list}. - ${dictionary} Create Dictionary openflow=0 - CompareStream.Run_Keyword_If_At_Least_Neon Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_No_Content_Member_List_Or_All uri=${RFC8040_OPERATIONAL_NODES_API} member_index_list=${controller_index_list} - CompareStream.Run_Keyword_If_At_Most_Fluorine Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_OPERATIONAL_NODES_API} dictionary=${dictionary} + [Arguments] ${controller_index_list}=${EMPTY} + ${dictionary}= Create Dictionary openflow=0 + CompareStream.Run_Keyword_If_At_Least_Neon + ... Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_No_Content_Member_List_Or_All + ... uri=${RFC8040_OPERATIONAL_NODES_API} + ... member_index_list=${controller_index_list} + CompareStream.Run_Keyword_If_At_Most_Fluorine + ... Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_OPERATIONAL_NODES_API} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} + ${dictionary}= Create Dictionary openflow=0 + Wait Until Keyword Succeeds + ... 20s + ... 2s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_OPERATIONAL_TOPO_API} + ... dictionary=${dictionary} ... member_index_list=${controller_index_list} - ${dictionary} Create Dictionary openflow=0 - Wait Until Keyword Succeeds 20s 2s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_OPERATIONAL_TOPO_API} dictionary=${dictionary} member_index_list=${controller_index_list} Add Sample Flow And Verify - [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} [Documentation] Add sample flow in ${controller_index} and verify it gets applied in all instances in ${controller_index_list}. + [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} ${body}= OperatingSystem.Get File ${CURDIR}/../variables/openflowplugin/sample_flow_1.json # There are slight differences on the way He and Li plugin display table information. He plugin has an additional Hashmap field # replicating some of the matches in the flows section. Same comment applies for further keywords. - Run Keyword If '${ODL_OF_PLUGIN}' == 'helium' Set Test Variable &{dictionary} 10.0.1.0/24=2 "output-node-connector":"1"=1 - Run Keyword If '${ODL_OF_PLUGIN}' == 'lithium' Set Test Variable &{dictionary} 10.0.1.0/24=1 "output-node-connector":"1"=1 - ClusterManagement.Put_As_Json_And_Check_Member_List_Or_All ${config_table_0}/flow=1 ${body} ${controller_index} ${controller_index_list} - Wait Until Keyword Succeeds 15s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${operational_table_0} dictionary=${dictionary} member_index_list=${controller_index_list} + IF '${ODL_OF_PLUGIN}' == 'helium' + Set Test Variable &{dictionary} 10.0.1.0/24=2 "output-node-connector":"1"=1 + END + IF '${ODL_OF_PLUGIN}' == 'lithium' + Set Test Variable &{dictionary} 10.0.1.0/24=1 "output-node-connector":"1"=1 + END + ClusterManagement.Put_As_Json_And_Check_Member_List_Or_All + ... ${config_table_0}/flow=1 + ... ${body} + ... ${controller_index} + ... ${controller_index_list} + Wait Until Keyword Succeeds + ... 15s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${operational_table_0} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} Verify Sample Flow - [Arguments] ${controller_index_list}=${EMPTY} [Documentation] Verify sample flow gets applied in all instances in ${controller_index_list}. + [Arguments] ${controller_index_list}=${EMPTY} # There are slight differences on the way He and Li plugin display table information. He plugin has an additional Hashmap field # replicating some of the matches in the flows section. Same comment applies for further keywords. - Run Keyword If '${ODL_OF_PLUGIN}' == 'helium' Set Test Variable &{dictionary} 10.0.1.0/24=2 "output-node-connector":"1"=1 - Run Keyword If '${ODL_OF_PLUGIN}' == 'lithium' Set Test Variable &{dictionary} 10.0.1.0/24=1 "output-node-connector":"1"=1 - Wait Until Keyword Succeeds 15s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${operational_table_0} dictionary=${dictionary} member_index_list=${controller_index_list} + IF '${ODL_OF_PLUGIN}' == 'helium' + Set Test Variable &{dictionary} 10.0.1.0/24=2 "output-node-connector":"1"=1 + END + IF '${ODL_OF_PLUGIN}' == 'lithium' + Set Test Variable &{dictionary} 10.0.1.0/24=1 "output-node-connector":"1"=1 + END + Wait Until Keyword Succeeds + ... 15s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${operational_table_0} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} Modify Sample Flow And Verify - [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} [Documentation] Modify sample flow in ${controller_index} and verify it gets applied in all instances in ${controller_index_list}. + [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} ${body}= OperatingSystem.Get File ${CURDIR}/../variables/openflowplugin/sample_flow_2.json - Run Keyword If '${ODL_OF_PLUGIN}' == 'helium' Set Test Variable &{dictionary} 10.0.1.0/24=2 "output-node-connector":"2"=1 - Run Keyword If '${ODL_OF_PLUGIN}' == 'lithium' Set Test Variable &{dictionary} 10.0.1.0/24=1 "output-node-connector":"2"=1 - ClusterManagement.Put_As_Json_And_Check_Member_List_Or_All ${config_table_0}/flow=1 ${body} ${controller_index} ${controller_index_list} - Wait Until Keyword Succeeds 15s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${operational_table_0} dictionary=${dictionary} member_index_list=${controller_index_list} + IF '${ODL_OF_PLUGIN}' == 'helium' + Set Test Variable &{dictionary} 10.0.1.0/24=2 "output-node-connector":"2"=1 + END + IF '${ODL_OF_PLUGIN}' == 'lithium' + Set Test Variable &{dictionary} 10.0.1.0/24=1 "output-node-connector":"2"=1 + END + ClusterManagement.Put_As_Json_And_Check_Member_List_Or_All + ... ${config_table_0}/flow=1 + ... ${body} + ... ${controller_index} + ... ${controller_index_list} + Wait Until Keyword Succeeds + ... 15s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${operational_table_0} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} Delete Sample Flow And Verify - [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} [Documentation] Delete sample flow in Owner and verify it gets removed from all instances. + [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} ${dictionary}= Create Dictionary 10.0.1.0/24=0 - ClusterManagement.Delete_And_Check_Member_List_Or_All ${config_table_0}/flow=1 ${controller_index} ${controller_index_list} - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${operational_table_0} dictionary=${dictionary} member_index_list=${controller_index_list} + ClusterManagement.Delete_And_Check_Member_List_Or_All + ... ${config_table_0}/flow=1 + ... ${controller_index} + ... ${controller_index_list} + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${operational_table_0} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} Send RPC Add Sample Flow And Verify - [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} [Documentation] Add sample flow in ${controller_index} and verify it gets applied from all instances in ${controller_index_list}. + [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} ${body}= OperatingSystem.Get File ${CURDIR}/../variables/openflowplugin/add_flow_rpc.json - Run Keyword If '${ODL_OF_PLUGIN}' == 'helium' Set Test Variable &{dictionary} 10.0.1.0/24=2 - Run Keyword If '${ODL_OF_PLUGIN}' == 'lithium' Set Test Variable &{dictionary} 10.0.1.0/24=1 - ClusterManagement.Post_As_Json_To_Member uri=/rests/operations/sal-flow:add-flow data=${body} member_index=${controller_index} - Wait Until Keyword Succeeds 15s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${operational_table_0} dictionary=${dictionary} member_index_list=${controller_index_list} + IF '${ODL_OF_PLUGIN}' == 'helium' + Set Test Variable &{dictionary} 10.0.1.0/24=2 + END + IF '${ODL_OF_PLUGIN}' == 'lithium' + Set Test Variable &{dictionary} 10.0.1.0/24=1 + END + ClusterManagement.Post_As_Json_To_Member + ... uri=/rests/operations/sal-flow:add-flow + ... data=${body} + ... member_index=${controller_index} + Wait Until Keyword Succeeds + ... 15s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${operational_table_0} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} Send RPC Delete Sample Flow And Verify - [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} [Documentation] Delete sample flow in ${controller_index} and verify it gets removed from all instances in ${controller_index_list}. + [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} ${body}= OperatingSystem.Get File ${CURDIR}/../variables/openflowplugin/delete_flow_rpc.json ${dictionary}= Create Dictionary 10.0.1.0/24=0 - ClusterManagement.Post_As_Json_To_Member uri=/rests/operations/sal-flow:remove-flow data=${body} member_index=${controller_index} - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${operational_table_0} dictionary=${dictionary} member_index_list=${controller_index_list} + ClusterManagement.Post_As_Json_To_Member + ... uri=/rests/operations/sal-flow:remove-flow + ... data=${body} + ... member_index=${controller_index} + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${operational_table_0} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} Take OpenFlow Device Link Down and Verify - [Arguments] ${controller_index_list}=${EMPTY} [Documentation] Take a link down and verify port status in all instances in ${controller_index_list}. + [Arguments] ${controller_index_list}=${EMPTY} ${dictionary}= Create Dictionary "link-down":true=1 ${ouput}= MininetKeywords.Send Mininet Command ${mininet_conn_id} link s1 s2 down - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${operational_port_1} dictionary=${dictionary} member_index_list=${controller_index_list} - ${dictionary} Create Dictionary openflow:1=16 openflow:2=14 openflow:3=19 - Wait Until Keyword Succeeds 20s 2s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_OPERATIONAL_TOPO_API} dictionary=${dictionary} member_index_list=${controller_index_list} + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${operational_port_1} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} + ${dictionary}= Create Dictionary openflow:1=16 openflow:2=14 openflow:3=19 + Wait Until Keyword Succeeds + ... 20s + ... 2s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_OPERATIONAL_TOPO_API} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} Take OpenFlow Device Link Up and Verify - [Arguments] ${controller_index_list}=${EMPTY} [Documentation] Take the link up and verify port status in all instances in ${controller_index_list}. + [Arguments] ${controller_index_list}=${EMPTY} ${dictionary}= Create Dictionary "link-down":true=0 ${ouput}= MininetKeywords.Send Mininet Command ${mininet_conn_id} link s1 s2 up - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${operational_port_1} dictionary=${dictionary} member_index_list=${controller_index_list} - ${dictionary} Create Dictionary openflow:1=21 openflow:2=19 openflow:3=19 - Wait Until Keyword Succeeds 10s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_OPERATIONAL_TOPO_API} dictionary=${dictionary} member_index_list=${controller_index_list} + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${operational_port_1} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} + ${dictionary}= Create Dictionary openflow:1=21 openflow:2=19 openflow:3=19 + Wait Until Keyword Succeeds + ... 10s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_OPERATIONAL_TOPO_API} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} Verify Switch Connections Running On Member - [Arguments] ${switch_count} ${member_index} [Documentation] Check if number of Switch connections on member of given index is equal to ${switch_count}. - ${count} = ScaleClient.Get_Switches_Count controller=${ODL_SYSTEM_${member_index}_IP} + [Arguments] ${switch_count} ${member_index} + ${count}= ScaleClient.Get_Switches_Count controller=${ODL_SYSTEM_${member_index}_IP} BuiltIn.Should_Be_Equal_As_Numbers ${switch_count} ${count} Check Flows Operational Datastore On Member - [Arguments] ${flow_count} ${member_index} [Documentation] Check if number of Operational Flows on member of given index is equal to ${flow_count}. - ${sw} ${reported_flow} ${found_flow}= ScaleClient.Flow Stats Collected controller=${ODL_SYSTEM_${member_index}_IP} + [Arguments] ${flow_count} ${member_index} + ${sw} ${reported_flow} ${found_flow}= ScaleClient.Flow Stats Collected + ... controller=${ODL_SYSTEM_${member_index}_IP} BuiltIn.Should_Be_Equal_As_Numbers ${flow_count} ${found_flow} Check Linear Topology On Member - [Arguments] ${switches} ${member_index}=1 [Documentation] Check Linear topology. - ${session} = Resolve_Http_Session_For_Member member_index=${member_index} - ${resp} RequestsLibrary.Get Request ${session} ${RFC8040_OPERATIONAL_TOPO_API} + [Arguments] ${switches} ${member_index}=1 + ${session}= Resolve_Http_Session_For_Member member_index=${member_index} + ${resp}= RequestsLibrary.Get Request ${session} ${RFC8040_OPERATIONAL_TOPO_API} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 FOR ${switch} IN RANGE 1 ${switches+1} @@ -168,17 +326,23 @@ Check Linear Topology On Member Should Contain ${resp.text} "tp-id":"openflow:${switch}:2" Should Contain ${resp.text} "source-tp":"openflow:${switch}:2" Should Contain ${resp.text} "dest-tp":"openflow:${switch}:2" - ${edge} Evaluate ${switch}==1 or ${switch}==${switches} - Run Keyword If not ${edge} Should Contain ${resp.text} "tp-id":"openflow:${switch}:3" - Run Keyword If not ${edge} Should Contain ${resp.text} "source-tp":"openflow:${switch}:3" - Run Keyword If not ${edge} Should Contain ${resp.text} "dest-tp":"openflow:${switch}:3 + ${edge}= Evaluate ${switch}==1 or ${switch}==${switches} + IF not ${edge} + Should Contain ${resp.text} "tp-id":"openflow:${switch}:3" + END + IF not ${edge} + Should Contain ${resp.text} "source-tp":"openflow:${switch}:3" + END + IF not ${edge} + Should Contain ${resp.text} "dest-tp":"openflow:${switch}:3 + END END Check No Switches On Member - [Arguments] ${switches} ${member_index}=1 [Documentation] Check no switch is in topology - ${session} = Resolve_Http_Session_For_Member member_index=${member_index} - ${resp} RequestsLibrary.Get Request ${session} ${RFC8040_OPERATIONAL_TOPO_API} + [Arguments] ${switches} ${member_index}=1 + ${session}= Resolve_Http_Session_For_Member member_index=${member_index} + ${resp}= RequestsLibrary.Get Request ${session} ${RFC8040_OPERATIONAL_TOPO_API} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 FOR ${switch} IN RANGE 1 ${switches+1} @@ -186,9 +350,9 @@ Check No Switches On Member END Check Number Of Flows On Member - [Arguments] ${flows} ${member_index}=1 [Documentation] Check number of flows in the inventory. - ${session} = Resolve_Http_Session_For_Member member_index=${member_index} + [Arguments] ${flows} ${member_index}=1 + ${session}= Resolve_Http_Session_For_Member member_index=${member_index} ${resp}= RequestsLibrary.Get Request ${session} ${RFC8040_OPERATIONAL_NODES_API} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 @@ -196,9 +360,9 @@ Check Number Of Flows On Member Should Be Equal As Integers ${count} ${flows} Check Number Of Groups On Member - [Arguments] ${groups} ${member_index}=1 [Documentation] Check number of groups in the inventory. - ${session} = Resolve_Http_Session_For_Member member_index=${member_index} + [Arguments] ${groups} ${member_index}=1 + ${session}= Resolve_Http_Session_For_Member member_index=${member_index} ${resp}= RequestsLibrary.Get Request ${session} ${RFC8040_OPERATIONAL_NODES_API} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 diff --git a/csit/libraries/ClusterOvsdb.robot b/csit/libraries/ClusterOvsdb.robot index 41b95eed9f..ed9999d370 100644 --- a/csit/libraries/ClusterOvsdb.robot +++ b/csit/libraries/ClusterOvsdb.robot @@ -1,88 +1,150 @@ *** Settings *** -Documentation Cluster Ovsdb library. So far this library is only to be used by Ovsdb cluster test as it is very specific for this test. -Library Collections -Library RequestsLibrary -Resource ClusterManagement.robot -Resource CompareStream.robot -Resource MininetKeywords.robot -Resource Utils.robot -Resource OVSDB.robot -Resource ../variables/ovsdb/Variables.robot -Variables ../variables/Variables.py +Documentation Cluster Ovsdb library. So far this library is only to be used by Ovsdb cluster test as it is very specific for this test. + +Library Collections +Library RequestsLibrary +Resource ClusterManagement.robot +Resource CompareStream.robot +Resource MininetKeywords.robot +Resource Utils.robot +Resource OVSDB.robot +Resource ../variables/ovsdb/Variables.robot +Variables ../variables/Variables.py + *** Variables *** -@{SHARD_OPER_LIST} topology default entity-ownership -@{SHARD_CONF_LIST} topology default -${BRIDGE} br01 -${OVSDB_CONFIG_DIR} ${CURDIR}/../variables/ovsdb +@{SHARD_OPER_LIST} topology default entity-ownership +@{SHARD_CONF_LIST} topology default +${BRIDGE} br01 +${OVSDB_CONFIG_DIR} ${CURDIR}/../variables/ovsdb + *** Keywords *** Check Ovsdb Shards Status - [Arguments] ${controller_index_list}=${EMPTY} [Documentation] Check Status for all shards in Ovsdb application. - CompareStream.Run_Keyword_If_At_Least_Phosphorus Collections.Remove Values From List ${SHARD_OPER_LIST} entity-ownership + [Arguments] ${controller_index_list}=${EMPTY} + CompareStream.Run_Keyword_If_At_Least_Phosphorus + ... Collections.Remove Values From List + ... ${SHARD_OPER_LIST} + ... entity-ownership Log ${SHARD_OPER_LIST} - ClusterManagement.Verify_Leader_Exists_For_Each_Shard shard_name_list=${SHARD_OPER_LIST} shard_type=operational member_index_list=${controller_index_list} - ClusterManagement.Verify_Leader_Exists_For_Each_Shard shard_name_list=${SHARD_CONF_LIST} shard_type=config member_index_list=${controller_index_list} + ClusterManagement.Verify_Leader_Exists_For_Each_Shard + ... shard_name_list=${SHARD_OPER_LIST} + ... shard_type=operational + ... member_index_list=${controller_index_list} + ClusterManagement.Verify_Leader_Exists_For_Each_Shard + ... shard_name_list=${SHARD_CONF_LIST} + ... shard_type=config + ... member_index_list=${controller_index_list} Check Ovsdb Shards Status After Cluster Event - [Arguments] ${controller_index_list}=${EMPTY} [Documentation] Check Shard Status after some cluster event. + [Arguments] ${controller_index_list}=${EMPTY} Wait Until Keyword Succeeds 90s 1s Check Ovsdb Shards Status ${controller_index_list} Get Ovsdb Entity Owner Status For One Device - [Arguments] ${device} ${controller_index} ${controller_index_list}=${EMPTY} [Documentation] Check Entity Owner Status and identify owner and successors for an ovs device ${device}. Request is sent to controller ${controller_index}. - ${owner} ${successor_list} Wait Until Keyword Succeeds 20s 1s ClusterManagement.Verify_Owner_And_Successors_For_Device device_name=${device} - ... device_type=ovsdb member_index=${controller_index} candidate_list=${controller_index_list} - [Return] ${owner} ${successor_list} + [Arguments] ${device} ${controller_index} ${controller_index_list}=${EMPTY} + ${owner} ${successor_list} Wait Until Keyword Succeeds + ... 20s + ... 1s + ... ClusterManagement.Verify_Owner_And_Successors_For_Device + ... device_name=${device} + ... device_type=ovsdb + ... member_index=${controller_index} + ... candidate_list=${controller_index_list} + RETURN ${owner} ${successor_list} Create Sample Bridge Manually And Verify - [Arguments] ${ovs_system_ip}=${TOOLS_SYSTEM_IP} ${controller_index_list}=${EMPTY} [Documentation] Create bridge br-s1 using OVS command and verify it gets created in all instances in ${controller_index_list}. + [Arguments] ${ovs_system_ip}=${TOOLS_SYSTEM_IP} ${controller_index_list}=${EMPTY} Utils.Run Command On Mininet ${ovs_system_ip} sudo ovs-vsctl add-br br-s1 - ${dictionary_operational}= Create Dictionary br-s1=5 - ${dictionary_config}= Create Dictionary br-s1=0 - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_CONFIG_TOPO_API} dictionary=${dictionary_config} member_index_list=${controller_index_list} - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_OPERATIONAL_TOPO_API} dictionary=${dictionary_operational} member_index_list=${controller_index_list} + ${dictionary_operational} Create Dictionary br-s1=5 + ${dictionary_config} Create Dictionary br-s1=0 + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_CONFIG_TOPO_API} + ... dictionary=${dictionary_config} + ... member_index_list=${controller_index_list} + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_OPERATIONAL_TOPO_API} + ... dictionary=${dictionary_operational} + ... member_index_list=${controller_index_list} Add Sample Port To The Manual Bridge And Verify - [Arguments] ${ovs_system_ip}=${TOOLS_SYSTEM_IP} ${controller_index_list}=${EMPTY} [Documentation] Add Port vx1 to br-s1 using OVS command and verify it gets added in all instances in ${controller_index_list}. - Utils.Run Command On Mininet ${ovs_system_ip} sudo ovs-vsctl add-port br-s1 vx1 -- set Interface vx1 type=vxlan - ${dictionary_operational}= Create Dictionary vx1=2 - ${dictionary_config}= Create Dictionary vx1=0 - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_CONFIG_TOPO_API} dictionary=${dictionary_config} member_index_list=${controller_index_list} - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_OPERATIONAL_TOPO_API} dictionary=${dictionary_operational} member_index_list=${controller_index_list} + [Arguments] ${ovs_system_ip}=${TOOLS_SYSTEM_IP} ${controller_index_list}=${EMPTY} + Utils.Run Command On Mininet + ... ${ovs_system_ip} + ... sudo ovs-vsctl add-port br-s1 vx1 -- set Interface vx1 type=vxlan + ${dictionary_operational} Create Dictionary vx1=2 + ${dictionary_config} Create Dictionary vx1=0 + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_CONFIG_TOPO_API} + ... dictionary=${dictionary_config} + ... member_index_list=${controller_index_list} + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_OPERATIONAL_TOPO_API} + ... dictionary=${dictionary_operational} + ... member_index_list=${controller_index_list} Create Sample Tap Device - [Arguments] ${ovs_system_ip}=${TOOLS_SYSTEM_IP} [Documentation] Create Tap Device vport1 and vport2 to add to the bridge br-s1 using OVS command. + [Arguments] ${ovs_system_ip}=${TOOLS_SYSTEM_IP} Utils.Run Command On Mininet ${ovs_system_ip} ip tuntap add mode tap vport1 Utils.Run Command On Mininet ${ovs_system_ip} ip tuntap add mode tap vport2 Utils.Run Command On Mininet ${ovs_system_ip} ifconfig vport1 up Utils.Run Command On Mininet ${ovs_system_ip} ifconfig vport2 up Add Sample Tap Device To The Manual Bridge And Verify - [Arguments] ${ovs_system_ip}=${TOOLS_SYSTEM_IP} ${controller_index_list}=${EMPTY} [Documentation] Add Tap Device vport1 and vport2 to br-s1 using OVS command and verify it gets added in all instances in ${controller_index_list}. + [Arguments] ${ovs_system_ip}=${TOOLS_SYSTEM_IP} ${controller_index_list}=${EMPTY} Utils.Run Command On Mininet ${ovs_system_ip} sudo ovs-vsctl add-port br-s1 vport1 -- add-port br-s1 vport2 - ${dictionary_operational}= Create Dictionary vport1=2 vport2=2 - ${dictionary_config}= Create Dictionary vport1=0 vport2=0 - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_CONFIG_TOPO_API} dictionary=${dictionary_config} member_index_list=${controller_index_list} - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_OPERATIONAL_TOPO_API} dictionary=${dictionary_operational} member_index_list=${controller_index_list} + ${dictionary_operational} Create Dictionary vport1=2 vport2=2 + ${dictionary_config} Create Dictionary vport1=0 vport2=0 + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_CONFIG_TOPO_API} + ... dictionary=${dictionary_config} + ... member_index_list=${controller_index_list} + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_OPERATIONAL_TOPO_API} + ... dictionary=${dictionary_operational} + ... member_index_list=${controller_index_list} Delete Sample Bridge Manually And Verify - [Arguments] ${ovs_system_ip}=${TOOLS_SYSTEM_IP} ${controller_index_list}=${EMPTY} [Documentation] Delete bridge br-s1 using OVS command and verify it gets applied in all instances in ${controller_index_list}. + [Arguments] ${ovs_system_ip}=${TOOLS_SYSTEM_IP} ${controller_index_list}=${EMPTY} Utils.Run Command On Mininet ${ovs_system_ip} sudo ovs-vsctl del-br br-s1 - ${dictionary}= Create Dictionary br-s1=0 - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_OPERATIONAL_TOPO_API} dictionary=${dictionary} member_index_list=${controller_index_list} + ${dictionary} Create Dictionary br-s1=0 + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_OPERATIONAL_TOPO_API} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} Create Sample Bridge And Verify - [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} [Documentation] Create bridge ${BRIDGE} in controller ${controller_index} and verify it gets created in all instances in ${controller_index_list}. - ${body}= OperatingSystem.Get File ${CURDIR}/../variables/ovsdb/create_bridge_3node.json + [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} + ${body} OperatingSystem.Get File ${CURDIR}/../variables/ovsdb/create_bridge_3node.json ${body} Replace String ${body} ovsdb://127.0.0.1:61644 ovsdb://uuid/${ovsdb_uuid} ${body} Replace String ${body} tcp:controller1:6633 tcp:${ODL_SYSTEM_1_IP}:6633 ${body} Replace String ${body} tcp:controller2:6633 tcp:${ODL_SYSTEM_2_IP}:6633 @@ -92,54 +154,113 @@ Create Sample Bridge And Verify ${body} Replace String ${body} 61644 ${OVSDB_PORT} Log ${body} ${TOOLS_SYSTEM_IP1} Replace String ${TOOLS_SYSTEM_IP} ${TOOLS_SYSTEM_IP} "${TOOLS_SYSTEM_IP}" - ${dictionary}= Create Dictionary ${TOOLS_SYSTEM_IP1}=1 ${OVSDBPORT}=4 ${BRIDGE}=1 - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Put_As_Json_And_Check_Member_List_Or_All ${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE} ${body} ${controller_index} + ${dictionary} Create Dictionary ${TOOLS_SYSTEM_IP1}=1 ${OVSDBPORT}=4 ${BRIDGE}=1 + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Put_As_Json_And_Check_Member_List_Or_All + ... ${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE} + ... ${body} + ... ${controller_index} ... ${controller_index_list} - Wait Until Keyword Succeeds 10s 2s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}?${RFC8040_OPERATIONAL_CONTENT} dictionary=${dictionary} member_index_list=${controller_index_list} + Wait Until Keyword Succeeds + ... 10s + ... 2s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}?${RFC8040_OPERATIONAL_CONTENT} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} Create Sample Port And Verify - [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} [Documentation] Add Port vx2 to bridge ${BRIDGE} in controller ${controller_index} and verify it gets added in all instances in ${controller_index_list}. + [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} ${sample} OperatingSystem.Get File ${OVSDB_CONFIG_DIR}/create_port_3node.json ${body} Replace String ${sample} 192.168.1.10 ${TOOLS_SYSTEM_IP} Log ${body} Log URL is ${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE}/termination-point=vx2 - ${port_dictionary}= Create Dictionary ${BRIDGE}=1 vx2=3 - ClusterManagement.Put_As_Json_And_Check_Member_List_Or_All ${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE}/termination-point=vx2 ${body} ${controller_index} ${controller_index_list} - Wait Until Keyword Succeeds 10s 2s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE}/termination-point=vx2?${RFC8040_OPERATIONAL_CONTENT} dictionary=${port_dictionary} member_index_list=${controller_index_list} + ${port_dictionary} Create Dictionary ${BRIDGE}=1 vx2=3 + ClusterManagement.Put_As_Json_And_Check_Member_List_Or_All + ... ${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE}/termination-point=vx2 + ... ${body} + ... ${controller_index} + ... ${controller_index_list} + Wait Until Keyword Succeeds + ... 10s + ... 2s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE}/termination-point=vx2?${RFC8040_OPERATIONAL_CONTENT} + ... dictionary=${port_dictionary} + ... member_index_list=${controller_index_list} Modify the destination IP of Sample Port - [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} [Documentation] Modify the dst ip of port vx2 in bridge ${BRIDGE} in controller ${controller_index}. + [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} ${sample} OperatingSystem.Get File ${OVSDB_CONFIG_DIR}/create_port_3node.json ${body} Replace String ${sample} 192.168.1.10 10.0.0.19 Log URL is ${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE}/termination-point=vx2 Log ${body} - ClusterManagement.Put_As_Json_And_Check_Member_List_Or_All ${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE}/termination-point=vx2 ${body} ${controller_index} ${controller_index_list} + ClusterManagement.Put_As_Json_And_Check_Member_List_Or_All + ... ${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE}/termination-point=vx2 + ... ${body} + ... ${controller_index} + ... ${controller_index_list} Verify Sample Port Is Modified - [Arguments] ${controller_index_list}=${EMPTY} [Documentation] Verify dst ip of port vx2 in bridge ${BRIDGE} gets modified in all instances in ${controller_index_list}. + [Arguments] ${controller_index_list}=${EMPTY} ${port_dictionary} Create Dictionary br01=6 vx2=3 10.0.0.19=1 - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE}?${RFC8040_OPERATIONAL_CONTENT} dictionary=${port_dictionary} member_index_list=${controller_index_list} + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE}?${RFC8040_OPERATIONAL_CONTENT} + ... dictionary=${port_dictionary} + ... member_index_list=${controller_index_list} Delete Sample Port And Verify - [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} [Documentation] Delete port vx2 from bridge ${BRIDGE} in controller ${controller_index} and verify it gets deleted in all instances in ${controller_index_list}. - ${dictionary}= Create Dictionary vx2=0 - ClusterManagement.Delete_And_Check_Member_List_Or_All ${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE}/termination-point=vx2 ${controller_index} ${controller_index_list} - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}?${RFC8040_OPERATIONAL_CONTENT} dictionary=${dictionary} member_index_list=${controller_index_list} + [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} + ${dictionary} Create Dictionary vx2=0 + ClusterManagement.Delete_And_Check_Member_List_Or_All + ... ${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE}/termination-point=vx2 + ... ${controller_index} + ... ${controller_index_list} + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}?${RFC8040_OPERATIONAL_CONTENT} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} Delete Sample Bridge And Verify - [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} [Documentation] Delete bridge ${BRIDGE} in ${controller_index} and verify it gets deleted in all instances in ${controller_index_list}. - ${dictionary}= Create Dictionary ${BRIDGE}=0 - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Delete_And_Check_Member_List_Or_All ${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE} ${controller_index} ${controller_index_list} - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}?${RFC8040_OPERATIONAL_CONTENT} dictionary=${dictionary} member_index_list=${controller_index_list} + [Arguments] ${controller_index} ${controller_index_list}=${EMPTY} + ${dictionary} Create Dictionary ${BRIDGE}=0 + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Delete_And_Check_Member_List_Or_All + ... ${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}%2Fbridge%2F${BRIDGE} + ... ${controller_index} + ... ${controller_index_list} + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_SOUTHBOUND_NODE_API}uuid%2F${ovsdb_uuid}?${RFC8040_OPERATIONAL_CONTENT} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} Configure Exit OVSDB Connection - [Arguments] ${controller_index_list}=${EMPTY} [Documentation] Cleans up test environment, close existing sessions. + [Arguments] ${controller_index_list}=${EMPTY} OVSDB.Clean OVSDB Test Environment ${TOOLS_SYSTEM_IP} - ${dictionary}= Create Dictionary ovsdb://uuid=0 - Wait Until Keyword Succeeds 5s 1s ClusterManagement.Check_Item_Occurrence_Member_List_Or_All uri=${RFC8040_OPERATIONAL_TOPO_API} dictionary=${dictionary} member_index_list=${controller_index_list} + ${dictionary} Create Dictionary ovsdb://uuid=0 + Wait Until Keyword Succeeds + ... 5s + ... 1s + ... ClusterManagement.Check_Item_Occurrence_Member_List_Or_All + ... uri=${RFC8040_OPERATIONAL_TOPO_API} + ... dictionary=${dictionary} + ... member_index_list=${controller_index_list} diff --git a/csit/libraries/Coe.robot b/csit/libraries/Coe.robot index e572aaee7a..40853635c9 100644 --- a/csit/libraries/Coe.robot +++ b/csit/libraries/Coe.robot @@ -1,33 +1,35 @@ *** Settings *** -Library BuiltIn -Library SSHLibrary -Library String -Resource DataModels.robot -Resource Genius.robot -Resource OVSDB.robot -Resource SSHKeywords.robot -Resource Utils.robot -Resource ../variables/netvirt/Variables.robot -Resource ../variables/Variables.robot -Resource VpnOperations.robot -Variables ../variables/coe/Modules.py -Variables ../variables/netvirt/Modules.py -Resource ToolsSystem.robot +Library BuiltIn +Library SSHLibrary +Library String +Resource DataModels.robot +Resource Genius.robot +Resource OVSDB.robot +Resource SSHKeywords.robot +Resource Utils.robot +Resource ../variables/netvirt/Variables.robot +Resource ../variables/Variables.robot +Resource VpnOperations.robot +Variables ../variables/coe/Modules.py +Variables ../variables/netvirt/Modules.py +Resource ToolsSystem.robot + *** Variables *** -${BUSY_BOX} ${CURDIR}/../variables/coe/busy-box.yaml -${CNI_BINARY_FILE} /opt/cni/bin/odlovs-cni -${CONFIG_FILE} /etc/cni/net.d/odlovs-cni.conf -${CONFIG_FILE_TEMPLATE} ${CURDIR}/../variables/coe/odlovs-cni.conf.j2 -${HOST_INVENTORY} ${CURDIR}/../variables/coe/hosts.yaml -${K8s_MASTER_IP} ${TOOLS_SYSTEM_1_IP} -${HOSTS_FILE_TEMPLATE} ${CURDIR}/../variables/coe/minions_template.yaml -${NODE_READY_STATUS} \\sReady # The check using this variable should not mess up with NotReady -${PLAYBOOK_FILE} ${CURDIR}/../variables/coe/coe_play.yaml -${POD_RUNNING_STATUS} \\sRunning -${VARIABLES_PATH} ${CURDIR}/../variables/coe -${WATCHER_COE} ${CURDIR}/../variables/coe/coe.yaml -@{COE_DIAG_SERVICES} OPENFLOW IFM ITM DATASTORE ELAN OVSDB +${BUSY_BOX} ${CURDIR}/../variables/coe/busy-box.yaml +${CNI_BINARY_FILE} /opt/cni/bin/odlovs-cni +${CONFIG_FILE} /etc/cni/net.d/odlovs-cni.conf +${CONFIG_FILE_TEMPLATE} ${CURDIR}/../variables/coe/odlovs-cni.conf.j2 +${HOST_INVENTORY} ${CURDIR}/../variables/coe/hosts.yaml +${K8s_MASTER_IP} ${TOOLS_SYSTEM_1_IP} +${HOSTS_FILE_TEMPLATE} ${CURDIR}/../variables/coe/minions_template.yaml +${NODE_READY_STATUS} \\sReady # The check using this variable should not mess up with NotReady +${PLAYBOOK_FILE} ${CURDIR}/../variables/coe/coe_play.yaml +${POD_RUNNING_STATUS} \\sRunning +${VARIABLES_PATH} ${CURDIR}/../variables/coe +${WATCHER_COE} ${CURDIR}/../variables/coe/coe.yaml +@{COE_DIAG_SERVICES} OPENFLOW IFM ITM DATASTORE ELAN OVSDB + *** Keywords *** Coe Suite Setup @@ -35,10 +37,10 @@ Coe Suite Setup ToolsSystem.Get Tools System Nodes Data Coe.Set Connection ids and Bridge Coe.Derive Coe Data Models - ${current suite} ${suite names updated} Extract current suite name + ${current suite} ${suite names updated} = Extract current suite name ${first_suite} = Set Variable ${suite names updated[0]} ${status} = BuiltIn.Evaluate '${first_suite}' == '${current suite}' - Run Keyword If '${status}' == 'True' Coe.Start Suite + IF '${status}' == 'True' Coe.Start Suite Start Suite [Documentation] Suite setup keyword. @@ -47,7 +49,11 @@ Start Suite Coe.Verify Watcher Is Running BuiltIn.Wait Until Keyword Succeeds 40s 2s Coe.Check Node Status Is Ready Coe.Label Nodes - BuiltIn.Wait Until Keyword Succeeds 60 2 ClusterManagement.Check Status Of Services Is OPERATIONAL @{COE_DIAG_SERVICES} + BuiltIn.Wait Until Keyword Succeeds + ... 60 + ... 2 + ... ClusterManagement.Check Status Of Services Is OPERATIONAL + ... @{COE_DIAG_SERVICES} BuiltIn.Wait Until Keyword Succeeds 85 2 Genius.Verify Tunnel Status As Up Set Connection ids and Bridge @@ -62,7 +68,7 @@ Set Connection ids and Bridge Configuration Playbook [Documentation] Ansible playbook which does all basic configuration for kubernetes nodes. - ${playbook minions} ${playbook hosts} ${host file} Modifying templates in playbook + ${playbook minions} ${playbook hosts} ${host file} = Modifying templates in playbook ${playbook} = OperatingSystem.Get File ${PLAYBOOK_FILE} ${playbook} = String.Replace String ${playbook} coe-hosts ${playbook hosts} ${playbook} = String.Replace String ${playbook} coe-minions ${playbook minions} @@ -75,20 +81,24 @@ Configuration Playbook SSHKeywords.Copy_File_To_Remote_System ${K8s_MASTER_IP} ${WATCHER_COE} ${USER_HOME} OperatingSystem.Copy File ${PLAYBOOK_FILE} ${USER_HOME} ${branch_ref_spec} = BuiltIn.Catenate SEPARATOR= refs/heads/ ${GERRIT_BRANCH} - ${gerrit_ref_spec} = BuiltIn.Set Variable If '${GERRIT_PROJECT}' != 'coe' ${branch_ref_spec} ${GERRIT_REFSPEC} + ${gerrit_ref_spec} = BuiltIn.Set Variable If + ... '${GERRIT_PROJECT}' != 'coe' + ... ${branch_ref_spec} + ... ${GERRIT_REFSPEC} Run Coe Playbook ${gerrit_ref_spec} Run Coe Playbook [Arguments] ${gerrit_ref_spec} - ${play_output} = OperatingSystem.Run ansible-playbook -v ${USER_HOME}/coe_play.yaml -i ${USER_HOME}/hosts.yaml --extra-vars '{"gerrit_branch":"FETCH_HEAD","gerrit_refspec":"${gerrit_ref_spec}"}' + ${play_output} = OperatingSystem.Run + ... ansible-playbook -v ${USER_HOME}/coe_play.yaml -i ${USER_HOME}/hosts.yaml --extra-vars '{"gerrit_branch":"FETCH_HEAD","gerrit_refspec":"${gerrit_ref_spec}"}' BuiltIn.Log ${play_output} Modifying templates in playbook ${inventory} = OperatingSystem.Get File ${HOST_INVENTORY} ${template} = OperatingSystem.Get File ${HOSTS_FILE_TEMPLATE} ${template} = String.Replace String ${template} minion_ip ${TOOLS_SYSTEM_ALL_IPS[0]} - @{minions} Create List coe-minion - ${hosts} Set Variable coe-master: + @{minions} = Create List coe-minion + ${hosts} = Set Variable coe-master: FOR ${i} IN RANGE 1 ${NUM_TOOLS_SYSTEM} Append To List ${minions} coe-minion${i} ${hosts} = Catenate ${hosts} coe-minion${i}: @@ -99,7 +109,10 @@ Modifying templates in playbook FOR ${i} IN RANGE 1 ${NUM_TOOLS_SYSTEM} ${j} = Evaluate ${i}+1 ${template} = String.Replace String ${template} ${minions[${i}-1]} ${minions[${i}]} - ${template} = String.Replace String ${template} ${TOOLS_SYSTEM_ALL_IPS[${i}-1]} ${TOOLS_SYSTEM_ALL_IPS[${i}]} + ${template} = String.Replace String + ... ${template} + ... ${TOOLS_SYSTEM_ALL_IPS[${i}-1]} + ... ${TOOLS_SYSTEM_ALL_IPS[${i}]} ${template} = String.Replace String ${template} 192.168.50.1${i} 192.168.50.1${j} ${template} = String.Replace String ${template} 10.11.${i}.0/24 10.11.${j}.0/24 ${template} = String.Replace String ${template} 10.11.${i}.1 10.11.${j}.1 @@ -113,7 +126,7 @@ Modifying templates in playbook ${host file} = String.Replace String ${host file} filepath ${CONFIG_FILE_TEMPLATE} ${host file} = String.Replace String ${host file} yamlpath ${USER_HOME}/coe.yaml log ${host file} - [Return] ${minion hosts} ${hosts} ${host file} + RETURN ${minion hosts} ${hosts} ${host file} Verify Config Files [Documentation] Checks if the configuration files are present in all nodes @@ -131,7 +144,12 @@ Verify Watcher Is Running Check Node Status Is Ready [Documentation] Checks the status of nodes.This keyword is repeated until the status of all nodes is Ready - ${nodes} = Utils.Run Command On Remote System And Log ${K8s_MASTER_IP} kubectl get nodes ${DEFAULT_USER} ${DEFAULT_PASSWORD} ${DEFAULT_LINUX_PROMPT_STRICT} + ${nodes} = Utils.Run Command On Remote System And Log + ... ${K8s_MASTER_IP} + ... kubectl get nodes + ... ${DEFAULT_USER} + ... ${DEFAULT_PASSWORD} + ... ${DEFAULT_LINUX_PROMPT_STRICT} ${node_status} = String.Get Lines Matching Regexp ${nodes} ${NODE_READY_STATUS} partial_match=True ${lines_containing_ready} = String.Get Line Count ${node_status} BuiltIn.Should Be Equal As Strings ${lines_containing_ready} ${NUM_TOOLS_SYSTEM} @@ -156,7 +174,12 @@ Derive Coe Data Models Check Pod Status Is Running [Documentation] Checks the status of pods.This keyword is repeated until the status of all pods is Running - ${pods} = Utils.Run Command On Remote System And Log ${K8s_MASTER_IP} kubectl get pods -o wide ${DEFAULT_USER} ${DEFAULT_PASSWORD} ${DEFAULT_LINUX_PROMPT_STRICT} + ${pods} = Utils.Run Command On Remote System And Log + ... ${K8s_MASTER_IP} + ... kubectl get pods -o wide + ... ${DEFAULT_USER} + ... ${DEFAULT_PASSWORD} + ... ${DEFAULT_LINUX_PROMPT_STRICT} @{cluster} = String.Split To Lines ${pods} 1 FOR ${pod} IN @{cluster} BuiltIn.Should Match Regexp ${pod} ${POD_RUNNING_STATUS} @@ -169,8 +192,18 @@ Tear Down END BuiltIn.Run Keyword And Ignore Error DataModels.Get Model Dump ${ODL_SYSTEM_IP} ${coe_data_models} Coe.DumpConfig File - Utils.Run Command On Remote System And Log ${K8s_MASTER_IP} kubectl get nodes ${DEFAULT_USER} ${DEFAULT_PASSWORD} ${DEFAULT_LINUX_PROMPT_STRICT} - Utils.Run Command On Remote System And Log ${K8s_MASTER_IP} kubectl get pods -o wide ${DEFAULT_USER} ${DEFAULT_PASSWORD} ${DEFAULT_LINUX_PROMPT_STRICT} + Utils.Run Command On Remote System And Log + ... ${K8s_MASTER_IP} + ... kubectl get nodes + ... ${DEFAULT_USER} + ... ${DEFAULT_PASSWORD} + ... ${DEFAULT_LINUX_PROMPT_STRICT} + Utils.Run Command On Remote System And Log + ... ${K8s_MASTER_IP} + ... kubectl get pods -o wide + ... ${DEFAULT_USER} + ... ${DEFAULT_PASSWORD} + ... ${DEFAULT_LINUX_PROMPT_STRICT} Coe.Delete Pods Delete Pods @@ -186,8 +219,15 @@ Delete Pods Check If Pods Are Terminated [Documentation] Checks if the pods created have been terminated.The keyword is repeated until the pods are deleted - ${status} = Utils.Run Command On Remote System ${K8s_MASTER_IP} kubectl get pods -o wide ${DEFAULT_USER} ${DEFAULT_PASSWORD} ${DEFAULT_LINUX_PROMPT_STRICT} - ... ${DEFAULT_TIMEOUT} return_stdout=False return_stderr=True + ${status} = Utils.Run Command On Remote System + ... ${K8s_MASTER_IP} + ... kubectl get pods -o wide + ... ${DEFAULT_USER} + ... ${DEFAULT_PASSWORD} + ... ${DEFAULT_LINUX_PROMPT_STRICT} + ... ${DEFAULT_TIMEOUT} + ... return_stdout=False + ... return_stderr=True BuiltIn.Should Contain ${status} No resources Dump Config File @@ -211,7 +251,9 @@ Collect Watcher Log Collect Journalctl Log [Documentation] Logs of the command journalctl -u kubelet is copied to ${JENKINS_WORKSPACE}/archives/journal.log - Utils.Run Command On Remote System And Log ${K8s_MASTER_IP} sudo journalctl -u kubelet > ${USER_HOME}/journal.txt + Utils.Run Command On Remote System And Log + ... ${K8s_MASTER_IP} + ... sudo journalctl -u kubelet > ${USER_HOME}/journal.txt SSHLibrary.Switch Connection ${TOOLS_SYSTEM_ALL_CONN_IDS[0]} SSHLibrary.Get File ${USER_HOME}/journal.txt ${JENKINS_WORKSPACE}/archives/journalctl.log @@ -229,8 +271,8 @@ Kube reset END Create Pods - [Arguments] ${label} ${yaml} ${name} [Documentation] Creates pods using the labels of the nodes and busy box names passed as arguments. + [Arguments] ${label} ${yaml} ${name} ${busybox} = OperatingSystem.Get File ${BUSY_BOX} ${busybox} = String.Replace String ${busybox} string ${label} ${busybox} = String.Replace String ${busybox} busyboxname ${name} @@ -254,47 +296,56 @@ Log Statements @{log statement} = Create List ${i} = Set Variable 0 FOR ${pod_ip} IN @{pod ips} - ${ping statement} Set Variable Ping from ${pod_name} to ${pod names[${i}]} (${pod ip}) + ${ping statement} = Set Variable Ping from ${pod_name} to ${pod names[${i}]} (${pod ip}) Append To List ${log statement} ${ping statement} ${i} = Evaluate ${i}+1 END - [Return] @{log statement} + RETURN @{log statement} Ping Pods [Arguments] ${pod_name} ${pod ips} ${logs} ${i} = Set Variable 0 FOR ${ping info} IN @{logs} - ${ping} = Write Commands Until Expected Prompt kubectl exec -it ${pod_name} -- ping -c 3 ${pod ips[${i}]} ${DEFAULT_LINUX_PROMPT_STRICT} + ${ping} = Write Commands Until Expected Prompt + ... kubectl exec -it ${pod_name} -- ping -c 3 ${pod ips[${i}]} + ... ${DEFAULT_LINUX_PROMPT_STRICT} BuiltIn.log ${ping} BuiltIn.Should Contain ${ping} 64 bytes - ${i} Evaluate ${i}+1 + ${i} = Evaluate ${i}+1 END Coe Suite Teardown [Documentation] COE project requires stop suite to be executed only for the last test suite.This keyword find the current suite,compares it with the stored last suite value and executes Coe.Stop suite only if the cuurent suite is equal to the last suite. - ${current suite} ${suite names updated} Extract current suite name + ${current suite} ${suite names updated} = Extract current suite name ${last_suite} = Set Variable ${suite names updated[-1]} ${status} = BuiltIn.Evaluate '${last_suite}' == '${current suite}' - Run Keyword If '${status}' == 'True' Coe.Stop Suite + IF '${status}' == 'True' Coe.Stop Suite Extract current suite name [Documentation] This keyword returns the name of current test suite.Appropriate replacement in text is done to make test suite names in SUITES and SUITE_NAME similar. BuiltIn.Log SUITE_NAME: ${SUITE_NAME} BuiltIn.Log SUITES: ${SUITES} - @{suite_names} Get Regexp Matches ${SUITES} coe\\/(\\w+).robot 1 - @{suite_names_updated} Create List + @{suite_names} = Get Regexp Matches ${SUITES} coe\\/(\\w+).robot 1 + @{suite_names_updated} = Create List FOR ${suite} IN @{suite_names} - ${suite} Replace String ${suite} _ ${SPACE} + ${suite} = Replace String ${suite} _ ${SPACE} Append To List ${suite_names_updated} ${suite} END ${num_suites} = BuiltIn.Get Length ${suite_names_updated} - ${suite line} ${current_suite} = BuiltIn.Run Keyword If ${num_suites} > ${1} Should Match Regexp ${SUITE_NAME} .txt.(\\w.*) - ... ELSE BuiltIn.Set Variable ${suite_names_updated}[0] ${suite_names_updated}[0] - [Return] ${current_suite} ${suite_names_updated} + IF ${num_suites} > ${1} + ${suite line} ${current_suite} = Should Match Regexp ${SUITE_NAME} .txt.(\\w.*) + ELSE + ${suite line} ${current_suite} = BuiltIn.Set Variable + ... ${suite_names_updated}[0] + ... ${suite_names_updated}[0] + END + RETURN ${current_suite} ${suite_names_updated} Check For Stale veth Ports [Documentation] Check on switches(except master) where pods were created and deleted to ensure there are no stale veth ports left behind. FOR ${minion_index} IN RANGE 2 ${NUM_TOOLS_SYSTEM}+1 - ${switch output} = Utils.Run Command On Remote System And Log ${TOOLS_SYSTEM_${minion_index}_IP} sudo ovs-vsctl show + ${switch output} = Utils.Run Command On Remote System And Log + ... ${TOOLS_SYSTEM_${minion_index}_IP} + ... sudo ovs-vsctl show BuiltIn.Should Not Contain ${switch output} veth END diff --git a/csit/libraries/CompareStream.robot b/csit/libraries/CompareStream.robot index f85a7e02b3..f1c9b4afc0 100644 --- a/csit/libraries/CompareStream.robot +++ b/csit/libraries/CompareStream.robot @@ -1,544 +1,609 @@ *** Settings *** -Documentation This Resource contains list of Keywords Set_Variable_If_At_Least*, Set_Variable_If_At_Most, -... Run_Keyword_If_At_Least*, Run_Keyword_If_At_Most*, -... Run_Keyword_If_More_Than*, Run_Keyword_If_Less_Than*, -... for comparison ${ODL_STREAM} to the given ${lower_bound}, -... in order to replace ad-hoc conditional execution in suites. -Library Collections -Library String +Documentation This Resource contains list of Keywords Set_Variable_If_At_Least*, Set_Variable_If_At_Most, +... Run_Keyword_If_At_Least*, Run_Keyword_If_At_Most*, +... Run_Keyword_If_More_Than*, Run_Keyword_If_Less_Than*, +... for comparison ${ODL_STREAM} to the given ${lower_bound}, +... in order to replace ad-hoc conditional execution in suites. + +Library Collections +Library String + *** Variables *** -&{Stream_dict} carbon=${6} nitrogen=${7} oxygen=${8} fluorine=${9} neon=${10} sodium=${11} magnesium=${12} aluminium=${13} silicon=${14} phosphorus=${15} sulfur=${16} chlorine=${17} master=${999} +&{Stream_dict} +... carbon=${6} +... nitrogen=${7} +... oxygen=${8} +... fluorine=${9} +... neon=${10} +... sodium=${11} +... magnesium=${12} +... aluminium=${13} +... silicon=${14} +... phosphorus=${15} +... sulfur=${16} +... chlorine=${17} +... master=${999} + *** Keywords *** Set_Variable_If_At_Least - [Arguments] ${lower_bound} ${value_if_true} ${value_if_false} [Documentation] Compare ${lower_bound} to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at least ${lower_bound}, ... return ${value_if_false} otherwise. - BuiltIn.Run_Keyword_And_Return BuiltIn.Set_Variable_If ${Stream_dict}[${ODL_STREAM}] >= ${Stream_dict}[${lower_bound}] ${value_if_true} ${value_if_false} + [Arguments] ${lower_bound} ${value_if_true} ${value_if_false} + BuiltIn.Run_Keyword_And_Return + ... BuiltIn.Set_Variable_If + ... ${Stream_dict}[${ODL_STREAM}] >= ${Stream_dict}[${lower_bound}] + ... ${value_if_true} + ... ${value_if_false} Set_Variable_If_At_Most - [Arguments] ${upper_bound} ${value_if_true} ${value_if_false} [Documentation] Compare ${upper_bound} to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at most ${upper_bound}, ... return ${value_if_false} otherwise. - BuiltIn.Run_Keyword_And_Return BuiltIn.Set_Variable_If ${Stream_dict}[${ODL_STREAM}] <= ${Stream_dict}[${upper_bound}] ${value_if_true} ${value_if_false} + [Arguments] ${upper_bound} ${value_if_true} ${value_if_false} + BuiltIn.Run_Keyword_And_Return + ... BuiltIn.Set_Variable_If + ... ${Stream_dict}[${ODL_STREAM}] <= ${Stream_dict}[${upper_bound}] + ... ${value_if_true} + ... ${value_if_false} Set_Variable_If_At_Least_Carbon - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare carbon to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at least carbon, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Least carbon ${value_if_true} ${value_if_false} Set_Variable_If_At_Least_Nitrogen - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare nitrogen to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at least nitrogen, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Least nitrogen ${value_if_true} ${value_if_false} Set_Variable_If_At_Least_Oxygen - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare oxygen to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at least oxygen, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Least oxygen ${value_if_true} ${value_if_false} Set_Variable_If_At_Least_Fluorine - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare fluorine to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at least fluorine, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Least fluorine ${value_if_true} ${value_if_false} Set_Variable_If_At_Least_Neon - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare neon to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at least neon, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Least neon ${value_if_true} ${value_if_false} Set_Variable_If_At_Least_Sodium - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare neon to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at least sodium, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Least sodium ${value_if_true} ${value_if_false} Set_Variable_If_At_Least_Magnesium - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare magnesium to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at least magnesium, return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Least magnesium ${value_if_true} ${value_if_false} Set_Variable_If_At_Least_Aluminium - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare aluminium to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at least aluminium, return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Least aluminium ${value_if_true} ${value_if_false} Set_Variable_If_At_Least_Silicon - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare silicon to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at least silicon, return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Least silicon ${value_if_true} ${value_if_false} Set_Variable_If_At_Least_Phosphorus - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare phosphorus to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at least phosphorus, return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Least phosphorus ${value_if_true} ${value_if_false} Set_Variable_If_At_Least_Sulfur - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare sulfur to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at least sulfur, return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Least sulfur ${value_if_true} ${value_if_false} Set_Variable_If_At_Least_Chlorine - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare chlorine to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at least chlorine, return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Least chlorine ${value_if_true} ${value_if_false} Set_Variable_If_At_Most_Carbon - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare carbon to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at most carbon, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Most carbon ${value_if_true} ${value_if_false} Set_Variable_If_At_Most_Nitrogen - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare nitrogen to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at most nitrogen, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Most nitrogen ${value_if_true} ${value_if_false} Set_Variable_If_At_Most_Oxygen - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare oxygen to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at most oxygen, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Most oxygen ${value_if_true} ${value_if_false} Set_Variable_If_At_Most_Fluorine - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare fluorine to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at most fluorine, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Most fluorine ${value_if_true} ${value_if_false} Set_Variable_If_At_Most_Neon - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare neon to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at most neon, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Most neon ${value_if_true} ${value_if_false} Set_Variable_If_At_Most_Sodium - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare neon to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at most sodium, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Most sodium ${value_if_true} ${value_if_false} Set_Variable_If_At_Most_Magnesium - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare magnesium to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at most magnesium, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Most magnesium ${value_if_true} ${value_if_false} Set_Variable_If_At_Most_Aluminium - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare aluminium to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at most aluminium, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Most aluminium ${value_if_true} ${value_if_false} Set_Variable_If_At_Most_Silicon - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare silicon to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at most silicon, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Most silicon ${value_if_true} ${value_if_false} Set_Variable_If_At_Most_Phosphorus - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare phosphorus to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at most phosphorus, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Most phosphorus ${value_if_true} ${value_if_false} Set_Variable_If_At_Most_Sulfur - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare sulfur to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at most sulfur, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Most sulfur ${value_if_true} ${value_if_false} Set_Variable_If_At_Most_Chlorine - [Arguments] ${value_if_true} ${value_if_false} [Documentation] Compare chlorine to ${ODL_STREAM} and return ${value_if_true} if ${ODL_STREAM} is at most chlorine, ... return ${value_if_false} otherwise. + [Arguments] ${value_if_true} ${value_if_false} BuiltIn.Run_Keyword_And_Return Set_Variable_If_At_Most chlorine ${value_if_true} ${value_if_false} CompareStream__Convert_Input - [Arguments] @{arguments} [Documentation] Splits arguments into args and kwargs is used in Run_Keyword_If_At_Least_Else and Run_Keyword_If_At_Most_Else. ... The problem is, when the string contains =, but it is not a named argument (name=value). There can be many values containing =, but ... for sure it is present in xmls. If the string starts with "<" it will be treated as it is xml and splitting for ... name and value will not be executed. ... If named argument is passed into this kw, only string data are supported e.g. name=string. Complex variables such as lists or dictionaries ... are not supported. + [Arguments] @{arguments} ${args} BuiltIn.Create_List ${kwargs} BuiltIn.Create_Dictionary FOR ${arg} IN @{arguments} ${arg} BuiltIn.Convert_To_String ${arg} ${removed} String.Remove_String ${arg} \n ${Space} \t ... \r - ${splitted} BuiltIn.Run_Keyword_If "${removed[0]}" == "<" BuiltIn.Create List ${arg} - ... ELSE String.Split_String ${arg} separator== max_split=1 + IF "${removed[0]}" == "<" + ${splitted} BuiltIn.Create List ${arg} + ELSE + ${splitted} String.Split_String ${arg} separator== max_split=1 + END ${len} BuiltIn.Get_Length ${splitted} - Run Keyword If ${len}==1 Collections.Append_To_List ${args} ${splitted}[0] - ... ELSE Collections.Set_To_Dictionary ${kwargs} @{splitted} + IF ${len}==1 + Collections.Append_To_List ${args} ${splitted}[0] + ELSE + Collections.Set_To_Dictionary ${kwargs} @{splitted} + END END - BuiltIn.Return_From_Keyword ${args} ${kwargs} + RETURN ${args} ${kwargs} Run_Keyword_If_At_Least - [Arguments] ${lower_bound} ${kw_name} @{varargs} &{kwargs} [Documentation] Compare ${lower_bound} to ${ODL_STREAM} and in case ${ODL_STREAM} is at least ${lower_bound}, ... run ${kw_name} @{varargs} &{kwargs} and return its value. - BuiltIn.Run_Keyword_And_Return_If ${Stream_dict}[${ODL_STREAM}] >= ${Stream_dict}[${lower_bound}] ${kw_name} @{varargs} &{kwargs} + [Arguments] ${lower_bound} ${kw_name} @{varargs} &{kwargs} + BuiltIn.Run_Keyword_And_Return_If + ... ${Stream_dict}[${ODL_STREAM}] >= ${Stream_dict}[${lower_bound}] + ... ${kw_name} + ... @{varargs} + ... &{kwargs} Run_Keyword_If_At_Least_Else - [Arguments] ${lower_bound} @{varargs} [Documentation] Compare ${lower_bound} to ${ODL_STREAM} and in case ${ODL_STREAM} is at least ${lower_bound}, ... run keyword defined before ELSE statement otherwise run keyword defined after ELSE statement and return its value. + [Arguments] ${lower_bound} @{varargs} ${position} Collections.Get_Index_From_List ${varargs} \ELSE - BuiltIn.Run_Keyword_If "${position}" == "-1" BuiltIn.Fail Missing else statement in defined expresion + IF "${position}" == "-1" + BuiltIn.Fail Missing else statement in defined expresion + END ${varargs_if} Collections.Get_Slice_From_List ${varargs} 0 ${position} ${varargs_else} Collections.Get_Slice_From_List ${varargs} ${position+1} ${args_if} ${kwargs_if} CompareStream__Convert_Input @{varargs_if} ${args_else} ${kwargs_else} CompareStream__Convert_Input @{varargs_else} - ${resp} BuiltIn.Run_Keyword_If ${Stream_dict}[${ODL_STREAM}] >= ${Stream_dict}[${lower_bound}] @{args_if} &{kwargs_if} - ... ELSE @{args_else} &{kwargs_else} - [Return] ${resp} + IF ${Stream_dict}[${ODL_STREAM}] >= ${Stream_dict}[${lower_bound}] + ${resp} BuiltIn.Run_Keyword @{args_if} &{kwargs_if} + ELSE + ${resp} BuiltIn.Run_Keyword @{args_else} &{kwargs_else} + END + RETURN ${resp} Run_Keyword_If_At_Most - [Arguments] ${upper_bound} ${kw_name} @{varargs} &{kwargs} [Documentation] Compare ${upper_bound} to ${ODL_STREAM} and in case ${ODL_STREAM} is at most ${upper_bound}, ... run ${kw_name} @{varargs} &{kwargs} and return its value. - BuiltIn.Run_Keyword_And_Return_If ${Stream_dict}[${ODL_STREAM}] <= ${Stream_dict}[${upper_bound}] ${kw_name} @{varargs} &{kwargs} + [Arguments] ${upper_bound} ${kw_name} @{varargs} &{kwargs} + BuiltIn.Run_Keyword_And_Return_If + ... ${Stream_dict}[${ODL_STREAM}] <= ${Stream_dict}[${upper_bound}] + ... ${kw_name} + ... @{varargs} + ... &{kwargs} Run_Keyword_If_At_Most_Else - [Arguments] ${upper_bound} @{varargs} [Documentation] Compare ${upper_bound} to ${ODL_STREAM} and in case ${ODL_STREAM} is at most ${upper_bound}, ... run keyword defined before ELSE statement otherwise run keyword defined after ELSE statement and return its value. + [Arguments] ${upper_bound} @{varargs} ${position} Collections.Get_Index_From_List ${varargs} \ELSE - BuiltIn.Run_Keyword_If "${position}" == "-1" BuiltIn.Fail Missing else statement in defined expresion + IF "${position}" == "-1" + BuiltIn.Fail Missing else statement in defined expresion + END ${varargs_if} Collections.Get_Slice_From_List ${varargs} 0 ${position} ${varargs_else} Collections.Get_Slice_From_List ${varargs} ${position+1} ${args_if} ${kwargs_if} CompareStream__Convert_Input @{varargs_if} ${args_else} ${kwargs_else} CompareStream__Convert_Input @{varargs_else} - ${resp} BuiltIn.Run_Keyword_If ${Stream_dict}[${ODL_STREAM}] >= ${Stream_dict}[${lower_bound}] @{args_if} &{kwargs_if} - ... ELSE @{args_else} &{kwargs_else} - [Return] ${resp} + IF ${Stream_dict}[${ODL_STREAM}] <= ${Stream_dict}[${upper_bound}] + ${resp} BuiltIn.Run_Keyword @{args_if} &{kwargs_if} + ELSE + ${resp} BuiltIn.Run_Keyword @{args_else} &{kwargs_else} + END + RETURN ${resp} Run_Keyword_If_More_Than - [Arguments] ${lower_bound} ${kw_name} @{varargs} &{kwargs} [Documentation] Compare ${lower_bound} to ${ODL_STREAM} and in case ${ODL_STREAM} is more than ${lower_bound}, ... run ${kw_name} @{varargs} &{kwargs} and return its value. - BuiltIn.Run_Keyword_And_Return_If ${Stream_dict}[${ODL_STREAM}] > ${Stream_dict}[${lower_bound}] ${kw_name} @{varargs} &{kwargs} + [Arguments] ${lower_bound} ${kw_name} @{varargs} &{kwargs} + BuiltIn.Run_Keyword_And_Return_If + ... ${Stream_dict}[${ODL_STREAM}] > ${Stream_dict}[${lower_bound}] + ... ${kw_name} + ... @{varargs} + ... &{kwargs} Run_Keyword_If_Equals - [Arguments] ${stream} ${kw_name} @{varargs} &{kwargs} [Documentation] Compare ${stream} to ${ODL_STREAM} and in case ${ODL_STREAM} equals ${stream}, ... run ${kw_name} @{varargs} &{kwargs} and return its value. - BuiltIn.Run_Keyword_And_Return_If ${Stream_dict}[${ODL_STREAM}] == ${Stream_dict}[${stream}] ${kw_name} @{varargs} &{kwargs} + [Arguments] ${stream} ${kw_name} @{varargs} &{kwargs} + BuiltIn.Run_Keyword_And_Return_If + ... ${Stream_dict}[${ODL_STREAM}] == ${Stream_dict}[${stream}] + ... ${kw_name} + ... @{varargs} + ... &{kwargs} Run_Keyword_If_Equals_Else - [Arguments] ${stream} @{varargs} [Documentation] Compare ${stream} to ${ODL_STREAM} and in case ${ODL_STREAM} equals ${stream}, ... run keyword defined before ELSE statement otherwise run keyword defined after ELSE statement and return its value. + [Arguments] ${stream} @{varargs} ${position} Collections.Get_Index_From_List ${varargs} \ELSE - BuiltIn.Run_Keyword_If "${position}" == "-1" BuiltIn.Fail Missing else statement in defined expresion + IF "${position}" == "-1" + BuiltIn.Fail Missing else statement in defined expresion + END ${varargs_if} Collections.Get_Slice_From_List ${varargs} 0 ${position} ${varargs_else} Collections.Get_Slice_From_List ${varargs} ${position+1} ${args_if} ${kwargs_if} CompareStream__Convert_Input @{varargs_if} ${args_else} ${kwargs_else} CompareStream__Convert_Input @{varargs_else} - ${resp} BuiltIn.Run_Keyword_If ${Stream_dict}[${ODL_STREAM}] == ${Stream_dict}[${stream}] @{args_if} &{kwargs_if} - ... ELSE @{args_else} &{kwargs_else} - [Return] ${resp} + IF ${Stream_dict}[${ODL_STREAM}] == ${Stream_dict}[${stream}] + ${resp} BuiltIn.Run_Keyword @{args_if} &{kwargs_if} + ELSE + ${resp} BuiltIn.Run_Keyword @{args_else} &{kwargs_else} + END + RETURN ${resp} Run_Keyword_If_Less_Than - [Arguments] ${lower_bound} ${kw_name} @{varargs} &{kwargs} [Documentation] Compare ${lower_bound} to ${ODL_STREAM} and in case ${ODL_STREAM} is less than ${lower_bound}, ... run ${kw_name} @{varargs} &{kwargs} and return its value. - BuiltIn.Run_Keyword_And_Return_If ${Stream_dict}[${ODL_STREAM}] < ${Stream_dict}[${lower_bound}] ${kw_name} @{varargs} &{kwargs} + [Arguments] ${lower_bound} ${kw_name} @{varargs} &{kwargs} + BuiltIn.Run_Keyword_And_Return_If + ... ${Stream_dict}[${ODL_STREAM}] < ${Stream_dict}[${lower_bound}] + ... ${kw_name} + ... @{varargs} + ... &{kwargs} Run_Keyword_If_At_Least_Carbon - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare carbon to ${ODL_STREAM} and in case ${ODL_STREAM} is at least carbon, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Least carbon ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Least_Nitrogen - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare nitrogen to ${ODL_STREAM} and in case ${ODL_STREAM} is at least nitrogen, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Least nitrogen ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Least_Oxygen - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare oxygen to ${ODL_STREAM} and in case ${ODL_STREAM} is at least oxygen, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Least oxygen ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Least_Fluorine - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare fluorine to ${ODL_STREAM} and in case ${ODL_STREAM} is at least fluorine, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Least fluorine ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Least_Neon - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare neon to ${ODL_STREAM} and in case ${ODL_STREAM} is at least neon, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Least neon ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Least_Sodium - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare sodium to ${ODL_STREAM} and in case ${ODL_STREAM} is at least sodium, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Least sodium ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Least_Magnesium - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare magnesium to ${ODL_STREAM} and in case ${ODL_STREAM} is at least magnesium, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Least magnesium ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Least_Aluminium - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare aluminium to ${ODL_STREAM} and in case ${ODL_STREAM} is at least aluminium, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Least aluminium ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Least_Silicon - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare silicon to ${ODL_STREAM} and in case ${ODL_STREAM} is at least silicon, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Least silicon ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Least_Phosphorus - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare phosphorus to ${ODL_STREAM} and in case ${ODL_STREAM} is at least phosphorus, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Least phosphorus ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Least_Sulfur - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare sulfur to ${ODL_STREAM} and in case ${ODL_STREAM} is at least sulfur, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Least sulfur ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Least_Chlorine - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare chlorine to ${ODL_STREAM} and in case ${ODL_STREAM} is at least chlorine, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Least chlorine ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Most_Carbon - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare carbon to ${ODL_STREAM} and in case ${ODL_STREAM} is at most carbon, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Most carbon ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Most_Nitrogen - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare nitrogen to ${ODL_STREAM} and in case ${ODL_STREAM} is at most nitrogen, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Most nitrogen ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Most_Oxygen - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare oxygen to ${ODL_STREAM} and in case ${ODL_STREAM} is at most oxygen, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Most oxygen ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Most_Fluorine - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare fluorine to ${ODL_STREAM} and in case ${ODL_STREAM} is at most fluroine, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Most fluorine ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Most_Neon - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare neon to ${ODL_STREAM} and in case ${ODL_STREAM} is at most neon, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Most neon ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Most_Sodium - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare sodium to ${ODL_STREAM} and in case ${ODL_STREAM} is at most sodium, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Most sodium ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Most_Magnesium - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare magnesium to ${ODL_STREAM} and in case ${ODL_STREAM} is at most magnesium, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Most magnesium ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Most_Aluminium - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare aluminium to ${ODL_STREAM} and in case ${ODL_STREAM} is at most aluminium, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Most aluminium ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Most_Silicon - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare silicon to ${ODL_STREAM} and in case ${ODL_STREAM} is at most silicon, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Most silicon ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Most_Phosphorus - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare phosphorus to ${ODL_STREAM} and in case ${ODL_STREAM} is at most phosphorus, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Most phosphorus ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Most_Sulfur - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare sulfur to ${ODL_STREAM} and in case ${ODL_STREAM} is at most sulfur, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Most sulfur ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_At_Most_Chlorine - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare chlorine to ${ODL_STREAM} and in case ${ODL_STREAM} is at most chlorine, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_At_Most chlorine ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_More_Than_Carbon - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare carbon to ${ODL_STREAM} and in case ${ODL_STREAM} is more than carbon, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_More_Than carbon ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_More_Than_Nitrogen - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare nitrogen to ${ODL_STREAM} and in case ${ODL_STREAM} is more than nitrogen, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_More_Than nitrogen ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_More_Than_Oxygen - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare oxygen to ${ODL_STREAM} and in case ${ODL_STREAM} is more than oxygen, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_More_Than oxygen ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_More_Than_Fluorine - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare fluorine to ${ODL_STREAM} and in case ${ODL_STREAM} is more than fluorine, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_More_Than fluorine ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_More_Than_Neon - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare neon to ${ODL_STREAM} and in case ${ODL_STREAM} is more than neon, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_More_Than neon ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_More_Than_Sodium - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare sodium to ${ODL_STREAM} and in case ${ODL_STREAM} is more than sodium, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_More_Than sodium ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_More_Than_Magnesium - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare magnesium to ${ODL_STREAM} and in case ${ODL_STREAM} is more than magnesium, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_More_Than magnesium ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_More_Than_Aluminium - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare aluminium to ${ODL_STREAM} and in case ${ODL_STREAM} is more than aluminium, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_More_Than aluminium ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_More_Than_Silicon - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare silicon to ${ODL_STREAM} and in case ${ODL_STREAM} is more than silicon, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_More_Than silicon ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_More_Than_Phosphorus - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare phosphorus to ${ODL_STREAM} and in case ${ODL_STREAM} is more than phosphorus, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_More_Than phosphorus ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_More_Than_Sulfur - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare sulfur to ${ODL_STREAM} and in case ${ODL_STREAM} is more than sulfur, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_More_Than sulfur ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_More_Than_Chlorine - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare chlorine to ${ODL_STREAM} and in case ${ODL_STREAM} is more than chlorine, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_More_Than chlorine ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_Less_Than_Carbon - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare carbon to ${ODL_STREAM} and in case ${ODL_STREAM} is less than carbon, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_Less_Than carbon ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_Less_Than_Nitrogen - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare nitrogen to ${ODL_STREAM} and in case ${ODL_STREAM} is less than nitrogen, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_Less_Than nitrogen ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_Less_Than_Oxygen - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare oxygen to ${ODL_STREAM} and in case ${ODL_STREAM} is less than oxygen, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_Less_Than oxygen ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_Less_Than_Fluorine - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare fluorine to ${ODL_STREAM} and in case ${ODL_STREAM} is less than fluorine, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_Less_Than fluorine ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_Less_Than_Neon - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare neon to ${ODL_STREAM} and in case ${ODL_STREAM} is less than neon, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_Less_Than neon ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_Less_Than_Sodium - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare sodium to ${ODL_STREAM} and in case ${ODL_STREAM} is less than sodium, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_Less_Than sodium ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_Less_Than_Magnesium - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare magnesium to ${ODL_STREAM} and in case ${ODL_STREAM} is less than magnesium, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_Less_Than magnesium ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_Less_Than_Aluminium - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare aluminium to ${ODL_STREAM} and in case ${ODL_STREAM} is less than aluminium, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_Less_Than aluminium ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_Less_Than_Silicon - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare silicon to ${ODL_STREAM} and in case ${ODL_STREAM} is less than silicon, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_Less_Than silicon ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_Less_Than_Phosphorus - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare phosphorus to ${ODL_STREAM} and in case ${ODL_STREAM} is less than phosphorus, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_Less_Than phosphorus ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_Less_Than_Sulfur - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare sulfur to ${ODL_STREAM} and in case ${ODL_STREAM} is less than sulfur, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_Less_Than sulfur ${kw_name} @{varargs} &{kwargs} Run_Keyword_If_Less_Than_Chlorine - [Arguments] ${kw_name} @{varargs} &{kwargs} [Documentation] Compare chlorine to ${ODL_STREAM} and in case ${ODL_STREAM} is less than chlorine, ... run ${kw_name} @{varargs} &{kwargs} and return its value. + [Arguments] ${kw_name} @{varargs} &{kwargs} BuiltIn.Run_Keyword_And_Return Run_Keyword_If_Less_Than chlorine ${kw_name} @{varargs} &{kwargs} diff --git a/csit/libraries/DIDMKeywords.robot b/csit/libraries/DIDMKeywords.robot index a42e047ccc..9905ee117a 100644 --- a/csit/libraries/DIDMKeywords.robot +++ b/csit/libraries/DIDMKeywords.robot @@ -1,11 +1,13 @@ *** Settings *** -Documentation Keywords for DIDM suites -Library SSHLibrary -Library Collections -Library RequestsLibrary -Variables ../variables/Variables.py -Resource ./Utils.robot -Resource ../variables/openflowplugin/Variables.robot +Documentation Keywords for DIDM suites + +Library SSHLibrary +Library Collections +Library RequestsLibrary +Variables ../variables/Variables.py +Resource ./Utils.robot +Resource ../variables/openflowplugin/Variables.robot + *** Keywords *** Check DIDM Registered With Device @@ -14,7 +16,7 @@ Check DIDM Registered With Device Should Be Equal As Strings ${resp.status_code} 200 Log ${resp.text} Should Contain ${resp.text} didm - [Return] ${resp.text} + RETURN ${resp.text} Find Device Data [Documentation] Extract device information @@ -25,7 +27,7 @@ Find Device Data ${node_data}= Get From List ${node_resp} 0 Log ${node_data} Set Suite Variable ${node_data} - [Return] ${node_data} + RETURN ${node_data} Check Device IP [Documentation] Check for the device IP address @@ -38,7 +40,7 @@ Check Device IP ${line}= Get From List ${device_keys} ${index} Run Keyword And Return If '${dev_ip}' == '${line}' Get From Dictionary ${node_data} ${dev_ip} END - [Return] ${dev_ip} + RETURN ${dev_ip} Find Device Type [Documentation] Look for the device type @@ -50,9 +52,13 @@ Find Device Type ${length}= Get Length ${device_keys} FOR ${index} IN RANGE 0 ${length} ${line}= Get From List ${device_keys} ${index} - Run Keyword And Return If '${device_type}' == '${line}' Get From Dictionary ${node_data} ${device_type} + Run Keyword And Return If + ... '${device_type}' == '${line}' + ... Get From Dictionary + ... ${node_data} + ... ${device_type} END - [Return] ${device_type} + RETURN ${device_type} Find Device Hardware [Documentation] Look for the device hardware information @@ -64,7 +70,7 @@ Find Device Hardware ${line}= Get From List ${device_keys} ${index} Run Keyword And Return If '${device_hw}' == '${line}' Get From Dictionary ${node_data} ${device_hw} END - [Return] ${device_hw} + RETURN ${device_hw} Find Device Software [Documentation] Look for the device software information @@ -76,7 +82,7 @@ Find Device Software ${line}= Get From List ${device_keys} ${index} Run Keyword And Return If '${device_sw}' == '${line}' Get From Dictionary ${node_data} ${device_sw} END - [Return] ${device_sw} + RETURN ${device_sw} Find Device Manufacturer [Documentation] Look for the device manufacture @@ -86,9 +92,13 @@ Find Device Manufacturer ${length}= Get Length ${device_keys} FOR ${index} IN RANGE 0 ${length} ${line}= Get From List ${device_keys} ${index} - Run Keyword And Return If '${manufacture}' == '${line}' Get From Dictionary ${node_data} ${manufacture} + Run Keyword And Return If + ... '${manufacture}' == '${line}' + ... Get From Dictionary + ... ${node_data} + ... ${manufacture} END - [Return] ${manufacture} + RETURN ${manufacture} Find Serial Number [Documentation] Look for the device serial number @@ -98,9 +108,13 @@ Find Serial Number ${length}= Get Length ${device_keys} FOR ${index} IN RANGE 0 ${length} ${line}= Get From List ${device_keys} ${index} - Run Keyword And Return If '${serial_number}' == '${line}' Get From Dictionary ${node_data} ${serial_number} + Run Keyword And Return If + ... '${serial_number}' == '${line}' + ... Get From Dictionary + ... ${node_data} + ... ${serial_number} END - [Return] ${serial_number} + RETURN ${serial_number} Find Device Description [Documentation] Look for the device description @@ -110,6 +124,10 @@ Find Device Description ${length}= Get Length ${device_keys} FOR ${index} IN RANGE 0 ${length} ${line}= Get From List ${device_keys} ${index} - Run Keyword And Return If '${description}' == '${line}' Get From Dictionary ${node_data} ${description} + Run Keyword And Return If + ... '${description}' == '${line}' + ... Get From Dictionary + ... ${node_data} + ... ${description} END - [Return] ${description} + RETURN ${description} diff --git a/csit/libraries/DaeximKeywords.robot b/csit/libraries/DaeximKeywords.robot index 67af13ed71..cc1aa1c202 100644 --- a/csit/libraries/DaeximKeywords.robot +++ b/csit/libraries/DaeximKeywords.robot @@ -1,107 +1,144 @@ *** Settings *** -Library OperatingSystem -Library SSHLibrary -Library Collections -Library RequestsLibrary -Resource ClusterManagement.robot -Resource ../variables/daexim/DaeximVariables.robot -Resource ../variables/Variables.robot -Resource SSHKeywords.robot +Library OperatingSystem +Library SSHLibrary +Library Collections +Library RequestsLibrary +Resource ClusterManagement.robot +Resource ../variables/daexim/DaeximVariables.robot +Resource ../variables/Variables.robot +Resource SSHKeywords.robot + *** Keywords *** Verify Export Files - [Arguments] ${host_index} [Documentation] Verify if the backedup files are present in the controller + [Arguments] ${host_index} ${host_index} Builtin.Convert To Integer ${host_index} - ${cfg} ClusterManagement.Run Bash Command On Member ls -lart ${WORKSPACE}/${BUNDLEFOLDER}/daexim/${EXP_DATA_FILE} ${host_index} + ${cfg} ClusterManagement.Run Bash Command On Member + ... ls -lart ${WORKSPACE}/${BUNDLEFOLDER}/daexim/${EXP_DATA_FILE} + ... ${host_index} Builtin.Log ${cfg} Builtin.Should Match Regexp ${cfg} .*${EXP_DATA_FILE} - ${mdl} ClusterManagement.Run Bash Command On Member ls -lart ${WORKSPACE}/${BUNDLEFOLDER}/daexim/${MODELS_FILE} ${host_index} + ${mdl} ClusterManagement.Run Bash Command On Member + ... ls -lart ${WORKSPACE}/${BUNDLEFOLDER}/daexim/${MODELS_FILE} + ... ${host_index} Builtin.Log ${mdl} Builtin.Should Match Regexp ${mdl} .*${MODELS_FILE} - ${opr} ClusterManagement.Run Bash Command On Member ls -lart ${WORKSPACE}/${BUNDLEFOLDER}/daexim/${EXP_OPER_FILE} ${host_index} + ${opr} ClusterManagement.Run Bash Command On Member + ... ls -lart ${WORKSPACE}/${BUNDLEFOLDER}/daexim/${EXP_OPER_FILE} + ... ${host_index} Builtin.Log ${opr} Builtin.Should Match Regexp ${opr} .*${EXP_OPER_FILE} Verify Export Files Not Present - [Arguments] ${host_index} [Documentation] Verify if the backedup files are not present in the controller + [Arguments] ${host_index} ${host_index} Builtin.Convert To Integer ${host_index} - ${cfg} ClusterManagement.Run Bash Command On Member ls -lart ${WORKSPACE}/${BUNDLEFOLDER}/daexim/${EXP_DATA_FILE} ${host_index} + ${cfg} ClusterManagement.Run Bash Command On Member + ... ls -lart ${WORKSPACE}/${BUNDLEFOLDER}/daexim/${EXP_DATA_FILE} + ... ${host_index} Builtin.Log ${cfg} Builtin.Should Not Match Regexp ${cfg} .*${EXP_DATA_FILE} - ${mdl} ClusterManagement.Run Bash Command On Member ls -lart ${WORKSPACE}/${BUNDLEFOLDER}/daexim/${MODELS_FILE} ${host_index} + ${mdl} ClusterManagement.Run Bash Command On Member + ... ls -lart ${WORKSPACE}/${BUNDLEFOLDER}/daexim/${MODELS_FILE} + ... ${host_index} Builtin.Log ${mdl} Builtin.Should Not Match Regexp ${mdl} .*${MODELS_FILE} - ${opr} ClusterManagement.Run Bash Command On Member ls -lart ${WORKSPACE}/${BUNDLEFOLDER}/daexim/${EXP_OPER_FILE} ${host_index} + ${opr} ClusterManagement.Run Bash Command On Member + ... ls -lart ${WORKSPACE}/${BUNDLEFOLDER}/daexim/${EXP_OPER_FILE} + ... ${host_index} Builtin.Log ${opr} Builtin.Should Not Match Regexp ${opr} .*${EXP_OPER_FILE} Cleanup The Export Files - [Arguments] ${host_index} [Documentation] Verify if the export directory exists and delete the files if needed + [Arguments] ${host_index} ${host_index} Builtin.Convert To Integer ${host_index} - Builtin.Run Keyword And Ignore Error ClusterManagement.Delete And Check Member List Or All ${TOPOLOGY_URL} ${host_index} - ${output1} Builtin.Run Keyword and IgnoreError ClusterManagement.Run Bash Command On Member sudo rm -rf ${WORKSPACE}/${BUNDLEFOLDER}/daexim;clear ${host_index} - ${output2} Builtin.Run Keyword and IgnoreError ClusterManagement.Run Bash Command On Member rm -rf ${WORKSPACE}/${BUNDLEFOLDER}/daexim;clear ${host_index} + Builtin.Run Keyword And Ignore Error + ... ClusterManagement.Delete And Check Member List Or All + ... ${TOPOLOGY_URL} + ... ${host_index} + ${output1} Builtin.Run Keyword and IgnoreError + ... ClusterManagement.Run Bash Command On Member + ... sudo rm -rf ${WORKSPACE}/${BUNDLEFOLDER}/daexim;clear + ... ${host_index} + ${output2} Builtin.Run Keyword and IgnoreError + ... ClusterManagement.Run Bash Command On Member + ... rm -rf ${WORKSPACE}/${BUNDLEFOLDER}/daexim;clear + ... ${host_index} ${output} ClusterManagement.Run Bash Command On Member ls -lart ${WORKSPACE}/${BUNDLEFOLDER} ${host_index} Builtin.Log ${output} Builtin.Should Not Match Regexp ${output} daexim Verify Export Status - [Arguments] ${status} ${controller_index} [Documentation] Verify export status is as expected - ${response_json} ClusterManagement.Post As Json To Member ${STATUS_EXPORT_URL} ${EMPTY} ${controller_index} + [Arguments] ${status} ${controller_index} + ${response_json} ClusterManagement.Post As Json To Member + ... ${STATUS_EXPORT_URL} + ... ${EMPTY} + ... ${controller_index} Builtin.Log ${response_json} ${response_json} Builtin.Convert To String ${response_json} Verify Export Status Message ${status} ${response_json} Verify Scheduled Export Timestamp - [Arguments] ${controller_index} ${time} [Documentation] Verify export timestamp is as expected - ${response_json} ClusterManagement.Post As Json To Member ${STATUS_EXPORT_URL} ${EMPTY} ${controller_index} + [Arguments] ${controller_index} ${time} + ${response_json} ClusterManagement.Post As Json To Member + ... ${STATUS_EXPORT_URL} + ... ${EMPTY} + ... ${controller_index} Builtin.Log ${response_json} ${response_json} Builtin.Convert To String ${response_json} Builtin.Should Match Regexp ${response_json} .*"run-at": "${time}" Verify Export Status Message - [Arguments] ${status} ${output} [Documentation] Verify export restconf response message is as expected + [Arguments] ${status} ${output} Builtin.Should Match Regexp ${output} "status": "${status}" - Builtin.Run Keyword If "${status}" == "initial" or "${status}" == "scheduled" or "${status}" == "skipped" Verify Json Files Not Present ${output} - ... ELSE Verify Json Files Present ${output} + IF "${status}" == "initial" or "${status}" == "scheduled" or "${status}" == "skipped" + Verify Json Files Not Present ${output} + ELSE + Verify Json Files Present ${output} + END Verify Json Files Present - [Arguments] ${output} ${config_json}=${EXP_DATA_FILE} ${models_json}=${MODELS_FILE} ${operational_json}=${EXP_OPER_FILE} [Documentation] Verify if the json files are generated after a export/export + [Arguments] ${output} ${config_json}=${EXP_DATA_FILE} ${models_json}=${MODELS_FILE} ${operational_json}=${EXP_OPER_FILE} Builtin.Should Match Regexp ${output} .*${config_json} Builtin.Should Match Regexp ${output} .*${models_json} Builtin.Should Match Regexp ${output} .*${operational_json} Builtin.Log Found all Json Files Verify Json Files Not Present - [Arguments] ${output} ${config_json}=${EXP_DATA_FILE} ${models_json}=${MODELS_FILE} ${operational_json}=${EXP_OPER_FILE} [Documentation] Verify if the json files are not present under the daexim folder + [Arguments] ${output} ${config_json}=${EXP_DATA_FILE} ${models_json}=${MODELS_FILE} ${operational_json}=${EXP_OPER_FILE} Builtin.Should Not Match Regexp ${output} .*${config_json} Builtin.Should Not Match Regexp ${output} .*${models_json} Builtin.Should Not Match Regexp ${output} .*${operational_json} Builtin.Log Did not Find all Json Files Schedule Export + [Documentation] Schedule Export job [Arguments] ${controller_index} ${time}=500 ${exclude}=${FALSE} ${module}=${EMPTY} ${store}=${EMPTY} ${flag}=false ... ${include}=${FALSE} - [Documentation] Schedule Export job - ${file} = Builtin.Run Keyword If ${include} Builtin.Set Variable ${EXPORT_INCLUDE_FILE} - ... ELSE Builtin.Set Variable If ${exclude} ${EXPORT_EXCLUDE_FILE} ${EXPORT_FILE} + IF ${include} + ${file} Builtin.Set Variable ${EXPORT_INCLUDE_FILE} + ELSE + ${file} Builtin.Set Variable If ${exclude} ${EXPORT_EXCLUDE_FILE} ${EXPORT_FILE} + END ${json} OperatingSystem.Get File ${file} ${json} Builtin.Replace Variables ${json} Cleanup The Export Files ${controller_index} - ${response_json} ClusterManagement.Post As Json To Member ${SCHEDULE_EXPORT_URL} ${json} ${controller_index} + ${response_json} ClusterManagement.Post As Json To Member + ... ${SCHEDULE_EXPORT_URL} + ... ${json} + ... ${controller_index} Builtin.Log ${response_json} Schedule Exclude Export - [Arguments] ${controller_index} ${store} ${module} [Documentation] Schedules a export with exclude option. Returns the file that has the excluded export. + [Arguments] ${controller_index} ${store} ${module} ${controller_index} Builtin.Convert To Integer ${controller_index} ${host} ClusterManagement.Resolve IP Address For Member ${controller_index} Schedule Export ${controller_index} 500 ${TRUE} ${module} ${store} @@ -110,52 +147,58 @@ Schedule Exclude Export Copy Export Directory To Test VM ${host} ${export_file} Builtin.Set Variable If '${store}' == 'operational' ${EXP_OPER_FILE} ${EXP_DATA_FILE} ${file_path} OperatingSystem.Join Path ${EXP_DIR}${host} ${export_file} - [Return] ${file_path} + RETURN ${file_path} Schedule Include Export - [Arguments] ${controller_index} ${store} ${module}=${EMPTY} ${exclude}=${FALSE} [Documentation] Schedules a export with include option. Returns the file that has the included export. + [Arguments] ${controller_index} ${store} ${module}=${EMPTY} ${exclude}=${FALSE} ${controller_index} Builtin.Convert To Integer ${controller_index} ${host} ClusterManagement.Resolve IP Address For Member ${controller_index} ${time} Builtin.Set Variable 500 - ${file} = Builtin.Set Variable If ${exclude} ${EXPORT_INCEXCLUDE_FILE} ${EXPORT_INCLUDE_FILE} + ${file} Builtin.Set Variable If ${exclude} ${EXPORT_INCEXCLUDE_FILE} ${EXPORT_INCLUDE_FILE} ${json} OperatingSystem.Get File ${file} ${json} Builtin.Replace Variables ${json} Cleanup The Export Files ${controller_index} - ${response_json} ClusterManagement.Post As Json To Member ${SCHEDULE_EXPORT_URL} ${json} ${controller_index} + ${response_json} ClusterManagement.Post As Json To Member + ... ${SCHEDULE_EXPORT_URL} + ... ${json} + ... ${controller_index} Builtin.Log ${response_json} Builtin.Wait Until Keyword Succeeds 10 sec 5 sec Verify Export Status complete ${controller_index} Verify Export Files ${controller_index} Copy Export Directory To Test VM ${host} ${export_file} Builtin.Set Variable If '${store}' == 'operational' ${EXP_OPER_FILE} ${EXP_DATA_FILE} ${file_path} OperatingSystem.Join Path ${EXP_DIR}${host} ${export_file} - [Return] ${file_path} + RETURN ${file_path} Cancel Export - [Arguments] ${controller_index} [Documentation] Cancel the export job - ${response_json} ClusterManagement.Post As Json To Member ${CANCEL_EXPORT_URL} ${EMPTY} ${controller_index} + [Arguments] ${controller_index} + ${response_json} ClusterManagement.Post As Json To Member + ... ${CANCEL_EXPORT_URL} + ... ${EMPTY} + ... ${controller_index} Builtin.Log ${response_json} Return ConnnectionID - [Arguments] ${system}=${ODL_SYSTEM_IP} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=${DEFAULT_TIMEOUT} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} [Documentation] Returns the connection of any host. Defaults to controller + [Arguments] ${system}=${ODL_SYSTEM_IP} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=${DEFAULT_TIMEOUT} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${conn_id} SSHLibrary.Open Connection ${system} prompt=${prompt} timeout=${prompt_timeout} SSHKeywords.Flexible SSH Login ${user} ${password} - [Return] ${conn_id} + RETURN ${conn_id} Cleanup Directory - [Arguments] ${dir} [Documentation] Cleans up the given directory if it exists + [Arguments] ${dir} OperatingSystem.Empty Directory ${dir} OperatingSystem.Remove Directory ${dir} Copy Export Directory To Test VM - [Arguments] ${host} [Documentation] This keyword copies the daexim folder genereated in the controller to robot vm. This is done to editing if needed on the json files + [Arguments] ${host} ${new_dir} Builtin.Set Variable ${EXP_DIR}${host} ${directory_exist} Builtin.Run Keyword And Return Status OperatingSystem.Directory Should Exist ${new_dir} - Builtin.Run Keyword If ${directory_exist} Cleanup Directory ${new_dir} + IF ${directory_exist} Cleanup Directory ${new_dir} ${connections} Return ConnnectionID ${host} SSHLibrary.Switch Connection ${connections} SSHLibrary.Directory Should Exist ${WORKSPACE}/${BUNDLEFOLDER}/daexim @@ -167,8 +210,8 @@ Copy Export Directory To Test VM Builtin.Log ${fl} Copy Config Data To Controller - [Arguments] ${host_index} [Documentation] This keyword copies the daexim folder under variables folder to the Controller + [Arguments] ${host_index} ${host_index} Builtin.Convert To Integer ${host_index} ${host} ClusterManagement.Resolve IP Address For Member ${host_index} ${connections} Return ConnnectionID ${host} @@ -177,8 +220,8 @@ Copy Config Data To Controller SSHLibrary.Close Connection Mount Netconf Endpoint - [Arguments] ${endpoint} ${host_index} [Documentation] Mount a netconf endpoint + [Arguments] ${endpoint} ${host_index} ${ENDPOINT} Builtin.Set Variable ${endpoint} ${json} OperatingSystem.Get File ${CURDIR}/${NETCONF_PAYLOAD_JSON} ${json} Builtin.Replace Variables ${json} @@ -187,28 +230,30 @@ Mount Netconf Endpoint Builtin.Log ${resp} Fetch Status Information From Netconf Endpoint - [Arguments] ${endpoint} ${host_index} [Documentation] This keyword fetches netconf endpoint information + [Arguments] ${endpoint} ${host_index} ${resp} ClusterManagement.Get From Member ${NETCONF_NODE_URL}=${endpoint} ${host_index} ${output1} Builtin.Set Variable ${resp} ${output} RequestsLibrary.To Json ${output1} Builtin.Log ${output} - ${status} Collections.Get From Dictionary ${output['network-topology:node'][0]} netconf-node-topology:connection-status - [Return] ${status} ${output} + ${status} Collections.Get From Dictionary + ... ${output['network-topology:node'][0]} + ... netconf-node-topology:connection-status + RETURN ${status} ${output} Verify Status Information - [Arguments] ${endpoint} ${host_index} ${itr}=50 [Documentation] Verify if a netconf endpoint status is connected by running in a loop + [Arguments] ${endpoint} ${host_index} ${itr}=50 FOR ${i} IN RANGE ${itr} ${sts} ${op} Fetch Status Information From Netconf Endpoint ${endpoint} ${host_index} Builtin.Log ${i} - Builtin.Exit For Loop If "${sts}" == "${NTCF_OPR_STATUS}" + IF "${sts}" == "${NTCF_OPR_STATUS}" BREAK END - [Return] ${sts} ${op} + RETURN ${sts} ${op} Verify Netconf Mount - [Arguments] ${endpoint} ${host_index} [Documentation] Verify if a netconf endpoint is mounted + [Arguments] ${endpoint} ${host_index} ${sts1} ${output} Verify Status Information ${endpoint} ${host_index} ${ep} Collections.Get From Dictionary ${output['network-topology:node'][0]} node-id ${port} Collections.Get From Dictionary ${output['network-topology:node'][0]} netconf-node-topology:port @@ -217,23 +262,30 @@ Verify Netconf Mount Builtin.Should Be Equal ${port} ${NETCONF_PORT} Schedule Import - [Arguments] ${host_index} ${result}=true ${reason}=${EMPTY} ${mdlflag}=${MDL_DEF_FLAG} ${strflag}=${STR_DEF_FLAG} [Documentation] Schedule an Import API + [Arguments] ${host_index} ${result}=true ${reason}=${EMPTY} ${mdlflag}=${MDL_DEF_FLAG} ${strflag}=${STR_DEF_FLAG} ${modelflag} Builtin.Set Variable ${mdlflag} ${storeflag} Builtin.Set Variable ${strflag} ${json} OperatingSystem.Get File ${CURDIR}/${IMPORT_PAYLOAD} ${json} Builtin.Replace Variables ${json} Builtin.Log ${json} - ${resp} Builtin.Wait Until Keyword Succeeds 120 seconds 10 seconds ClusterManagement.Post As Json To Member ${IMPORT_URL} ${json} + ${resp} Builtin.Wait Until Keyword Succeeds + ... 120 seconds + ... 10 seconds + ... ClusterManagement.Post As Json To Member + ... ${IMPORT_URL} + ... ${json} ... ${host_index} Builtin.Log ${resp} Builtin.Should Match Regexp ${resp} .*"result": ${result} - Builtin.Run Keyword If "${reason}" != "${EMPTY}" Builtin.Should Match Regexp ${response_json} .*"reason":"${reason} + IF "${reason}" != "${EMPTY}" + Builtin.Should Match Regexp ${response_json} .*"reason":"${reason} + END Cleanup Cluster Export Files - [Arguments] ${member_index_list}=${EMPTY} [Documentation] This keyword cleansup export files of a cluster - ${index_list} = List Indices Or All given_list=${member_index_list} + [Arguments] ${member_index_list}=${EMPTY} + ${index_list} List Indices Or All given_list=${member_index_list} FOR ${index} IN @{index_list} # usually: 1, 2, 3. DaeximKeywords.Cleanup The Export Files ${index} END diff --git a/csit/libraries/DataModels.robot b/csit/libraries/DataModels.robot index f9df0cfa6e..57ed07d2da 100644 --- a/csit/libraries/DataModels.robot +++ b/csit/libraries/DataModels.robot @@ -1,22 +1,31 @@ *** Settings *** -Documentation Library to deal with mdsal data models. Initially, as a common place to show and -... debug a list of data models. -Library RequestsLibrary -Resource ../variables/netvirt/Variables.robot +Documentation Library to deal with mdsal data models. Initially, as a common place to show and +... debug a list of data models. + +Library RequestsLibrary +Resource ../variables/netvirt/Variables.robot + *** Variables *** -@{internal_data_models} ${EMPTY} +@{internal_data_models} ${EMPTY} + *** Keywords *** Get Model Dump - [Arguments] ${controller_ip} ${data_models}=@{internal_data_models} ${restconf_root}=restconf [Documentation] Will output a list of mdsal models using ${data_models} list + [Arguments] ${controller_ip} ${data_models}=@{internal_data_models} ${restconf_root}=restconf # while feature request in bug 7892 is not done, we will quickly timeout and not retry the model dump get # request. This is because when it's done in a failed cluster state, it could take 20s for the reesponse to # to come back as the internal clustering times out waiting for a leader which will not come. When bug 7892 # is resolved, we can remove the timeout=1 and max_retries=0, but likely have to modify the request itself to # pass a timeout to restconf - Create Session model_dump_session http://${controller_ip}:${RESTCONFPORT} auth=${AUTH} headers=${HEADERS} timeout=1 max_retries=0 + Create Session + ... model_dump_session + ... http://${controller_ip}:${RESTCONFPORT} + ... auth=${AUTH} + ... headers=${HEADERS} + ... timeout=1 + ... max_retries=0 FOR ${model} IN @{data_models} ${resp}= RequestsLibrary.Get Request model_dump_session ${restconf_root}/${model} ${pretty_output}= To Json ${resp.text} pretty_print=True @@ -24,9 +33,11 @@ Get Model Dump END Verify No Ingress Dispatcher Non-Default Flow Entries - [Arguments] ${ovs_ip} [Documentation] Verify the ingress dispatcher table has no non-default flows after neutron was cleaned up - ${flow_output}= Run Command On Remote System ${ovs_ip} sudo ovs-ofctl -O OpenFlow13 dump-flows ${INTEGRATION_BRIDGE} table=${DISPATCHER_TABLE} | grep -v "priority=0" + [Arguments] ${ovs_ip} + ${flow_output}= Run Command On Remote System + ... ${ovs_ip} + ... sudo ovs-ofctl -O OpenFlow13 dump-flows ${INTEGRATION_BRIDGE} table=${DISPATCHER_TABLE} | grep -v "priority=0" Log ${flow_output} #Should Not Contain ${flow_output} table=${DISPATCHER_TABLE} # Skipping test verification until bug 7451 is resolved diff --git a/csit/libraries/DatastoreCRUD.robot b/csit/libraries/DatastoreCRUD.robot index ce6f98a50e..dd591fe3e8 100644 --- a/csit/libraries/DatastoreCRUD.robot +++ b/csit/libraries/DatastoreCRUD.robot @@ -1,74 +1,95 @@ *** Settings *** -Library Collections -Library RequestsLibrary -Variables ../variables/Variables.py +Library Collections +Library RequestsLibrary +Variables ../variables/Variables.py + *** Keywords *** Create Records - [Arguments] ${controller_ip} ${node} ${first} ${last} ${prefix} ${field bases} - ... ${postfix} [Documentation] POSTs records to a controller's data store. First and last index numbers are specified ... as is a dictionary called field_bases containing the base name for the field contents ... onto which will be appended the index number. Prefix and postfix are used to complete ... the JSON payload. The keyword passes if return code is correct. - ${last} Convert to Integer ${last} + [Arguments] ${controller_ip} ${node} ${first} ${last} ${prefix} ${field bases} + ... ${postfix} + ${last}= Convert to Integer ${last} FOR ${INDEX} IN RANGE ${first} ${last+1} ${payload}= Assemble Payload ${INDEX} ${prefix} ${field bases} ${postfix} Log ${payload} - Create_Session session http://${controller_ip}:${RESTCONFPORT}${CONFIG_API} headers=${HEADERS} auth=${AUTH} - ${resp} RequestsLibrary.Post Request session ${node} ${payload} + Create_Session + ... session + ... http://${controller_ip}:${RESTCONFPORT}${CONFIG_API} + ... headers=${HEADERS} + ... auth=${AUTH} + ${resp}= RequestsLibrary.Post Request session ${node} ${payload} Log ${resp} Should Be Equal As Strings ${resp} END Read Records - [Arguments] ${controller_ip} ${node} [Documentation] GETs records from a shard on a controller's data store. - Create_Session session http://${controller_ip}:${RESTCONFPORT}${CONFIG_API} headers=${HEADERS} auth=${AUTH} + [Arguments] ${controller_ip} ${node} + Create_Session + ... session + ... http://${controller_ip}:${RESTCONFPORT}${CONFIG_API} + ... headers=${HEADERS} + ... auth=${AUTH} ${resp}= RequestsLibrary.Get Request session ${node} - [Return] ${resp.json()} + RETURN ${resp.json()} Update Records - [Arguments] ${controller_ip} ${node} ${first} ${last} ${prefix} ${field bases} - ... ${postfix} [Documentation] PUTs records to shard on a controller's data store. First and last index numbers are specified ... as is a dictionary called field_bases containing the base name for the field contents ... onto which will be appended the index number. Prefix and postfix are used to complete ... the JSON payload. The keyword passes if return code is correct. - ${last} Convert to Integer ${last} + [Arguments] ${controller_ip} ${node} ${first} ${last} ${prefix} ${field bases} + ... ${postfix} + ${last}= Convert to Integer ${last} FOR ${INDEX} IN RANGE ${first} ${last+1} ${payload}= Assemble Payload ${INDEX} ${prefix} ${field bases} ${postfix} Log ${payload} - Create_Session session http://${controller_ip}:${RESTCONFPORT}${CONFIG_API} headers=${HEADERS} auth=${AUTH} + Create_Session + ... session + ... http://${controller_ip}:${RESTCONFPORT}${CONFIG_API} + ... headers=${HEADERS} + ... auth=${AUTH} ${resp}= RequestsLibrary.Put Request session ${node}/${INDEX} ${payload} Log ${resp} Should Be Equal As Strings ${resp} END Delete Records - [Arguments] ${controller_ip} ${node} ${first} ${last} [Documentation] DELETEs specified range of records from a shard on a contrsoller's data store. - ${last} Convert to Integer ${last} + [Arguments] ${controller_ip} ${node} ${first} ${last} + ${last}= Convert to Integer ${last} FOR ${INDEX} IN RANGE ${first} ${last+1} - Create_Session session http://${controller_ip}:${RESTCONFPORT}${CONFIG_API} headers=${HEADERS} auth=${AUTH} + Create_Session + ... session + ... http://${controller_ip}:${RESTCONFPORT}${CONFIG_API} + ... headers=${HEADERS} + ... auth=${AUTH} ${resp}= RequestsLibrary.Delete Request session ${node}/${INDEX} Should Be Equal As Strings ${resp} END Delete All Records - [Arguments] ${controller_ip} ${node} [Documentation] DELETEs all records from a shard on a controller's data store. - Create_Session session http://${controller_ip}:${RESTCONFPORT}${CONFIG_API} headers=${HEADERS} auth=${AUTH} + [Arguments] ${controller_ip} ${node} + Create_Session + ... session + ... http://${controller_ip}:${RESTCONFPORT}${CONFIG_API} + ... headers=${HEADERS} + ... auth=${AUTH} ${resp}= RequestsLibrary.Delete Request session ${node} Should Be Equal As Strings ${resp} Assemble Payload - [Arguments] ${id} ${prefix} ${field bases} ${postfix} [Documentation] Populates a payload for creating or updating a shard record. ... id: The record number and is also appended onto each field to uniquely identify it. ... prefix: The portion of the json payload before the records. ... field bases: A dictionary of records onto which the id is appended. ... prefix: The portion of the json payload after the records. + [Arguments] ${id} ${prefix} ${field bases} ${postfix} ${length}= Get Length ${field bases} ${keys}= Get Dictionary Keys ${field bases} ${payload}= Set Variable ${prefix} @@ -78,4 +99,4 @@ Assemble Payload END ${payload}= Get Substring ${payload} ${EMPTY} -1 ${payload}= Catenate ${payload} ${postfix} - [Return] ${payload} + RETURN ${payload} diff --git a/csit/libraries/DevstackUtils.robot b/csit/libraries/DevstackUtils.robot index 3f5ef5debb..a8bb601073 100644 --- a/csit/libraries/DevstackUtils.robot +++ b/csit/libraries/DevstackUtils.robot @@ -1,22 +1,25 @@ *** Settings *** -Documentation General Utils library. This library has broad scope, it can be used by any robot system tests. -Library RequestsLibrary -Library SSHLibrary -Resource OpenStackOperations.robot -Resource ../variables/Variables.robot +Documentation General Utils library. This library has broad scope, it can be used by any robot system tests. + +Library RequestsLibrary +Library SSHLibrary +Resource OpenStackOperations.robot +Resource ../variables/Variables.robot + *** Variables *** -${DEFAULT_DEVSTACK_PROMPT_TIMEOUT} 10s -${DEVSTACK_SYSTEM_PASSWORD} \ # set to empty, but provide for others to override if desired -${OS_CNTL_CONN_ID} None -${OS_CMP1_CONN_ID} None -${OS_CMP2_CONN_ID} None -${OS_CNTL_IP} ${EMPTY} -${OS_CMP1_IP} ${EMPTY} -${OS_CMP2_IP} ${EMPTY} -@{OS_ALL_IPS} @{EMPTY} -@{OS_CMP_IPS} @{EMPTY} -${OS_NODE_CNT} ${1} +${DEFAULT_DEVSTACK_PROMPT_TIMEOUT} 10s +${DEVSTACK_SYSTEM_PASSWORD} \ # set to empty, but provide for others to override if desired +${OS_CNTL_CONN_ID} None +${OS_CMP1_CONN_ID} None +${OS_CMP2_CONN_ID} None +${OS_CNTL_IP} ${EMPTY} +${OS_CMP1_IP} ${EMPTY} +${OS_CMP2_IP} ${EMPTY} +@{OS_ALL_IPS} @{EMPTY} +@{OS_CMP_IPS} @{EMPTY} +${OS_NODE_CNT} ${1} + *** Keywords *** Open Connection @@ -24,34 +27,42 @@ Open Connection ${conn_id} = SSHLibrary.Open Connection ${ip} prompt=${DEFAULT_LINUX_PROMPT} SSHKeywords.Flexible SSH Login ${OS_USER} ${DEVSTACK_SYSTEM_PASSWORD} BuiltIn.Set Suite Variable \${${name}} ${conn_id} - [Return] ${conn_id} + RETURN ${conn_id} Devstack Suite Setup - [Arguments] ${odl_ip}=${ODL_SYSTEM_IP} [Documentation] Open connections to the nodes + [Arguments] ${odl_ip}=${ODL_SYSTEM_IP} SSHLibrary.Set Default Configuration timeout=${DEFAULT_DEVSTACK_PROMPT_TIMEOUT} DevstackUtils.Get DevStack Nodes Data RequestsLibrary.Create Session session http://${odl_ip}:${RESTCONFPORT} auth=${AUTH} headers=${HEADERS} Write Commands Until Prompt - [Arguments] ${cmd} ${timeout}=${DEFAULT_DEVSTACK_PROMPT_TIMEOUT} [Documentation] quick wrapper for Write and Read Until Prompt Keywords to make test cases more readable + [Arguments] ${cmd} ${timeout}=${DEFAULT_DEVSTACK_PROMPT_TIMEOUT} SSHLibrary.Set Client Configuration timeout=${timeout} SSHLibrary.Read SSHLibrary.Write ${cmd};echo Command Returns $? ${output} = SSHLibrary.Read Until Prompt - [Return] ${output} + RETURN ${output} Write Commands Until Prompt And Log - [Arguments] ${cmd} ${timeout}=${DEFAULT_DEVSTACK_PROMPT_TIMEOUT} [Documentation] quick wrapper for Write and Read Until Prompt Keywords to make test cases more readable + [Arguments] ${cmd} ${timeout}=${DEFAULT_DEVSTACK_PROMPT_TIMEOUT} ${output} = DevstackUtils.Write Commands Until Prompt ${cmd} ${timeout} BuiltIn.Log ${output} - [Return] ${output} + RETURN ${output} Log Devstack Nodes Data - ${output} = BuiltIn.Catenate SEPARATOR=\n OS_CNTL_HOSTNAME: ${OS_CNTL_HOSTNAME} - OS_CNTL_IP: ${OS_CNTL_IP} - OS_CONTROL_NODE_IP: ${OS_CONTROL_NODE_IP} OS_CMP1_HOSTNAME: ${OS_CMP1_HOSTNAME} - OS_CMP1_IP: ${OS_CMP1_IP} - OS_COMPUTE_1_IP: ${OS_COMPUTE_1_IP} OS_CMP2_HOSTNAME: ${OS_CMP2_HOSTNAME} - OS_CMP2_IP: ${OS_CMP2_IP} - OS_COMPUTE_2_IP: ${OS_COMPUTE_2_IP} OS_ALL_IPS: @{OS_ALL_IPS} - ... OS_CMP_IPS: @{OS_CMP_IPS} OS_NODE_CNT: ${OS_NODE_CNT} OS_ALL_CONN_IDS: @{OS_ALL_CONN_IDS} OS_CMP_CONN_IDS: @{OS_CMP_CONN_IDS} + ${output} = BuiltIn.Catenate + ... SEPARATOR=\n + ... OS_CNTL_HOSTNAME: ${OS_CNTL_HOSTNAME} - OS_CNTL_IP: ${OS_CNTL_IP} - OS_CONTROL_NODE_IP: ${OS_CONTROL_NODE_IP} + ... OS_CMP1_HOSTNAME: ${OS_CMP1_HOSTNAME} - OS_CMP1_IP: ${OS_CMP1_IP} - OS_COMPUTE_1_IP: ${OS_COMPUTE_1_IP} + ... OS_CMP2_HOSTNAME: ${OS_CMP2_HOSTNAME} - OS_CMP2_IP: ${OS_CMP2_IP} - OS_COMPUTE_2_IP: ${OS_COMPUTE_2_IP} + ... OS_ALL_IPS: @{OS_ALL_IPS} + ... OS_CMP_IPS: @{OS_CMP_IPS} + ... OS_NODE_CNT: ${OS_NODE_CNT} + ... OS_ALL_CONN_IDS: @{OS_ALL_CONN_IDS} + ... OS_CMP_CONN_IDS: @{OS_CMP_CONN_IDS} BuiltIn.Log DevStack Nodes Data:\n${output} Get DevStack Hostnames @@ -100,9 +111,13 @@ Get DevStack Nodes Data [Documentation] Assign global variables for DevStack nodes BuiltIn.Set Suite Variable ${OS_CNTL_IP} ${OS_CONTROL_NODE_IP} DevstackUtils.Open Connection OS_CNTL_CONN_ID ${OS_CNTL_IP} - BuiltIn.Run Keyword If "${OPENSTACK_TOPO}" == "1cmb-0ctl-0cmp" DevstackUtils.Set Node Data For AllinOne Setup - ... ELSE IF "${OPENSTACK_TOPO}" == "1cmb-0ctl-1cmp" DevstackUtils.Set Node Data For Control And Compute Node Setup - ... ELSE IF "${OPENSTACK_TOPO}" == "0cmb-1ctl-2cmp" DevstackUtils.Set Node Data For Control And Two Compute Node Setup + IF "${OPENSTACK_TOPO}" == "1cmb-0ctl-0cmp" + DevstackUtils.Set Node Data For AllinOne Setup + ELSE IF "${OPENSTACK_TOPO}" == "1cmb-0ctl-1cmp" + DevstackUtils.Set Node Data For Control And Compute Node Setup + ELSE IF "${OPENSTACK_TOPO}" == "0cmb-1ctl-2cmp" + DevstackUtils.Set Node Data For Control And Two Compute Node Setup + END ${OS_NODE_CNT} = BuiltIn.Get Length ${OS_ALL_IPS} BuiltIn.Set Suite Variable ${OS_NODE_CNT} DevstackUtils.Get DevStack Hostnames diff --git a/csit/libraries/ExaBgpLib.robot b/csit/libraries/ExaBgpLib.robot index 1517a3764c..276e0cc3e1 100644 --- a/csit/libraries/ExaBgpLib.robot +++ b/csit/libraries/ExaBgpLib.robot @@ -1,32 +1,35 @@ *** Settings *** -Documentation Robot keyword library (Resource) for handling the ExaBgp tool. +Documentation Robot keyword library (Resource) for handling the ExaBgp tool. ... -... Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... This library assumes that a SSH connection exists (and is switched to) -... to a Linux machine (usualy TOOLS_SYSTEM) where the ExaBgp should be run. +... This library assumes that a SSH connection exists (and is switched to) +... to a Linux machine (usualy TOOLS_SYSTEM) where the ExaBgp should be run. ... -... TODO: RemoteBash.robot contains logic which could be reused here. -Library SSHLibrary -Resource ${CURDIR}/SSHKeywords.robot -Resource ${CURDIR}/RemoteBash.robot -Resource ${CURDIR}/BGPcliKeywords.robot +... TODO: RemoteBash.robot contains logic which could be reused here. + +Library SSHLibrary +Resource ${CURDIR}/SSHKeywords.robot +Resource ${CURDIR}/RemoteBash.robot +Resource ${CURDIR}/BGPcliKeywords.robot + *** Variables *** -${EXABGP_KILL_COMMAND} ps axf | grep exabgp | grep -v grep | awk '{print \"kill -9 \" $1}' | sh -${CMD} env exabgp.tcp.port=1790 exabgp --debug +${EXABGP_KILL_COMMAND} ps axf | grep exabgp | grep -v grep | awk '{print \"kill -9 \" $1}' | sh +${CMD} env exabgp.tcp.port=1790 exabgp --debug + *** Keywords *** Start_ExaBgp - [Arguments] ${cfg_file} [Documentation] Dump the start command into prompt. It assumes that no exabgp is running. For verified ... start use Start_ExaBgp_And_Verify_Connected keyword. - ${start_cmd} BuiltIn.Set_Variable ${CMD} ${cfg_file} + [Arguments] ${cfg_file} + ${start_cmd}= BuiltIn.Set_Variable ${CMD} ${cfg_file} BuiltIn.Log ${start_cmd} SSHKeywords.Virtual_Env_Activate_On_Current_Session log_output=${True} ${output}= SSHLibrary.Write ${start_cmd} @@ -43,27 +46,33 @@ Stop_ExaBgp Stop_All_ExaBgps [Documentation] Sends kill command to stop all exabgps running - ${output} SSHLibrary.Read + ${output}= SSHLibrary.Read BuiltIn.Log ${output} - ${output} SSHLibrary.Write ${EXABGP_KILL_COMMAND} + ${output}= SSHLibrary.Write ${EXABGP_KILL_COMMAND} BuiltIn.Log ${output} Start_ExaBgp_And_Verify_Connected - [Arguments] ${cfg_file} ${session} ${exabgp_ip} ${connection_retries}=${3} [Documentation] Starts the ExaBgp and verifies its connection. The verification is done by checking the presence ... of the peer in the bgp rib. + [Arguments] ${cfg_file} ${session} ${exabgp_ip} ${connection_retries}=${3} FOR ${idx} IN RANGE ${connection_retries} Start_ExaBgp ${cfg_file} - ${status} ${value}= BuiltIn.Run_Keyword_And_Ignore_Error BuiltIn.Wait_Until_Keyword_Succeeds 3x 3s - ... Verify_ExaBgps_Connection ${session} ${exabgp_ip} connected=${True} - BuiltIn.Run_Keyword_If "${status}" != "PASS" Stop_ExaBgp - BuiltIn.Return_From_Keyword_If "${status}" == "PASS" + ${status} ${value}= BuiltIn.Run_Keyword_And_Ignore_Error + ... BuiltIn.Wait_Until_Keyword_Succeeds + ... 3x + ... 3s + ... Verify_ExaBgps_Connection + ... ${session} + ... ${exabgp_ip} + ... connected=${True} + IF "${status}" != "PASS" Stop_ExaBgp + IF "${status}" == "PASS" RETURN END BuiltIn.Fail Unable to connect ExaBgp to ODL Verify_ExaBgps_Connection - [Arguments] ${session} ${exabgp_ip}=${TOOLS_SYSTEM_IP} ${connected}=${True} [Documentation] Checks peer presence in operational datastore + [Arguments] ${session} ${exabgp_ip}=${TOOLS_SYSTEM_IP} ${connected}=${True} ${peer_check_url}= BuiltIn.Set_Variable ${REST_API}/bgp-rib:bgp-rib/rib=example-bgp-rib/peer=bgp:%2F%2F ${exp_status_code}= BuiltIn.Set_Variable_If ${connected} ${200} ${404} ${rsp}= RequestsLibrary.Get Request ${session} ${peer_check_url}${exabgp_ip}?content=nonconfig @@ -71,8 +80,8 @@ Verify_ExaBgps_Connection BuiltIn.Should_Be_Equal_As_Numbers ${exp_status_code} ${rsp.status_code} Upload_ExaBgp_Cluster_Config_Files - [Arguments] ${bgp_var_folder} ${cfg_file} [Documentation] Uploads exabgp config files. + [Arguments] ${bgp_var_folder} ${cfg_file} SSHLibrary.Put_File ${bgp_var_folder}/${cfg_file} . @{cfgfiles}= SSHLibrary.List_Files_In_Directory . *.cfg FOR ${cfgfile} IN @{cfgfiles} diff --git a/csit/libraries/FailFast.robot b/csit/libraries/FailFast.robot index b9fb8e7a79..68c548890b 100644 --- a/csit/libraries/FailFast.robot +++ b/csit/libraries/FailFast.robot @@ -1,27 +1,28 @@ *** Settings *** -Documentation Robot keyword library (Resource) for implementing fail fast behavior in Robot suites. +Documentation Robot keyword library (Resource) for implementing fail fast behavior in Robot suites. ... -... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... This Resource uses suite variable SuiteFastFail, beware of possible conflicts. +... This Resource uses suite variable SuiteFastFail, beware of possible conflicts. ... -... Recommended usage: -... In suite setup, call Do_Not_Fail_Fast_From_Now_On -... Set Fail_This_Fast_On_Previous_Error as Test Setup -... and Start_Failing_Fast_If_This_Failed as Test Teardown -... in the suite setting table. -... If you do not want the test teardown, use this in test case: -... [Teardown] Do_Not_Start_Failing_If_This_Failed -... If you do not want the test setup in a particular test, use this in the test case: -... [Setup] Run_Even_When_Failing_Fast -... If success of such "run even when failing" test case can return the system under test -... back to corret state, call at the end of such test case this: -... Do_Not_Fail_Fast_From_Now_On +... Recommended usage: +... In suite setup, call Do_Not_Fail_Fast_From_Now_On +... Set Fail_This_Fast_On_Previous_Error as Test Setup +... and Start_Failing_Fast_If_This_Failed as Test Teardown +... in the suite setting table. +... If you do not want the test teardown, use this in test case: +... [Teardown] Do_Not_Start_Failing_If_This_Failed +... If you do not want the test setup in a particular test, use this in the test case: +... [Setup] Run_Even_When_Failing_Fast +... If success of such "run even when failing" test case can return the system under test +... back to corret state, call at the end of such test case this: +... Do_Not_Fail_Fast_From_Now_On + *** Keywords *** Do_Not_Fail_Fast_From_Now_On @@ -30,7 +31,9 @@ Do_Not_Fail_Fast_From_Now_On Fail_This_Fast_On_Previous_Error [Documentation] Mark (immediately) this test case as failed when fast-fail is enabled in suite. - BuiltIn.Run_Keyword_If '''${SuiteFastFail}'''=='True' BuiltIn.Fail SKIPPED due to a failure in a previous fundamental test case. + IF '''${SuiteFastFail}'''=='True' + BuiltIn.Fail SKIPPED due to a failure in a previous fundamental test case. + END Start_Failing_Fast_If_This_Failed [Documentation] Set suite fail fast behavior on, if current test case has failed. diff --git a/csit/libraries/FlowLib.robot b/csit/libraries/FlowLib.robot index 70b6e02701..18c163e2f0 100644 --- a/csit/libraries/FlowLib.robot +++ b/csit/libraries/FlowLib.robot @@ -1,33 +1,35 @@ *** Settings *** -Documentation Keywords used to create/modify flow objects. The object is defined in the -... corresponding FlowLib.py library and contains pertinent fields and methods (e.g., -... cookie and barrier fields, string formatted xml that can be used to push to -... controller). TODO: Remove hard dependency on controller HTTP "session". -Library XML -Library String -Library RequestsLibrary -Library ScaleClient.py -Library FlowLib.py -Library XmlComparator.py -Library Common.py -Resource CompareStream.robot -Resource ../variables/openflowplugin/Variables.robot -Variables ../variables/Variables.py +Documentation Keywords used to create/modify flow objects. The object is defined in the +... corresponding FlowLib.py library and contains pertinent fields and methods (e.g., +... cookie and barrier fields, string formatted xml that can be used to push to +... controller). TODO: Remove hard dependency on controller HTTP "session". + +Library XML +Library String +Library RequestsLibrary +Library ScaleClient.py +Library FlowLib.py +Library XmlComparator.py +Library Common.py +Resource CompareStream.robot +Resource ../variables/openflowplugin/Variables.robot +Variables ../variables/Variables.py + *** Keywords *** Check No Switches In Inventory - [Arguments] ${switches} [Documentation] Check no switch is in inventory - ${resp} RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_NODES_API} + [Arguments] ${switches} + ${resp}= RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_NODES_API} Log ${resp.text} FOR ${switch} IN RANGE 1 ${switches+1} Should Not Contain ${resp.text} "openflow:${switch}" END Check No Switches In Topology - [Arguments] ${switches} [Documentation] Check no switch is in topology - ${resp} RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_TOPO_API} + [Arguments] ${switches} + ${resp}= RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_TOPO_API} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 FOR ${switch} IN RANGE 1 ${switches+1} @@ -35,10 +37,10 @@ Check No Switches In Topology END Check Switches In Inventory - [Arguments] ${switches} [Documentation] Check all switches and stats in operational inventory + [Arguments] ${switches} FOR ${switch} IN RANGE 1 ${switches+1} - ${resp} RequestsLibrary.Get Request session ${RFC8040_NODES_API}/node=openflow%3A${switch} + ${resp}= RequestsLibrary.Get Request session ${RFC8040_NODES_API}/node=openflow%3A${switch} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 Should Contain ${resp.text} flow-capable-node-connector-statistics @@ -46,8 +48,8 @@ Check Switches In Inventory END Check Switches In Topology - [Arguments] ${switches} [Documentation] Check switches are in the topology. + [Arguments] ${switches} ${resp}= RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_TOPO_API} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 @@ -55,8 +57,8 @@ Check Switches In Topology BuiltIn.Should Be Equal As Numbers ${count} ${switches} Check Number Of Links - [Arguments] ${links} [Documentation] Check number of links in the topolgy. + [Arguments] ${links} ${resp}= RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_TOPO_API} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 @@ -64,9 +66,9 @@ Check Number Of Links Should Be Equal As Integers ${count} ${links} Check Linear Topology - [Arguments] ${switches} [Documentation] Check Linear topology. - ${resp} RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_TOPO_API} + [Arguments] ${switches} + ${resp}= RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_TOPO_API} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 FOR ${switch} IN RANGE 1 ${switches+1} @@ -75,21 +77,27 @@ Check Linear Topology Should Contain ${resp.text} "tp-id":"openflow:${switch}:2" Should Contain ${resp.text} "source-tp":"openflow:${switch}:2" Should Contain ${resp.text} "dest-tp":"openflow:${switch}:2" - ${edge} Evaluate ${switch}==1 or ${switch}==${switches} - Run Keyword If not ${edge} Should Contain ${resp.text} "tp-id":"openflow:${switch}:3" - Run Keyword If not ${edge} Should Contain ${resp.text} "source-tp":"openflow:${switch}:3" - Run Keyword If not ${edge} Should Contain ${resp.text} "dest-tp":"openflow:${switch}:3" + ${edge}= Evaluate ${switch}==1 or ${switch}==${switches} + IF not ${edge} + Should Contain ${resp.text} "tp-id":"openflow:${switch}:3" + END + IF not ${edge} + Should Contain ${resp.text} "source-tp":"openflow:${switch}:3" + END + IF not ${edge} + Should Contain ${resp.text} "dest-tp":"openflow:${switch}:3" + END END Check Flows Operational Datastore - [Arguments] ${flow_count} ${controller_ip}=${ODL_SYSTEM_IP} [Documentation] Check if number of Operational Flows on member of given index is equal to ${flow_count}. + [Arguments] ${flow_count} ${controller_ip}=${ODL_SYSTEM_IP} ${sw} ${reported_flow} ${found_flow}= ScaleClient.Flow Stats Collected controller=${controller_ip} Should_Be_Equal_As_Numbers ${flow_count} ${found_flow} Check Number Of Flows - [Arguments] ${flows} [Documentation] Check number of flows in the inventory. + [Arguments] ${flows} ${resp}= RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_NODES_API} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 @@ -97,8 +105,8 @@ Check Number Of Flows Should Be Equal As Integers ${count} ${flows} Check Number Of Groups - [Arguments] ${groups} [Documentation] Check number of groups in the inventory. + [Arguments] ${groups} ${resp}= RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_NODES_API} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 @@ -106,16 +114,18 @@ Check Number Of Groups Should Be Equal As Integers ${group_count} ${groups} Check Flow Stats Are Available - [Arguments] ${node_id} ${flows} [Documentation] A GET on the /node=${node_id} inventory API is made and flow stats string is checked for existence. - ${resp} RequestsLibrary.Get Request session ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:table=2 + [Arguments] ${node_id} ${flows} + ${resp}= RequestsLibrary.Get Request + ... session + ... ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:table=2 Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 Should Contain X Times ${resp.text} priority ${flows} Check Number Of Hosts - [Arguments] ${hosts} [Documentation] Check number of hosts in topology + [Arguments] ${hosts} ${resp}= RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_TOPO_API} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 @@ -129,33 +139,38 @@ Check No Hosts Should Not Contain ${resp.text} "node-id":"host: Add Table Miss Flows - [Arguments] ${switches} [Documentation] Add table miss flows to switches. + [Arguments] ${switches} ${switches}= Convert To Integer ${switches} ${data}= OperatingSystem.Get File ${CURDIR}/../variables/openflowplugin/table_miss_flow.json FOR ${switch} IN RANGE 1 ${switches+1} - TemplatedRequests.Put As Json To Uri ${RFC8040_NODES_API}/node=openflow%3A${switch}/flow-node-inventory:table=0/flow=default ${data} session + TemplatedRequests.Put As Json To Uri + ... ${RFC8040_NODES_API}/node=openflow%3A${switch}/flow-node-inventory:table=0/flow=default + ... ${data} + ... session END Check Table Miss Flows - [Arguments] ${switches} [Documentation] Check table miss flows in switches. + [Arguments] ${switches} ${switches}= Convert To Integer ${switches} FOR ${switch} IN RANGE 1 ${switches+1} - TemplatedRequests.Get As Json From Uri ${RFC8040_NODES_API}/node=openflow%3A${switch}/flow-node-inventory:table=0/flow=default session + TemplatedRequests.Get As Json From Uri + ... ${RFC8040_NODES_API}/node=openflow%3A${switch}/flow-node-inventory:table=0/flow=default + ... session END Create Inventory Flow [Documentation] Calls FlowLib.Make_Inventory_Flow function and initializes and sanitizes ... the basic flow elements that can be given to flow:inventory ${flow}= Make Inventory Flow - [Return] ${flow} + RETURN ${flow} Create Service Flow [Documentation] Used for creating an object that will use an XML format that ... can be given to flow:service. ${flow}= Make Service Flow - [Return] ${flow} + RETURN ${flow} Set "${flow}" "${property}" With "${property_val}" [Documentation] Embedded variables to make higher level keywords more readable. @@ -167,17 +182,20 @@ Set "${flow}" "${property}" With "${property_val}" ... xml representation of the flow and reset with the given value. \ It's not ... possible, yet, to have multiple elements with the same name. \ That will ... likely be needed in the future. - ${property} Run Keyword If "table_id" != "${property}" and "cookie_mask" != "${property}" Replace String ${property} _ - - ... ELSE Set Variable ${property} + IF "table_id" != "${property}" and "cookie_mask" != "${property}" + ${property}= Replace String ${property} _ - + ELSE + ${property}= Set Variable ${property} + END Remove Flow XML Element ${flow} ${property} Add Flow XML Element ${flow} ${property} ${property_val} Set Flow Field ${flow} ${property} ${property_val} - [Return] ${flow} + RETURN ${flow} Set Flow Action - [Arguments] ${flow} ${instruction_order} ${action_order} ${action} ${action_val}=${EMPTY} [Documentation] Will remove the instruction element first, then add the proper xml structure ... to implement the action as given in the arguments + [Arguments] ${flow} ${instruction_order} ${action_order} ${action} ${action_val}=${EMPTY} ##For the case that any of the instruction/apply-actions/action elements are not there we need to add them' Remove Flow XML Element ${flow} instruction Add Flow XML Element ${flow} instruction ${EMPTY} instructions @@ -186,19 +204,23 @@ Set Flow Action Add Flow XML Element ${flow} action ${EMPTY} instructions/instruction/apply-actions Add Flow XML Element ${flow} order ${action_order} instructions/instruction/apply-actions/action Add Flow XML Element ${flow} ${action} ${action_val} instructions/instruction/apply-actions/action - [Return] ${flow} + RETURN ${flow} Set Flow Output Action [Arguments] ${flow} ${instruction_order} ${action_order} ${output_port} Set Flow Action ${flow} ${instruction_order} ${action_order} output-action - Add Flow XML Element ${flow} output-node-connector ${output_port} instructions/instruction/apply-actions/action/output-action - [Return] ${flow} + Add Flow XML Element + ... ${flow} + ... output-node-connector + ... ${output_port} + ... instructions/instruction/apply-actions/action/output-action + RETURN ${flow} Set Flow Ethernet Match - [Arguments] ${flow} ${match_value_dict} [Documentation] Specific keyword for adding an ethernet match rules where the elements are given ... in key/value pairs inside the ${match_value_dict} argument. This keyword will also remove any ... existing ethernet-match elements from the flow before adding + [Arguments] ${flow} ${match_value_dict} Clear Flow Matches ${flow} match/ethernet-match Add Flow XML Element ${flow} ethernet-match ${EMPTY} match ${type}= Get From Dictionary ${match_value_dict} type @@ -210,138 +232,160 @@ Set Flow Ethernet Match ${dst}= Get From Dictionary ${match_value_dict} destination Add Flow XML Element ${flow} ethernet-destination ${EMPTY} match/ethernet-match Add Flow XML Element ${flow} address ${dst} match/ethernet-match/ethernet-destination - [Return] ${flow} + RETURN ${flow} Set Flow IPv4 Match - [Arguments] ${flow} ${match_value_dict} [Documentation] Specific keyword for adding an ipv4 match rules where the elements are given ... in key/value pairs inside the ${match_value_dict} argument. This keyword will also remove any ... existing ipv4 match elements from the flow before adding + [Arguments] ${flow} ${match_value_dict} Clear Flow Matches ${flow} match/ipv4-source Clear Flow Matches ${flow} match/ipv4-destination ${src}= Get From Dictionary ${match_value_dict} source Add Flow XML Element ${flow} ipv4-source ${src} match ${dst}= Get From Dictionary ${match_value_dict} destination Add Flow XML Element ${flow} ipv4-destination ${dst} match - [Return] ${flow} + RETURN ${flow} Clear Flow Actions - [Arguments] ${flow} [Documentation] Will clean out any existing flow actions in the given ${flow} object + [Arguments] ${flow} Remove Flow XML Element ${flow} instructions/instruction - [Return] ${flow} + RETURN ${flow} Clear Flow Matches - [Arguments] ${flow} ${match_element} [Documentation] Will clean out any existing flow matches in the given ${flow} object + [Arguments] ${flow} ${match_element} Remove Flow XML Element ${flow} match/${match_element} - [Return] ${flow} + RETURN ${flow} Set Flow XML Element Attribute - [Arguments] ${flow} ${element} ${id} ${value} [Documentation] Will set the given id/value pair to the given to the element provided ... and make the proper changes to the ${flow} object also provided. + [Arguments] ${flow} ${element} ${id} ${value} ${flow_xml}= Parse XML ${flow.xml} Set Element Attribute ${flow_xml} ${id} ${value} xpath=${element} ${xml_string}= Element To String ${flow_xml} Set Flow Field ${flow} xml ${xml_string} Log ${flow.xml} - [Return] ${flow} + RETURN ${flow} Add Flow XML Element - [Arguments] ${flow} ${element} ${element_val}=${EMPTY} ${xpath}=. [Documentation] Will modify the current xml representation of the ${flow} object to contain ... the given ${element} at the given ${xpath}. If the ${element} uses a value, that can be ... passed eith the ${element_val} which defaults to ${EMPTY} if not used. NOTE: since there ... are two default parameters to this keyword, if you have an ${xpath} to use, but no ${element_val} ... you will still need to pass ${EMPTY} when invoking so that ${xpath} will end up at the right ... location in the parameter list + [Arguments] ${flow} ${element} ${element_val}=${EMPTY} ${xpath}=. ${flow_xml}= Parse XML ${flow.xml} Add Element ${flow_xml} <${element}>${element_val} xpath=${xpath} ${xml_string}= Element To String ${flow_xml} Set Flow Field ${flow} xml ${xml_string} Log ${flow.xml} - [Return] ${flow} + RETURN ${flow} Remove Flow XML Element - [Arguments] ${flow} ${element_xpath} [Documentation] Removes the element at the given ${element_xpath} within the given ${flow} ... object. The ${flow} object's xml representation will be updated to reflect this removal. + [Arguments] ${flow} ${element_xpath} ${flow_xml}= Parse XML ${flow.xml} Run Keyword And Ignore Error Remove Elements ${flow_xml} xpath=${element_xpath} ${xml_string}= Element To String ${flow_xml} Set Flow Field ${flow} xml ${xml_string} - [Return] ${flow} + RETURN ${flow} Add Group To Controller And Verify - [Arguments] ${group_body} ${node_id} ${group_id} [Documentation] Push group through REST-API and verify in data-store - ${resp} RequestsLibrary.Put Request session ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:group=${group_id} headers=${HEADERS_XML} data=${group_body} + [Arguments] ${group_body} ${node_id} ${group_id} + ${resp}= RequestsLibrary.Put Request + ... session + ... ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:group=${group_id} + ... headers=${HEADERS_XML} + ... data=${group_body} Log ${resp.text} BuiltIn.Should_Match "${resp.status_code}" "20?" - ${resp} RequestsLibrary.Get Request session ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:group=${group_id}?content=config headers=${ACCEPT_XML} + ${resp}= RequestsLibrary.Get Request + ... session + ... ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:group=${group_id}?content=config + ... headers=${ACCEPT_XML} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 Compare Xml ${group_body} ${resp.text} Add Flow To Controller And Verify - [Arguments] ${flow_body} ${node_id} ${table_id} ${flow_id} [Documentation] Push flow through REST-API and verify in data-store - ${resp} RequestsLibrary.Put Request session ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id} headers=${HEADERS_XML} data=${flow_body} + [Arguments] ${flow_body} ${node_id} ${table_id} ${flow_id} + ${resp}= RequestsLibrary.Put Request + ... session + ... ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id} + ... headers=${HEADERS_XML} + ... data=${flow_body} Log ${resp.text} BuiltIn.Should_Match "${resp.status_code}" "20?" - ${resp} RequestsLibrary.Get Request session ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id}?content=config headers=${ACCEPT_XML} + ${resp}= RequestsLibrary.Get Request + ... session + ... ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id}?content=config + ... headers=${ACCEPT_XML} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 Compare Xml ${flow_body} ${resp.text} Verify Flow On Mininet Switch - [Arguments] ${flow_elements} [Documentation] Checking flow on switch + [Arguments] ${flow_elements} Sleep 1 Write dpctl dump-flows -O OpenFlow13 - ${switchoutput} Read Until > + ${switchoutput}= Read Until > FOR ${flowElement} IN @{flow_elements} Should Contain ${switchoutput} ${flowElement} END Remove Group From Controller And Verify - [Arguments] ${node_id} ${group_id} [Documentation] Remove group and verify - ${resp} RequestsLibrary.Delete Request session ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:group=${group_id} + [Arguments] ${node_id} ${group_id} + ${resp}= RequestsLibrary.Delete Request + ... session + ... ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:group=${group_id} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 204 - ${resp} RequestsLibrary.Get Request session ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:group=${group_id}?content=config - Builtin.Return_From_Keyword_If ${resp.status_code} == 404 or ${resp.status_code} == 409 + ${resp}= RequestsLibrary.Get Request + ... session + ... ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:group=${group_id}?content=config + IF ${resp.status_code} == 404 or ${resp.status_code} == 409 RETURN Builtin.Log ${resp.text} Builtin.Fail The request failed with code ${resp.status_code} Remove Flow From Controller And Verify - [Arguments] ${node_id} ${table_id} ${flow_id} [Documentation] Remove flow and verify - ${resp} RequestsLibrary.Delete Request session ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id} + [Arguments] ${node_id} ${table_id} ${flow_id} + ${resp}= RequestsLibrary.Delete Request + ... session + ... ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 204 - ${resp} RequestsLibrary.Get Request session ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id}?content=config - Builtin.Return_From_Keyword_If ${resp.status_code} == 404 or ${resp.status_code} == 409 + ${resp}= RequestsLibrary.Get Request + ... session + ... ${RFC8040_NODES_API}/node=${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id}?content=config + IF ${resp.status_code} == 404 or ${resp.status_code} == 409 RETURN Builtin.Log ${resp.text} Builtin.Fail The request failed with code ${resp.status_code} Verify Flow Does Not Exist On Mininet Switch - [Arguments] ${flow_elements} [Documentation] Checking flow on switch is removed + [Arguments] ${flow_elements} Sleep 1 Write dpctl dump-flows -O OpenFlow13 - ${switchoutput} Read Until > + ${switchoutput}= Read Until > FOR ${flowElement} IN @{flow_elements} Should Not Contain ${switchoutput} ${flowElement} END Remove Default Flows - [Arguments] ${node_id} [Documentation] Removes any flows considered "default". one such flow is ... to forward all traffic to the CONTROLLER with priority 0 at flow-table 0 ... If/When others are implemented this keyword can be updated to include those. + [Arguments] ${node_id} ${flow}= Make Service Flow Set "${flow}" "priority" With "0" Set "${flow}" "flow-table" With "0" @@ -349,9 +393,13 @@ Remove Default Flows Set Flow XML Element Attribute ${flow} node xmlns:inv urn:opendaylight:inventory Log Flow XML is ${flow.xml} write dpctl dump-flows -O OpenFlow13 - ${switchoutput} Read Until > + ${switchoutput}= Read Until > ${headers}= Create Dictionary Content-Type=application/yang-data+xml - ${resp} RequestsLibrary.Post Request session rests/operations/sal-flow:remove-flow data=${flow.xml} headers=${headers} + ${resp}= RequestsLibrary.Post Request + ... session + ... rests/operations/sal-flow:remove-flow + ... data=${flow.xml} + ... headers=${headers} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 ${resp}= RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_NODES_API} @@ -361,8 +409,8 @@ Remove Default Flows Verify Flow Does Not Exist On Mininet Switch ${strings_to_check_for} Create Flow Variables For Suite From XML File - [Arguments] ${file} [Documentation] Given the flow XML ${file}, it will create several suite wide variables + [Arguments] ${file} ${data}= OperatingSystem.Get File ${file} ${xmlroot}= Parse Xml ${file} ${table_id}= Get Element Text ${xmlroot} table_id @@ -377,9 +425,9 @@ Create Flow Variables For Suite From XML File Set Suite Variable ${xmlroot} Check Datastore Presence - [Arguments] ${fname} ${reqconfpres} ${reqoperpres} ${upd} ${check_id}=${False} [Documentation] Checks if flow is properly existing or not existing in the config and operational ... datastores, based on the variables ${reqconfpres} and ${reqoperpres} + [Arguments] ${fname} ${reqconfpres} ${reqoperpres} ${upd} ${check_id}=${False} Create Flow Variables For Suite From XML File ${XmlsDir}/${fname} # Note: ${upddata} and ${data} are suite variables set by the keyword above. ${det}= Set Variable If ${upd}==${True} ${upddata} ${data} @@ -388,60 +436,71 @@ Check Datastore Presence Check Operational Flow ${reqoperpres} ${det} ${check_id} Flow Presence In Config Store - [Arguments] ${expvalue} [Documentation] Checks the config store for given flow. Returns True if present, otherwise returns False ... This keyword assumes that the global/suite variables are available (${table_id}, ${flow_id} and ${switch_idx} + [Arguments] ${expvalue} ${headers}= Create Dictionary Accept=application/xml - ${resp}= RequestsLibrary.Get Request session ${RFC8040_NODES_API}/node=openflow%3A${switch_idx}/flow-node-inventory:table=${table_id}/flow=${flow_id}?content=config headers=${headers} + ${resp}= RequestsLibrary.Get Request + ... session + ... ${RFC8040_NODES_API}/node=openflow%3A${switch_idx}/flow-node-inventory:table=${table_id}/flow=${flow_id}?content=config + ... headers=${headers} Log ${resp} Log ${resp.text} - Return From Keyword If ${resp.status_code}!=200 ${False} ${EMPTY} + IF ${resp.status_code}!=200 RETURN ${False} ${EMPTY} ${pres} ${msg}= Is Flow Configured ${expvalue} ${resp.text} - Run Keyword If '''${msg}'''!='${EMPTY}' Log ${msg} - Return From Keyword ${pres} ${msg} + IF '''${msg}'''!='${EMPTY}' Log ${msg} + RETURN ${pres} ${msg} Flow Presence In Operational Store - [Arguments] ${expvalue} ${check_id}=${False} [Documentation] Checks the operational store for given flow. Returns True if present, otherwise returns False ... This keyword assumes that the global/suite variables are available (${table_id}, ${flow_id} and ${switch_idx} + [Arguments] ${expvalue} ${check_id}=${False} ${headers}= Create Dictionary Accept=application/xml - ${resp}= RequestsLibrary.Get Request session ${RFC8040_NODES_API}/node=openflow%3A${switch_idx}/flow-node-inventory:table=${table_id} headers=${headers} + ${resp}= RequestsLibrary.Get Request + ... session + ... ${RFC8040_NODES_API}/node=openflow%3A${switch_idx}/flow-node-inventory:table=${table_id} + ... headers=${headers} Log ${resp} Log ${resp.text} - Return From Keyword If ${resp.status_code}!=200 ${False} ${EMPTY} + IF ${resp.status_code}!=200 RETURN ${False} ${EMPTY} ${pres} ${msg}= Is Flow Operational2 ${expvalue} ${resp.text} ${check_id} - Run Keyword If '''${msg}'''!='${EMPTY}' Log ${msg} - Return From Keyword ${pres} ${msg} + IF '''${msg}'''!='${EMPTY}' Log ${msg} + RETURN ${pres} ${msg} Get Presence Failure Message - [Arguments] ${ds} ${expected} ${presence} ${diffmsg} [Documentation] Utility keyword to help manipulate mesage strings that may be used later to PASS or FAIL with - Return From Keyword If '''${diffmsg}'''!='${EMPTY}' Flow found in ${ds} data store but: ${diffmsg} - ${msgf}= Set Variable If ${expected}==${True} The flow is expected in ${ds} data store, but The flow is not expected in ${ds} data store, but + [Arguments] ${ds} ${expected} ${presence} ${diffmsg} + IF '''${diffmsg}'''!='${EMPTY}' + RETURN Flow found in ${ds} data store but: ${diffmsg} + END + ${msgf}= Set Variable If + ... ${expected}==${True} + ... The flow is expected in ${ds} data store, but + ... The flow is not expected in ${ds} data store, but ${msgp}= Set Variable If ${presence}==${True} it is present. it is not present. - Return From Keyword ${msgf} ${msgp} + RETURN ${msgf} ${msgp} Check Config Flow - [Arguments] ${expected} ${expvalue} [Documentation] Wrapper keyword that calls "Flow Presence In Config Store" and "Get Presence Failure Message" from this library ... to verify that the ${expvalue} flow is or is not found in the config store, depending on whether or not it was ${expected} + [Arguments] ${expected} ${expvalue} ${presence_flow} ${msg}= Flow Presence In Config Store ${expvalue} ${msgf}= Get Presence Failure Message config ${expected} ${presence_flow} ${msg} Should Be Equal ${expected} ${presence_flow} msg=${msgf} Check Operational Flow - [Arguments] ${expected} ${expvalue} ${check_id}=${False} [Documentation] Wrapper keyword that calls "Flow Presence In Operational Store" and "Get Presence Failure Message" from this library ... to verify that the ${expvalue} flow is or is not found in the operational store, depending on whether or not it was ${expected} + [Arguments] ${expected} ${expvalue} ${check_id}=${False} ${presence_table} ${msg}= Flow Presence In Operational Store ${expvalue} ${check_id} ${msgf}= Get Presence Failure Message operational ${expected} ${presence_table} ${msg} Should Be Equal ${expected} ${presence_table} msg=${msgf} Add Flow Via RPC - [Arguments] ${node_id} ${xmlroot} [Documentation] Deploys a flow specified by given flow details (${node_id}, ${xmlroot}) using add-flow operation. ... ${xmlroot} is an xml object of parser xml flow details, usually created by Create Flow Variables For Suite From XML File ... keyword from this library. + [Arguments] ${node_id} ${xmlroot} ${req}= Copy Element ${xmlroot} Remove Element ${req} id clear_tail=True Set Element Tag ${req} input @@ -458,21 +517,25 @@ Add Flow Via RPC Should Be Equal As Strings ${resp.status_code} ${expected_status_code} Add Flow Via Restconf - [Arguments] ${node_id} ${table_id} ${flow_body} [Documentation] Configures a flow specified by given flow details (${node_id}, ${table_id}, ${flow_body}) using POST method + [Arguments] ${node_id} ${table_id} ${flow_body} Log ${flow_body} - ${resp}= RequestsLibrary.Post Request session ${RFC8040_NODES_API}/node=openflow%3A${node_id}/flow-node-inventory:table=${table_id} data=${flow_body} + ${resp}= RequestsLibrary.Post Request + ... session + ... ${RFC8040_NODES_API}/node=openflow%3A${node_id}/flow-node-inventory:table=${table_id} + ... data=${flow_body} Log ${resp.text} - ${msg}= Set Variable Adding flow for ${RFC8040_NODES_API}/node=openflow%3A${node_id}/flow-node-inventory:table=${table_id} failed, http response ${resp.status_code} received. + ${msg}= Set Variable + ... Adding flow for ${RFC8040_NODES_API}/node=openflow%3A${node_id}/flow-node-inventory:table=${table_id} failed, http response ${resp.status_code} received. Should Be Equal As Strings ${resp.status_code} 201 msg=${msg} Update Flow Via RPC - [Arguments] ${node_id} ${configured_flow_body} ${updating_flow_body} [Documentation] Updates a flow by using update-flow operation. ${xmlroot} is usually a variable created by ... Create Flow Variables For Suite From XML File keyword from this library. + [Arguments] ${node_id} ${configured_flow_body} ${updating_flow_body} Log ${configured_flow_body} Log ${updating_flow_body} - ${xml} Parse Xml + ${xml}= Parse Xml Log Element ${xml} ${origflow}= Parse Xml ${configured_flow_body} ${updflow}= Parse Xml ${updating_flow_body} @@ -496,18 +559,22 @@ Update Flow Via RPC Should Be Equal As Strings ${resp.status_code} ${expected_status_code} Update Flow Via Restconf - [Arguments] ${node_id} ${table_id} ${flow_id} ${flow_body} [Documentation] Updates a flow configuration by given flow details (${node_id}, ${table_id}, ${flow_body}) using PUT method + [Arguments] ${node_id} ${table_id} ${flow_id} ${flow_body} Log ${flow_body} - ${resp}= RequestsLibrary.Put Request session ${RFC8040_NODES_API}/node=openflow%3A${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id} data=${flow_body} + ${resp}= RequestsLibrary.Put Request + ... session + ... ${RFC8040_NODES_API}/node=openflow%3A${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id} + ... data=${flow_body} Log ${resp.text} - ${msg}= Set Variable Updating flow for ${RFC8040_NODES_API}/node=openflow%3A${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id} failed, http response ${resp.status_code} received. + ${msg}= Set Variable + ... Updating flow for ${RFC8040_NODES_API}/node=openflow%3A${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id} failed, http response ${resp.status_code} received. Should Be Equal As Strings ${resp.status_code} 204 msg=${msg} Delete Flow Via RPC - [Arguments] ${node_id} ${xmlroot} [Documentation] Deletes a flow by using remove-flow opearation. ${xmlroot} is usually a variable created by ... Create Flow Variables For Suite From XML File keyword from this library. + [Arguments] ${node_id} ${xmlroot} ${req}= Copy Element ${xmlroot} Remove Element ${req} id clear_tail=True Set Element Tag ${req} input @@ -524,17 +591,22 @@ Delete Flow Via RPC Should Be Equal As Strings ${resp.status_code} ${expected_status_code} Delete Flow Via Restconf - [Arguments] ${node_id} ${table_id} ${flow_id} [Documentation] Deletes a flow from configuration datastore specified by given flow details (${node_id}, ${table_id}, ${flow_body}) using DELETE method - ${resp}= RequestsLibrary.Delete Request session ${RFC8040_NODES_API}/node=openflow%3A${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id} + [Arguments] ${node_id} ${table_id} ${flow_id} + ${resp}= RequestsLibrary.Delete Request + ... session + ... ${RFC8040_NODES_API}/node=openflow%3A${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id} Log ${resp.text} - ${msg}= Set Variable Delete flow for ${RFC8040_NODES_API}/node=openflow%3A${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id} failed, http response ${resp.status_code} received. + ${msg}= Set Variable + ... Delete flow for ${RFC8040_NODES_API}/node=openflow%3A${node_id}/flow-node-inventory:table=${table_id}/flow=${flow_id} failed, http response ${resp.status_code} received. Should Be Equal As Strings ${resp.status_code} 204 msg=${msg} Get Flow Id - [Arguments] ${dpnid} ${table_id} ${flow_element} [Documentation] This verifies specific flow-id for particular table-id matching from the flow element - ${resp} = RequestsLibrary.Get Request session ${RFC8040_NODES_API}/node=openflow%3A${dpnid}/flow-node-inventory:table=${table_id}?content=config + [Arguments] ${dpnid} ${table_id} ${flow_element} + ${resp}= RequestsLibrary.Get Request + ... session + ... ${RFC8040_NODES_API}/node=openflow%3A${dpnid}/flow-node-inventory:table=${table_id}?content=config BuiltIn.Log ${resp.text} - @{flow_id} = String.Get Regexp Matches ${resp.text} id\":\"(\\d+${flow_element}) 1 - [Return] @{flow_id}[0] + @{flow_id}= String.Get Regexp Matches ${resp.text} id\":\"(\\d+${flow_element}) 1 + RETURN @{flow_id}[0] diff --git a/csit/libraries/GBP/AssertionUtils.robot b/csit/libraries/GBP/AssertionUtils.robot index 392f56801c..e2efa5234f 100644 --- a/csit/libraries/GBP/AssertionUtils.robot +++ b/csit/libraries/GBP/AssertionUtils.robot @@ -1,73 +1,79 @@ *** Settings *** -Documentation Utils for Restconf operations for GBP -Library RequestsLibrary -Library OperatingSystem -Library String -Variables ../../variables/Variables.py -Resource ../../variables/gbp/Constants.robot -Resource ../Utils.robot -Resource RestconfUtils.robot +Documentation Utils for Restconf operations for GBP + +Library RequestsLibrary +Library OperatingSystem +Library String +Variables ../../variables/Variables.py +Resource ../../variables/gbp/Constants.robot +Resource ../Utils.robot +Resource RestconfUtils.robot -*** Variables *** *** Keywords *** Assert Subnet - [Arguments] ${subnet_to_check} ${subnet_name} ${ip_prefix_to_check} [Documentation] Checks name and ip prefix of given subnet and returns parent ID + [Arguments] ${subnet_to_check} ${subnet_name} ${ip_prefix_to_check} ${parent} Assert Forwarding Domain ${subnet_to_check} ${subnet_name} return_parent=TRUE ${ip_prefix} Get Ip Prefix of Subnet ${subnet_to_check} Should Be Equal As Strings ${ip_prefix} ${ip_prefix_to_check} - [Return] ${parent} + RETURN ${parent} Assert L2-Flood-Domain - [Arguments] ${l2_flood_domain_to_check} ${l2_flood_domain_name} [Documentation] Checks name of given l2-flood-domain and returns parent ID - ${parent} Assert Forwarding Domain ${l2_flood_domain_to_check} ${l2_flood_domain_name} return_parent=TRUE - [Return] ${parent} + [Arguments] ${l2_flood_domain_to_check} ${l2_flood_domain_name} + ${parent} Assert Forwarding Domain + ... ${l2_flood_domain_to_check} + ... ${l2_flood_domain_name} + ... return_parent=TRUE + RETURN ${parent} Assert L2-Bridge-Domain - [Arguments] ${l2_bridge_domain_to_check} ${l2_bridge_domain_name} [Documentation] Checks name of given l2-bridge-domain and returns parent ID - ${parent} Assert Forwarding Domain ${l2_bridge_domain_to_check} ${l2_bridge_domain_name} return_parent=TRUE - [Return] ${parent} + [Arguments] ${l2_bridge_domain_to_check} ${l2_bridge_domain_name} + ${parent} Assert Forwarding Domain + ... ${l2_bridge_domain_to_check} + ... ${l2_bridge_domain_name} + ... return_parent=TRUE + RETURN ${parent} Assert L3-Context - [Arguments] ${l3_context_to_check} ${l3_context_name} [Documentation] Checks name of given l3-context + [Arguments] ${l3_context_to_check} ${l3_context_name} ${parent} Assert Forwarding Domain ${l3_context_to_check} ${l3_context_name} - [Return] ${parent} + RETURN ${parent} Assert Forwarding Domain - [Arguments] ${domain_to_check} ${domain_name} ${return_parent}=FALSE [Documentation] Checks name of given l3-context + [Arguments] ${domain_to_check} ${domain_name} ${return_parent}=FALSE Check Name ${domain_to_check} ${domain_name} - Return From Keyword If "${return_parent}" == "FALSE" + IF "${return_parent}" == "FALSE" RETURN ${parent} Get Parent ${domain_to_check} - [Return] ${parent} + RETURN ${parent} Check Name - [Arguments] ${data} ${name} [Documentation] Checks correct format of a name field in JSON data + [Arguments] ${data} ${name} Should Not Be Empty ${data} Should Match Regexp ${data} \"name\":\"${NAME_PATTERN}\" Check CI Range Values - [Arguments] ${range_value_json} ${min} ${max} [Documentation] Veriefies min and max values of range-value of classifier-instance in JSON format + [Arguments] ${range_value_json} ${min} ${max} Should Be Equal As Numbers ${min} ${range_value_json['min']} Should Be Equal As Numbers ${max} ${range_value_json['max']} Get Parent - [Arguments] ${data} [Documentation] Returns 'parent' value of an JSON object. Can be applied to Subnet, L2-Flood-Domain or L2-Bridge-Domain + [Arguments] ${data} Should Not Be Empty ${data} ${parent_line} Should Match Regexp ${data} \"parent\":\"${UUID_PATTERN}\" ${parent_uuid} Should Match Regexp ${parent_line} ${UUID_PATTERN} - [Return] ${parent_uuid} + RETURN ${parent_uuid} Check Endpoint - [Arguments] ${endpoint} ${ip_address} ${epg} ${l3-context} ${network-containment} ${tenant} [Documentation] Verifies parameters of given endpoint in JSON format + [Arguments] ${endpoint} ${ip_address} ${epg} ${l3-context} ${network-containment} ${tenant} Should Contain ${endpoint} ofoverlay:port-name @{ep_l3-addresses} Get L3-Addresses of Endpoint ${endpoint} @{ep_endpoint_groups} Get Groups of Endpoint ${endpoint} @@ -83,13 +89,15 @@ Check Endpoint LOG ${ip_address} LOG ${l3['l3-context']} LOG ${l3['ip-address']} - Continue For Loop If "${l3['l3-context']}" == "${l3-context}" and "${l3['ip-address']}" == "${ip_address}" + IF "${l3['l3-context']}" == "${l3-context}" and "${l3['ip-address']}" == "${ip_address}" + CONTINUE + END Fail END Check Endpoint-L3 - [Arguments] ${endpoint-l3} ${mac_address} ${epg} ${l2-context} ${network-containment} ${tenant} [Documentation] Verifies parameters of registerd endpoint-l3 in JSON format + [Arguments] ${endpoint-l3} ${mac_address} ${epg} ${l2-context} ${network-containment} ${tenant} Should Contain ${endpoint-l3} ofoverlay:port-name ${ep_l2-context} Get L2 Context of Endpoint-L3 ${endpoint-l3} ${ep_mac_address} Get Mac Address of Endpoint-L3 ${endpoint-l3} @@ -103,20 +111,20 @@ Check Endpoint-L3 Check Group References ${epg} @{ep_endpoint_groups} Check Group References - [Arguments] ${epg_to_look_for} @{endpoint_groups} [Documentation] Verifies presence of endpoint group to which endpoint belongs and presence of network_client group ... among given endpoint groups + [Arguments] ${epg_to_look_for} @{endpoint_groups} Should Not Be Empty ${epg_to_look_for} Should Not Be Empty ${endpoint_groups} FOR ${epg} IN @{endpoint_groups} - Continue For Loop If "${epg}" == "${epg_to_look_for}" - Continue For Loop If "${epg}" == "${NETWORK_CLIENT_GROUP}" + IF "${epg}" == "${epg_to_look_for}" CONTINUE + IF "${epg}" == "${NETWORK_CLIENT_GROUP}" CONTINUE Fail END Check Endpoint Group Name and Selector - [Arguments] ${epg_id} ${epg_name} ${tenant_id} ${contract_id} ${named-selector} [Documentation] Verifies data generated by security group and security group rules + [Arguments] ${epg_id} ${epg_name} ${tenant_id} ${contract_id} ${named-selector} ${epg_path} Get Endpoint Group Path ${tenant_id} ${epg_id} ${endpoint_group} Get Data From URI session ${epg_path} headers=${headers} Should Not Be Empty ${endpoint_group} @@ -125,6 +133,6 @@ Check Endpoint Group Name and Selector ${named_selectors} Set Variable ${endpoint_group_json['endpoint-group'][0]['${named-selector}']} ${selector_found} Set Variable FALSE FOR ${selector} IN @{named_selectors} - Return From Keyword If "${selector['contract'][0]}" == "${contract_id}" + IF "${selector['contract'][0]}" == "${contract_id}" RETURN END Fail diff --git a/csit/libraries/GBP/ConnUtils.robot b/csit/libraries/GBP/ConnUtils.robot index 4ca15f699d..e8099a4d49 100644 --- a/csit/libraries/GBP/ConnUtils.robot +++ b/csit/libraries/GBP/ConnUtils.robot @@ -1,9 +1,11 @@ *** Settings *** -Library SSHLibrary -Resource ../SSHKeywords.robot +Library SSHLibrary +Resource ../SSHKeywords.robot + *** Variables *** -${VE_DIR} ${WORKSPACE}/GBPSFC_VE +${VE_DIR} ${WORKSPACE}/GBPSFC_VE + *** Keywords *** Connect and Login @@ -12,9 +14,12 @@ Connect and Login SSHKeywords.Flexible Mininet Login Execute in VE - [Arguments] ${cmd} ${virt_env_path}=${VE_DIR} ${timeout}=10s [Documentation] Wrapper method for executing commands in python virtual environment. + [Arguments] ${cmd} ${virt_env_path}=${VE_DIR} ${timeout}=10s Set Client Configuration timeout=${timeout} - ${stdout} ${stderr} ${rc} SSHLibrary.Execute Command source ${virt_env_path}/bin/activate;${cmd} return_stderr=True return_stdout=True + ${stdout} ${stderr} ${rc} SSHLibrary.Execute Command + ... source ${virt_env_path}/bin/activate;${cmd} + ... return_stderr=True + ... return_stdout=True ... return_rc=True - [Return] ${stdout} ${stderr} ${rc} + RETURN ${stdout} ${stderr} ${rc} diff --git a/csit/libraries/GBP/DockerUtils.robot b/csit/libraries/GBP/DockerUtils.robot index 99c44efb13..7ee38e884c 100644 --- a/csit/libraries/GBP/DockerUtils.robot +++ b/csit/libraries/GBP/DockerUtils.robot @@ -1,81 +1,132 @@ *** Settings *** -Library SSHLibrary +Library SSHLibrary -*** Variables *** *** Keywords *** Ping from Docker - [Arguments] ${docker_name} ${dest_address} ${count}=1 [Documentation] Sends ICMP requests from docker container to remote address. - ${output} ${rc} SSHLibrary.Execute Command docker exec ${docker_name} ping ${dest_address} -c ${count} >/dev/null 2>&1 && echo success return_stdout=True return_stderr=False return_rc=True + [Arguments] ${docker_name} ${dest_address} ${count}=1 + ${output} ${rc} SSHLibrary.Execute Command + ... docker exec ${docker_name} ping ${dest_address} -c ${count} >/dev/null 2>&1 && echo success + ... return_stdout=True + ... return_stderr=False + ... return_rc=True Should Contain ${output} success Should Be Equal As Numbers ${rc} 0 Start Endless Ping from Docker - [Arguments] ${docker_name} ${dest_address} [Documentation] Starts endless ICMP pinging from docker container to remote address. + [Arguments] ${docker_name} ${dest_address} Ping from Docker ${docker_name} ${dest_address} SSHLibrary.Execute Command docker exec -d ${docker_name} ping ${dest_address} Start HTTP Service on Docker - [Arguments] ${docker_name} ${service_port}=80 ${timeout}=20s [Documentation] Starts SimpleHTTPServer on docker container. Service port should be idle. - ${stdout} SSHLibrary.Execute Command docker exec ${docker_name} ps aux | grep 'SimpleHTTPServer ${service_port}' return_stdout=True return_stderr=False return_rc=False + [Arguments] ${docker_name} ${service_port}=80 ${timeout}=20s + ${stdout} SSHLibrary.Execute Command + ... docker exec ${docker_name} ps aux | grep 'SimpleHTTPServer ${service_port}' + ... return_stdout=True + ... return_stderr=False + ... return_rc=False Should Be Empty ${stdout} SSHLibrary.Write docker exec ${docker_name} python -m SimpleHTTPServer ${service_port} & Wait Until Keyword Succeeds 2 min 5 sec Test Port On Docker ${docker_name} ${service_port} Stop HTTP Service on Docker - [Arguments] ${docker_name} ${service_port}=80 [Documentation] Stops SimpleHTTPServer on docker container. Service port should not be idle. - ${stdout} SSHLibrary.Execute Command docker exec ${docker_name} ps aux | grep 'SimpleHTTPServer ${service_port}' | awk '{print $2}' return_stdout=True return_stderr=False return_rc=False + [Arguments] ${docker_name} ${service_port}=80 + ${stdout} SSHLibrary.Execute Command + ... docker exec ${docker_name} ps aux | grep 'SimpleHTTPServer ${service_port}' | awk '{print $2}' + ... return_stdout=True + ... return_stderr=False + ... return_rc=False Should Not Be Empty ${stdout} - ${stdout} SSHLibrary.Execute Command docker exec ${docker_name} kill ${stdout} return_stdout=True return_stderr=False return_rc=False + ${stdout} SSHLibrary.Execute Command + ... docker exec ${docker_name} kill ${stdout} + ... return_stdout=True + ... return_stderr=False + ... return_rc=False Curl from Docker - [Arguments] ${docker_name} ${dest_address} ${service_port}=80 ${connect_timeout}=2 ${retry}=5x ${retry_after}=1s [Documentation] Sends HTTP request to remote server. Endless curl should not be running. - ${output} SSHLibrary.Execute Command docker exec ${docker_name} ls | grep curl_running return_stdout=True return_stderr=False return_rc=False + [Arguments] ${docker_name} ${dest_address} ${service_port}=80 ${connect_timeout}=2 ${retry}=5x ${retry_after}=1s + ${output} SSHLibrary.Execute Command + ... docker exec ${docker_name} ls | grep curl_running + ... return_stdout=True + ... return_stderr=False + ... return_rc=False Should Be Empty ${output} - Wait Until Keyword Succeeds ${retry} ${retry_after} Execute Curl ${docker_name} ${dest_address} ${service_port} + Wait Until Keyword Succeeds + ... ${retry} + ... ${retry_after} + ... Execute Curl + ... ${docker_name} + ... ${dest_address} + ... ${service_port} Start Endless Curl from Docker + [Documentation] Starts endless curl from docker container. Only one endless curl can be running on docker container. [Arguments] ${docker_name} ${dest_address} ${service_port} ${retry_after}=1s ${retry}=5 ${timeout}=20s ... ${sleep}=1 - [Documentation] Starts endless curl from docker container. Only one endless curl can be running on docker container. - ${output} SSHLibrary.Execute Command docker exec ${docker_name} ls | grep curl_running return_stdout=True return_stderr=False return_rc=False + ${output} SSHLibrary.Execute Command + ... docker exec ${docker_name} ls | grep curl_running + ... return_stdout=True + ... return_stderr=False + ... return_rc=False Should Be Empty ${output} - ${output} SSHLibrary.Execute Command docker exec ${docker_name} touch curl_running && echo success return_stdout=True return_stderr=False return_rc=False + ${output} SSHLibrary.Execute Command + ... docker exec ${docker_name} touch curl_running && echo success + ... return_stdout=True + ... return_stderr=False + ... return_rc=False Should Contain ${output} success Execute Curl ${docker_name} ${dest_address} ${service_port} endless="TRUE" Stop Endless Curl from Docker - [Arguments] ${docker_name} [Documentation] Stops endless curl from docker container. Endless curl should be running before stopping it. - ${output} SSHLibrary.Execute Command docker exec ${docker_name} ls | grep curl_running return_stdout=True return_stderr=False return_rc=False + [Arguments] ${docker_name} + ${output} SSHLibrary.Execute Command + ... docker exec ${docker_name} ls | grep curl_running + ... return_stdout=True + ... return_stderr=False + ... return_rc=False Should Not Be Empty ${output} - ${output} SSHLibrary.Execute Command docker exec ${docker_name} rm curl_running && echo success return_stdout=True return_stderr=False return_rc=False + ${output} SSHLibrary.Execute Command + ... docker exec ${docker_name} rm curl_running && echo success + ... return_stdout=True + ... return_stderr=False + ... return_rc=False Should Contain ${output} success Stop Endless Ping from Docker to Address - [Arguments] ${docker_name} ${dest_address} [Documentation] Stops endless ping from docker to remote address. Endless ping session should be running before stopping it. - ${output} SSHLibrary.Execute Command docker exec ${docker_name} ps aux | grep 'ping ${dest_address}' | grep -v grep | awk '{print $2}' return_stdout=True return_stderr=False return_rc=False + [Arguments] ${docker_name} ${dest_address} + ${output} SSHLibrary.Execute Command + ... docker exec ${docker_name} ps aux | grep 'ping ${dest_address}' | grep -v grep | awk '{print $2}' + ... return_stdout=True + ... return_stderr=False + ... return_rc=False Should Not Be Empty ${output} SSHLibrary.Execute Command docker exec ${docker_name} kill ${output} - ${output} SSHLibrary.Execute Command docker exec ${docker_name} ps aux | grep 'ping ${dest_address}' | grep -v grep | awk '{print $2}' + ${output} SSHLibrary.Execute Command + ... docker exec ${docker_name} ps aux | grep 'ping ${dest_address}' | grep -v grep | awk '{print $2}' Should Be Empty ${output} Test Port On Docker - [Arguments] ${docker_name} ${service_port} [Documentation] Tests if a service is running on service port. - ${out} SSHLibrary.Execute Command docker exec ${docker_name} nc -z -w 5 127.0.0.1 ${service_port} && echo 'opened' + [Arguments] ${docker_name} ${service_port} + ${out} SSHLibrary.Execute Command + ... docker exec ${docker_name} nc -z -w 5 127.0.0.1 ${service_port} && echo 'opened' Should Not Be Empty ${out} Execute Curl - [Arguments] ${docker_name} ${dest_address} ${service_port} ${endless}="FALSE" ${sleep}=1 [Documentation] Executes curl or curl loop for caller methods based on given parameters. - Run Keyword If ${endless} == "TRUE" Run Keywords SSHLibrary.Execute Command docker exec -d ${docker_name} /bin/sh -c "while [ -f curl_running ]; do curl ${dest_address}:${service_port} -m 1 && sleep ${sleep}; done" - ... AND Return From Keyword - ${output} SSHLibrary.Execute Command docker exec ${docker_name} curl ${dest_address}:${service_port} -m 5 >/dev/null 2>&1 && echo success + [Arguments] ${docker_name} ${dest_address} ${service_port} ${endless}="FALSE" ${sleep}=1 + IF ${endless} == "TRUE" + SSHLibrary.Execute Command + ... docker exec -d ${docker_name} /bin/sh -c "while [ -f curl_running ]; do curl ${dest_address}:${service_port} -m 1 && sleep ${sleep}; done" + RETURN + END + ${output} SSHLibrary.Execute Command + ... docker exec ${docker_name} curl ${dest_address}:${service_port} -m 5 >/dev/null 2>&1 && echo success Should Contain ${output} success diff --git a/csit/libraries/GBP/OpenFlowUtils.robot b/csit/libraries/GBP/OpenFlowUtils.robot index 69729ef9c1..1018da5dc6 100644 --- a/csit/libraries/GBP/OpenFlowUtils.robot +++ b/csit/libraries/GBP/OpenFlowUtils.robot @@ -1,28 +1,35 @@ *** Settings *** -Documentation Operations on Docker containers for GBP -Library SSHLibrary -Library Collections -Resource ../Utils.robot -Resource ConnUtils.robot -Resource DockerUtils.robot -Variables ../../variables/Variables.py -Library OperatingSystem +Documentation Operations on Docker containers for GBP + +Library SSHLibrary +Library Collections +Resource ../Utils.robot +Resource ConnUtils.robot +Resource DockerUtils.robot +Variables ../../variables/Variables.py +Library OperatingSystem + *** Keywords *** Inspect Service Function + [Documentation] Inspects traffic passing through service function node. [Arguments] ${in_port} ${out_port} ${outer_src_ip} ${outer_dst_ip} ${eth_type} ${inner_src_ip} ... ${inner_dst_ip} ${next_hop_ip} ${nsp} ${received_nsi} ${proto}=${EMPTY} - [Documentation] Inspects traffic passing through service function node. @{matches} Create List @{actions} Create List Append In Port Check ${matches} ${in_port} Append Ether-Type Check ${matches} ${eth_type} Append Tunnel Set Check ${matches} - Append Outer IPs Check ${matches} src_ip=${outer__src_ip}/255.255.255.255 dst_ip=${outer_dst_ip}/255.255.255.255 + Append Outer IPs Check + ... ${matches} + ... src_ip=${outer__src_ip}/255.255.255.255 + ... dst_ip=${outer_dst_ip}/255.255.255.255 Append NSI Check ${matches} ${received_nsi} Append NSP Check ${matches} ${nsp} Append Inner IPs Check ${matches} ${inner_src_ip}/0.0.0.0 ${inner_dst_ip}/0.0.0.0 - Run Keyword If "${proto}" != "${EMPTY}" Append Proto Check ${matches} ${proto} + IF "${proto}" != "${EMPTY}" + Append Proto Check ${matches} ${proto} + END Append Tunnel Set Check ${actions} Append Outer IPs Check ${actions} dst_ip=${next_hop_ip} ${rewritten_nsi} Evaluate ${received_nsi} -1 @@ -30,12 +37,12 @@ Inspect Service Function Append NSP Check ${actions} ${nsp} Append Out Port Check ${actions} ${out_port} ${flow} Find Flow in DPCTL Output ${matches} ${actions} - [Return] ${flow} + RETURN ${flow} Inspect Service Function Forwarder + [Documentation] Inspects traffic passing through service function forwarder node. [Arguments] ${in_port} ${out_port} ${outer_src_ip} ${outer_dst_ip} ${eth_type} ${inner_src_ip} ... ${inner_dst_ip} ${next_hop_ip} ${nsp} ${nsi} ${proto}=${EMPTY} - [Documentation] Inspects traffic passing through service function forwarder node. @{matches} Create List @{actions} Create List Append In Port Check ${matches} ${in_port} @@ -45,69 +52,84 @@ Inspect Service Function Forwarder Append NSI Check ${matches} ${nsi} Append NSP Check ${matches} ${nsp} Append Inner IPs Check ${matches} ${inner_src_ip}/255.255.255.255 ${inner_dst_ip}/255.255.255.255 - Run Keyword If "${proto}" != "${EMPTY}" Append Proto Check ${matches} ${proto} + IF "${proto}" != "${EMPTY}" + Append Proto Check ${matches} ${proto} + END Append Tunnel Set Check ${actions} Append Outer IPs Check ${actions} dst_ip=${next_hop_ip} Append NSI Check ${actions} ${nsi} Append NSP Check ${actions} ${nsp} Append Out Port Check ${actions} ${out_port} ${flow} Find Flow in DPCTL Output ${matches} ${actions} - [Return] ${flow} + RETURN ${flow} Inspect Classifier Outbound - [Arguments] ${in_port} ${out_port} ${eth_type} ${inner_src_ip} ${inner_dst_ip} ${next_hop_ip}=${EMPTY} - ... ${nsi}=${EMPTY} ${proto}=${EMPTY} ${src_port}=${EMPTY} ${dst_port}=${EMPTY} [Documentation] Inspects outbound traffic of a classifier. Traffic source should be located on the classifier. ... If traffic destination is located on the same VM, do not specify neither of next_hop_ip and nsi. ... If traffic destination is located on different VM and the traffic is not forwarded into a chain, specify ... next_hop_ip and don't specify nsi. ... If traffic destination is located on different VM and the traffic is forwarded into a chain, specify both ... next_hop_ip and nsi. + [Arguments] ${in_port} ${out_port} ${eth_type} ${inner_src_ip} ${inner_dst_ip} ${next_hop_ip}=${EMPTY} + ... ${nsi}=${EMPTY} ${proto}=${EMPTY} ${src_port}=${EMPTY} ${dst_port}=${EMPTY} @{matches} Create List @{actions} Create List Append In Port Check ${matches} ${in_port} Append Ether-Type Check ${matches} ${eth_type} - Run Keyword If "${proto}" != "${EMPTY}" Append Proto Check ${matches} ${proto} - Run Keyword If "${src_port}"!="${EMPTY}" or "${dst_port}"!="${EMPTY}" Append L4 Check ${matches} src_port=${src_port} dst_port=${dst_port} + IF "${proto}" != "${EMPTY}" + Append Proto Check ${matches} ${proto} + END + IF "${src_port}"!="${EMPTY}" or "${dst_port}"!="${EMPTY}" + Append L4 Check ${matches} src_port=${src_port} dst_port=${dst_port} + END Append Out Port Check ${actions} ${out_port} Append Inner IPs Check ${actions} ${inner_src_ip} ${inner_dst_ip} - Run Keyword If "${next_hop_ip}"!="${EMPTY}" Run Keywords Append Tunnel Set Check ${actions} - ... AND Append Outer IPs Check ${actions} dst_ip=${next_hop_ip} - ... ELSE Append Tunnel Not Set Check ${actions} - Run Keyword If "${nsi}"!="${EMPTY}" Append NSI Check ${actions} 255 + IF "${next_hop_ip}"!="${EMPTY}" + Append Tunnel Set Check ${actions} + Append Outer IPs Check ${actions} dst_ip=${next_hop_ip} + ELSE + Append Tunnel Not Set Check ${actions} + END + IF "${nsi}"!="${EMPTY}" Append NSI Check ${actions} 255 ${flow} Find Flow in DPCTL Output ${matches} ${actions} - [Return] ${flow} + RETURN ${flow} Inspect Classifier Inbound - [Arguments] ${in_port} ${out_port} ${eth_type} ${inner_src_ip} ${inner_dst_ip} ${outer_src_ip} - ... ${outer_dst_ip} ${nsp}=${EMPTY} ${nsi}=${EMPTY} ${proto}=${EMPTY} ${src_port}=${EMPTY} ${dst_port}=${EMPTY} [Documentation] Inspects inbound traffic of a classifier. Traffic destination should be located on the classifier. ... If traffic source is located on different VM and the traffic comes out of a chain, specify nsi and nsp values. ... If traffic source is located on different VM and the traffic does not comes out of a chain, do not specify ... neither of nsi and nsp values. + [Arguments] ${in_port} ${out_port} ${eth_type} ${inner_src_ip} ${inner_dst_ip} ${outer_src_ip} + ... ${outer_dst_ip} ${nsp}=${EMPTY} ${nsi}=${EMPTY} ${proto}=${EMPTY} ${src_port}=${EMPTY} ${dst_port}=${EMPTY} @{matches} Create List @{actions} Create List Append In Port Check ${matches} ${in_port} Append Ether-Type Check ${matches} ${eth_type} Append Outer IPs Check ${matches} src_ip=${outer_src_ip} dst_ip=${outer_dst_ip} Append Inner IPs Check ${matches} ${inner_src_ip} ${inner_dst_ip} - Run Keyword If "${src_port}"!="${EMPTY}" or "${dst_port}"!="${EMPTY}" Append L4 Check ${matches} src_port=${src_port} dst_port=${dst_port} + IF "${src_port}"!="${EMPTY}" or "${dst_port}"!="${EMPTY}" + Append L4 Check ${matches} src_port=${src_port} dst_port=${dst_port} + END Append Tunnel Set Check ${matches} - Run Keyword If "${nsi}"!="${EMPTY}" and "${nsp}"!="${EMPTY}" Run Keywords Append NSI Check ${matches} ${nsi} - ... AND Append NSP Check ${matches} ${nsp} - Run Keyword If "${proto}" != "${EMPTY}" Run Keywords Append Proto Check ${matches} ${proto} - ... AND Append Proto Check ${actions} ${proto} + IF "${nsi}"!="${EMPTY}" and "${nsp}"!="${EMPTY}" + Append NSI Check ${matches} ${nsi} + Append NSP Check ${matches} ${nsp} + END + IF "${proto}" != "${EMPTY}" + Append Proto Check ${matches} ${proto} + Append Proto Check ${actions} ${proto} + END Append Out Port Check ${actions} ${out_port} Append Inner IPs Check ${actions} ${inner_src_ip} ${inner_dst_ip} ${flow} Find Flow in DPCTL Output ${matches} ${actions} - [Return] ${flow} + RETURN ${flow} Find Flow in DPCTL Output - [Arguments] ${flow_match_criteria} ${flow_action_criteria} [Documentation] Executes 'ovs-dpctl dump-flows' on remote system and goes through each output line. ... A line is returned if all the criterias in actions part and matches part are matched. This is ... done by calling 'Check Match' keyword. If no match is found for any of the flows, caller test case ... will be failed. + [Arguments] ${flow_match_criteria} ${flow_action_criteria} ${output} SSHLibrary.Execute Command sudo ovs-dpctl dump-flows Log ${output} @{lines} Split To Lines ${output} @@ -118,121 +140,140 @@ Find Flow in DPCTL Output ${action} Get Actions Part ${line} ${match_result} Check Match ${match} @{flow_match_criteria} ${action_result} Check Match ${action} @{flow_action_criteria} - Run Keyword If "${match_result}" == "TRUE" and "${action_result}" == "TRUE" Return From Keyword ${line} + IF "${match_result}" == "TRUE" and "${action_result}" == "TRUE" + RETURN ${line} + END END Log ${flow_match_criteria} Log ${flow_action_criteria} Fail Flow not found! Get Matches Part - [Arguments] ${ovs-dpctl_flow} [Documentation] Returns matches part of a flow captured with 'ovs-dpctl dump-flows'. + [Arguments] ${ovs-dpctl_flow} @{matches_actions} Split String ${ovs-dpctl_flow} actions Log ${matches_actions[0]} - [Return] ${matches_actions[0]} + RETURN ${matches_actions[0]} Get Actions Part - [Arguments] ${ovs-dpctl_flow} [Documentation] Returns actions part of a flow captured with 'ovs-dpctl dump-flows'. + [Arguments] ${ovs-dpctl_flow} @{matches_actions} Split String ${ovs-dpctl_flow} actions - [Return] ${matches_actions[1]} + RETURN ${matches_actions[1]} Check Match - [Arguments] ${string} @{match_criteria} [Documentation] Applies 'grep' on the string argument for each criterion. + [Arguments] ${string} @{match_criteria} ${conditions} Set Variable FOR ${criterio} IN @{match_criteria} ${grep_criterio} Catenate | grep ${criterio} ${conditions} Catenate ${conditions} ${grep_criterio} ${debug_output} OperatingSystem.Run echo "${string}" ${conditions} Log ${debug_output} - Run Keyword If "${debug_output}" == "${EMPTY}" Log ${criterio} + IF "${debug_output}" == "${EMPTY}" Log ${criterio} END ${output} OperatingSystem.Run echo "${string}" ${conditions} Log ${output} - Run Keyword If "${output}" == "${EMPTY}" Return From Keyword FALSE - ... ELSE Return From Keyword TRUE + IF "${output}" == "${EMPTY}" RETURN FALSE ELSE RETURN TRUE Append Proto Check - [Arguments] ${list} ${proto} [Documentation] Returns proto part of flow can be captured with 'ovs-dpctl dump-flows'. + [Arguments] ${list} ${proto} Append To List ${list} proto=${proto} Append Inner MAC Check - [Arguments] ${list} ${src_addr}=${EMPTY} ${dst_addr}=${EMPTY} [Documentation] Returns encapsulated MAC addresses part of flow can be captured with 'ovs-dpctl dump-flows'. - Run Keyword If "${src_addr}" != "${EMPTY}" and "${dst_addr}" != "${EMPTY}" Append To List ${list} "eth(src=${src_addr},dst=${dst_addr})" - ... ELSE IF "${src_addr}" != "${EMPTY}" Append To List ${list} "eth(src=${src_addr},dst=.*)" - ... ELSE IF "${dst_addr}" != "${EMPTY}" Append To List ${list} "eth(src=.*,dst=${dst_addr})" - ... ELSE Fail Specify at liest src or dest IP! + [Arguments] ${list} ${src_addr}=${EMPTY} ${dst_addr}=${EMPTY} + IF "${src_addr}" != "${EMPTY}" and "${dst_addr}" != "${EMPTY}" + Append To List ${list} "eth(src=${src_addr},dst=${dst_addr})" + ELSE IF "${src_addr}" != "${EMPTY}" + Append To List ${list} "eth(src=${src_addr},dst=.*)" + ELSE IF "${dst_addr}" != "${EMPTY}" + Append To List ${list} "eth(src=.*,dst=${dst_addr})" + ELSE + Fail Specify at liest src or dest IP! + END Append Inner IPs Check - [Arguments] ${list} ${src_ip}=${EMPTY} ${dst_ip}=${EMPTY} [Documentation] Returns encapsulated IP addresses part of flow can be captured with 'ovs-dpctl dump-flows'. - Run Keyword If "${src_ip}" != "${EMPTY}" and "${dst_ip}" != "${EMPTY}" Append To List ${list} "ipv4(src=${src_ip},dst=${dst_ip}" - ... ELSE IF "${src_ip}" != "${EMPTY}" Append To List ${list} "ipv4(src=${src_ip},dst=.*" - ... ELSE IF "${dst_ip}" != "${EMPTY}" Append To List ${list} "ipv4(src=.*,dst=${dst_ip}" - ... ELSE Fail Specify at liest src or dest IP! + [Arguments] ${list} ${src_ip}=${EMPTY} ${dst_ip}=${EMPTY} + IF "${src_ip}" != "${EMPTY}" and "${dst_ip}" != "${EMPTY}" + Append To List ${list} "ipv4(src=${src_ip},dst=${dst_ip}" + ELSE IF "${src_ip}" != "${EMPTY}" + Append To List ${list} "ipv4(src=${src_ip},dst=.*" + ELSE IF "${dst_ip}" != "${EMPTY}" + Append To List ${list} "ipv4(src=.*,dst=${dst_ip}" + ELSE + Fail Specify at liest src or dest IP! + END Append Outer IPs Check - [Arguments] ${list} ${src_ip}=${EMPTY} ${dst_ip}=${EMPTY} [Documentation] Returns packet IP addresses part of flow can be captured with 'ovs-dpctl dump-flows'. - Run Keyword If "${src_ip}" != "${EMPTY}" Append To List ${list} src=${src_ip} - ... ELSE IF "${dst_ip}" != "${EMPTY}" Append To List ${list} dst=${dst_ip} - ... ELSE Fail Specify at liest src or dest IP! + [Arguments] ${list} ${src_ip}=${EMPTY} ${dst_ip}=${EMPTY} + IF "${src_ip}" != "${EMPTY}" + Append To List ${list} src=${src_ip} + ELSE IF "${dst_ip}" != "${EMPTY}" + Append To List ${list} dst=${dst_ip} + ELSE + Fail Specify at liest src or dest IP! + END Append In Port Check - [Arguments] ${list} ${in_port} [Documentation] Returns ingress port part of flow can be captured with 'ovs-dpctl dump-flows'. + [Arguments] ${list} ${in_port} Append To List ${list} "in_port(${in_port})" Append Out Port Check - [Arguments] ${list} ${out_port} [Documentation] Returns egress port part of flow can be captured with 'ovs-dpctl dump-flows'. + [Arguments] ${list} ${out_port} Append To List ${list} ,${out_port} Append L4 Check - [Arguments] ${list} ${src_port}=${EMPTY} ${dst_port}=${EMPTY} [Documentation] Returns L4 port part of flow can be captured with 'ovs-dpctl dump-flows'. - Run Keyword If "${src_port}" != "${EMPTY}" Append To List ${list} src=${src_port} - ... ELSE IF "${dst_port}" != "${EMPTY}" Append To List ${list} dst=${dst_port} - ... ELSE Fail Specify at liest src or dest port! + [Arguments] ${list} ${src_port}=${EMPTY} ${dst_port}=${EMPTY} + IF "${src_port}" != "${EMPTY}" + Append To List ${list} src=${src_port} + ELSE IF "${dst_port}" != "${EMPTY}" + Append To List ${list} dst=${dst_port} + ELSE + Fail Specify at liest src or dest port! + END Append NSI Check - [Arguments] ${list} ${nsi} [Documentation] Returns NSI part of flow can be captured with 'ovs-dpctl dump-flows'. + [Arguments] ${list} ${nsi} Append To List ${list} nsi=${nsi} Append NSP Check - [Arguments] ${list} ${nsp} [Documentation] Returns NSP part of flow can be captured with 'ovs-dpctl dump-flows'. + [Arguments] ${list} ${nsp} Append To List ${list} nsp=${nsp} Append Ether-Type Check - [Arguments] ${list} ${eth_type} [Documentation] Returns Ether-Type part of flow can be captured with 'ovs-dpctl dump-flows'. + [Arguments] ${list} ${eth_type} Append To List ${list} "eth_type(${eth_type})" Append Tunnel Set Check - [Arguments] ${list} [Documentation] Tunnel ID is locally significant to neighbouring nodes and it is not ... statically determined. By checking it's presence in match ( or action) fields, ... we can say whether a packet was received (or send out) via tunnel port. + [Arguments] ${list} Append To List ${list} tun_id Append Tunnel Not Set Check - [Arguments] ${list} [Documentation] Tunnel ID is locally significant to neighbouring nodes and it is not ... statically determined. By checking it's presence in match ( or action) fields, ... we can say whether a packet was received (or send out) via tunnel port. + [Arguments] ${list} Append To List ${list} -v tun_id Get NSP Value From Flow - [Arguments] ${flow} [Documentation] Reads and returns nsp value from flow captured with 'ovs-dpctl dump-flows'. + [Arguments] ${flow} ${flow} Get Actions Part ${flow} ${output} OperatingSystem.Run echo "\$${flow}" | sed 's/.*nsp=/nsp=/' | sed 's/,.*//' | sed 's/.*=//' - [Return] ${output} + RETURN ${output} Manager is Connected ${output} SSHLibrary.Execute Command sudo ovs-vsctl show @@ -245,24 +286,29 @@ Manager and Switch Connected Should Contain x Times ${output} is_connected: true 2 Wait For Flows On Switch - [Arguments] ${switch_ip} ${switch_name} [Documentation] Counts flows on switch, fails if 0 + [Arguments] ${switch_ip} ${switch_name} ConnUtils.Connect and Login ${switch_ip} # check for OVS errors first - ${stdout} ${stderr} SSHLibrary.Execute Command sudo ovs-ofctl dump-flows ${switch_name} -OOpenFlow13 return_stderr=True - Run Keyword If "${stderr}" != "${EMPTY}" Fatal Error ${stderr} + ${stdout} ${stderr} SSHLibrary.Execute Command + ... sudo ovs-ofctl dump-flows ${switch_name} -OOpenFlow13 + ... return_stderr=True + IF "${stderr}" != "${EMPTY}" Fatal Error ${stderr} Wait Until Keyword Succeeds 120s 20s Count Flows On Switch ${switch_name} SSHLibrary.Close Connection Show Switch Status - [Arguments] ${switch_name} [Documentation] Shows status of a switch for easier debugging. - ${stdout} ${stderr} SSHLibrary.Execute Command sudo ovs-ofctl dump-flows ${switch_name} -OOpenFlow13 return_stderr=True + [Arguments] ${switch_name} + ${stdout} ${stderr} SSHLibrary.Execute Command + ... sudo ovs-ofctl dump-flows ${switch_name} -OOpenFlow13 + ... return_stderr=True Log ${stdout} ${stdout} ${stderr} SSHLibrary.Execute Command sudo ovs-vsctl show return_stderr=True Log ${stdout} Count Flows On Switch [Arguments] ${switch_name} - ${out} SSHLibrary.Execute Command printf "%d" $(($(sudo ovs-ofctl dump-flows ${switch_name} -OOpenFlow13 | wc -l)-1)) + ${out} SSHLibrary.Execute Command + ... printf "%d" $(($(sudo ovs-ofctl dump-flows ${switch_name} -OOpenFlow13 | wc -l)-1)) Should Be True ${out}>0 diff --git a/csit/libraries/GBP/RestconfUtils.robot b/csit/libraries/GBP/RestconfUtils.robot index 268226a6a3..7f1966e0ac 100644 --- a/csit/libraries/GBP/RestconfUtils.robot +++ b/csit/libraries/GBP/RestconfUtils.robot @@ -1,211 +1,217 @@ *** Settings *** -Documentation Utils for Restconf operations for GBP -Library RequestsLibrary -Library OperatingSystem -Library String -Library json -Variables ../../variables/Variables.py -Resource ../Utils.robot +Documentation Utils for Restconf operations for GBP + +Library RequestsLibrary +Library OperatingSystem +Library String +Library json +Variables ../../variables/Variables.py +Resource ../Utils.robot + *** Variables *** -${ENDPOINT_UNREG_PATH} ${GBP_UNREGEP_API} -${ENDPOINTS_OPER_PATH} /restconf/operational/endpoint:endpoints +${ENDPOINT_UNREG_PATH} ${GBP_UNREGEP_API} +${ENDPOINTS_OPER_PATH} /restconf/operational/endpoint:endpoints + *** Keywords *** Unregister Endpoints [Documentation] Unregister Endpoints Endpoints from ODL - ${result} = RequestsLibrary.Get Request session ${ENDPOINTS_OPER_PATH} - ${json_result} = json.loads ${result.text} + ${result} RequestsLibrary.Get Request session ${ENDPOINTS_OPER_PATH} + ${json_result} json.loads ${result.text} Pass Execution If ${json_result['endpoints']}=={} No Endpoints available - ${L2_ENDPOINTS} = Set Variable ${json_result['endpoints']['endpoint']} - ${L3_ENDPOINTS} = Set Variable ${json_result['endpoints']['endpoint-l3']} + ${L2_ENDPOINTS} Set Variable ${json_result['endpoints']['endpoint']} + ${L3_ENDPOINTS} Set Variable ${json_result['endpoints']['endpoint-l3']} Log ${L2_ENDPOINTS} Unregister L2Endpoints ${L2_ENDPOINTS} Log ${L3_ENDPOINTS} Unregister L3Endpoints ${L3_ENDPOINTS} - ${result} = RequestsLibrary.Get Request session ${ENDPOINTS_OPER_PATH} - ${json_result} = json.loads ${result.text} + ${result} RequestsLibrary.Get Request session ${ENDPOINTS_OPER_PATH} + ${json_result} json.loads ${result.text} Should Be Empty ${json_result['endpoints']} Unregister L2Endpoints - [Arguments] ${l2_eps} [Documentation] Unregister Endpoints L2Endpoints from ODL + [Arguments] ${l2_eps} FOR ${endpoint} IN @{l2_eps} - ${l2_data} = Create L2 Endpoint JSON Data ${endpoint} + ${l2_data} Create L2 Endpoint JSON Data ${endpoint} Post Elements To URI ${ENDPOINT_UNREG_PATH} ${l2_data} ${HEADERS_YANG_JSON} END Unregister L3Endpoints - [Arguments] ${l3_eps} [Documentation] Unregister Endpoints L3Endpoints from ODL + [Arguments] ${l3_eps} FOR ${endpoint} IN @{l3_eps} - ${l3_data} = Create L3 Endpoint JSON Data ${endpoint} + ${l3_data} Create L3 Endpoint JSON Data ${endpoint} Post Elements To URI ${ENDPOINT_UNREG_PATH} ${l3_data} ${HEADERS_YANG_JSON} END Create L2 Endpoint JSON Data - [Arguments] ${endpoint} [Documentation] Generate the JSON data required for unregistering L2 Endpoints - ${data} Set Variable {"input": {"l2": [{"mac-address": "${endpoint['mac-address']}", "l2-context": "${endpoint['l2-context']}"}]}} - [Return] ${data} + [Arguments] ${endpoint} + ${data} Set Variable + ... {"input": {"l2": [{"mac-address": "${endpoint['mac-address']}", "l2-context": "${endpoint['l2-context']}"}]}} + RETURN ${data} Create L3 Endpoint JSON Data - [Arguments] ${endpoint} [Documentation] Generate the JSON data required for unregistering L3 Endpoints - ${data} Set Variable {"input": {"l3": [{"l3-context": "${endpoint['l3-context']}", "ip-address": "${endpoint['ip-address']}"}]}} - [Return] ${data} + [Arguments] ${endpoint} + ${data} Set Variable + ... {"input": {"l3": [{"l3-context": "${endpoint['l3-context']}", "ip-address": "${endpoint['ip-address']}"}]}} + RETURN ${data} Get Endpoint Path - [Arguments] ${l2-context} ${mac_address} [Documentation] Returns path for a registered endpoint based on key in arguments + [Arguments] ${l2-context} ${mac_address} ${mac_address} Convert To Uppercase ${mac_address} - [Return] restconf/operational/endpoint:endpoints/endpoint/${l2-context}/${mac_address} + RETURN restconf/operational/endpoint:endpoints/endpoint/${l2-context}/${mac_address} Get EndpointL3 Path - [Arguments] ${l3-context} ${ip_address} [Documentation] Returns path for a registered endpoint-l3 based on key in arguments - [Return] restconf/operational/endpoint:endpoints/endpoint-l3/${l3-context}/${ip_address} + [Arguments] ${l3-context} ${ip_address} + RETURN restconf/operational/endpoint:endpoints/endpoint-l3/${l3-context}/${ip_address} Get Tenant Path - [Arguments] ${tenant_id} [Documentation] Returns path for a tenant based on key in arguments - [Return] ${TENANTS_CONF_PATH}/policy:tenant/${tenant_id} + [Arguments] ${tenant_id} + RETURN ${TENANTS_CONF_PATH}/policy:tenant/${tenant_id} Get Policy Path - [Arguments] ${tenant_id} [Documentation] Returns policy path for a particular tenant + [Arguments] ${tenant_id} ${tenant_path} Get Tenant Path ${tenant_id} - [Return] ${tenant_path}/policy + RETURN ${tenant_path}/policy Get Contract Path - [Arguments] ${tenant_id} ${contract_id} [Documentation] Returns path for a contract based on key and tenant-id in arguments + [Arguments] ${tenant_id} ${contract_id} ${policy_path} Get Policy Path ${tenant_id} - [Return] ${policy_path}/contract/${contract_id} + RETURN ${policy_path}/contract/${contract_id} Get Endpoint Group Path - [Arguments] ${tenant_id} ${endpoint_group_id} [Documentation] Returns path for an EPG based on key and tenant-id in arguments + [Arguments] ${tenant_id} ${endpoint_group_id} ${policy_path} Get Policy Path ${tenant_id} - [Return] ${policy_path}/endpoint-group/${endpoint_group_id} + RETURN ${policy_path}/endpoint-group/${endpoint_group_id} Get Classifier Instance Path - [Arguments] ${tenant_id} ${classif_instance_id} [Documentation] Returns path for a classifier-instance based on key and tenant-id in arguments + [Arguments] ${tenant_id} ${classif_instance_id} ${policy_path} Get Policy Path ${tenant_id} - [Return] ${policy_path}/subject-feature-instances/classifier-instance/${classif_instance_id} + RETURN ${policy_path}/subject-feature-instances/classifier-instance/${classif_instance_id} Get Forwarding Context Path - [Arguments] ${tenant_id} [Documentation] Returns forwarding path for a particular tenant + [Arguments] ${tenant_id} ${tenant_path} Get Tenant Path ${tenant_id} - [Return] ${tenant_path}/forwarding-context + RETURN ${tenant_path}/forwarding-context Get L3 Context Path - [Arguments] ${tenant_id} ${l3_ctx_id} [Documentation] Returns l3-context path based on key and tenant-id in arguments + [Arguments] ${tenant_id} ${l3_ctx_id} ${fwd_ctx_path} Get Forwarding Context Path ${tenant_id} - [Return] ${fwd_ctx_path}/l3-context/${l3_ctx_id} + RETURN ${fwd_ctx_path}/l3-context/${l3_ctx_id} Get L2 Bridge Domain Path - [Arguments] ${tenant_id} ${l2_br_domain_id} [Documentation] Returns l2-bridge-domain path based on key and tenant-id in arguments + [Arguments] ${tenant_id} ${l2_br_domain_id} ${fwd_ctx_path} Get Forwarding Context Path ${tenant_id} - [Return] ${fwd_ctx_path}/l2-bridge-domain/${l2_br_domain_id} + RETURN ${fwd_ctx_path}/l2-bridge-domain/${l2_br_domain_id} Get L2 Flood Domain Path - [Arguments] ${tenant_id} ${l2_flood_domain_id} [Documentation] Returns l2-flood-domain path based on key and tenant-id in arguments + [Arguments] ${tenant_id} ${l2_flood_domain_id} ${fwd_ctx_path} Get Forwarding Context Path ${tenant_id} - [Return] ${fwd_ctx_path}/l2-flood-domain/${l2_flood_domain_id} + RETURN ${fwd_ctx_path}/l2-flood-domain/${l2_flood_domain_id} Get Subnet Path - [Arguments] ${tenant_id} ${subnet_id} [Documentation] Returns path for a subnet based on key and tenant-id in arguments + [Arguments] ${tenant_id} ${subnet_id} ${fwd_ctx_path} Get Forwarding Context Path ${tenant_id} - [Return] ${fwd_ctx_path}/subnet/${subnet_id} + RETURN ${fwd_ctx_path}/subnet/${subnet_id} Get Prefix Constraint of Single Rule Contract - [Arguments] ${contract} [Documentation] Returns first prefix-constraint from a single rule contract + [Arguments] ${contract} ${contract_json} To Json ${contract} - ${eic} Set Variable ${contract_json['contract'][0]['clause'][0]['consumer-matchers']['endpoint-identification-constraints']} - [Return] ${eic['l3-endpoint-identification-constraints']['prefix-constraint'][0]} + ${eic} Set Variable + ... ${contract_json['contract'][0]['clause'][0]['consumer-matchers']['endpoint-identification-constraints']} + RETURN ${eic['l3-endpoint-identification-constraints']['prefix-constraint'][0]} Get Action of Single Rule Contract - [Arguments] ${contract} [Documentation] Returns first action-ref from a single rule contract + [Arguments] ${contract} ${contract_json} To Json ${contract} - [Return] ${contract_json['contract'][0]['subject'][0]['rule'][0]['action-ref'][0]} + RETURN ${contract_json['contract'][0]['subject'][0]['rule'][0]['action-ref'][0]} Get Ip Prefix of Subnet - [Arguments] ${subnet} [Documentation] Returns ip-prefix from a given subnet + [Arguments] ${subnet} ${subnet_json} To Json ${subnet} - [Return] ${subnet_json['subnet'][0]['ip-prefix']} + RETURN ${subnet_json['subnet'][0]['ip-prefix']} Get Action Instance Name of Single Rule Contract - [Arguments] ${contract} [Documentation] Returns action-instance name from a single rule contract + [Arguments] ${contract} ${contract_json} To Json ${contract} - [Return] ${contract_json['contract'][0]['subject'][0]['rule'][0]['classifier-ref'][0]['instance-name']} + RETURN ${contract_json['contract'][0]['subject'][0]['rule'][0]['classifier-ref'][0]['instance-name']} Get Groups of Endpoint - [Arguments] ${endpoint} [Documentation] Returns endpoint-groups from a given endpoint + [Arguments] ${endpoint} ${endpoint_json} To Json ${endpoint} - [Return] ${endpoint_json['endpoint'][0]['endpoint-groups']} + RETURN ${endpoint_json['endpoint'][0]['endpoint-groups']} Get Groups of Endpoint-L3 - [Arguments] ${endpoint-l3} [Documentation] Returns endpoint-groups from a given endpoint-l3 + [Arguments] ${endpoint-l3} ${endpoint_json} To Json ${endpoint-l3} - [Return] ${endpoint_json['endpoint-l3'][0]['endpoint-groups']} + RETURN ${endpoint_json['endpoint-l3'][0]['endpoint-groups']} Get L3-Addresses of Endpoint - [Arguments] ${endpoint} [Documentation] Returns l3-addresses from a given endpoint + [Arguments] ${endpoint} ${endpoint_json} To Json ${endpoint} - [Return] ${endpoint_json['endpoint'][0]['l3-address']} + RETURN ${endpoint_json['endpoint'][0]['l3-address']} Get Tenant of Endpoint - [Arguments] ${endpoint} [Documentation] Returns tenant-id from a given endpoint + [Arguments] ${endpoint} ${endpoint_json} To Json ${endpoint} - [Return] ${endpoint_json['endpoint'][0]['tenant']} + RETURN ${endpoint_json['endpoint'][0]['tenant']} Get Tenant of Endpoint-L3 - [Arguments] ${endpoint-l3} [Documentation] Returns tenant-id from a given endpoint-l3 + [Arguments] ${endpoint-l3} ${endpoint_json} To Json ${endpoint-l3} - [Return] ${endpoint_json['endpoint-l3'][0]['tenant']} + RETURN ${endpoint_json['endpoint-l3'][0]['tenant']} Get Network Containment of Endpoint - [Arguments] ${endpoint} [Documentation] Returns network-containment from a given endpoint + [Arguments] ${endpoint} ${endpoint_json} To Json ${endpoint} - [Return] ${endpoint_json['endpoint'][0]['network-containment']} + RETURN ${endpoint_json['endpoint'][0]['network-containment']} Get Network Containment of Endpoint-L3 - [Arguments] ${endpoint-l3} [Documentation] Returns network-containment from a given endpoint-l3 + [Arguments] ${endpoint-l3} ${endpoint_json} To Json ${endpoint-l3} - [Return] ${endpoint_json['endpoint-l3'][0]['network-containment']} + RETURN ${endpoint_json['endpoint-l3'][0]['network-containment']} Get Mac Address of Endpoint - [Arguments] ${endpoint} [Documentation] Returns mac-address from a given endpoint + [Arguments] ${endpoint} ${endpoint_json} To Json ${endpoint} - [Return] ${endpoint_json['endpoint'][0]['mac-address']} + RETURN ${endpoint_json['endpoint'][0]['mac-address']} Get Mac Address of Endpoint-L3 - [Arguments] ${endpoint-l3} [Documentation] Returns mac-address from a given endpoint-l3 + [Arguments] ${endpoint-l3} ${endpoint_json} To Json ${endpoint-l3} - [Return] ${endpoint_json['endpoint-l3'][0]['mac-address']} + RETURN ${endpoint_json['endpoint-l3'][0]['mac-address']} Get L2 Context of Endpoint-L3 - [Arguments] ${endpoint-l3} [Documentation] Returns l2-context from a given endpoint-l3 + [Arguments] ${endpoint-l3} ${endpoint_json} To Json ${endpoint-l3} - [Return] ${endpoint_json['endpoint-l3'][0]['l2-context']} + RETURN ${endpoint_json['endpoint-l3'][0]['l2-context']} diff --git a/csit/libraries/GUIKeywords.robot b/csit/libraries/GUIKeywords.robot index ab33e8346d..f15933d360 100644 --- a/csit/libraries/GUIKeywords.robot +++ b/csit/libraries/GUIKeywords.robot @@ -1,57 +1,60 @@ *** Settings *** -Documentation A resource file containing all global -... elements (Variables, keywords) to help -... DLUX csit testing. -Library OperatingSystem -Library Process -Library Selenium2Library timeout=30 implicit_wait=30 run_on_failure=Selenium2Library.Log Source -Resource ../variables/Variables.robot -Resource Utils.robot +Documentation A resource file containing all global +... elements (Variables, keywords) to help +... DLUX csit testing. + +Library OperatingSystem +Library Process +Library Selenium2Library timeout=30 implicit_wait=30 run_on_failure=Selenium2Library.Log Source +Resource ../variables/Variables.robot +Resource Utils.robot + *** Variables *** -${BROWSER} phantomjs -${BASE_URL} http://${ODL_SYSTEM_IP}:${RESTCONFPORT}/index.html -${LOGIN_URL} ${BASE_URL}#/login -${XVFB_PORT} 99 -${LOGGED_URL} ${BASE_URL}#/topology -${LOGIN_USERNAME} admin -${LOGIN_PASSWORD} admin -${INVALID_USER} invaliduser -${INVALID_PWD} invalidpwd +${BROWSER} phantomjs +${BASE_URL} http://${ODL_SYSTEM_IP}:${RESTCONFPORT}/index.html +${LOGIN_URL} ${BASE_URL}#/login +${XVFB_PORT} 99 +${LOGGED_URL} ${BASE_URL}#/topology +${LOGIN_USERNAME} admin +${LOGIN_PASSWORD} admin +${INVALID_USER} invaliduser +${INVALID_PWD} invalidpwd # Login page -${OPENDAYLIGHT_IMAGE} //img[@alt='OpenDayLight'] -${LOGIN_USERNAME_INPUT_FIELD} //form/fieldset/div/input[@name='username'] -${LOGIN_PASSWORD_INPUT_FIELD} //form/fieldset/div[2]/input[@name='password'] -${REMEMBER_ME_CHECKBOX} //div[@class="checkbox"] -${LOGIN_BUTTON} //fieldset/button -${PLEASE_SIGN_IN_PANEL} //div/h3[contains(text(),"${PLEASE_SIGN_IN_MSG}")] -${PLEASE_SIGN_IN_MSG} Please Sign In -${LOGIN_ERROR_MSG} Unable to login +${OPENDAYLIGHT_IMAGE} //img[@alt='OpenDayLight'] +${LOGIN_USERNAME_INPUT_FIELD} //form/fieldset/div/input[@name='username'] +${LOGIN_PASSWORD_INPUT_FIELD} //form/fieldset/div[2]/input[@name='password'] +${REMEMBER_ME_CHECKBOX} //div[@class="checkbox"] +${LOGIN_BUTTON} //fieldset/button +${PLEASE_SIGN_IN_PANEL} //div/h3[contains(text(),"${PLEASE_SIGN_IN_MSG}")] +${PLEASE_SIGN_IN_MSG} Please Sign In +${LOGIN_ERROR_MSG} Unable to login # DLUX Home page -${TOPOLOGY_SUBMENU} //a[@href='#/topology'] -${NODES_SUBMENU} //a[@href='#/node/index')] -${YANG_UI_SUBMENU} //a[@href='#/yangui/index'] -${YANG_VISUALIZER_SUBMENU} //a[@href='#/yangvisualizer/index'] -${YANGMAN_SUBMENU} //a[@href='#/yangman/index'] +${TOPOLOGY_SUBMENU} //a[@href='#/topology'] +${NODES_SUBMENU} //a[@href='#/node/index')] +${YANG_UI_SUBMENU} //a[@href='#/yangui/index'] +${YANG_VISUALIZER_SUBMENU} //a[@href='#/yangvisualizer/index'] +${YANGMAN_SUBMENU} //a[@href='#/yangman/index'] # Topology Submenu -${TOPOLOGY_SUBMENU_URL} ${BASE_URL}#/topology -${RELOAD_BUTTON} //button[@ng-click='createTopology()'] -${CONTROLS_TEXT} //div[@class="col-md-2"]/h3 +${TOPOLOGY_SUBMENU_URL} ${BASE_URL}#/topology +${RELOAD_BUTTON} //button[@ng-click='createTopology()'] +${CONTROLS_TEXT} //div[@class="col-md-2"]/h3 # Nodes Submenu -${NODES_SUBMENU_URL} ${BASE_URL}#/node/index +${NODES_SUBMENU_URL} ${BASE_URL}#/node/index # Yang UI Submenu -${YANG_UI_SUBMENU_URL} ${BASE_URL}#/yangui/index +${YANG_UI_SUBMENU_URL} ${BASE_URL}#/yangui/index # Yang Visualizer Submenu -${YANG_VISUALIZER_SUBMENU_URL} ${BASE_URL}#/yangvisualizer/index +${YANG_VISUALIZER_SUBMENU_URL} ${BASE_URL}#/yangvisualizer/index # Yangman Submenu -${YANGMAN_SUBMENU_URL} ${BASE_URL}#/yangman/index +${YANGMAN_SUBMENU_URL} ${BASE_URL}#/yangman/index # Failback variables -${USE_XVFB} True -${BROWSER_NAME} phantomjs-1.9.8-linux-x86_64 -${BROWSER_EXT} tar.bz2 -${BROWSER_FILE_NAME} ${BROWSER_NAME}.${BROWSER_EXT} -${BROWSER_URL} https://bitbucket.org/ariya/phantomjs/downloads/${BROWSER_FILE_NAME} -${BROWSER_PATH_EXECUTABLE} ${BROWSER_NAME}/bin/phantomjs +${USE_XVFB} True +${BROWSER_NAME} phantomjs-1.9.8-linux-x86_64 +${BROWSER_EXT} tar.bz2 +${BROWSER_FILE_NAME} ${BROWSER_NAME}.${BROWSER_EXT} +${BROWSER_URL} https://bitbucket.org/ariya/phantomjs/downloads/${BROWSER_FILE_NAME} +${BROWSER_PATH_EXECUTABLE} ${BROWSER_NAME}/bin/phantomjs + *** Keywords *** Check If Phantom Is Downloaded @@ -60,7 +63,7 @@ Check If Phantom Is Downloaded ... verification if there is one containing the word 'phantomjs'. Result is that the PhantomJS ... compressed file is downloaded and uncompressed locally related to the path of the running script. ${installed}= OperatingSystem.Run ls -d */ | grep -m 1 phantomjs - [Return] ${installed} + RETURN ${installed} Download PhantomJS [Documentation] Downloads and uncompress the headless browser PhantomJS. @@ -70,13 +73,13 @@ Download PhantomJS Get Headless Browser Path [Documentation] Returns the path of the executable headless browser. ${is_downloaded}= Check If Phantom Is Downloaded - BuiltIn.Run Keyword If "${is_downloaded}"=="${EMPTY}" Download PhantomJS + IF "${is_downloaded}"=="${EMPTY}" Download PhantomJS ${path}= BuiltIn.Set Variable ${EXECDIR}/${BROWSER_PATH_EXECUTABLE} - [Return] ${path} + RETURN ${path} Open Headless Browser - [Arguments] ${url} [Documentation] Failback browser, download and use the WebKit headless browser PhantomJS. + [Arguments] ${url} BuiltIn.Log \n Using failback browser console=yes BuiltIn.Set Global Variable ${USE_XVFB} False ${executable_path}= Get Headless Browser Path @@ -84,8 +87,8 @@ Open Headless Browser Selenium2Library.Go To ${url} Set Display Port - [Arguments] ${port}=${XVFB_PORT} [Documentation] Sets the environment variable used by xvfb and the browser. + [Arguments] ${port}=${XVFB_PORT} OperatingSystem.Set Environment Variable DISPLAY :${port} Open Virtual Display @@ -93,12 +96,12 @@ Open Virtual Display Process.Start Process Xvfb :${XVFB_PORT} -ac -screen 0 1280x1024x16 ... alias=xvfb ${display}= OperatingSystem.Get Environment Variable DISPLAY ${EMPTY} - BuiltIn.Run Keyword If "${display}"!=":${XVFB_PORT}" Set Display Port + IF "${display}"!=":${XVFB_PORT}" Set Display Port Close DLUX And Terminate XVFB Process If Running [Documentation] Closes all browser instances and terminates Xvfb if the process is running. Selenium2Library.Close All Browsers - BuiltIn.Run Keyword If ${USE_XVFB} Terminate Process xvfb + IF ${USE_XVFB} Terminate Process xvfb Launch DLUX [Documentation] Launches with a delay to let the page load. If it cannot run the default browser, it will download @@ -110,12 +113,12 @@ Launch DLUX ... 3. Go to DLUX login URL and wait until the HTML page contains a specific element. ${status}= BuiltIn.Run Keyword And Return Status Run Keywords Open Virtual Display ... AND Selenium2Library.Open Browser ${LOGIN_URL} ${BROWSER} - BuiltIn.Run Keyword If not ${status} Open Headless Browser ${LOGIN_URL} + IF not ${status} Open Headless Browser ${LOGIN_URL} Selenium2Library.Wait Until Page Contains Element css=div.container Open DLUX Login Page - [Arguments] ${LOGIN URL} [Documentation] Loads DLUX login page. + [Arguments] ${LOGIN URL} Selenium2Library.Open Browser ${LOGIN_URL} ${BROWSER} Selenium2Library.Maximize Browser Window Selenium2Library.Wait Until Page Contains Element ${PLEASE_SIGN_IN_PANEL} @@ -129,8 +132,8 @@ Verify Elements Of DLUX Login Page Selenium2Library.Page Should Contain Element ${LOGIN_BUTTON} Log In To DLUX - [Arguments] ${username} ${password} [Documentation] Inserts username and password and logs in DLUX. + [Arguments] ${username} ${password} Selenium2Library.Focus ${LOGIN_USERNAME_INPUT_FIELD} Selenium2Library.Input Text ${LOGIN_USERNAME_INPUT_FIELD} ${username} Selenium2Library.Focus ${LOGIN_PASSWORD_INPUT_FIELD} @@ -138,8 +141,8 @@ Log In To DLUX Focus And Click Element ${LOGIN_BUTTON} Log In To DLUX With Invalid Credentials - [Arguments] ${username} ${password} [Documentation] Tries to log in to DLUX with invalid credentials and verifies occurence of the error message. + [Arguments] ${username} ${password} Selenium2Library.Focus ${LOGIN_USERNAME_INPUT_FIELD} Selenium2Library.Input Text ${LOGIN_USERNAME_INPUT_FIELD} ${username} Selenium2Library.Focus ${LOGIN_PASSWORD_INPUT_FIELD} @@ -151,7 +154,7 @@ Log In To DLUX With Invalid Credentials Open Or Launch DLUX [Documentation] Tries to open Dlux login page. If it fails, then launches Dlux using xvfb or headless browser. ${status}= BuiltIn.Run Keyword And Return Status Open DLUX Login Page ${LOGIN_URL} - BuiltIn.Run Keyword If "${status}"=="False" Launch DLUX + IF "${status}"=="False" Launch DLUX Verify Elements Of DLUX Login Page Open Or Launch DLUX Page And Log In To DLUX @@ -160,22 +163,22 @@ Open Or Launch DLUX Page And Log In To DLUX Log In To DLUX ${LOGIN_USERNAME} ${LOGIN_PASSWORD} Navigate To URL - [Arguments] ${url} [Documentation] Goes to the defined URL provided in an argument. + [Arguments] ${url} ${status}= BuiltIn.Run Keyword And Return Status Selenium2Library.Location Should Be ${url} - BuiltIn.Run Keyword If not ${status} Selenium2Library.Go To ${url} + IF not ${status} Selenium2Library.Go To ${url} Focus And Click Element - [Arguments] ${element} [Documentation] Clicks the element with previous element visibility check and element focus. + [Arguments] ${element} Selenium2Library.Wait Until Element Is Visible ${element} Selenium2Library.Focus ${element} Selenium2Library.Mouse Over ${element} Selenium2Library.Click Element ${element} Mouse Down And Mouse Up Click Element - [Arguments] ${element} [Documentation] Clicks the element by imitating mouse left button click down and click up. + [Arguments] ${element} Selenium2Library.Wait Until Page Contains Element ${element} Selenium2Library.Focus ${element} Selenium2Library.Mouse Over ${element} @@ -183,20 +186,25 @@ Mouse Down And Mouse Up Click Element Selenium2Library.Mouse Up ${element} Page Should Contain Element With Wait - [Arguments] ${element} [Documentation] Similar to Selenium2Library.Wait Until Page Contains Element but returns web page source code when fails. + [Arguments] ${element} BuiltIn.Wait Until Keyword Succeeds 1 min 5 sec Selenium2Library.Page Should Contain Element ${element} Helper Click - [Arguments] ${element_to_be_clicked} ${element_to_be_checked} [Documentation] Clicks the ${element_to_be_clicked} and verifies that page contains ${element_to_be_checked}. + [Arguments] ${element_to_be_clicked} ${element_to_be_checked} Selenium2Library.Focus ${element_to_be_clicked} Selenium2Library.Click Element ${element_to_be_clicked} Selenium2Library.Wait Until Page Contains Element ${element_to_be_checked} Patient Click - [Arguments] ${element_to_be_clicked} ${element_to_be_checked} [Documentation] Combines clicking ${element_to_be_clicked} and checking that ${element_to_be_checked} is visible with ... BuiltIn.Wait Until Keyword Succeeds keyword in order to secure reliable execution of Selenium2Library.Click Element ... keyword in AngularJS webapp. - BuiltIn.Wait Until Keyword Succeeds 1 min 5 sec Helper Click ${element_to_be_clicked} ${element_to_be_checked} + [Arguments] ${element_to_be_clicked} ${element_to_be_checked} + BuiltIn.Wait Until Keyword Succeeds + ... 1 min + ... 5 sec + ... Helper Click + ... ${element_to_be_clicked} + ... ${element_to_be_checked} diff --git a/csit/libraries/GbpSxp.robot b/csit/libraries/GbpSxp.robot index 54864522fb..c36f168a90 100644 --- a/csit/libraries/GbpSxp.robot +++ b/csit/libraries/GbpSxp.robot @@ -1,69 +1,80 @@ *** Settings *** -Documentation GbpSxp library covering common tasks of gbp-sxp test cases. -Library OperatingSystem WITH NAME os -Library SSHLibrary -Library RequestsLibrary -Library DateTime -Library ./GbpSxp.py WITH NAME gbpsxp -Resource ../variables/Variables.robot -Resource ./Utils.robot -Resource ./SSHKeywords.robot +Documentation GbpSxp library covering common tasks of gbp-sxp test cases. + +Library OperatingSystem WITH NAME os +Library SSHLibrary +Library RequestsLibrary +Library DateTime +Library ./GbpSxp.py WITH NAME gbpsxp +Resource ../variables/Variables.robot +Resource ./Utils.robot +Resource ./SSHKeywords.robot + *** Variables *** -${ISE_API_DIR} ${CURDIR}/../variables/gbp/ise-mock-server-api -${ISE_REST_PORT} 9060 -${GBP_ENDPOINTS_URI} /restconf/operational/base-endpoint:endpoints -${GBP_EP_TEMPLATES_CONFIG_URI} /restconf/config/sxp-ep-provider-model:sxp-ep-mapper -${GBP_RENDERER_CONFIG_URI} /restconf/config/renderer:renderers/renderer/ios-xe-renderer -${GBP_RENDERER_POLICY_OPERATIONAL_URI} /restconf/operational/renderer:renderers/renderer/ios-xe-renderer/renderer-policy -${GBP_RENDERER_POLICY_STATUS_OPERATIONAL_URI} ${GBP_RENDERER_POLICY_OPERATIONAL_URI}/status -${GBP_RPC_UNREGISTER_ENDPOINT_URI} /restconf/operations/base-endpoint:unregister-endpoint -${GBP_TENANT_CONFIG_URI} /restconf/config/policy:tenants/tenant/tenant-red -${MOUNTPOINT_IOSXE_SUFFIX} yang-ext:mount/ned:native -${NETCONF_CONFIG_URI} /restconf/config/network-topology:network-topology/topology/topology-netconf -${NETCONF_OPERATIONAL_URI} /restconf/operational/network-topology:network-topology/topology/topology-netconf -${SXP_EP_PROVIDER_CONFIG_URI} /restconf/config/sxp-ep-provider-model:sxp-ep-mapper -${SXP_ISE_ADAPTER_CONFIG_URI} /restconf/config/sxp-ise-adapter-model:gbp-sxp-ise-adapter -${SXP_ISE_ADAPTER_OPERATIONAL_URI} /restconf/operational/sxp-ise-adapter-model:gbp-sxp-ise-adapter -${SXP_NODE_RPC_ADD_ENTRY_URI} /restconf/operations/sxp-controller:add-entry -${SXP_TOPOLOGY_NODE_CONFIG_URI} /restconf/config/network-topology:network-topology/topology/sxp -${SXP_TOPOLOGY_NODE_OPERATIONAL_URI} /restconf/operational/network-topology:network-topology/topology/sxp +${ISE_API_DIR} ${CURDIR}/../variables/gbp/ise-mock-server-api +${ISE_REST_PORT} 9060 +${GBP_ENDPOINTS_URI} /restconf/operational/base-endpoint:endpoints +${GBP_EP_TEMPLATES_CONFIG_URI} /restconf/config/sxp-ep-provider-model:sxp-ep-mapper +${GBP_RENDERER_CONFIG_URI} /restconf/config/renderer:renderers/renderer/ios-xe-renderer +${GBP_RENDERER_POLICY_OPERATIONAL_URI} +... /restconf/operational/renderer:renderers/renderer/ios-xe-renderer/renderer-policy +${GBP_RENDERER_POLICY_STATUS_OPERATIONAL_URI} ${GBP_RENDERER_POLICY_OPERATIONAL_URI}/status +${GBP_RPC_UNREGISTER_ENDPOINT_URI} /restconf/operations/base-endpoint:unregister-endpoint +${GBP_TENANT_CONFIG_URI} /restconf/config/policy:tenants/tenant/tenant-red +${MOUNTPOINT_IOSXE_SUFFIX} yang-ext:mount/ned:native +${NETCONF_CONFIG_URI} +... /restconf/config/network-topology:network-topology/topology/topology-netconf +${NETCONF_OPERATIONAL_URI} +... /restconf/operational/network-topology:network-topology/topology/topology-netconf +${SXP_EP_PROVIDER_CONFIG_URI} /restconf/config/sxp-ep-provider-model:sxp-ep-mapper +${SXP_ISE_ADAPTER_CONFIG_URI} /restconf/config/sxp-ise-adapter-model:gbp-sxp-ise-adapter +${SXP_ISE_ADAPTER_OPERATIONAL_URI} /restconf/operational/sxp-ise-adapter-model:gbp-sxp-ise-adapter +${SXP_NODE_RPC_ADD_ENTRY_URI} /restconf/operations/sxp-controller:add-entry +${SXP_TOPOLOGY_NODE_CONFIG_URI} /restconf/config/network-topology:network-topology/topology/sxp +${SXP_TOPOLOGY_NODE_OPERATIONAL_URI} +... /restconf/operational/network-topology:network-topology/topology/sxp + *** Keywords *** Prepare_Ssh_Tooling - [Arguments] ${ip_address}=${TOOLS_SYSTEM_IP} [Documentation] Setup ssh session to tools system + [Arguments] ${ip_address}=${TOOLS_SYSTEM_IP} ${tools_connection} SSHKeywords.Open_Connection_To_Tools_System ${ip_address} SSHKeywords.Virtual_Env_Create SSHKeywords.Virtual_Env_Install_Package mock-server tornado==4.2 - ${sed_output} SSHKeywords.Execute_Command_At_Path_Should_Pass sed -r -i 's/^(DEFAULT_FORMAT = ).+$/\\1XML/' lib/python2.7/site-packages/mock_server/data.py path=${SSHKeywords__current_venv_path} + ${sed_output} SSHKeywords.Execute_Command_At_Path_Should_Pass + ... sed -r -i 's/^(DEFAULT_FORMAT = ).+$/\\1XML/' lib/python2.7/site-packages/mock_server/data.py + ... path=${SSHKeywords__current_venv_path} SSHKeywords.Virtual_Env_Freeze - [Return] ${tools_connection} + RETURN ${tools_connection} Deploy_Ise_Mock_Server - [Arguments] ${ise_mock_server_api_folder} ${ise_rest_port} [Documentation] Deploy and start ise mock-server + [Arguments] ${ise_mock_server_api_folder} ${ise_rest_port} # deploy ise mock-server SSHLibrary.Put_Directory ${ISE_API_DIR}/${ise_mock_server_api_folder} destination=. recursive=True # start ise mock-server SSHKeywords.Virtual_Env_Activate_On_Current_Session - SSHLibrary.Write mock-server --dir=${ise_mock_server_api_folder} --port=${ise_rest_port} --address=${TOOLS_SYSTEM_IP} --debug + SSHLibrary.Write + ... mock-server --dir=${ise_mock_server_api_folder} --port=${ise_rest_port} --address=${TOOLS_SYSTEM_IP} --debug BuiltIn.Wait_Until_Keyword_Succeeds 5 1 gbpsxp.Check_Ise_Mock_Server_Is_Online ${ise_rest_port} ${mock_server_pid} SSHKeywords.Execute_Command_Should_Pass pgrep -f mock-server SSHKeywords.Execute_Command_Should_Pass lsof -p ${mock_server_pid} Teardown_Ise_Mock_Server - [Arguments] ${ise_mock_server_api_folder} [Documentation] Stop and wipe clean ise mock-server + [Arguments] ${ise_mock_server_api_folder} # stop ise mock-server SSHLibrary.Execute_command pkill -f mock-server return_stderr=True return_rc=False - SSHKeywords.Execute_Command_Should_Pass ls -la ${ise_mock_server_api_folder}; cat ${ise_mock_server_api_folder}/access-*.log + SSHKeywords.Execute_Command_Should_Pass + ... ls -la ${ise_mock_server_api_folder}; cat ${ise_mock_server_api_folder}/access-*.log # wipe ise mock-server deployment SSHLibrary.Execute_command rm -rf ${ise_mock_server_api_folder} return_stderr=True return_rc=False Teardown_Ssh_Tooling - [Arguments] ${session_list}=@{EMPTY} [Documentation] Deactivate virtualenv and close ssh session on tools system + [Arguments] ${session_list}=@{EMPTY} FOR ${ssh_session} IN @{session_list} BuiltIn.Log ${ssh_session} SSHKeywords.Restore_Current_Ssh_Connection_From_Index ${ssh_session} @@ -73,41 +84,53 @@ Teardown_Ssh_Tooling END ${session_list_size} get length ${session_list} BuiltIn.Log ${session_list_size} - BuiltIn.Run_Keyword_If ${session_list_size} == 0 SSHKeywords.Virtual_Env_Deactivate_On_Current_Session - BuiltIn.Run_Keyword_If ${session_list_size} == 0 SSHKeywords.Virtual_Env_Delete + IF ${session_list_size} == 0 + SSHKeywords.Virtual_Env_Deactivate_On_Current_Session + END + IF ${session_list_size} == 0 SSHKeywords.Virtual_Env_Delete SSHLibrary.Close_All_Connections Configure_Ise_Source_And_Gain_Harvest_Status - [Arguments] ${session_arg} ${configure_ise_source_file} ${ise_rest_uri} [Documentation] Post ise-source configuration and wait for ise harvest status + [Arguments] ${session_arg} ${configure_ise_source_file} ${ise_rest_uri} # post ise-source configuration and wait for status ${sxp_source_config_json} Utils.Json_Parse_From_File ${configure_ise_source_file} gbpsxp.Replace_Ise_Source_Address ${sxp_source_config_json} ${ise_rest_uri} BuiltIn.Log ${sxp_source_config_json} ${now} DateTime.Get_Current_Date result_format=%Y-%m-%dT%H:%M:%S.%f Utils.Post_Elements_To_URI ${SXP_ISE_ADAPTER_CONFIG_URI} ${sxp_source_config_json} - ${ise_harvest_status_json} BuiltIn.Wait_Until_Keyword_Succeeds 20 1 Gain_Uptodate_Harvest_Status ${session_arg} ${now} - [Return] ${ise_harvest_status_json} + ${ise_harvest_status_json} BuiltIn.Wait_Until_Keyword_Succeeds + ... 20 + ... 1 + ... Gain_Uptodate_Harvest_Status + ... ${session_arg} + ... ${now} + RETURN ${ise_harvest_status_json} Gain_Uptodate_Harvest_Status - [Arguments] ${session_arg} ${now_timestamp} [Documentation] Read ise source harvest status and check if timestamp not older then limit + [Arguments] ${session_arg} ${now_timestamp} ${ise_harvest_status} Utils.Get_Data_From_URI ${session_arg} ${SXP_ISE_ADAPTER_OPERATIONAL_URI} ${ise_harvest_status_json} Utils.Json_Parse_From_String ${ise_harvest_status} - ${status_timestamp} BuiltIn.Set_Variable ${ise_harvest_status_json['gbp-sxp-ise-adapter']['ise-harvest-status']['timestamp']} + ${status_timestamp} BuiltIn.Set_Variable + ... ${ise_harvest_status_json['gbp-sxp-ise-adapter']['ise-harvest-status']['timestamp']} gbpsxp.Check_iso8601_datetime_younger_then_limit ${status_timestamp} ${now_timestamp} - [Return] ${ise_harvest_status_json} + RETURN ${ise_harvest_status_json} Check_Ise_Mock_Server_Is_Online - [Arguments] ${ise_port} [Documentation] Checks if the port ${ise_port} is occupied on tools system - ${ise_port_occupied} SSHLibrary.Execute_command netstat -lnp | grep '${ise_port}' return_stdout=False return_rc=True + [Arguments] ${ise_port} + ${ise_port_occupied} SSHLibrary.Execute_command + ... netstat -lnp | grep '${ise_port}' + ... return_stdout=False + ... return_rc=True BuiltIn.Should_Be_Equal_As_Integers 0 ${ise_port_occupied} Check_Ise_Harvest_Status - [Arguments] ${ise_harvest_status_json} ${expected_templates_amount} [Documentation] Check ise harvest status by templatest written amount - ${templates_written} BuiltIn.Set_Variable ${ise_harvest_status_json['gbp-sxp-ise-adapter']['ise-harvest-status']['templates-written']} + [Arguments] ${ise_harvest_status_json} ${expected_templates_amount} + ${templates_written} BuiltIn.Set_Variable + ... ${ise_harvest_status_json['gbp-sxp-ise-adapter']['ise-harvest-status']['templates-written']} BuiltIn.Should_Be_Equal_As_Integers ${expected_templates_amount} ${templates_written} Clean_ise_source_config diff --git a/csit/libraries/Genius.robot b/csit/libraries/Genius.robot index 7e499e6c33..6d1ff4d55a 100644 --- a/csit/libraries/Genius.robot +++ b/csit/libraries/Genius.robot @@ -1,42 +1,50 @@ *** Settings *** -Documentation This suite is a common keywords file for genius project. -Library Collections -Library OperatingSystem -Library RequestsLibrary -Library SSHLibrary -Library string -Resource ClusterManagement.robot -Resource CompareStream.robot -Resource DataModels.robot -Resource KarafKeywords.robot -Resource ODLTools.robot -Resource OVSDB.robot -Resource ToolsSystem.robot -Resource Utils.robot -Resource VpnOperations.robot -Resource ../variables/Variables.robot -Resource ../variables/netvirt/Variables.robot +Documentation This suite is a common keywords file for genius project. + +Library Collections +Library OperatingSystem +Library RequestsLibrary +Library SSHLibrary +Library string +Resource ClusterManagement.robot +Resource CompareStream.robot +Resource DataModels.robot +Resource KarafKeywords.robot +Resource ODLTools.robot +Resource OVSDB.robot +Resource ToolsSystem.robot +Resource Utils.robot +Resource VpnOperations.robot +Resource ../variables/Variables.robot +Resource ../variables/netvirt/Variables.robot + *** Variables *** -@{itm_created} TZA -${genius_config_dir} ${CURDIR}/../variables/genius -${Bridge} ${INTEGRATION_BRIDGE} -${DEFAULT_MONITORING_INTERVAL} Tunnel Monitoring Interval (for VXLAN tunnels): 1000 -@{GENIUS_DIAG_SERVICES} OPENFLOW IFM ITM DATASTORE OVSDB -${gateway_ip} 0.0.0.0 -${port_name} br-int-eth1 -${VLAN} 100 -${NO_VLAN} 0 -${DEFAULT_TRANSPORT_ZONE} default-transport-zone -${SET_LOCAL_IP} sudo ovs-vsctl set O . other_config:local_ip= -${REMOVE_LOCAL_IP} sudo ovs-vsctl remove O . other_config local_ip -${odl_stream_check } ${Stream_dict}[${ODL_STREAM}] <= ${Stream_dict}[neon] +@{itm_created} TZA +${genius_config_dir} ${CURDIR}/../variables/genius +${Bridge} ${INTEGRATION_BRIDGE} +${DEFAULT_MONITORING_INTERVAL} Tunnel Monitoring Interval (for VXLAN tunnels): 1000 +@{GENIUS_DIAG_SERVICES} OPENFLOW IFM ITM DATASTORE OVSDB +${gateway_ip} 0.0.0.0 +${port_name} br-int-eth1 +${VLAN} 100 +${NO_VLAN} 0 +${DEFAULT_TRANSPORT_ZONE} default-transport-zone +${SET_LOCAL_IP} sudo ovs-vsctl set O . other_config:local_ip= +${REMOVE_LOCAL_IP} sudo ovs-vsctl remove O . other_config local_ip +${odl_stream_check } ${Stream_dict}[${ODL_STREAM}] <= ${Stream_dict}[neon] + *** Keywords *** Genius Suite Setup [Documentation] Create Rest Session to http://${ODL_SYSTEM_IP}:${RESTCONFPORT} Genius.Start Suite - RequestsLibrary.Create Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} auth=${AUTH} headers=${HEADERS} timeout=5 + RequestsLibrary.Create Session + ... session + ... http://${ODL_SYSTEM_IP}:${RESTCONFPORT} + ... auth=${AUTH} + ... headers=${HEADERS} + ... timeout=5 Genius Suite Teardown [Documentation] Delete all sessions @@ -45,18 +53,35 @@ Genius Suite Teardown Start Suite [Documentation] Initial setup for Genius test suites - Run_Keyword_If_At_Least_Oxygen Wait Until Keyword Succeeds 60 2 ClusterManagement.Check Status Of Services Is OPERATIONAL @{GENIUS_DIAG_SERVICES} + Run_Keyword_If_At_Least_Oxygen + ... Wait Until Keyword Succeeds + ... 60 + ... 2 + ... ClusterManagement.Check Status Of Services Is OPERATIONAL + ... @{GENIUS_DIAG_SERVICES} KarafKeywords.Setup_Karaf_Keywords ToolsSystem.Get Tools System Nodes Data ${karaf_debug_enabled} = BuiltIn.Get_Variable_Value ${KARAF_DEBUG} ${False} - BuiltIn.run_keyword_if ${karaf_debug_enabled} KarafKeywords.Execute_Controller_Karaf_Command_On_Background log:set DEBUG org.opendaylight.genius + IF ${karaf_debug_enabled} + KarafKeywords.Execute_Controller_Karaf_Command_On_Background log:set DEBUG org.opendaylight.genius + END Genius.Set Switch Configuration - ${check} = BuiltIn.Wait Until Keyword Succeeds 30 10 Check Port Status Is ESTABLISHED ${ODL_OF_PORT_6653} @{TOOLS_SYSTEM_ALL_IPS} - ${check} = BuiltIn.Wait Until Keyword Succeeds 30 10 Check Port Status Is ESTABLISHED ${OVSDBPORT} @{TOOLS_SYSTEM_ALL_IPS} + ${check} = BuiltIn.Wait Until Keyword Succeeds + ... 30 + ... 10 + ... Check Port Status Is ESTABLISHED + ... ${ODL_OF_PORT_6653} + ... @{TOOLS_SYSTEM_ALL_IPS} + ${check} = BuiltIn.Wait Until Keyword Succeeds + ... 30 + ... 10 + ... Check Port Status Is ESTABLISHED + ... ${OVSDBPORT} + ... @{TOOLS_SYSTEM_ALL_IPS} Genius.Build Dpn List @{SWITCH_DATA} = Collections.Combine Lists ${DPN_ID_LIST} ${TOOLS_SYSTEM_ALL_IPS} BuiltIn.Set Suite Variable @{SWITCH_DATA} - ${substr} Should Match Regexp ${TOOLS_SYSTEM_1_IP} [0-9]\{1,3}\.[0-9]\{1,3}\.[0-9]\{1,3}\. + ${substr} = Should Match Regexp ${TOOLS_SYSTEM_1_IP} [0-9]\{1,3}\.[0-9]\{1,3}\.[0-9]\{1,3}\. ${SUBNET} = Catenate ${substr}0 BuiltIn.Set Suite Variable ${SUBNET} @@ -71,45 +96,70 @@ Stop Suite END Check Port Status Is ESTABLISHED - [Arguments] ${port} @{tools_ips} [Documentation] This keyword will check whether ports are established or not on OVS + [Arguments] ${port} @{tools_ips} FOR ${tools_ip} IN @{tools_ips} - ${check_establishment} = Utils.Run Command On Remote System And Log ${tools_ip} netstat -anp | grep ${port} + ${check_establishment} = Utils.Run Command On Remote System And Log + ... ${tools_ip} + ... netstat -anp | grep ${port} BuiltIn.Should Contain ${check_establishment} ESTABLISHED END - [Return] ${check_establishment} + RETURN ${check_establishment} Create Vteps - [Arguments] ${vlan_id} ${gateway_ip} [Documentation] This keyword creates VTEPs between OVS + [Arguments] ${vlan_id} ${gateway_ip} ${body} = Genius.Set Json ${vlan_id} ${gateway_ip} ${SUBNET} @{TOOLS_SYSTEM_ALL_IPS} - ${resp} = RequestsLibrary.Put Request session ${CONFIG_API}/itm:transport-zones/transport-zone/TZA data=${body} + ${resp} = RequestsLibrary.Put Request + ... session + ... ${CONFIG_API}/itm:transport-zones/transport-zone/TZA + ... data=${body} BuiltIn.Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Set Json - [Arguments] ${vlan} ${gateway_ip} ${subnet} @{tools_ips} [Documentation] Sets Json with the values passed for it. - ${body} = BuiltIn.Run Keyword If ${odl_stream_check } OperatingSystem.Get File ${genius_config_dir}/Itm_creation_no_vlan_below_sodium.json - ... ELSE OperatingSystem.Get File ${genius_config_dir}/Itm_creation_no_vlan_sodium_and_above.json - ${body} = BuiltIn.Run Keyword If ${odl_stream_check } String.Replace String ${body} 1.1.1.1 ${subnet} - ... ELSE BuiltIn.Set Variable ${body} - ${body} = BuiltIn.Run Keyword If ${odl_stream_check } String.Replace String ${body} "vlan-id": 0 "vlan-id": ${vlan} - ... ELSE BuiltIn.Set Variable ${body} - ${body} = BuiltIn.Run Keyword If ${odl_stream_check } String.Replace String ${body} "gateway-ip": "0.0.0.0" "gateway-ip": "${gateway_ip}" - ... ELSE BuiltIn.Set Variable ${body} + [Arguments] ${vlan} ${gateway_ip} ${subnet} @{tools_ips} + IF ${odl_stream_check } + ${body} = OperatingSystem.Get File ${genius_config_dir}/Itm_creation_no_vlan_below_sodium.json + ELSE + ${body} = OperatingSystem.Get File ${genius_config_dir}/Itm_creation_no_vlan_sodium_and_above.json + END + IF ${odl_stream_check } + ${body} = String.Replace String ${body} 1.1.1.1 ${subnet} + ELSE + ${body} = BuiltIn.Set Variable ${body} + END + IF ${odl_stream_check } + ${body} = String.Replace String ${body} "vlan-id": 0 "vlan-id": ${vlan} + ELSE + ${body} = BuiltIn.Set Variable ${body} + END + IF ${odl_stream_check } + ${body} = String.Replace String ${body} "gateway-ip": "0.0.0.0" "gateway-ip": "${gateway_ip}" + ELSE + ${body} = BuiltIn.Set Variable ${body} + END FOR ${tool_system_index} IN RANGE ${NUM_TOOLS_SYSTEM} - ${body} String.Replace String ${body} "dpn-id": 10${tool_system_index} "dpn-id": ${DPN_ID_LIST[${tool_system_index}]} - ${body} String.Replace String ${body} "ip-address": "${tool_system_index+2}.${tool_system_index+2}.${tool_system_index+2}.${tool_system_index+2}" "ip-address": "${tools_ips}[${tool_system_index}]" + ${body} = String.Replace String + ... ${body} + ... "dpn-id": 10${tool_system_index} + ... "dpn-id": ${DPN_ID_LIST[${tool_system_index}]} + ${body} = String.Replace String + ... ${body} + ... "ip-address": "${tool_system_index+2}.${tool_system_index+2}.${tool_system_index+2}.${tool_system_index+2}" + ... "ip-address": "${tools_ips}[${tool_system_index}]" END BuiltIn.Log ${body} - [Return] ${body} # returns complete json that has been updated + RETURN ${body} # returns complete json that has been updated Build Dpn List [Documentation] This keyword builds the list of DPN ids after configuring OVS bridges on each of the TOOLS_SYSTEM_IPs. @{DPN_ID_LIST} = BuiltIn.Create List FOR ${tools_ip} IN @{TOOLS_SYSTEM_ALL_IPS} - ${output} Utils.Run Command On Remote System And Log ${tools_ip} sudo ovs-ofctl show -O Openflow13 ${Bridge} | head -1 | awk -F "dpid:" '{ print $2 }' - ${dpn_id} Utils.Run Command On Remote System And Log ${tools_ip} echo \$\(\(16\#${output}\)\) + ${output} = Utils.Run Command On Remote System And Log + ... ${tools_ip} + ... sudo ovs-ofctl show -O Openflow13 ${Bridge} | head -1 | awk -F "dpid:" '{ print $2 }' + ${dpn_id} = Utils.Run Command On Remote System And Log ${tools_ip} echo \$\(\(16\#${output}\)\) Collections.Append To List ${DPN_ID_LIST} ${dpn_id} END BuiltIn.Set Suite Variable @{DPN_ID_LIST} @@ -147,7 +197,9 @@ ITM Direct Tunnels Start Suite ClusterManagement.ClusterManagement_Setup ClusterManagement.Stop_Members_From_List_Or_All FOR ${controller_index} IN RANGE ${NUM_ODL_SYSTEM} - Utils.Run Command On Remote System And Log ${ODL_SYSTEM_${controller_index+1}_IP} sed -i -- 's/false/true/g' ${GENIUS_IFM_CONFIG_FLAG} + Utils.Run Command On Remote System And Log + ... ${ODL_SYSTEM_${controller_index+1}_IP} + ... sed -i -- 's/false/true/g' ${GENIUS_IFM_CONFIG_FLAG} END ClusterManagement.Start_Members_From_List_Or_All Genius.Genius Suite Setup @@ -155,7 +207,9 @@ ITM Direct Tunnels Start Suite ITM Direct Tunnels Stop Suite [Documentation] Stop suite for ITM Direct Tunnels. FOR ${controller_index} IN RANGE ${NUM_ODL_SYSTEM} - Utils.Run Command On Remote System And Log ${ODL_SYSTEM_${controller_index+1}_IP} sed -i -- 's/true/false/g' ${GENIUS_IFM_CONFIG_FLAG} + Utils.Run Command On Remote System And Log + ... ${ODL_SYSTEM_${controller_index+1}_IP} + ... sed -i -- 's/true/false/g' ${GENIUS_IFM_CONFIG_FLAG} END Genius.Genius Suite Teardown @@ -166,31 +220,33 @@ Ovs Interface Verification END Get ITM - [Arguments] ${itm_created[0]} ${switch_data}=${SWITCH_DATA} [Documentation] It returns the created ITM Transport zone with the passed values during the creation is done. + [Arguments] ${itm_created[0]} ${switch_data}=${SWITCH_DATA} Collections.Append To List ${switch_data} ${itm_created[0]} Utils.Check For Elements At URI ${TUNNEL_TRANSPORTZONE}/transport-zone/${itm_created[0]} ${switch_data} Check Tunnel Delete On OVS - [Arguments] ${tunnel_list} [Documentation] Verifies the Tunnel is deleted from OVS. + [Arguments] ${tunnel_list} FOR ${tools_ip} IN @{TOOLS_SYSTEM_ALL_IPS} ${output} = Utils.Run Command On Remote System ${tools_ip} sudo ovs-vsctl show Genius.Verify Deleted Tunnels on OVS ${tunnel_list} ${output} END Check Table0 Entry In a Dpn - [Arguments] ${tools_ip} ${bridgename} ${port_numbers} [Documentation] Checks the Table 0 entry in the OVS when flows are dumped. - ${check} = Utils.Run Command On Remote System And Log ${tools_ip} sudo ovs-ofctl -OOpenFlow13 dump-flows ${bridgename} + [Arguments] ${tools_ip} ${bridgename} ${port_numbers} + ${check} = Utils.Run Command On Remote System And Log + ... ${tools_ip} + ... sudo ovs-ofctl -OOpenFlow13 dump-flows ${bridgename} ${num_ports} = BuiltIn.Get Length ${port_numbers} FOR ${port_index} IN RANGE ${num_ports} BuiltIn.Should Contain ${check} in_port=${port_numbers}[${port_index}] END Verify Tunnel Status As Up - [Arguments] ${no_of_switches}=${NUM_TOOLS_SYSTEM} [Documentation] Verify that the number of tunnels are UP + [Arguments] ${no_of_switches}=${NUM_TOOLS_SYSTEM} ${no_of_tunnels} = KarafKeywords.Issue Command On Karaf Console ${TEP_SHOW_STATE} ${lines_of_state_up} = String.Get Lines Containing String ${no_of_tunnels} ${STATE_UP} ${actual_tunnel_count} = String.Get Line Count ${lines_of_state_up} @@ -198,8 +254,8 @@ Verify Tunnel Status As Up BuiltIn.Should Be Equal As Strings ${actual_tunnel_count} ${expected_tunnel_count} Verify Tunnel Status - [Arguments] ${tunnel_status} ${tunnel_names} [Documentation] Verifies if all tunnels in the input, has the expected status(UP/DOWN/UNKNOWN) + [Arguments] ${tunnel_status} ${tunnel_names} ${tep_result} = KarafKeywords.Issue Command On Karaf Console ${TEP_SHOW_STATE} ${number_of_tunnels} = BuiltIn.Get Length ${tunnel_names} FOR ${each_tunnel} IN RANGE ${number_of_tunnels} @@ -209,46 +265,72 @@ Verify Tunnel Status END Get Tunnels On OVS - [Arguments] ${connection_id} [Documentation] Retrieves the list of tunnel ports present on OVS + [Arguments] ${connection_id} SSHLibrary.Switch Connection ${connection_id} - ${ovs_result} = Utils.Write Commands Until Expected Prompt sudo ovs-vsctl show ${DEFAULT_LINUX_PROMPT_STRICT} + ${ovs_result} = Utils.Write Commands Until Expected Prompt + ... sudo ovs-vsctl show + ... ${DEFAULT_LINUX_PROMPT_STRICT} @{tunnel_names} = BuiltIn.Create List ${tunnels} = String.Get Lines Matching Regexp ${ovs_result} Interface "tun.*" True @{tunnels_list} = String.Split To Lines ${tunnels} FOR ${tun} IN @{tunnels_list} - ${tun_list} Get Regexp Matches ${tun} tun.*\\w + ${tun_list} = Get Regexp Matches ${tun} tun.*\\w Collections.Append To List ${tunnel_names} @{tun_list} END ${items_in_list} = BuiltIn.Get Length ${tunnel_names} - [Return] @{tunnel_names} + RETURN @{tunnel_names} Get Tunnel - [Arguments] ${src} ${dst} ${type} ${config_api_type}=${EMPTY} [Documentation] This keyword returns tunnel interface name between source DPN and destination DPN. ... Statements are executed depending on whether it is itm tunnel state(default) or dpn tep state. - ${resp} = BuiltIn.Run Keyword If '${config_api_type}' == '${EMPTY}' RequestsLibrary.Get Request session ${CONFIG_API}/itm-state:tunnel-list/internal-tunnel/${src}/${dst}/${type}/ - ... ELSE RequestsLibrary.Get Request session ${CONFIG_API}/itm-state:dpn-teps-state/dpns-teps/${src}/remote-dpns/${dst}/ + [Arguments] ${src} ${dst} ${type} ${config_api_type}=${EMPTY} + IF '${config_api_type}' == '${EMPTY}' + ${resp} = RequestsLibrary.Get Request + ... session + ... ${CONFIG_API}/itm-state:tunnel-list/internal-tunnel/${src}/${dst}/${type}/ + ELSE + ${resp} = RequestsLibrary.Get Request + ... session + ... ${CONFIG_API}/itm-state:dpn-teps-state/dpns-teps/${src}/remote-dpns/${dst}/ + END BuiltIn.Should Be Equal As Strings ${resp.status_code} ${RESP_CODE} BuiltIn.Log ${resp.text} ${respjson} = RequestsLibrary.To Json ${resp.text} pretty_print=True ${json} = Utils.Json Parse From String ${resp.text} BuiltIn.Should Contain ${resp.text} ${dst} - BuiltIn.Run Keyword If '${config_api_type}' == '${EMPTY}' BuiltIn.Should Contain ${resp.text} ${src} - ${tunnel_interface_name} = BuiltIn.Run Keyword If "tunnel-interface-names" in "${json}" Genius.Get Tunnel Interface Name ${json["internal-tunnel"][0]} tunnel-interface-names - ${tunnel_name_output} ${tunnel_name} = BuiltIn.Run Keyword If '${config_api_type}' != '${EMPTY}' BuiltIn.Should Match Regexp ${resp.text} "tunnel-name":"(tun[\\w\\d]+)" - ${tunnel} = BuiltIn.Set Variable If '${config_api_type}' == '${EMPTY}' ${tunnel_interface_name} ${tunnel_name} - [Return] ${tunnel} + IF '${config_api_type}' == '${EMPTY}' + BuiltIn.Should Contain ${resp.text} ${src} + END + IF "tunnel-interface-names" in "${json}" + ${tunnel_interface_name} = Genius.Get Tunnel Interface Name + ... ${json["internal-tunnel"][0]} + ... tunnel-interface-names + ELSE + ${tunnel_interface_name} = Set Variable ${None} + END + IF '${config_api_type}' != '${EMPTY}' + ${tunnel_name_output} ${tunnel_name} = BuiltIn.Should Match Regexp + ... ${resp.text} + ... "tunnel-name":"(tun[\\w\\d]+)" + ELSE + ${tunnel_name_output} ${tunnel_name} = Set Variable ${None} ${None} + END + ${tunnel} = BuiltIn.Set Variable If + ... '${config_api_type}' == '${EMPTY}' + ... ${tunnel_interface_name} + ... ${tunnel_name} + RETURN ${tunnel} Get Tunnel Interface Name - [Arguments] ${json} ${expected_tunnel_interface_name} [Documentation] This keyword extracts tunnel interface name from json given as input. + [Arguments] ${json} ${expected_tunnel_interface_name} ${tunnels} = Collections.Get From Dictionary ${json} ${expected_tunnel_interface_name} - [Return] ${tunnels[0]} + RETURN ${tunnels[0]} Verify Tunnel Delete on DS - [Arguments] ${tunnel} [Documentation] This keyword confirms that specified tunnel is not present by giving command from karaf console. + [Arguments] ${tunnel} ${output} = KarafKeywords.Issue Command On Karaf Console ${TEP_SHOW_STATE} BuiltIn.Should Not Contain ${output} ${tunnel} @@ -267,7 +349,7 @@ SRM Stop Suite Verify Tunnel Monitoring Status [Arguments] ${tunnel_monitor_status} - ${output}= KarafKeywords.Issue Command On Karaf Console ${TEP_SHOW} + ${output} = KarafKeywords.Issue Command On Karaf Console ${TEP_SHOW} BuiltIn.Should Contain ${output} ${tunnel_monitor_status} Set Switch Configuration @@ -279,19 +361,20 @@ Set Switch Configuration SSHLibrary.Execute Command sudo ovs-vsctl set bridge ${Bridge} protocols=OpenFlow13 SSHLibrary.Execute Command sudo ovs-vsctl set-controller ${Bridge} tcp:${ODL_SYSTEM_IP}:${ODL_OF_PORT_6653} SSHLibrary.Execute Command sudo ifconfig ${Bridge} up - SSHLibrary.Execute Command sudo ovs-vsctl add-port ${Bridge} tap${tool_system_index}ed70586-6c -- set Interface tap${tool_system_index}ed70586-6c type=tap + SSHLibrary.Execute Command + ... sudo ovs-vsctl add-port ${Bridge} tap${tool_system_index}ed70586-6c -- set Interface tap${tool_system_index}ed70586-6c type=tap SSHLibrary.Execute Command sudo ovs-vsctl set-manager tcp:${ODL_SYSTEM_IP}:${OVSDBPORT} SSHLibrary.Execute Command sudo ovs-vsctl show END Ovs Verification For Each Dpn - [Arguments] ${tools_system_ip} ${tools_ips} [Documentation] This keyword will verify whether local and remote ip are present on the tunnels available on OVS + [Arguments] ${tools_system_ip} ${tools_ips} ${ovs_output} = Utils.Run Command On Remote System And Log ${tools_system_ip} sudo ovs-vsctl show @{updated_tools_ip_list} = BuiltIn.Create List @{tools_ips} Collections.Remove Values From List ${updated_tools_ip_list} ${tools_system_ip} BuiltIn.Log Many @{updated_tools_ip_list} - ${num_tool_ips} BuiltIn.Get Length ${updated_tools_ip_list} + ${num_tool_ips} = BuiltIn.Get Length ${updated_tools_ip_list} FOR ${num} IN RANGE ${num_tool_ips} ${tools_ip} = Collections.Get From List ${updated_tools_ip_list} ${num} BuiltIn.Should Contain ${ovs_output} ${tools_ip} @@ -299,45 +382,52 @@ Ovs Verification For Each Dpn Get Tunnels List [Documentation] The keyword fetches the list of operational tunnels from ODL - ${no_of_tunnels} KarafKeywords.Issue Command On Karaf Console ${TEP_SHOW_STATE} + ${no_of_tunnels} = KarafKeywords.Issue Command On Karaf Console ${TEP_SHOW_STATE} ${tunnels} = String.Get Regexp Matches ${no_of_tunnels} tun[\\w\\d]+ BuiltIn.Log ${tunnels} - [Return] ${tunnels} + RETURN ${tunnels} Verify Table0 Entry After fetching Port Number [Documentation] This keyword will get the port number and checks the table0 entry for each dpn FOR ${tools_ip} IN @{TOOLS_SYSTEM_ALL_IPS} - ${check} = Utils.Run Command On Remote System And Log ${tools_ip} sudo ovs-ofctl -O OpenFlow13 show ${Bridge} + ${check} = Utils.Run Command On Remote System And Log + ... ${tools_ip} + ... sudo ovs-ofctl -O OpenFlow13 show ${Bridge} ${port_numbers} = String.Get Regexp Matches ${check} (\\d+).tun.* 1 Genius.Check Table0 Entry In a Dpn ${tools_ip} ${Bridge} ${port_numbers} END Verify Deleted Tunnels On OVS - [Arguments] ${tunnel_list} ${resp_data} [Documentation] This will verify whether tunnel is deleted. + [Arguments] ${tunnel_list} ${resp_data} BuiltIn.Log ${resp_data} FOR ${tunnel} IN @{tunnel_list} BuiltIn.Should Not Contain ${resp_data} ${tunnel} END Verify Response Code Of Dpn End Point Config API - [Arguments] ${dpn_list}=${DPN_ID_LIST} [Documentation] This keyword will verify response code from itm-state: dpn endpoints config api for each dpn + [Arguments] ${dpn_list}=${DPN_ID_LIST} FOR ${dpn} IN @{dpn_list} - BuiltIn.Wait Until Keyword Succeeds 40 5 Utils.Get Data From URI session ${CONFIG_API}/itm-state:dpn-endpoints/DPN-TEPs-info/${dpn}/ + BuiltIn.Wait Until Keyword Succeeds + ... 40 + ... 5 + ... Utils.Get Data From URI + ... session + ... ${CONFIG_API}/itm-state:dpn-endpoints/DPN-TEPs-info/${dpn}/ END Get Tunnel Between DPNs - [Arguments] ${tunnel_type} ${config_api_type} ${src_dpn_id} @{dst_dpn_ids} [Documentation] This keyword will Get All the Tunnels available on DPN's + [Arguments] ${tunnel_type} ${config_api_type} ${src_dpn_id} @{dst_dpn_ids} FOR ${dst_dpn_id} IN @{dst_dpn_ids} ${tunnel} = BuiltIn.Wait Until Keyword Succeeds 30 10 Genius.Get Tunnel ${src_dpn_id} ... ${dst_dpn_id} ${tunnel_type} ${config_api_type} END Update Dpn id List And Get Tunnels - [Arguments] ${tunnel_type} ${config_api_type}=${EMPTY} ${dpn_ids}=${DPN_ID_LIST} [Documentation] Update the exisisting dpn id list to form different combination of dpn ids such that tunnel formation between all dpns is verified. + [Arguments] ${tunnel_type} ${config_api_type}=${EMPTY} ${dpn_ids}=${DPN_ID_LIST} FOR ${dpn_id} IN @{dpn_ids} @{dpn_ids_updated} = BuiltIn.Create List @{dpn_ids} Collections.Remove Values From List ${dpn_ids_updated} ${dpn_id} diff --git a/csit/libraries/GoBgpLib.robot b/csit/libraries/GoBgpLib.robot index 39946ebd87..da71866c35 100644 --- a/csit/libraries/GoBgpLib.robot +++ b/csit/libraries/GoBgpLib.robot @@ -1,32 +1,35 @@ *** Settings *** -Documentation Robot keyword library (Resource) for handling the GoBgp tool. +Documentation Robot keyword library (Resource) for handling the GoBgp tool. ... -... Copyright (c) 2020 Lumina Networks and others. All rights reserved. +... Copyright (c) 2020 Lumina Networks and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... This library assumes that a SSH connection exists (and is switched to) -... to a Linux machine (usualy TOOLS_SYSTEM) where the GoBgp should be run. +... This library assumes that a SSH connection exists (and is switched to) +... to a Linux machine (usualy TOOLS_SYSTEM) where the GoBgp should be run. ... -Library Process -Library SSHLibrary -Resource ${CURDIR}/BGPcliKeywords.robot -Resource ${CURDIR}/RemoteBash.robot -Resource ${CURDIR}/SSHKeywords.robot + +Library Process +Library SSHLibrary +Resource ${CURDIR}/BGPcliKeywords.robot +Resource ${CURDIR}/RemoteBash.robot +Resource ${CURDIR}/SSHKeywords.robot + *** Variables *** -${GOBGP_KILL_COMMAND} ps axf | grep gobgp | grep -v grep | awk '{print \"kill -9 \" $1}' | sh -${GOBGP_EXECUTION_COMMAND} /home/jenkins/gobgpd -l debug -f +${GOBGP_KILL_COMMAND} ps axf | grep gobgp | grep -v grep | awk '{print \"kill -9 \" $1}' | sh +${GOBGP_EXECUTION_COMMAND} /home/jenkins/gobgpd -l debug -f + *** Keywords *** Start_GoBgp - [Arguments] ${cfg_file} [Documentation] Dump the start command into prompt. It assumes that no gobgp is running. For verified ... start use Start_GoBgp_And_Verify_Connected keyword. - ${start_cmd} BuiltIn.Set Variable ${GOBGP_EXECUTION_COMMAND} /home/jenkins/${cfg_file} + [Arguments] ${cfg_file} + ${start_cmd}= BuiltIn.Set Variable ${GOBGP_EXECUTION_COMMAND} /home/jenkins/${cfg_file} BuiltIn.Log ${start_cmd} ${output}= SSHLibrary.Write ${start_cmd} BuiltIn.Log ${output} @@ -41,26 +44,35 @@ Stop_GoBgp Stop_All_GoBgps [Documentation] Sends kill command to stop all Gobgps running - ${output} SSHLibrary.Read + ${output}= SSHLibrary.Read BuiltIn.Log ${output} - ${output} SSHLibrary.Write ${GOBGP_KILL_COMMAND} + ${output}= SSHLibrary.Write ${GOBGP_KILL_COMMAND} BuiltIn.Log ${output} Start_GoBgp_And_Verify_Connected - [Arguments] ${cfg_file} ${session} ${gobgp_ip} ${connection_retries}=${3} [Documentation] Starts the GoBgp and verifies its connection. The verification is done by checking the presence ... of the peer in the bgp rib. [Gobgp at times might take more time, hence the loop] + [Arguments] ${cfg_file} ${session} ${gobgp_ip} ${connection_retries}=${3} Start_GoBgp ${cfg_file} - ${status} ${value}= BuiltIn.Run_Keyword_And_Ignore_Error BuiltIn.Wait_Until_Keyword_Succeeds ${connection_retries}x 15s - ... Verify_GoBgps_Connection ${session} ${gobgp_ip} connected=${True} - BuiltIn.Run_Keyword_If "${status}" != "PASS" Stop_GoBgp - BuiltIn.Return_From_Keyword_If "${status}" == "PASS" + ${status} ${value}= BuiltIn.Run_Keyword_And_Ignore_Error + ... BuiltIn.Wait_Until_Keyword_Succeeds + ... ${connection_retries}x + ... 15s + ... Verify_GoBgps_Connection + ... ${session} + ... ${gobgp_ip} + ... connected=${True} + IF "${status}" != "PASS" Stop_GoBgp + IF "${status}" == "PASS" RETURN Verify_GoBgps_Connection - [Arguments] ${session} ${gobgp_ip}=${TOOLS_SYSTEM_IP} ${connected}=${True} [Documentation] Checks peer presence in operational datastore + [Arguments] ${session} ${gobgp_ip}=${TOOLS_SYSTEM_IP} ${connected}=${True} ${peer_check_url}= BuiltIn.Set_Variable ${REST_API}/bgp-rib:bgp-rib/rib=example-bgp-rib/peer=bgp:%2F%2F - ${exp_status_code}= BuiltIn.Set_Variable_If ${connected} ${ALLOWED_STATUS_CODES} ${DELETED_STATUS_CODES} + ${exp_status_code}= BuiltIn.Set_Variable_If + ... ${connected} + ... ${ALLOWED_STATUS_CODES} + ... ${DELETED_STATUS_CODES} ${rsp}= RequestsLibrary.Get Request ${session} ${peer_check_url}${gobgp_ip}?content=nonconfig BuiltIn.Log ${rsp.content} BuiltIn.Should_Be_Equal_As_Numbers ${exp_status_code} ${rsp.status_code} diff --git a/csit/libraries/IoTDM/IoTDMKeywords.robot b/csit/libraries/IoTDM/IoTDMKeywords.robot index 3f39a51b8a..7a6eb5df64 100644 --- a/csit/libraries/IoTDM/IoTDMKeywords.robot +++ b/csit/libraries/IoTDM/IoTDMKeywords.robot @@ -1,22 +1,22 @@ *** Settings *** -Documentation Keywords specific for IoTDM test suites. -Library ./criotdm.py -Library OperatingSystem -Library iotdm_comm.py +Documentation Keywords specific for IoTDM test suites. + +Library ./criotdm.py +Library OperatingSystem +Library iotdm_comm.py -*** Variables *** *** Keywords *** IOTDM Basic Suite Setup - [Arguments] ${odl_ip_address} ${odl_user_name} ${odl_password} [Documentation] Set up basic test suite + [Arguments] ${odl_ip_address} ${odl_user_name} ${odl_password} ${iserver} = Connect To Iotdm ${odl_ip_address} ${odl_user_name} ${odl_password} http Set Suite Variable ${iserver} Resolve Local Ip Address [Documentation] Retrieve list of IP addresses of local host, try to find IP address accessible from the ... host where tested ODL system is running and set it as global variable named local_ip - ${ip_list} OperatingSystem.Run hostname -I + ${ip_list} = OperatingSystem.Run hostname -I Log iotdm_ip: ${ODL_SYSTEM_1_IP} Log hostname -I: ${ip_list} ${local_ip} = Get Local Ip From List ${ODL_SYSTEM_1_IP} ${ip_list} diff --git a/csit/libraries/IoTDM/IoTDMResources.robot b/csit/libraries/IoTDM/IoTDMResources.robot index 1f338c2a0c..abc439ae0a 100644 --- a/csit/libraries/IoTDM/IoTDMResources.robot +++ b/csit/libraries/IoTDM/IoTDMResources.robot @@ -1,92 +1,116 @@ *** Settings *** -Documentation Keywords for sanity test suites testing basic functionality -... using multiple communication protocols -Library Collections -Resource ../../variables/Variables.robot -Resource IoTDMKeywords.robot -Library iotdm_comm.py -Library OperatingSystem -Variables client_libs/onem2m_primitive.py +Documentation Keywords for sanity test suites testing basic functionality +... using multiple communication protocols + +Library Collections +Resource ../../variables/Variables.robot +Resource IoTDMKeywords.robot +Library iotdm_comm.py +Library OperatingSystem +Variables client_libs/onem2m_primitive.py + *** Variables *** -${defCseBaseName} InCSE1 -${defAeId} robotTestAe +${defCseBaseName} InCSE1 +${defAeId} robotTestAe # when AeId and resourceName of the AE are equal -${defAeUri} ${defCseBaseName}/${defAeId} -${defTestApp} testApp -${defSubscriptionName} TestSubscription +${defAeUri} ${defCseBaseName}/${defAeId} +${defTestApp} testApp +${defSubscriptionName} TestSubscription + *** Keywords *** Log Primitive - [Arguments] ${primitive} [Documentation] Logs primitive parameters, content and protocol specific parameters + [Arguments] ${primitive} ${primitive_params} = Get Primitive Parameters ${primitive} ${content} = Get Primitive Content ${primitive} ${proto_specific_params} = Get Primitive Protocol Specific Parameters ${primitive} - ${debug} = Catenate Parameters: ${primitive_params} Content: ${content} ProtocolParams: ${proto_specific_params} + ${debug} = Catenate + ... Parameters: + ... ${primitive_params} + ... Content: + ... ${content} + ... ProtocolParams: ${proto_specific_params} Log ${debug} Create Resource - [Arguments] ${resourceContent} ${parentResourceUri} ${resourceType} [Documentation] Create resource, verify response and return the response + [Arguments] ${resourceContent} ${parentResourceUri} ${resourceType} ${primitive} = New Create Request Primitive ${parentResourceUri} ${resourceContent} ${resourceType} Log Primitive ${primitive} ${rsp_primitive} = Send Primitive ${primitive} Log Primitive ${rsp_primitive} Verify Exchange ${primitive} ${rsp_primitive} - [Return] ${rsp_primitive} + RETURN ${rsp_primitive} Update Resource - [Arguments] ${update_content} ${resourceUri} [Documentation] Update resource, verify response and return the response + [Arguments] ${update_content} ${resourceUri} ${primitive} = New Update Request Primitive ${resourceUri} ${update_content} Log Primitive ${primitive} ${rsp_primitive} = Send Primitive ${primitive} Log Primitive ${rsp_primitive} Verify Exchange ${primitive} ${rsp_primitive} - [Return] ${rsp_primitive} + RETURN ${rsp_primitive} Retrieve Resource - [Arguments] ${resourceUri} [Documentation] Retrieve resource, verify response and return the response + [Arguments] ${resourceUri} ${primitive} = New Retrieve Request Primitive ${resourceUri} Log Primitive ${primitive} ${rsp_primitive} = Send Primitive ${primitive} Log Primitive ${rsp_primitive} Verify Exchange ${primitive} ${rsp_primitive} - [Return] ${rsp_primitive} + RETURN ${rsp_primitive} Delete Resource - [Arguments] ${resourceUri} [Documentation] Delete resource, verify response and return the response + [Arguments] ${resourceUri} ${primitive} = New Delete Request Primitive ${resourceUri} Log Primitive ${primitive} ${rsp_primitive} = Send Primitive ${primitive} Log Primitive ${rsp_primitive} Verify Exchange ${primitive} ${rsp_primitive} - [Return] ${rsp_primitive} + RETURN ${rsp_primitive} Create Resource AE - [Arguments] ${cseBaseName}=${defCseBaseName} ${aeId}=${defAeId} ${appId}=${defTestApp} [Documentation] Create AE resource and verify response + [Arguments] ${cseBaseName}=${defCseBaseName} ${aeId}=${defAeId} ${appId}=${defTestApp} ${attr} = Set Variable {"m2m:ae": {"api":"${appId}", "rr":true, "rn":"${aeId}"}} - Run Keyword And Return Create Resource resourceContent=${attr} parentResourceUri=${cseBaseName} resourceType=${OneM2M.resource_type_application_entity} + Run Keyword And Return + ... Create Resource + ... resourceContent=${attr} + ... parentResourceUri=${cseBaseName} + ... resourceType=${OneM2M.resource_type_application_entity} Create Resource Container - [Arguments] ${parentResourceUri} ${resourceName} [Documentation] Create Container resource and verify response - ${content} Set Variable {"m2m:cnt": {"rn": "${resourceName}"}} - Run Keyword And Return Create Resource resourceContent=${content} parentResourceUri=${parentResourceUri} resourceType=${OneM2M.resource_type_container} + [Arguments] ${parentResourceUri} ${resourceName} + ${content} = Set Variable {"m2m:cnt": {"rn": "${resourceName}"}} + Run Keyword And Return + ... Create Resource + ... resourceContent=${content} + ... parentResourceUri=${parentResourceUri} + ... resourceType=${OneM2M.resource_type_container} Create Resource ContentInstance - [Arguments] ${parentResourceUri} ${contentValue} ${resourceName}=${EMPTY} [Documentation] Create ContentInstance resource and verify response - ${resourceName} = Set Variable If """${resourceName}""" != """${EMPTY}""" """, "rn":"${resourceName}""" ${EMPTY} - ${content} Set Variable {"m2m:cin":{"con":"${contentValue}"${resourceName}}} - Run Keyword And Return Create Resource resourceContent=${content} parentResourceUri=${parentResourceUri} resourceType=${OneM2M.resource_type_content_instance} + [Arguments] ${parentResourceUri} ${contentValue} ${resourceName}=${EMPTY} + ${resourceName} = Set Variable If + ... """${resourceName}""" != """${EMPTY}""" + ... """, "rn":"${resourceName}""" + ... ${EMPTY} + ${content} = Set Variable {"m2m:cin":{"con":"${contentValue}"${resourceName}}} + Run Keyword And Return + ... Create Resource + ... resourceContent=${content} + ... parentResourceUri=${parentResourceUri} + ... resourceType=${OneM2M.resource_type_content_instance} Create Resource Subscription - [Arguments] ${parentResourceUri} ${notificationUri} ${resourceName}=${defSubscriptionName} ${notifEventType}=${OneM2M.net_update_of_resource} ${notifContentType}=${OneM2M.nct_all_attributes} [Documentation] Create Suscription resource and verify response - ${attr} Set Variable {"m2m:sub":{"nu":["${notificationUri}"],"nct": ${notifContentType},"rn":"${resourceName}", "enc":{"net":[${notifEventType}]}}} + [Arguments] ${parentResourceUri} ${notificationUri} ${resourceName}=${defSubscriptionName} ${notifEventType}=${OneM2M.net_update_of_resource} ${notifContentType}=${OneM2M.nct_all_attributes} + ${attr} = Set Variable + ... {"m2m:sub":{"nu":["${notificationUri}"],"nct": ${notifContentType},"rn":"${resourceName}", "enc":{"net":[${notifEventType}]}}} Create Resource ${attr} ${parentResourceUri} ${OneM2M.resource_type_subscription} diff --git a/csit/libraries/IoTDM/iotdm_sanity_tests.robot b/csit/libraries/IoTDM/iotdm_sanity_tests.robot index 7abde7f2f4..8c29f4c832 100644 --- a/csit/libraries/IoTDM/iotdm_sanity_tests.robot +++ b/csit/libraries/IoTDM/iotdm_sanity_tests.robot @@ -1,13 +1,15 @@ *** Settings *** -Documentation Keywords for sanity test suites testing basic functionality -... using multiple communication protocols -Library Collections -Resource ../../variables/Variables.robot -Resource IoTDMKeywords.robot -Resource IoTDMResources.robot -Library iotdm_comm.py -Library OperatingSystem -Variables client_libs/onem2m_primitive.py +Documentation Keywords for sanity test suites testing basic functionality +... using multiple communication protocols + +Library Collections +Resource ../../variables/Variables.robot +Resource IoTDMKeywords.robot +Resource IoTDMResources.robot +Library iotdm_comm.py +Library OperatingSystem +Variables client_libs/onem2m_primitive.py + *** Keywords *** Sanity Test Create AE @@ -25,7 +27,7 @@ Sanity Test Update AE Sanity Test Retrieve Updated AE [Documentation] Retrieve updated AE, verify updated element and verify response - ${rsp_primitive} Retrieve Resource ${defAeUri} + ${rsp_primitive} = Retrieve Resource ${defAeUri} ${update_or} = Get Primitive Content Attribute ${rsp_primitive} /m2m:ae/or Should Be Equal ${update_or} http://hey/you/updated @@ -40,17 +42,25 @@ Sanity Test Retrieve Deleted AE ${rsp_primitive} = Send Primitive ${primitive} Log Primitive ${rsp_primitive} ${expected_message} = Set Variable Resource target URI not found: ${defAeUri} - Verify Exchange Negative ${primitive} ${rsp_primitive} ${OneM2M.result_code_not_found} ${expected_message} + Verify Exchange Negative + ... ${primitive} + ... ${rsp_primitive} + ... ${OneM2M.result_code_not_found} + ... ${expected_message} Sanity Test Create AE Container Subscription - [Arguments] ${notification_uri} [Documentation] Create AE, Container and Subscription resources. Subscription resource has set ... eventType 3 so notification will be trigerred when child resource of Container resource is ... created. Notifications will be sent to communication Rx channel. ... Verify response of create requests. + [Arguments] ${notification_uri} Sanity Test Create AE Create Resource Container ${defAeUri} Container1 - Create Resource Subscription ${defAeUri}/Container1 ${notification_uri} notifEventType=${OneM2M.net_create_of_direct_child_resource} notifContentType=${OneM2M.nct_resource_id} + Create Resource Subscription + ... ${defAeUri}/Container1 + ... ${notification_uri} + ... notifEventType=${OneM2M.net_create_of_direct_child_resource} + ... notifContentType=${OneM2M.nct_resource_id} Sanity Test Create Content Instance And Handle Notification [Documentation] Create contentInstance resource what should trigger notification. Receive the notification @@ -66,10 +76,15 @@ Sanity Test Create Content Instance And Use Automatic Notification Response [Documentation] Set up automatic reply for notifications from specific subscription resource. Create ... contentInstance resource what will trigger the notification and check if was handled ... automatically. - ${subscription_resource_id} Set Variable ${defAeUri}/Container1/${defSubscriptionName} + ${subscription_resource_id} = Set Variable ${defAeUri}/Container1/${defSubscriptionName} Add Auto Reply To Notification From Subscription ${subscription_resource_id} Create Content Instance - Wait Until Keyword Succeeds 3x 100ms Verify Number Of Auto Replies To Notification From Subscription ${subscription_resource_id} ${1} + Wait Until Keyword Succeeds + ... 3x + ... 100ms + ... Verify Number Of Auto Replies To Notification From Subscription + ... ${subscription_resource_id} + ... ${1} Remove Auto Reply To Notification From Subscription ${subscription_resource_id} Create Content Instance @@ -82,4 +97,4 @@ Receive Notification And Verify Should Be Equal ${from} /${defCseBaseName} ${operation} = Get Primitive Param ${notification} ${OneM2M.short_operation} Should Be Equal As Integers ${operation} ${OneM2M.operation_notify} - Return From Keyword ${notification} + RETURN ${notification} diff --git a/csit/libraries/JsonrpcKeywords.robot b/csit/libraries/JsonrpcKeywords.robot index d7204da745..070a56f15c 100644 --- a/csit/libraries/JsonrpcKeywords.robot +++ b/csit/libraries/JsonrpcKeywords.robot @@ -1,18 +1,19 @@ *** Settings *** -Library OperatingSystem -Library SSHLibrary -Library Collections -Library RequestsLibrary -Resource ClusterManagement.robot -Resource ../variables/jsonrpc/JsonrpcVariables.robot -Resource ../variables/Variables.robot -Resource SSHKeywords.robot -Resource Utils.robot +Library OperatingSystem +Library SSHLibrary +Library Collections +Library RequestsLibrary +Resource ClusterManagement.robot +Resource ../variables/jsonrpc/JsonrpcVariables.robot +Resource ../variables/Variables.robot +Resource SSHKeywords.robot +Resource Utils.robot + *** Keywords *** Run Read Service Python Script on Controller Vm - [Arguments] ${host_index}=${FIRST_CONTROLLER_INDEX} [Documentation] This keyword creates a new virtual environment, installs pyzmq & zmq and starts the read service on controller vm + [Arguments] ${host_index}=${FIRST_CONTROLLER_INDEX} ${host_index} Builtin.Convert To Integer ${host_index} ${host} ClusterManagement.Resolve IP Address For Member ${host_index} ${connections} SSHKeywords.Open_Connection_To_ODL_System ${host} @@ -20,7 +21,8 @@ Run Read Service Python Script on Controller Vm SSHLibrary.Put File ${READ_SERVICE_SCRIPT} ${WORKSPACE}/${BUNDLEFOLDER}/ mode=664 ${module} OperatingSystem.Get File ${JSONRPCCONFIG_MODULE_JSON} ${data} OperatingSystem.Get File ${JSONRPCCONFIG_DATA_JSON} - ${cmd} Builtin.Set Variable nohup python ${WORKSPACE}/${BUNDLEFOLDER}/odl-jsonrpc-test-read tcp://0.0.0.0:${DEFAULT_PORT} 'config' ${DEFAULT_ENDPOINT} '${module.replace("\n","").replace(" ","")}' '${data.replace("\n","").replace(" ","")}' + ${cmd} Builtin.Set Variable + ... nohup python ${WORKSPACE}/${BUNDLEFOLDER}/odl-jsonrpc-test-read tcp://0.0.0.0:${DEFAULT_PORT} 'config' ${DEFAULT_ENDPOINT} '${module.replace("\n","").replace(" ","")}' '${data.replace("\n","").replace(" ","")}' Log ${cmd} SSHKeywords.Virtual_Env_Set_Path /tmp/jsonrpc_venv SSHKeywords.Virtual_Env_Create_Python3 True @@ -39,22 +41,27 @@ Run Read Service Python Script on Controller Vm SSHLibrary.Close_Connection Mount Read Service Endpoint - [Arguments] ${controller_index}=${FIRST_CONTROLLER_INDEX} ${file}=${READ_SERVICE_PEER_PAYLOAD} ${endpoint}=${DEFAULT_ENDPOINT} [Documentation] This keyword mounts an endpoint after starting service + [Arguments] ${controller_index}=${FIRST_CONTROLLER_INDEX} ${file}=${READ_SERVICE_PEER_PAYLOAD} ${endpoint}=${DEFAULT_ENDPOINT} ${JSON1} OperatingSystem.Get File ${file} Log ${JSON1} - ${response_json} ClusterManagement.Put_As_Json_To_Member ${READ_SERVICE_PEER_URL}=${endpoint} ${JSON1} ${controller_index} + ${response_json} ClusterManagement.Put_As_Json_To_Member + ... ${READ_SERVICE_PEER_URL}=${endpoint} + ... ${JSON1} + ... ${controller_index} Builtin.Log ${response_json} Verify Data On Mounted Endpoint - [Arguments] ${controller_index}=${FIRST_CONTROLLER_INDEX} ${endpoint}=${DEFAULT_ENDPOINT} [Documentation] This keyword verifies if the data we get on the mount point is same as what we put - ${resp} ClusterManagement.Get_From_Member ${READ_SERVICE_PEER_URL}=${endpoint}${READ_SERVICE_PEER_MOUNT_PATH}?content=config ${controller_index} + [Arguments] ${controller_index}=${FIRST_CONTROLLER_INDEX} ${endpoint}=${DEFAULT_ENDPOINT} + ${resp} ClusterManagement.Get_From_Member + ... ${READ_SERVICE_PEER_URL}=${endpoint}${READ_SERVICE_PEER_MOUNT_PATH}?content=config + ... ${controller_index} ${response_json} Builtin.Convert To String ${resp} Log ${response_json} Verify Restconf Get On Mounted Endpoint ${response_json} ${READSERVICE_NAME} Verify Restconf Get On Mounted Endpoint - [Arguments] ${output} ${name} [Documentation] This keyword parses restconf get of mountpoint + [Arguments] ${output} ${name} Builtin.Should Match Regexp ${output} "name":"${name}" diff --git a/csit/libraries/KarafKeywords.robot b/csit/libraries/KarafKeywords.robot index 6e935f5eb9..c99a9dab71 100644 --- a/csit/libraries/KarafKeywords.robot +++ b/csit/libraries/KarafKeywords.robot @@ -1,185 +1,246 @@ *** Settings *** -Documentation Karaf library. General utility keywords for interacting with the karaf environment, such as the -... karaf console, karaf.log, karaf features, and karaf config files. +Documentation Karaf library. General utility keywords for interacting with the karaf environment, such as the +... karaf console, karaf.log, karaf features, and karaf config files. ... -... This library is useful to deal with controller Karaf console for ssh sessions in cluster. -... Running Setup_Karaf_Keywords is necessary. If SetupUtils initialization is called, this gets initialized as well. -... If this gets initialized, ClusterManagement gets initialized as well. -Library SSHLibrary -Library OperatingSystem -Library ${CURDIR}/netvirt/excepts.py -Resource ${CURDIR}/ClusterManagement.robot -Resource ${CURDIR}/SSHKeywords.robot -Variables ${CURDIR}/../variables/Variables.py +... This library is useful to deal with controller Karaf console for ssh sessions in cluster. +... Running Setup_Karaf_Keywords is necessary. If SetupUtils initialization is called, this gets initialized as well. +... If this gets initialized, ClusterManagement gets initialized as well. + +Library SSHLibrary +Library OperatingSystem +Library ${CURDIR}/netvirt/excepts.py +Resource ${CURDIR}/ClusterManagement.robot +Resource ${CURDIR}/SSHKeywords.robot +Variables ${CURDIR}/../variables/Variables.py + *** Variables *** -${WORKSPACE} /tmp +${WORKSPACE} /tmp ${connection_index_dict} &{EMPTY} + *** Keywords *** Setup_Karaf_Keywords - [Arguments] ${http_timeout}=${DEFAULT_TIMEOUT_HTTP} [Documentation] Initialize ClusterManagement. Open ssh karaf connections to each ODL. + [Arguments] ${http_timeout}=${DEFAULT_TIMEOUT_HTTP} ClusterManagement.ClusterManagement_Setup http_timeout=${http_timeout} - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - ClusterManagement.Run_Bash_Command_On_List_Or_All iptables -I INPUT -p tcp --dport ${KARAF_SHELL_PORT} -j ACCEPT; iptables-save + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + ClusterManagement.Run_Bash_Command_On_List_Or_All + ... iptables -I INPUT -p tcp --dport ${KARAF_SHELL_PORT} -j ACCEPT; iptables-save BuiltIn.Comment First connections to Karaf console may fail, so WUKS is used. TODO: Track as a Bug. FOR ${index} IN @{ClusterManagement__member_index_list} - BuiltIn.Run_Keyword_And_Ignore_Error BuiltIn.Wait_Until_Keyword_Succeeds 3s 1s Open_Controller_Karaf_Console_On_Background member_index=${index} + BuiltIn.Run_Keyword_And_Ignore_Error + ... BuiltIn.Wait_Until_Keyword_Succeeds + ... 3s + ... 1s + ... Open_Controller_Karaf_Console_On_Background + ... member_index=${index} END Verify_Feature_Is_Installed - [Arguments] ${feature_name} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} [Documentation] Will Succeed if the given ${feature_name} is found in the output of "feature:list -i" - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - ${output} = Issue_Command_On_Karaf_Console feature:list -i | grep ${feature_name} ${controller} ${karaf_port} + [Arguments] ${feature_name} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + ${output} = Issue_Command_On_Karaf_Console + ... feature:list -i | grep ${feature_name} + ... ${controller} + ... ${karaf_port} BuiltIn.Should_Contain ${output} ${feature_name} - [Return] ${output} + RETURN ${output} Issue_Command_On_Karaf_Console - [Arguments] ${cmd} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} ${timeout}=10 ${loglevel}=INFO [Documentation] Will execute the given ${cmd} by ssh'ing to the karaf console running on ${controller} ... Note that this keyword will open&close new SSH connection, without switching back to previously current session. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - SSHLibrary.Open_Connection ${controller} port=${karaf_port} prompt=${KARAF_PROMPT_LOGIN} timeout=${timeout} + [Arguments] ${cmd} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} ${timeout}=10 ${loglevel}=INFO + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + SSHLibrary.Open_Connection + ... ${controller} + ... port=${karaf_port} + ... prompt=${KARAF_PROMPT_LOGIN} + ... timeout=${timeout} SSHLibrary.Login ${KARAF_USER} ${KARAF_PASSWORD} loglevel=${loglevel} SSHLibrary.Write ${cmd} - ${output} SSHLibrary.Read_Until_Regexp ${KARAF_PROMPT} + ${output} = SSHLibrary.Read_Until_Regexp ${KARAF_PROMPT} SSHLibrary.Write_Bare logout\n SSHLibrary.Close_Connection BuiltIn.Log ${output} - [Return] ${output} + RETURN ${output} Safe_Issue_Command_On_Karaf_Console - [Arguments] ${cmd} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} ${timeout}=10 ${loglevel}=INFO [Documentation] Run Issue_Command_On_Karaf_Console but restore previous connection afterwards. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - BuiltIn.Run_Keyword_And_Return SSHKeywords.Run_Keyword_Preserve_Connection Issue_Command_On_Karaf_Console ${cmd} ${controller} ${karaf_port} ${timeout} + [Arguments] ${cmd} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} ${timeout}=10 ${loglevel}=INFO + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + BuiltIn.Run_Keyword_And_Return + ... SSHKeywords.Run_Keyword_Preserve_Connection + ... Issue_Command_On_Karaf_Console + ... ${cmd} + ... ${controller} + ... ${karaf_port} + ... ${timeout} ... ${loglevel} Check For Elements On Karaf Command Output Message - [Arguments] ${cmd} ${elements} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} ${timeout}=5 [Documentation] Will execute the command using Issue Command On Karaf Console then check for the given elements ... in the command output message - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - ${output} Issue_Command_On_Karaf_Console ${cmd} ${controller} ${karaf_port} ${timeout} + [Arguments] ${cmd} ${elements} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} ${timeout}=5 + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + ${output} = Issue_Command_On_Karaf_Console ${cmd} ${controller} ${karaf_port} ${timeout} FOR ${i} IN @{elements} BuiltIn.Should_Contain ${output} ${i} END Verify_Bundle_Is_Installed - [Arguments] ${bundle_name} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} [Documentation] Will succeed if the given ${bundle name} is present in the output of "bundle:list -s " - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - ${output} = Issue_Command_On_Karaf_Console bundle:list -s | grep ${bundle_name} ${controller} ${karaf_port} + [Arguments] ${bundle_name} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + ${output} = Issue_Command_On_Karaf_Console + ... bundle:list -s | grep ${bundle_name} + ... ${controller} + ... ${karaf_port} BuiltIn.Should_Contain ${output} ${bundle_name} - [Return] ${output} + RETURN ${output} Verify_Bundle_Is_Not_Installed - [Arguments] ${bundle_name} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} [Documentation] Will succeed if the given ${bundle_name} is NOT found in the output of "bundle:list -s" - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - ${output} = Issue_Command_On_Karaf_Console bundle:list -i | grep ${bundle_name} ${controller} ${karaf_port} + [Arguments] ${bundle_name} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + ${output} = Issue_Command_On_Karaf_Console + ... bundle:list -i | grep ${bundle_name} + ... ${controller} + ... ${karaf_port} BuiltIn.Should_Not_Contain ${output} ${bundle_name} - [Return] ${output} + RETURN ${output} Check_Karaf_Log_Has_Messages - [Arguments] ${filter_string} @{message_list} [Documentation] Will succeed if the @{messages} are found in \ the output of "log:display" - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${filter_string} @{message_list} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App ${output} = Issue_Command_On_Karaf_Console log:display | grep ${filter_string} FOR ${message} IN @{message_list} BuiltIn.Should_Contain ${output} ${message} END - [Return] ${output} + RETURN ${output} Check_Karaf_Log_Message_Count - [Arguments] ${message} ${count} ${use_console}=False [Documentation] Verifies that the ${message} exists specified number of times in ... karaf console log or Karaf Log Folder based on the arg ${use_console}. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - Run Keyword If ${use_console} == False Check_Karaf_Log_File ${message} ${count} - ... ELSE Check_Karaf_Log_From_Console ${message} ${count} + [Arguments] ${message} ${count} ${use_console}=False + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + IF ${use_console} == False + Check_Karaf_Log_File ${message} ${count} + ELSE + Check_Karaf_Log_From_Console ${message} ${count} + END Check_Karaf_Log_From_Console - [Arguments] ${message} ${count} [Documentation] Verifies that the ${message} exists in the Karaf Console log:display and checks ... that it appears ${count} number of times - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${message} ${count} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App ${output} = Issue_Command_On_Karaf_Console log:display | grep ${message} | wc -l ${line} = Get Line ${output} 0 ${stripped} = Strip String ${line} Should Be Equal As Strings ${stripped} ${count} Check_Karaf_Log_File - [Arguments] ${message} ${count} [Documentation] Verifies that the ${message} exists in the Karaf Log Folder and checks ... that it appears ${count} number of times - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - ${output} Run Command On Controller ${ODL_SYSTEM_IP} grep -o ${message} ${WORKSPACE}/${BUNDLEFOLDER}/data/log/* | wc -l + [Arguments] ${message} ${count} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + ${output} = Run Command On Controller + ... ${ODL_SYSTEM_IP} + ... grep -o ${message} ${WORKSPACE}/${BUNDLEFOLDER}/data/log/* | wc -l Should Be Equal As Strings ${output} ${count} Install_A_Feature - [Arguments] ${feature_name} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} ${timeout}=180 [Documentation] Will Install the given ${feature_name} - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${feature_name} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} ${timeout}=180 + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App BuiltIn.Log ${timeout} - ${output} = Issue_Command_On_Karaf_Console feature:install ${feature_name} ${controller} ${karaf_port} ${timeout} + ${output} = Issue_Command_On_Karaf_Console + ... feature:install ${feature_name} + ... ${controller} + ... ${karaf_port} + ... ${timeout} BuiltIn.Log ${output} - [Return] ${output} + RETURN ${output} Install_A_Feature_Using_Active_Connection - [Arguments] ${feature_name} [Documentation] Will Install the given ${feature_name} using active connection - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${feature_name} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App ${cmd} = BuiltIn.Set_Variable feature:install ${feature_name} SSHLibrary.Write ${cmd} - ${output} SSHLibrary.Read_Until_Regexp ${KARAF_PROMPT} + ${output} = SSHLibrary.Read_Until_Regexp ${KARAF_PROMPT} BuiltIn.Log ${output} - [Return] ${output} + RETURN ${output} Uninstall_A_Feature - [Arguments] ${feature_name} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} ${timeout}=180 [Documentation] Will UnInstall the given ${feature_name} - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - ${output} = Issue_Command_On_Karaf_Console feature:uninstall ${feature_name} ${controller} ${karaf_port} ${timeout} + [Arguments] ${feature_name} ${controller}=${ODL_SYSTEM_IP} ${karaf_port}=${KARAF_SHELL_PORT} ${timeout}=180 + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + ${output} = Issue_Command_On_Karaf_Console + ... feature:uninstall ${feature_name} + ... ${controller} + ... ${karaf_port} + ... ${timeout} BuiltIn.Log ${output} - [Return] ${output} + RETURN ${output} Open_Controller_Karaf_Console_On_Background - [Arguments] ${member_index}=${1} ${timeout}=10 ${loglevel}=INFO [Documentation] If there is a stored ssh connection index of connection to the controller's karaf console for ${member_index}, ... close the previous connection. In any case create a new connection ... to karaf console for ${member_index}, set correct prompt set and login to karaf console. ... Store connection index for ${member_index} and restore the previous active connection. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - ${current_ssh_connection_object}= SSHLibrary.Get_Connection + [Arguments] ${member_index}=${1} ${timeout}=10 ${loglevel}=INFO + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + ${current_ssh_connection_object} = SSHLibrary.Get_Connection BuiltIn.Log ${connection_index_dict} BuiltIn.Log ${member_index} - ${status} ${old_connection_index} = BuiltIn.Run_Keyword_And_Ignore_Error Get From Dictionary ${connection_index_dict} ${member_index} - BuiltIn.Run_Keyword_If '${status}'=='PASS' BuiltIn.Run_Keywords SSHLibrary.Switch_Connection ${old_connection_index} - ... AND BuiltIn.Run_Keyword_And_Ignore_Error SSHLibrary.Write logout - ... AND BuiltIn.Run_Keyword_And_Ignore_Error SSHLibrary.Close_Connection + ${status} ${old_connection_index} = BuiltIn.Run_Keyword_And_Ignore_Error + ... Get From Dictionary + ... ${connection_index_dict} + ... ${member_index} + IF '${status}'=='PASS' + BuiltIn.Run_Keywords + ... SSHLibrary.Switch_Connection + ... ${old_connection_index} + ... AND + ... BuiltIn.Run_Keyword_And_Ignore_Error + ... SSHLibrary.Write + ... logout + ... AND + ... BuiltIn.Run_Keyword_And_Ignore_Error + ... SSHLibrary.Close_Connection + END ${odl_ip} = ClusterManagement.Resolve_IP_Address_For_Member ${member_index} - SSHLibrary.Open_Connection ${odl_ip} port=${KARAF_SHELL_PORT} prompt=${KARAF_PROMPT_LOGIN} timeout=${timeout} + SSHLibrary.Open_Connection + ... ${odl_ip} + ... port=${KARAF_SHELL_PORT} + ... prompt=${KARAF_PROMPT_LOGIN} + ... timeout=${timeout} ${karaf_connection_object} = SSHLibrary.Get_Connection Collections.Set_To_Dictionary ${connection_index_dict} ${member_index} ${karaf_connection_object.index} SSHLibrary.Login ${KARAF_USER} ${KARAF_PASSWORD} loglevel=${loglevel} [Teardown] Run Keyword If '${IS_KARAF_APPL}' == 'True' SSHKeywords.Restore_Current_Ssh_Connection_From_Index ${current_ssh_connection_object.index} Open_Controller_Karaf_Console_With_Timeout - [Arguments] ${member_index}=${1} ${timeout}=3s [Documentation] Open new connection to karaf console for member index with specified timeout. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${member_index}=${1} ${timeout}=3s + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App BuiltIn.Log ${member_index} ${odl_ip} = ClusterManagement.Resolve_IP_Address_For_Member ${member_index} - SSHLibrary.Open_Connection ${odl_ip} port=${KARAF_SHELL_PORT} prompt=${KARAF_PROMPT_LOGIN} timeout=${timeout} + SSHLibrary.Open_Connection + ... ${odl_ip} + ... port=${KARAF_SHELL_PORT} + ... prompt=${KARAF_PROMPT_LOGIN} + ... timeout=${timeout} SSHLibrary.Login ${KARAF_USER} ${KARAF_PASSWORD} Configure_Timeout_For_Karaf_Console - [Arguments] ${timeout} ${member_index_list}=${EMPTY} [Documentation] Configure a different timeout for each Karaf console. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${timeout} ${member_index_list}=${EMPTY} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App ${index_list} = ClusterManagement.List_Indices_Or_All given_list=${member_index_list} ${current_connection_object} = SSHLibrary.Get_Connection FOR ${member_index} IN @{index_list} # usually: 1, 2, 3 @@ -190,179 +251,206 @@ Configure_Timeout_For_Karaf_Console [Teardown] Run Keyword If '${IS_KARAF_APPL}' == 'True' SSHKeywords.Restore_Current_Ssh_Connection_From_Index ${current_connection_object.index} Execute_Controller_Karaf_Command_On_Background - [Arguments] ${command} ${member_index}=${1} [Documentation] Send command to karaf without affecting current SSH connection. Read, log and return response. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${command} ${member_index}=${1} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App ${karaf_connection_index} = Collections.Get_From_Dictionary ${connection_index_dict} ${member_index} ${current_connection_index} = SSHLibrary.Switch_Connection ${karaf_connection_index} ${status_write} ${message_write} = BuiltIn.Run_Keyword_And_Ignore_Error SSHLibrary.Write ${command} - ${status_wait} ${message_wait} = BuiltIn.Run_Keyword_And_Ignore_Error SSHLibrary.Read_Until_Regexp ${KARAF_PROMPT} - BuiltIn.Run Keyword If '${status_write}' != 'PASS' BuiltIn.Fail Failed to send the command: ${command} + ${status_wait} ${message_wait} = BuiltIn.Run_Keyword_And_Ignore_Error + ... SSHLibrary.Read_Until_Regexp + ... ${KARAF_PROMPT} + IF '${status_write}' != 'PASS' + BuiltIn.Fail Failed to send the command: ${command} + END BuiltIn.Log ${message_wait} - BuiltIn.Run_Keyword_If '${status_wait}' != 'PASS' BuiltIn.Fail Failed to see prompt after sending the command: ${command} + IF '${status_wait}' != 'PASS' + BuiltIn.Fail Failed to see prompt after sending the command: ${command} + END + RETURN ${message_wait} [Teardown] Run Keyword If '${IS_KARAF_APPL}' == 'True' SSHKeywords.Restore_Current_Ssh_Connection_From_Index ${current_connection_index} - [Return] ${message_wait} Execute_Controller_Karaf_Command_With_Retry_On_Background - [Arguments] ${command} ${member_index}=${1} [Documentation] Attemp to send command to karaf for ${member_index}, if fail then open connection and try again. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error Execute_Controller_Karaf_Command_On_Background ${command} ${member_index} - BuiltIn.Return_From_Keyword_If '${status}' == 'PASS' ${message} + [Arguments] ${command} ${member_index}=${1} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error + ... Execute_Controller_Karaf_Command_On_Background + ... ${command} + ... ${member_index} + IF '${status}' == 'PASS' RETURN ${message} # TODO: Verify this does not leak connections indices. Open_Controller_Karaf_Console_On_Background ${member_index} ${message} = Execute_Controller_Karaf_Command_On_Background ${command} ${member_index} - [Return] ${message} + RETURN ${message} Log_Message_To_Controller_Karaf - [Arguments] ${message} ${member_index_list}=${EMPTY} ${tolerate_failure}=True [Documentation] Make sure this resource is initialized. Send a message into the controller's karaf log file on every node listed (or all). ... By default, failure while processing a node is silently ignored, unless ${tolerate_failure} is False. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${message} ${member_index_list}=${EMPTY} ${tolerate_failure}=True + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App ${index_list} = ClusterManagement.List_Indices_Or_All given_list=${member_index_list} FOR ${index} IN @{index_list} # usually: 1, 2, 3. - ${status} ${output} = BuiltIn.Run_Keyword_And_Ignore_Error Execute_Controller_Karaf_Command_With_Retry_On_Background log:log "ROBOT MESSAGE: ${message}" member_index=${index} - BuiltIn.Run_Keyword_If not ${tolerate_failure} and "${status}" != "PASS" BuiltIn.Fail ${output} + ${status} ${output} = BuiltIn.Run_Keyword_And_Ignore_Error + ... Execute_Controller_Karaf_Command_With_Retry_On_Background + ... log:log "ROBOT MESSAGE: ${message}" + ... member_index=${index} + IF not ${tolerate_failure} and "${status}" != "PASS" + BuiltIn.Fail ${output} + END END Log_Test_Suite_Start_To_Controller_Karaf - [Arguments] ${member_index_list}=${EMPTY} [Documentation] Log suite name to karaf log, useful in suite setup. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${member_index_list}=${EMPTY} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App Log_Message_To_Controller_Karaf Starting suite ${SUITE_SOURCE} ${member_index_list} Log_Testcase_Start_To_Controller_Karaf - [Arguments] ${member_index_list}=${EMPTY} [Documentation] Log test case name to karaf log, useful in test case setup. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${member_index_list}=${EMPTY} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App Log_Message_To_Controller_Karaf Starting test ${SUITE_NAME}.${TEST_NAME} ${member_index_list} Set_Bgpcep_Log_Levels - [Arguments] ${bgpcep_level}=${DEFAULT_BGPCEP_LOG_LEVEL} ${protocol_level}=${DEFAULT_PROTOCOL_LOG_LEVEL} ${member_index_list}=${EMPTY} [Documentation] Assuming OCKCOB was used, set logging level on bgpcep and protocol loggers without affecting current SSH session. + [Arguments] ${bgpcep_level}=${DEFAULT_BGPCEP_LOG_LEVEL} ${protocol_level}=${DEFAULT_PROTOCOL_LOG_LEVEL} ${member_index_list}=${EMPTY} # FIXME: Move to appropriate Resource - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App ${index_list} = ClusterManagement.List_Indices_Or_All given_list=${member_index_list} FOR ${index} IN @{index_list} # usually: 1, 2, 3. - Execute_Controller_Karaf_Command_On_Background log:set ${bgpcep_level} org.opendaylight.bgpcep member_index=${index} - Execute_Controller_Karaf_Command_On_Background log:set ${protocol_level} org.opendaylight.protocol member_index=${index} + Execute_Controller_Karaf_Command_On_Background + ... log:set ${bgpcep_level} org.opendaylight.bgpcep + ... member_index=${index} + Execute_Controller_Karaf_Command_On_Background + ... log:set ${protocol_level} org.opendaylight.protocol + ... member_index=${index} END Get Karaf Log Lines From Test Start - [Arguments] ${ip} ${test_name} ${cmd} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} - ... ${log_file}=${KARAF_LOG} [Documentation] Scrapes all log messages that match regexp ${type} which fall after a point given by a log message that ... contains ${test_name}. This is useful if your test cases are marking karaf.log with a message indicating when ... that test case has started; such that you can easily pull out any extra log messsages to parse/log/etc in the ... test logic itself. For example, you can grab all ERRORS that occur during your test case. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${ip} ${test_name} ${cmd} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} + ... ${log_file}=${KARAF_LOG} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App ${output} = Run Command On Controller ${ip} ${cmd} ${user} ${password} ${prompt} @{log_lines} = Split String ${output} ${\n} - [Return] ${log_lines} + RETURN ${log_lines} Fail If Exceptions Found During Test - [Arguments] ${test_name} ${log_file}=${KARAF_LOG} ${fail}=False [Documentation] Create a failure if an Exception is found in the karaf.log that has not been whitelisted. ... Will work for single controller jobs as well as 3node cluster jobs - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${test_name} ${log_file}=${KARAF_LOG} ${fail}=False + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App FOR ${i} IN RANGE 1 ${NUM_ODL_SYSTEM} + 1 ${cmd} = Set Variable sed '1,/ROBOT MESSAGE: Starting test ${test_name}/d' ${log_file} ${output} = Get Karaf Log Lines From Test Start ${ODL_SYSTEM_${i}_IP} ${test_name} ${cmd} ${exlist} ${matchlist} = Verify Exceptions ${output} Write Exceptions Map To File ${SUITE_NAME}.${TEST_NAME} /tmp/odl${i}_exceptions.txt ${listlength} = BuiltIn.Get Length ${exlist} - BuiltIn.Run Keyword If "${fail}"=="True" and ${listlength} != 0 Log And Fail Exceptions ${exlist} ${listlength} - ... ELSE Collections.Log List ${matchlist} + IF "${fail}"=="True" and ${listlength} != 0 + Log And Fail Exceptions ${exlist} ${listlength} + ELSE + Collections.Log List ${matchlist} + END END Log And Fail Exceptions - [Arguments] ${exlist} ${listlength} [Documentation] Print the list of failed exceptions and fail the test - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${exlist} ${listlength} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App Collections.Log List ${exlist} ${exstr} = BuiltIn.Catenate ${exlist} BuiltIn.Fail New exceptions found: ${listlength}\n${exstr} Get Karaf Log Type From Test Start - [Arguments] ${ip} ${test_name} ${type} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} - ... ${log_file}=${KARAF_LOG} [Documentation] Scrapes all log messages that match regexp ${type} which fall after a point given by a log message that ... contains ${test_name}. This is useful if your test cases are marking karaf.log with a message indicating when ... that test case has started; such that you can easily pull out any extra log messsages to parse/log/etc in the ... test logic itself. For example, you can grab all ERRORS that occur during your test case. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - ${cmd} Set Variable sed '1,/ROBOT MESSAGE: Starting test ${test_name}/d' ${log_file} | grep '${type}' - ${output} Run Command On Controller ${ip} ${cmd} ${user} ${password} ${prompt} - [Return] ${output} + [Arguments] ${ip} ${test_name} ${type} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} + ... ${log_file}=${KARAF_LOG} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + ${cmd} = Set Variable sed '1,/ROBOT MESSAGE: Starting test ${test_name}/d' ${log_file} | grep '${type}' + ${output} = Run Command On Controller ${ip} ${cmd} ${user} ${password} ${prompt} + RETURN ${output} Get Karaf Log Types From Test Start - [Arguments] ${ip} ${test_name} ${types} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} - ... ${log_file}=${KARAF_LOG} [Documentation] A wrapper keyword for "Get Karaf Log Type From Test Start" so that we can parse for multiple types ... of log messages. For example, we can grab all messages of type WARN and ERROR - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${ip} ${test_name} ${types} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} + ... ${log_file}=${KARAF_LOG} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App FOR ${type} IN @{types} Get Karaf Log Type From Test Start ${ip} ${test_name} ${type} ${user} ${password} ... ${prompt} ${log_file} END Get Karaf Log Events From Test Start - [Arguments] ${test_name} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} [Documentation] Wrapper for the wrapper "Get Karaf Log Types From Test Start" so that we can easily loop over ... any number of controllers to analyze karaf.log for ERROR, WARN and Exception log messages - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${test_name} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App ${log_types} = Create List ERROR WARN Exception FOR ${i} IN RANGE 1 ${NUM_ODL_SYSTEM} + 1 Get Karaf Log Types From Test Start ${ODL_SYSTEM_${i}_IP} ${test_name} ${log_types} END Fail If Exceptions Found During Test Deprecated - [Arguments] ${test_name} ${exceptions_white_list}=${EMPTY} [Documentation] Create a failure if an Exception is found in the karaf.log. Will work for single controller jobs ... as well as 3node cluster jobs - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + [Arguments] ${test_name} ${exceptions_white_list}=${EMPTY} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App FOR ${i} IN RANGE 1 ${NUM_ODL_SYSTEM} + 1 Verify Exception Logging In Controller ${ODL_SYSTEM_${i}_IP} ${test_name} ${exceptions_white_list} END Verify Exception Logging In Controller - [Arguments] ${controller_ip} ${test_name} ${exceptions_white_list} [Documentation] Local keyword to make it easier to loop through N controllers to pull Exceptions from the ... karaf.log file and validate with "Check Against White List" - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - ${exceptions}= Get Karaf Log Type From Test Start ${controller_ip} ${test_name} Exception - @{log_lines}= Split String ${exceptions} ${\n} - ${num_log_entries} Get Length ${log_lines} - Return From Keyword If ${num_log_entries} == ${0} No Exceptions found. + [Arguments] ${controller_ip} ${test_name} ${exceptions_white_list} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + ${exceptions} = Get Karaf Log Type From Test Start ${controller_ip} ${test_name} Exception + @{log_lines} = Split String ${exceptions} ${\n} + ${num_log_entries} = Get Length ${log_lines} + IF ${num_log_entries} == ${0} RETURN No Exceptions found. FOR ${log_message} IN @{log_lines} Check Against White List ${log_message} ${exceptions_white_list} END Check Against White List - [Arguments] ${exception_line} ${exceptions_white_list} [Documentation] As soon as the ${exceptions_line} is found in one of the elements of ${exceptions_white_list} ... this keyword will exit and give a Pass to the caller. If there is no match, this keyword will end up ... marking a failure. In the case that no exceptions are found, the caller could end up passing a single ... empty line as that is what is returned when a grep on karaf.log has no match, so we can safely return ... in that case as well. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App - Return From Keyword If "${exception_line}" == "" + [Arguments] ${exception_line} ${exceptions_white_list} + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App + IF "${exception_line}" == "" RETURN FOR ${exception} IN @{exceptions_white_list} - Return From Keyword If "${exception}" in "${exception_line}" Exceptions found, but whitelisted: ${\n}${exception_line}${\n} + IF "${exception}" in "${exception_line}" + RETURN Exceptions found, but whitelisted: ${\n}${exception_line}${\n} + END END Fail Exceptions Found: ${\n}${exception_line}${\n} Wait_For_Karaf_Log - [Arguments] ${message} ${timeout}=60 ${member_index}=${1} [Documentation] Read karaf logs until message appear + [Arguments] ${message} ${timeout}=60 ${member_index}=${1} # TODO: refactor this keyword to use the new workflow to account for multiple controllers. Initial work was done # in this patch https://git.opendaylight.org/gerrit/#/c/45596/ # however, the consumers of this keyword were breaking after that change. Initial theory is that a previous # keyword used before this "Wait For Karaf Log" keyword was closing the karaf console connection, so the # "Flexible SSH Login" keyword from the patch above (45596) was failing. - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App BuiltIn.Log Waiting for '${message}' in karaf log - SSHLibrary.Open_Connection ${ODL_SYSTEM_IP} port=${KARAF_SHELL_PORT} prompt=${KARAF_PROMPT_LOGIN} timeout=${timeout} + SSHLibrary.Open_Connection + ... ${ODL_SYSTEM_IP} + ... port=${KARAF_SHELL_PORT} + ... prompt=${KARAF_PROMPT_LOGIN} + ... timeout=${timeout} SSHLibrary.Login ${KARAF_USER} ${KARAF_PASSWORD} loglevel=${loglevel} SSHLibrary.Write log:tail SSHLibrary.Read_Until ${message} @@ -370,23 +458,28 @@ Wait_For_Karaf_Log SSHLibrary.Close_Connection Restart_Bundle - [Arguments] ${bundle_id} [Documentation] Restarts bundle passed as argument. Note this operation is only for testing and not production environments + [Arguments] ${bundle_id} # TODO: prepare this for cluster environment and multiple controllers - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App Execute_Controller_Karaf_Command_With_Retry_On_Background bundle:restart $(bundle:id '${bundle_id}') Restart_Karaf [Documentation] Restarts Karaf and polls log to detect when Karaf is up and running again # TODO: prepare this for cluster environment and multiple controllers - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App Execute_Controller_Karaf_Command_With_Retry_On_Background log:clear Execute_Controller_Karaf_Command_With_Retry_On_Background shutdown -r -f - BuiltIn.Run_Keyword_And_Return_Status BuiltIn.Wait_Until_Keyword_Succeeds 240s 60s Wait_For_Karaf_Log Shiro environment initialized in + BuiltIn.Run_Keyword_And_Return_Status + ... BuiltIn.Wait_Until_Keyword_Succeeds + ... 240s + ... 60s + ... Wait_For_Karaf_Log + ... Shiro environment initialized in Restart_Jetty [Documentation] Restarts jetty bundle (to reload certificates or key/truststore information) - Return From Keyword If '${IS_KARAF_APPL}' == 'False' Not A Karaf App + IF '${IS_KARAF_APPL}' == 'False' RETURN Not A Karaf App Execute_Controller_Karaf_Command_With_Retry_On_Background log:clear Restart_Bundle OPS4J Pax Web - Jetty Wait_For_Karaf_Log Started jetty-default diff --git a/csit/libraries/KillPythonTool.robot b/csit/libraries/KillPythonTool.robot index f5dcd7d740..7886c5228a 100644 --- a/csit/libraries/KillPythonTool.robot +++ b/csit/libraries/KillPythonTool.robot @@ -1,43 +1,48 @@ *** Settings *** -Documentation Robot keyword library (Resource) for killing possibly left-over Python utilities. +Documentation Robot keyword library (Resource) for killing possibly left-over Python utilities. ... -... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... This library assumes that a SSH connections exists (and is switched to) -... to a Linux machine (usualy TOOLS_SYSTEM_IP) where the Python process should be killed. -... TODO: The Utils.robot library has a "Run Command On Remote System" if we didn't want to make the assumption that an SSH connection was already open. -... alternative TODO: Explain that it is not worth to perform separate SSH logins. +... This library assumes that a SSH connections exists (and is switched to) +... to a Linux machine (usualy TOOLS_SYSTEM_IP) where the Python process should be killed. +... TODO: The Utils.robot library has a "Run Command On Remote System" if we didn't want to make the assumption that an SSH connection was already open. +... alternative TODO: Explain that it is not worth to perform separate SSH logins. ... -... The argument ${filter} should hold what you would type to grep command in bash: -... enclosed in single quotes, dots escaped by backslash and so on. -... Note that single quote inside cannot be escaped, but may be typed as this: '"'"' +... The argument ${filter} should hold what you would type to grep command in bash: +... enclosed in single quotes, dots escaped by backslash and so on. +... Note that single quote inside cannot be escaped, but may be typed as this: '"'"' + *** Keywords *** Search_And_Kill_Remote_Python - [Arguments] ${filter} [Documentation] The main keyword. Search for processes, Log the list of them, kill them. + [Arguments] ${filter} ${processes}= Search_For_Remote_Python_Processes ${filter} BuiltIn.Log ${processes} Kill_Remote_Processes ${processes} Search_For_Remote_Python_Processes - [Arguments] ${filter} [Documentation] Only searches for the list of processes, in case something else than kill has to be done with them. + [Arguments] ${filter} ${processes}= SSHLibrary.Execute_Command ps -elf | egrep python | egrep ${filter} | egrep -v grep + RETURN ${processes} + # TODO: Is "python" worth such a special treatment to have it mentioned in keyword name? - [Return] ${processes} Kill_Remote_Processes - [Arguments] ${pself_lines} ${signal}=9 [Documentation] Kill processes by PIDs from given list (no-op if the list is empty), using specified signal. Log the kill commands used. + [Arguments] ${pself_lines} ${signal}=9 ${arg_length}= BuiltIn.Get_Length ${pself_lines} - Return_From_Keyword_If ${arg_length} == 0 # nothing to kill here + # nothing to kill here + IF ${arg_length} == 0 RETURN ${commands}= SSHLibrary.Execute_Command echo '${pself_lines}' | awk '{print "kill -${signal}",$4}' BuiltIn.Log ${commands} - ${stdout} ${stderr}= SSHLibrary.Execute_Command echo 'set -exu; ${commands}' | sudo sh return_stderr=True + ${stdout} ${stderr}= SSHLibrary.Execute_Command + ... echo 'set -exu; ${commands}' | sudo sh + ... return_stderr=True # TODO: Is -exu needed? Should we Log ${std*}? diff --git a/csit/libraries/L2GatewayOperations.robot b/csit/libraries/L2GatewayOperations.robot index 4e7e085be5..f453078c21 100644 --- a/csit/libraries/L2GatewayOperations.robot +++ b/csit/libraries/L2GatewayOperations.robot @@ -1,24 +1,27 @@ *** Settings *** -Documentation L2Gateway Operations Library. This library has useful keywords for various actions on Hwvtep and Ovs connectivity. Most of the keywords expects that ovs_conn_id,ovs2_conn_id, hwvtep_conn_id, hwvtep2_conn_id and OS_CNTL_CONN_ID are available. -Library SSHLibrary -Library Collections -Library RequestsLibrary -Resource OVSDB.robot -Resource Utils.robot -Resource MininetKeywords.robot -Resource VpnOperations.robot -Resource OpenStackOperations.robot -Resource DevstackUtils.robot -Resource ../variables/l2gw/Variables.robot -Resource ../variables/netvirt/Variables.robot +Documentation L2Gateway Operations Library. This library has useful keywords for various actions on Hwvtep and Ovs connectivity. Most of the keywords expects that ovs_conn_id,ovs2_conn_id, hwvtep_conn_id, hwvtep2_conn_id and OS_CNTL_CONN_ID are available. + +Library SSHLibrary +Library Collections +Library RequestsLibrary +Resource OVSDB.robot +Resource Utils.robot +Resource MininetKeywords.robot +Resource VpnOperations.robot +Resource OpenStackOperations.robot +Resource DevstackUtils.robot +Resource ../variables/l2gw/Variables.robot +Resource ../variables/netvirt/Variables.robot + *** Variables *** ${L2GW_VAR_BASE} ${CURDIR}/../variables/l2gw + *** Keywords *** Add Ovs Bridge Manager Controller And Verify - [Arguments] ${conn_id}=${OS_CMP1_CONN_ID} ${hwvtep_bridge}=${HWVTEP_BRIDGE} [Documentation] Keyword to set OVS manager and controller to ${ODL_IP} for the OVS IP connected in ${conn_id} and verify the entries in OVSDB NETWORK TOPOLOGY and NETSTAT results. + [Arguments] ${conn_id}=${OS_CMP1_CONN_ID} ${hwvtep_bridge}=${HWVTEP_BRIDGE} ${output}= Exec Command ${conn_id} ${OVS_RESTART} ${output}= Exec Command ${conn_id} ${OVS_DEL_MGR} ${output}= Exec Command ${conn_id} ${OVS_DEL_CTRLR} ${INTEGRATION_BRIDGE} @@ -30,27 +33,42 @@ Add Ovs Bridge Manager Controller And Verify ${output}= Exec Command ${conn_id} ${SET_FAIL_MODE} ${INTEGRATION_BRIDGE} secure ${output}= Exec Command ${conn_id} ${OVS_SET_MGR}:${ODL_IP}:${OVSDBPORT} ${output}= Exec Command ${conn_id} ${OVS_SET_CTRLR} ${INTEGRATION_BRIDGE} tcp:${ODL_IP}:${ODL_OF_PORT} - Wait Until Keyword Succeeds 60s 2s Verify Strings In Command Output ${conn_id} ${OVS_SHOW} Manager "tcp:${ODL_IP}:${OVSDBPORT}" + Wait Until Keyword Succeeds + ... 60s + ... 2s + ... Verify Strings In Command Output + ... ${conn_id} + ... ${OVS_SHOW} + ... Manager "tcp:${ODL_IP}:${OVSDBPORT}" ... Controller "tcp:${ODL_IP}:${ODL_OF_PORT}" ${output}= Exec Command ${conn_id} ${NETSTAT} Wait Until Keyword Succeeds 30s 2s Validate Regexp In String ${output} ${NETSTAT_OVSDB_REGEX} Wait Until Keyword Succeeds 30s 2s Validate Regexp In String ${output} ${NETSTAT_OF_REGEX} @{list_to_check}= Create List bridge/${INTEGRATION_BRIDGE} bridge/${hwvtep_bridge} - Wait Until Keyword Succeeds 30s 2s Check For Elements At URI ${OVSDB_NETWORK_TOPOLOGY} ${list_to_check} session + Wait Until Keyword Succeeds + ... 30s + ... 2s + ... Check For Elements At URI + ... ${OVSDB_NETWORK_TOPOLOGY} + ... ${list_to_check} + ... session Create Itm Tunnel Between Hwvtep and Ovs - [Arguments] ${ovs_id} ${ovs_ip} [Documentation] Keyword to create ITM Tunnel Between HWVTEP and OVS connection in ${ovs_id}. + [Arguments] ${ovs_id} ${ovs_ip} ${dpn_id}= Get Dpnid Decimal ${ovs_id} ${first_two_octets} ${third_octet} ${last_octet}= Split String From Right ${ovs_ip} . 2 - ${prefix} = Set Variable ${first_two_octets}.0.0/24 - TemplatedRequests.Post_As_Json_Templated folder=${L2GW_VAR_BASE}/itm_create mapping={"dpnid":"${dpn_id}","ip":"${ovs_ip}","prefix":"${prefix}"} session=session + ${prefix}= Set Variable ${first_two_octets}.0.0/24 + TemplatedRequests.Post_As_Json_Templated + ... folder=${L2GW_VAR_BASE}/itm_create + ... mapping={"dpnid":"${dpn_id}","ip":"${ovs_ip}","prefix":"${prefix}"} + ... session=session ${output}= ITM Get Tunnels Log ${output} Add Vtep Manager And Verify - [Arguments] ${odl_ip} ${conn_id}=${hwvtep_conn_id} [Documentation] Keyword to add vtep manager for HWVTEP connected in ${conn_id} as ${odl_ip} received in argument and verify the entries in NETSTAT and HWVTEP NETWORK TOPOLOGY. + [Arguments] ${odl_ip} ${conn_id}=${hwvtep_conn_id} ${set_manager_command}= Set Variable ${VTEP_ADD_MGR}:${odl_ip}:${OVSDBPORT} ${output}= Exec Command ${conn_id} ${set_manager_command} Log ${output} @@ -59,11 +77,17 @@ Add Vtep Manager And Verify ${output}= Exec Command ${conn_id} ${NETSTAT} Should Contain ${output} ${OVSDBPORT} @{list_to_check}= Create List ${odl_ip} - Wait Until Keyword Succeeds 30s 2s Utils.Check For Elements At URI ${HWVTEP_NETWORK_TOPOLOGY} ${list_to_check} session + Wait Until Keyword Succeeds + ... 30s + ... 2s + ... Utils.Check For Elements At URI + ... ${HWVTEP_NETWORK_TOPOLOGY} + ... ${list_to_check} + ... session Create Verify L2Gateway - [Arguments] ${bridge_name} ${intf_name} ${gw_name} [Documentation] Keyword to create an L2 Gateway ${gw_name} for bridge ${bridge_name} connected to interface ${intf_name} (Using Neutron CLI). + [Arguments] ${bridge_name} ${intf_name} ${gw_name} ${l2gw_output}= OpenStackOperations.Create L2Gateway ${bridge_name} ${intf_name} ${gw_name} Log ${l2gw_output} ${output}= OpenStackOperations.Get All L2Gateway @@ -71,12 +95,16 @@ Create Verify L2Gateway Should Contain ${output} ${gw_name} @{list_to_check}= Create List ${gw_name} Utils.Check For Elements At URI ${L2GW_LIST_REST_URL} ${list_to_check} session - [Return] ${l2gw_output} + RETURN ${l2gw_output} Update And Verify L2Gateway - [Arguments] ${bridge_name} ${gw_name} ${intf_name_1} ${intf_name_2} [Documentation] Keyword to add interface {intf_name_2} to an existing L2 Gateway ${gw_name} for bridge ${bridge_name} (Using Neutron CLI). - ${l2gw_output}= OpenStackOperations.Update L2Gateway ${bridge_name} ${gw_name} ${intf_name_1} ${intf_name_2} + [Arguments] ${bridge_name} ${gw_name} ${intf_name_1} ${intf_name_2} + ${l2gw_output}= OpenStackOperations.Update L2Gateway + ... ${bridge_name} + ... ${gw_name} + ... ${intf_name_1} + ... ${intf_name_2} ${output}= OpenStackOperations.Get All L2Gateway Log ${output} Should Contain ${output} ${gw_name} @@ -84,22 +112,28 @@ Update And Verify L2Gateway Should Contain ${output} ${intf_name_2} @{list_to_check}= Create List ${gw_name} Utils.Check For Elements At URI ${L2GW_LIST_REST_URL} ${list_to_check} session - [Return] ${l2gw_output} + RETURN ${l2gw_output} Delete L2Gateway - [Arguments] ${gw_name} ${check_for_null}=False [Documentation] Keyword to delete the L2 Gateway ${gw_name} received in argument. ... If ${check_for_null} is True return of 404 is treated as empty list. From Neon onwards, ... an empty list is always returned as null, giving 404 on rest call. + [Arguments] ${gw_name} ${check_for_null}=False ${output}= Exec Command ${OS_CNTL_CONN_ID} ${L2GW_DELETE} ${gw_name} Log ${output} @{list_to_check}= Create List ${gw_name} - BuiltIn.Wait Until Keyword Succeeds 5s 1s Utils.Check For Elements Not At URI ${L2GW_LIST_REST_URL} ${list_to_check} session + BuiltIn.Wait Until Keyword Succeeds + ... 5s + ... 1s + ... Utils.Check For Elements Not At URI + ... ${L2GW_LIST_REST_URL} + ... ${list_to_check} + ... session ... check_for_null=${check_for_null} Create Verify L2Gateway Connection - [Arguments] ${gw_name} ${net_name} [Documentation] Keyword to create a new L2 Gateway Connection for ${gw_name} to ${net_name} (Using Neutron CLI). + [Arguments] ${gw_name} ${net_name} ${l2gw_output}= OpenStackOperations.Create L2Gateway Connection ${gw_name} ${net_name} Log ${l2gw_output} ${l2gw_id}= OpenStackOperations.Get L2gw Id ${gw_name} @@ -108,11 +142,11 @@ Create Verify L2Gateway Connection Should Contain ${output} ${l2gw_id} @{list_to_check}= Create List ${l2gw_id} Utils.Check For Elements At URI ${L2GW_CONN_LIST_REST_URL} ${list_to_check} session - [Return] ${l2gw_output} + RETURN ${l2gw_output} Verify L2Gateway Connection - [Arguments] ${gw_name} ${net_name} [Documentation] Keyword to verify existing L2 Gateway Connection for ${gw_name} to ${net_name} $(Using Neutron CLI). + [Arguments] ${gw_name} ${net_name} ${l2gw_id}= OpenStackOperations.Get L2gw Id ${gw_name} ${output}= OpenStackOperations.Get All L2Gateway Connection Log ${output} @@ -121,20 +155,26 @@ Verify L2Gateway Connection Utils.Check For Elements At URI ${L2GW_CONN_LIST_REST_URL} ${list_to_check} session Delete L2Gateway Connection - [Arguments] ${gw_name} ${check_for_null}=False [Documentation] Delete the L2 Gateway connection existing for Gateway ${gw_name} received in argument (Using Neutron CLI). ... If ${check_for_null} is True return of 404 is treated as empty list. From Neon onwards, an empty list is always ... returned as null, giving 404 on rest call. + [Arguments] ${gw_name} ${check_for_null}=False ${l2gw_conn_id}= OpenStackOperations.Get L2gw Connection Id ${gw_name} ${output}= Exec Command ${OS_CNTL_CONN_ID} ${L2GW_CONN_DELETE} ${l2gw_conn_id} Log ${output} @{list_to_check}= Create List ${l2gw_conn_id} - BuiltIn.Wait Until Keyword Succeeds 5s 1s Utils.Check For Elements Not At URI ${L2GW_CONN_LIST_REST_URL} ${list_to_check} session + BuiltIn.Wait Until Keyword Succeeds + ... 5s + ... 1s + ... Utils.Check For Elements Not At URI + ... ${L2GW_CONN_LIST_REST_URL} + ... ${list_to_check} + ... session ... check_for_null=${check_for_null} Update Port For Hwvtep - [Arguments] ${port_name} [Documentation] Keyword to update the Neutron Ports for specific configuration required to connect to HWVTEP (Using REST). + [Arguments] ${port_name} ${port_id}= Get Port Id ${port_name} Log ${port_id} ${json_data}= Get Neutron Port Rest ${port_id} @@ -149,32 +189,38 @@ Update Port For Hwvtep Should Contain ${output} ${STR_VNIC_REPLACE} Should Not Contain ${output} ${STR_VIF_TYPE} Should Not Contain ${output} ${STR_VNIC_TYPE} - [Return] ${return} + RETURN ${return} Attach Port To Hwvtep Namespace - [Arguments] ${port_mac} ${ns_name} ${tap_name} ${conn_id}=${hwvtep_conn_id} [Documentation] Keyword to assign the ${port_mac} to the tap port ${tap_name} in namespace ${ns_name} + [Arguments] ${port_mac} ${ns_name} ${tap_name} ${conn_id}=${hwvtep_conn_id} Exec Command ${conn_id} ${NETNS_EXEC} ${ns_name} ${IFCONF} ${tap_name} ${HW_ETHER} ${port_mac} ${output}= Exec Command ${conn_id} ${NETNS_EXEC} ${ns_name} ${IFCONF} Should Contain ${output} ${port_mac} Namespace Dhclient Verify - [Arguments] ${ns_name} ${ns_tap} ${ns_port_ip} ${conn_id}=${hwvtep_conn_id} ${hwvtep_ip}=${HWVTEP_IP} [Documentation] Keyword to run dhclient for the tap port ${ns_tap} and verify if it has got assigned with ${ns_port_ip}. + [Arguments] ${ns_name} ${ns_tap} ${ns_port_ip} ${conn_id}=${hwvtep_conn_id} ${hwvtep_ip}=${HWVTEP_IP} Start Command In Hwvtep ${NETNS_EXEC} ${ns_name} dhclient ${ns_tap} ${hwvtep_ip} - Wait Until Keyword Succeeds 60s 2s Verify Strings In Command Output ${conn_id} ${NETNS_EXEC} ${ns_name} ${IFCONF} ${ns_port_ip} + Wait Until Keyword Succeeds + ... 60s + ... 2s + ... Verify Strings In Command Output + ... ${conn_id} + ... ${NETNS_EXEC} ${ns_name} ${IFCONF} + ... ${ns_port_ip} Verify Strings In Command Output - [Arguments] ${conn_id} ${command} @{string_list} [Documentation] Keyword to run the ${command} in ${conn_id} and verify if the output contains the list @{string_list}. + [Arguments] ${conn_id} ${command} @{string_list} ${output}= Exec Command ${conn_id} ${command} FOR ${item} IN @{string_list} Should Contain ${output} ${item} END Verify Ping In Namespace Extra Timeout - [Arguments] ${ns_name} ${ns_port_mac} ${vm_ip} ${conn_id}=${hwvtep_conn_id} ${hwvtep_ip}=${HWVTEP_IP} [Documentation] Keyword to ping the IP ${vm_ip} from ${ns_name} and verify MCAS Local Table contains ${ns_port_mac}. + [Arguments] ${ns_name} ${ns_port_mac} ${vm_ip} ${conn_id}=${hwvtep_conn_id} ${hwvtep_ip}=${HWVTEP_IP} ${output}= Exec Command ${conn_id} ${NETNS_EXEC} ${ns_name} ${IFCONF} Log ${output} ${output}= Exec Command ${conn_id} ${NETNS_EXEC} ${ns_name} ping -c3 ${vm_ip} 30s @@ -183,42 +229,46 @@ Verify Ping In Namespace Extra Timeout Wait Until Keyword Succeeds 30s 2s Verify Macs Local Table While Ping ${ns_port_mac} ${conn_id} Verify Ping Fails In Namespace - [Arguments] ${ns_name} ${ns_port_mac} ${vm_ip} ${conn_id}=${hwvtep_conn_id} ${hwvtep_ip}=${HWVTEP_IP} [Documentation] Keyword to ping the IP ${vm_ip} from ${ns_name} and should verify that it fails + [Arguments] ${ns_name} ${ns_port_mac} ${vm_ip} ${conn_id}=${hwvtep_conn_id} ${hwvtep_ip}=${HWVTEP_IP} ${output}= Exec Command ${conn_id} ${NETNS_EXEC} ${ns_name} ping -c3 ${vm_ip} 30s Log ${output} Should Contain ${output} ${PACKET_LOSS} Verify Macs Local Table While Ping - [Arguments] ${mac} ${conn_id} [Documentation] Keyword to check if ${mac} is available under UCAST_MACS_LOCALE_TABLE of HWVTEP dump table. + [Arguments] ${mac} ${conn_id} Verify Vtep List ${conn_id} ${UCAST_MACS_LOCALE_TABLE} ${mac} Verify Nova VM IP - [Arguments] ${vm_name} [Documentation] Keyword to verify if the VM has received IP, and to verify it is not null. - @{vm_ip} ${dhcp_ip} = Get VM IPs ${vm_name} + [Arguments] ${vm_name} + @{vm_ip} ${dhcp_ip}= Get VM IPs ${vm_name} Should Not Contain ${vm_ip} None Should Not Contain ${dhcp_ip} None - [Return] ${vm_ip}[0] + RETURN ${vm_ip}[0] Get L2gw Debug Info [Documentation] Keyword to collect the general debug information required for HWVTEP Test Suite. Exec Command ${hwvtep_conn_id} ${OVSDB_CLIENT_DUMP} OpenStackOperations.Get Test Teardown Debugs - ${resp} = RequestsLibrary.Get Request session ${CONFIG_API}/itm-state:external-tunnel-list/ + ${resp}= RequestsLibrary.Get Request session ${CONFIG_API}/itm-state:external-tunnel-list/ Log ${resp.text} - ${resp} = RequestsLibrary.Get Request session ${CONFIG_API}/network-topology:network-topology/topology/hwvtep:1 + ${resp}= RequestsLibrary.Get Request + ... session + ... ${CONFIG_API}/network-topology:network-topology/topology/hwvtep:1 Log ${resp.text} - ${resp} = RequestsLibrary.Get Request session ${OPERATIONAL_API}/network-topology:network-topology/topology/hwvtep:1 + ${resp}= RequestsLibrary.Get Request + ... session + ... ${OPERATIONAL_API}/network-topology:network-topology/topology/hwvtep:1 Log ${resp.text} Exec Command ${OS_CNTL_CONN_ID} cat /etc/neutron/neutron.conf Exec Command ${OS_CNTL_CONN_ID} cat /etc/neutron/l2gw_plugin.ini Exec Command ${OS_CNTL_CONN_ID} ps -ef | grep neutron-server Start Command In Hwvtep - [Arguments] ${command} ${hwvtep_ip} [Documentation] Keyword to execute Start Command in HWVTEP IP. + [Arguments] ${command} ${hwvtep_ip} ${conn_id}= SSHLibrary.Open Connection ${hwvtep_ip} prompt=${DEFAULT_LINUX_PROMPT} timeout=30s Log ${conn_id} Flexible SSH Login ${DEFAULT_USER} ${DEFAULT_PASSWORD} @@ -228,32 +278,32 @@ Start Command In Hwvtep close connection Verify Vtep List - [Arguments] ${conn_id} ${table_name} @{list} [Documentation] Keyword to run vtep-ctl list for the table ${table_name} and verify the list @{list} contents exists in output. + [Arguments] ${conn_id} ${table_name} @{list} ${output}= Exec Command ${conn_id} ${VTEP LIST} ${table_name} FOR ${item} IN @{list} Should Contain ${output} ${item} END Get Vtep List - [Arguments] ${table_name} ${conn_id}=${hwvtep_conn_id} [Documentation] Keyword to return the contents of vtep-ctl list for table ${table_name}. + [Arguments] ${table_name} ${conn_id}=${hwvtep_conn_id} ${output}= Exec Command ${conn_id} ${VTEP LIST} ${table_name} - [Return] ${output} + RETURN ${output} Get Dpnid Decimal - [Arguments] ${conn_id} [Documentation] Keyword to return DPN ID in decimal for the br-int in IP connected via ${conn_id}. + [Arguments] ${conn_id} ${output}= Exec Command ${conn_id} ${GET_DPNID} Log ${output} ${splitted_output}= Split String ${output} ${EMPTY} ${dpn_id}= Get from List ${splitted_output} 0 Log ${dpn_id} - [Return] ${dpn_id} + RETURN ${dpn_id} Verify Ovs Tunnel - [Arguments] ${hwvtep_ip} ${ovs_ip} ${seg_id}=${NET_1_SEGID} ${conn_id}=${hwvtep_conn_id} [Documentation] Keyword to verify that the OVS tunnel entries are configured for OVS and HWVTEP. + [Arguments] ${hwvtep_ip} ${ovs_ip} ${seg_id}=${NET_1_SEGID} ${conn_id}=${hwvtep_conn_id} ${output}= Exec Command ${conn_id} ${OVS_SHOW} Log ${output} Should Contain ${output} key="${seg_id}", remote_ip="${ovs_ip}" @@ -262,13 +312,13 @@ Verify Ovs Tunnel Should Contain ${output} key=flow, local_ip="${ovs_ip}", remote_ip="${hwvtep_ip}" Get Vtep Field Values From Table - [Arguments] ${table_name} ${column_name} ${conn_id}=${hwvtep_conn_id} [Documentation] Keyword to return specific field value received in ${column_name} from the vtep-ctl list for ${table_name}. + [Arguments] ${table_name} ${column_name} ${conn_id}=${hwvtep_conn_id} ${output}= Exec Command ${conn_id} ${VTEP_LIST_COLUMN}${column_name} list ${table_name} | awk '{print $3}' Log ${output} @{keys}= Split String ${output} Log ${keys} - [Return] ${keys} + RETURN ${keys} Validate Regexp In String [Arguments] ${string} ${regexp} ${verify_count}=1 @@ -281,27 +331,29 @@ Exec Command Switch Connection ${conn_id} ${output}= DevstackUtils.Write Commands Until Prompt ${command} ${timeout} Log ${output} - [Return] ${output} + RETURN ${output} Verify Elan Flow Entries - [Arguments] ${ip} ${srcMacAddrs} ${destMacAddrs} [Documentation] Verify Flows Are Present For ELAN service - ${flow_output} = Run Command On Remote System ${ip} sudo ovs-ofctl -O OpenFlow13 dump-flows ${INTEGRATION_BRIDGE} + [Arguments] ${ip} ${srcMacAddrs} ${destMacAddrs} + ${flow_output}= Run Command On Remote System + ... ${ip} + ... sudo ovs-ofctl -O OpenFlow13 dump-flows ${INTEGRATION_BRIDGE} Log ${flow_output} Should Contain ${flow_output} table=50 - ${sMac_output} = Get Lines Containing String ${flow_output} table=50 + ${sMac_output}= Get Lines Containing String ${flow_output} table=50 Log ${sMac_output} FOR ${sMacAddr} IN @{srcMacAddrs} ${resp}= Should Contain ${sMac_output} dl_src=${sMacAddr} END Should Contain ${flow_output} table=51 - ${dMac_output} = Get Lines Containing String ${flow_output} table=51 + ${dMac_output}= Get Lines Containing String ${flow_output} table=51 Log ${dMac_output} FOR ${dMacAddr} IN @{destMacAddrs} ${resp}= Should Contain ${dMac_output} dl_dst=${dMacAddr} END Should Contain ${flow_output} table=52 - ${sMac_output} = Get Lines Containing String ${flow_output} table=52 + ${sMac_output}= Get Lines Containing String ${flow_output} table=52 Log ${sMac_output} Cleanup L2GW Optional Resources diff --git a/csit/libraries/LISPFlowMapping.robot b/csit/libraries/LISPFlowMapping.robot index 1eee8412b9..ba4775a69b 100644 --- a/csit/libraries/LISPFlowMapping.robot +++ b/csit/libraries/LISPFlowMapping.robot @@ -1,17 +1,20 @@ *** Settings *** -Documentation This resource file defines keywords that are used in more -... than one lispflowmapping test suite. Those suites include -... ../variables/Variables.py, which is where some of the -... variables are coming from. -Library JsonGenerator.py +Documentation This resource file defines keywords that are used in more +... than one lispflowmapping test suite. Those suites include +... ../variables/Variables.py, which is where some of the +... variables are coming from. + +Library JsonGenerator.py + *** Variables *** -${JSON_DIR} ${CURDIR}/../variables/lispflowmapping/Be +${JSON_DIR} ${CURDIR}/../variables/lispflowmapping/Be + *** Keywords *** Authentication Key Should Be - [Arguments] ${resp} ${password} [Documentation] Check if the authentication key in the ${resp} is ${password} + [Arguments] ${resp} ${password} ${authkey}= Get Authentication Key ${resp} Should Be Equal As Strings ${authkey} ${password} @@ -20,11 +23,11 @@ Get Authentication Key ${output}= Get From Dictionary ${resp.json()} output ${mapping_authkey}= Get From Dictionary ${output} mapping-authkey ${authkey}= Get From Dictionary ${mapping_authkey} key-string - [Return] ${authkey} + RETURN ${authkey} Ipv4 Rloc Should Be - [Arguments] ${resp} ${address} [Documentation] Check if the RLOC in the ${resp} is ${address} + [Arguments] ${resp} ${address} ${eid_record}= Get Eid Record ${resp} ${loc_record}= Get From Dictionary ${eid_record} LocatorRecord ${loc_record_0}= Get From List ${loc_record} 0 @@ -35,22 +38,22 @@ Get Eid Record [Arguments] ${resp} ${output}= Get From Dictionary ${resp.json()} output ${eid_record}= Get From Dictionary ${output} mapping-record - [Return] ${eid_record} + RETURN ${eid_record} Get Ipv4 Rloc [Arguments] ${loc_record} ${loc}= Get From Dictionary ${loc_record} rloc ${ipv4}= Get From Dictionary ${loc} ipv4 - [Return] ${ipv4} + RETURN ${ipv4} Get Elp Hop - [Arguments] ${loc_record} ${hop_index} [Documentation] Returns the Rloc object pointed to by ${hop_index} + [Arguments] ${loc_record} ${hop_index} ${rloc}= Get From Dictionary ${loc_record} rloc ${exp_loc_path}= Get From Dictionary ${rloc} explicit-locator-path ${actual_hop_index}= Evaluate ${hop_index} - 1 ${hop}= Get From List ${exp_loc_path} ${actual_hop_index} - [Return] ${hop} + RETURN ${hop} Check Key Removal [Arguments] ${json} @@ -61,30 +64,30 @@ Check Mapping Removal Post Log Check ${LFM_RPC_API}:get-mapping ${json} status_codes=${DELETED_STATUS_CODES} Get Mapping JSON - [Arguments] ${eid} ${rloc} [Documentation] Returns mapping record JSON dict + [Arguments] ${eid} ${rloc} ${loc_record}= Get LocatorRecord Object ${rloc} ${lisp_address}= Get LispAddress Object ${eid} ${loc_record_list}= Create List ${loc_record} ${mapping_record_json}= Get MappingRecord JSON ${lisp_address} ${loc_record_list} ${mapping}= Wrap input ${mapping_record_json} - [Return] ${mapping} + RETURN ${mapping} Post Log Check Authkey - [Arguments] ${json} ${password} [Documentation] Extend the 'Post Log Check' keyword to check for the correct authentication key + [Arguments] ${json} ${password} ${resp}= Post Log Check ${LFM_RPC_API}:get-key ${json} Authentication Key Should Be ${resp} ${password} Post Log Check Ipv4 Rloc - [Arguments] ${json} ${rloc} [Documentation] Extend the 'Post Log Check' keyword to check for the correct IPv4 RLOC + [Arguments] ${json} ${rloc} ${resp}= Post Log Check ${LFM_RPC_API}:get-mapping ${json} Ipv4 Rloc Should Be ${resp} ${rloc} Post Log Check LocatorRecord - [Arguments] ${json} [Documentation] Extend the 'Post Log Check' keyword to check for the existence of a LocatorRecord + [Arguments] ${json} ${resp}= Post Log Check ${LFM_RPC_API}:get-mapping ${json} ${eid_record}= Get Eid Record ${resp} Dictionary Should Contain Key ${eid_record} LocatorRecord diff --git a/csit/libraries/LISPFlowMapping__Lithium.robot b/csit/libraries/LISPFlowMapping__Lithium.robot index 9eae663efc..61d1064ac3 100644 --- a/csit/libraries/LISPFlowMapping__Lithium.robot +++ b/csit/libraries/LISPFlowMapping__Lithium.robot @@ -1,16 +1,18 @@ *** Settings *** -Documentation This resource file defines keywords that are used in more -... than one lispflowmapping test suite. Those suites include -... ../variables/Variables.py, which is where some of the -... variables are coming from. +Documentation This resource file defines keywords that are used in more +... than one lispflowmapping test suite. Those suites include +... ../variables/Variables.py, which is where some of the +... variables are coming from. + *** Variables *** -${JSON_DIR} ${CURDIR}/../variables/lispflowmapping/Li +${JSON_DIR} ${CURDIR}/../variables/lispflowmapping/Li + *** Keywords *** Authentication Key Should Be - [Arguments] ${resp} ${password} [Documentation] Check if the authentication key in the ${resp} is ${password} + [Arguments] ${resp} ${password} ${authkey}= Get Authentication Key ${resp} Should Be Equal As Strings ${authkey} ${password} @@ -18,11 +20,11 @@ Get Authentication Key [Arguments] ${resp} ${output}= Get From Dictionary ${resp.json()} output ${authkey}= Get From Dictionary ${output} authkey - [Return] ${authkey} + RETURN ${authkey} Ipv4 Rloc Should Be - [Arguments] ${resp} ${address} [Documentation] Check if the RLOC in the ${resp} is ${address} + [Arguments] ${resp} ${address} ${eid_record}= Get Eid Record ${resp} ${loc_record}= Get From Dictionary ${eid_record} LocatorRecord ${loc_record_0}= Get From List ${loc_record} 0 @@ -34,14 +36,14 @@ Get Eid Record ${output}= Get From Dictionary ${resp.json()} output ${eid_record}= Get From Dictionary ${output} eidToLocatorRecord ${eid_record}= Get From List ${eid_record} 0 - [Return] ${eid_record} + RETURN ${eid_record} Get Ipv4 Rloc [Arguments] ${loc_record} ${loc}= Get From Dictionary ${loc_record} LispAddressContainer ${address}= Get From Dictionary ${loc} Ipv4Address ${ipv4}= Get From Dictionary ${address} Ipv4Address - [Return] ${ipv4} + RETURN ${ipv4} Check Mapping Removal [Arguments] ${json} diff --git a/csit/libraries/LiveMigration.robot b/csit/libraries/LiveMigration.robot index f4cb9f8cb8..3bfefd1d56 100644 --- a/csit/libraries/LiveMigration.robot +++ b/csit/libraries/LiveMigration.robot @@ -1,15 +1,18 @@ *** Settings *** -Documentation Live Migration Library, This can be used by Live Migration tests. -Library SSHLibrary -Resource DevstackUtils.robot -Resource OpenStackOperations.robot -Resource SSHKeywords.robot -Resource ../variables/Variables.robot +Documentation Live Migration Library, This can be used by Live Migration tests. + +Library SSHLibrary +Resource DevstackUtils.robot +Resource OpenStackOperations.robot +Resource SSHKeywords.robot +Resource ../variables/Variables.robot + *** Variables *** -${NOVA_CPU_CONF} /etc/nova/nova-cpu.conf -${NOVA_COMPUTE_SERVICE} n-cpu -${CMP_INSTANCES_DEFAULT_PATH} /opt/stack/data/nova/instances +${NOVA_CPU_CONF} /etc/nova/nova-cpu.conf +${NOVA_COMPUTE_SERVICE} n-cpu +${CMP_INSTANCES_DEFAULT_PATH} /opt/stack/data/nova/instances + *** Keywords *** Live Migration Suite Setup @@ -25,13 +28,23 @@ Live Migration Suite Teardown Setup Live Migration In Compute Nodes [Documentation] Set instances to be created in the shared directory. FOR ${conn_id} IN @{OS_CMP_CONN_IDS} - OpenStackOperations.Modify OpenStack Configuration File ${conn_id} ${NOVA_CPU_CONF} DEFAULT instances_path ${CMP_INSTANCES_SHARED_PATH} + OpenStackOperations.Modify OpenStack Configuration File + ... ${conn_id} + ... ${NOVA_CPU_CONF} + ... DEFAULT + ... instances_path + ... ${CMP_INSTANCES_SHARED_PATH} OpenStackOperations.Restart DevStack Service ${conn_id} ${NOVA_COMPUTE_SERVICE} END UnSet Live Migration In Compute Nodes [Documentation] Clear settings done for Live Migration FOR ${conn_id} IN @{OS_CMP_CONN_IDS} - OpenStackOperations.Modify OpenStack Configuration File ${conn_id} ${NOVA_CPU_CONF} DEFAULT instances_path ${CMP_INSTANCES_DEFAULT_PATH} + OpenStackOperations.Modify OpenStack Configuration File + ... ${conn_id} + ... ${NOVA_CPU_CONF} + ... DEFAULT + ... instances_path + ... ${CMP_INSTANCES_DEFAULT_PATH} OpenStackOperations.Restart DevStack Service ${conn_id} ${NOVA_COMPUTE_SERVICE} END diff --git a/csit/libraries/MdsalLowlevel.robot b/csit/libraries/MdsalLowlevel.robot index 9dcaaa74e0..25b4fab33d 100644 --- a/csit/libraries/MdsalLowlevel.robot +++ b/csit/libraries/MdsalLowlevel.robot @@ -1,291 +1,362 @@ *** Settings *** -Documentation Keywords wrapping controller's odl-mdsal-lowlevel yang model rpcs. +Documentation Keywords wrapping controller's odl-mdsal-lowlevel yang model rpcs. ... -... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html -Library XML -Resource ${CURDIR}/ClusterManagement.robot -Resource ${CURDIR}/TemplatedRequests.robot +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html + +Library XML +Resource ${CURDIR}/ClusterManagement.robot +Resource ${CURDIR}/TemplatedRequests.robot + *** Variables *** -${LOWLEVEL_RPC_DIR} ${CURDIR}/../variables/mdsal/lowlevelrpc -${BECOME_PREFIX_LEADER_DIR} ${LOWLEVEL_RPC_DIR}/become_prefix_leader -${CHECK_PUBLISH_NOTIFICATIONS_DIR} ${LOWLEVEL_RPC_DIR}/check_publish_notifications -${CREATE_PREFIX_SHARD_DIR} ${LOWLEVEL_RPC_DIR}/create_prefix_shard -${GET_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/get_constant -${GET_CONTEXTED_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/get_contexted_constant -${GET_SINGLETON_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/get_singleton_constant -${PRODUCE_TRANSACTIONS_DIR} ${LOWLEVEL_RPC_DIR}/produce_transactions -${REGISTER_BOUND_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/register_bound_constant -${REGISTER_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/register_constant -${REGISTER_FLAPPING_SINGLETON_DIR} ${LOWLEVEL_RPC_DIR}/register_flapping_singleton -${REGISTER_SINGLETON_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/register_singleton_constant -${REMOVE_PREFIX_SHARD_DIR} ${LOWLEVEL_RPC_DIR}/remove_prefix_shard -${SHUTDOWN_SHARD_REPLICA_DIR} ${LOWLEVEL_RPC_DIR}/shutdown_shard_replica +${LOWLEVEL_RPC_DIR} ${CURDIR}/../variables/mdsal/lowlevelrpc +${BECOME_PREFIX_LEADER_DIR} ${LOWLEVEL_RPC_DIR}/become_prefix_leader +${CHECK_PUBLISH_NOTIFICATIONS_DIR} ${LOWLEVEL_RPC_DIR}/check_publish_notifications +${CREATE_PREFIX_SHARD_DIR} ${LOWLEVEL_RPC_DIR}/create_prefix_shard +${GET_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/get_constant +${GET_CONTEXTED_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/get_contexted_constant +${GET_SINGLETON_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/get_singleton_constant +${PRODUCE_TRANSACTIONS_DIR} ${LOWLEVEL_RPC_DIR}/produce_transactions +${REGISTER_BOUND_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/register_bound_constant +${REGISTER_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/register_constant +${REGISTER_FLAPPING_SINGLETON_DIR} ${LOWLEVEL_RPC_DIR}/register_flapping_singleton +${REGISTER_SINGLETON_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/register_singleton_constant +${REMOVE_PREFIX_SHARD_DIR} ${LOWLEVEL_RPC_DIR}/remove_prefix_shard +${SHUTDOWN_SHARD_REPLICA_DIR} ${LOWLEVEL_RPC_DIR}/shutdown_shard_replica ${SHUTDOWN_PREFIX_SHARD_REPLICA_DIR} ${LOWLEVEL_RPC_DIR}/shutdown_prefix_shard_replica -${START_PUBLISH_NOTIFICATIONS_DIR} ${LOWLEVEL_RPC_DIR}/start_publish_notifications -${SUBSCRIBE_DDTL_DIR} ${LOWLEVEL_RPC_DIR}/subscribe_ddtl -${SUBSCRIBE_DTCL_DIR} ${LOWLEVEL_RPC_DIR}/subscribe_dtcl -${SUBSCRIBE_YNL_DIR} ${LOWLEVEL_RPC_DIR}/subscribe_ynl -${UNREGISTER_BOUND_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/unregister_bound_constant -${UNREGISTER_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/unregister_constant +${START_PUBLISH_NOTIFICATIONS_DIR} ${LOWLEVEL_RPC_DIR}/start_publish_notifications +${SUBSCRIBE_DDTL_DIR} ${LOWLEVEL_RPC_DIR}/subscribe_ddtl +${SUBSCRIBE_DTCL_DIR} ${LOWLEVEL_RPC_DIR}/subscribe_dtcl +${SUBSCRIBE_YNL_DIR} ${LOWLEVEL_RPC_DIR}/subscribe_ynl +${UNREGISTER_BOUND_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/unregister_bound_constant +${UNREGISTER_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/unregister_constant ${UNREGISTER_FLAPPING_SINGLETON_DIR} ${LOWLEVEL_RPC_DIR}/unregister_flapping_singleton ${UNREGISTER_SINGLETON_CONSTANT_DIR} ${LOWLEVEL_RPC_DIR}/unregister_singleton_constant -${UNSUBSCRIBE_DDTL_DIR} ${LOWLEVEL_RPC_DIR}/unsubscribe_ddtl -${UNSUBSCRIBE_DTCL_DIR} ${LOWLEVEL_RPC_DIR}/unsubscribe_dtcl -${UNSUBSCRIBE_YNL_DIR} ${LOWLEVEL_RPC_DIR}/unsubscribe_ynl -${WRITE_TRANSACTIONS_DIR} ${LOWLEVEL_RPC_DIR}/write_transactions +${UNSUBSCRIBE_DDTL_DIR} ${LOWLEVEL_RPC_DIR}/unsubscribe_ddtl +${UNSUBSCRIBE_DTCL_DIR} ${LOWLEVEL_RPC_DIR}/unsubscribe_dtcl +${UNSUBSCRIBE_YNL_DIR} ${LOWLEVEL_RPC_DIR}/unsubscribe_ynl +${WRITE_TRANSACTIONS_DIR} ${LOWLEVEL_RPC_DIR}/write_transactions + *** Keywords *** Get_Constant - [Arguments] ${member_index} ${explicit_status_codes}=${NO_STATUS_CODES} [Documentation] Invoke get-constant rpc on the requested member and return the registered constant unless explicit status code is expected. ... The ${explicit_status_codes} is a list of http status codes for which the rpc call is considered as passed and is used for calls with ... expected failures on odl's side, such as calling the rpc on isolated node etc. + [Arguments] ${member_index} ${explicit_status_codes}=${NO_STATUS_CODES} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${GET_CONSTANT_DIR} session=${session} explicit_status_codes=${explicit_status_codes} - BuiltIn.Return_From_Keyword_If """${explicit_status_codes}""" != """${NO_STATUS_CODES}""" + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${GET_CONSTANT_DIR} + ... session=${session} + ... explicit_status_codes=${explicit_status_codes} + IF """${explicit_status_codes}""" != """${NO_STATUS_CODES}""" RETURN ${xml} = XML.Parse_Xml ${text} ${constant} = XML.Get_Element_Text ${xml} xpath=constant - BuiltIn.Return_From_Keyword ${constant} + RETURN ${constant} Get_Contexted_Constant - [Arguments] ${member_index} ${context} [Documentation] Invoke get-contexted-constant rpc on the requested member and return the registered constant. The argument ${context} is only the string part ... of the whole instance identifier. The ${explicit_status_codes} is a list of http status codes for which the rpc call is considered as passed and is used for ... calls with expected failures on odl's side, such as calling the rpc on isolated node etc. + [Arguments] ${member_index} ${context} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary CONTEXT=${context} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${GET_CONTEXTED_CONSTANT_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary CONTEXT=${context} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${GET_CONTEXTED_CONSTANT_DIR} + ... mapping=${mapping} + ... session=${session} ${xml} = XML.Parse_Xml ${text} ${constant} = XML.Get_Element_Text ${xml} xpath=constant - BuiltIn.Return_From_Keyword ${constant} + RETURN ${constant} Get_Singleton_Constant - [Arguments] ${member_index} ${explicit_status_codes}=${NO_STATUS_CODES} [Documentation] Invoke get-singleton-constant rpc on the requested member and return the registered constant unless explicit status code is ... expected. The ${explicit_status_codes} is a list of http status codes for which the rpc call is considered as passed and is used for calls ... with expected failures on odl's side, such as calling the rpc on isolated node etc. + [Arguments] ${member_index} ${explicit_status_codes}=${NO_STATUS_CODES} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${GET_SINGLETON_CONSTANT_DIR} session=${session} explicit_status_codes=${explicit_status_codes} - BuiltIn.Return_From_Keyword_If """${explicit_status_codes}""" != """${NO_STATUS_CODES}""" + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${GET_SINGLETON_CONSTANT_DIR} + ... session=${session} + ... explicit_status_codes=${explicit_status_codes} + IF """${explicit_status_codes}""" != """${NO_STATUS_CODES}""" RETURN ${xml} = XML.Parse_Xml ${text} ${constant} = XML.Get_Element_Text ${xml} xpath=constant - BuiltIn.Return_From_Keyword ${constant} + RETURN ${constant} Register_Constant - [Arguments] ${member_index} ${constant} [Documentation] Register the get-constant rpc on the requested node with given constant. + [Arguments] ${member_index} ${constant} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary CONSTANT=${constant} + &{mapping} = BuiltIn.Create_Dictionary CONSTANT=${constant} TemplatedRequests.Post_As_Xml_Templated ${REGISTER_CONSTANT_DIR} mapping=${mapping} session=${session} Unregister_Constant - [Arguments] ${member_index} [Documentation] Unregister the get-constant rpc on the given node. + [Arguments] ${member_index} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} TemplatedRequests.Post_As_Xml_Templated ${UNREGISTER_CONSTANT_DIR} session=${session} Register_Singleton_Constant - [Arguments] ${member_index} ${constant} [Documentation] Register singleton application on given node by invoking register-singleton-constant rpc. + [Arguments] ${member_index} ${constant} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary CONSTANT=${constant} - TemplatedRequests.Post_As_Xml_Templated ${REGISTER_SINGLETON_CONSTANT_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary CONSTANT=${constant} + TemplatedRequests.Post_As_Xml_Templated + ... ${REGISTER_SINGLETON_CONSTANT_DIR} + ... mapping=${mapping} + ... session=${session} Unregister_Singleton_Constant - [Arguments] ${member_index} [Documentation] Unregister singleton application on given node by invoking unregister-singleton-constant rpc. + [Arguments] ${member_index} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} TemplatedRequests.Post_As_Xml_Templated ${UNREGISTER_SINGLETON_CONSTANT_DIR} session=${session} Register_Flapping_Singleton - [Arguments] ${member_index} [Documentation] Activate flapping application on given node by invoking register-flapping-singleton rpc. + [Arguments] ${member_index} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} TemplatedRequests.Post_As_Xml_Templated ${REGISTER_FLAPPING_SINGLETON_DIR} session=${session} Unregister_Flapping_Singleton - [Arguments] ${member_index} [Documentation] Deactivate flapping singleton application by invoking unregister-flapping-singleton rpc. ... Return the successful re-registrations count. + [Arguments] ${member_index} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} ${text} = TemplatedRequests.Post_As_Xml_Templated ${UNREGISTER_FLAPPING_SINGLETON_DIR} session=${session} ${xml} = XML.Parse_Xml ${text} ${count} = XML.Get_Element_Text ${xml} xpath=flap-count - BuiltIn.Return_From_Keyword ${count} + RETURN ${count} Write_Transactions - [Arguments] ${member_index} ${identifier} ${seconds} ${trans_per_sec} ${chained_trans}=${True} [Documentation] Create transactions with given rate for given time for module-based shards. + [Arguments] ${member_index} ${identifier} ${seconds} ${trans_per_sec} ${chained_trans}=${True} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary ID=${identifier} DURATION=${seconds} RATE=${trans_per_sec} CHAINED_FLAG=${chained_trans} + &{mapping} = BuiltIn.Create_Dictionary + ... ID=${identifier} + ... DURATION=${seconds} + ... RATE=${trans_per_sec} + ... CHAINED_FLAG=${chained_trans} TemplatedRequests.Post_As_Xml_Templated ${WRITE_TRANSACTIONS_DIR} mapping=${mapping} session=${session} Produce_Transactions - [Arguments] ${member_index} ${seconds} ${trans_per_sec} ${isolated_trans}=${True} [Documentation] Create transactions with given rate for given time for prefix-based shards. + [Arguments] ${member_index} ${seconds} ${trans_per_sec} ${isolated_trans}=${True} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary SECONDS=${seconds} TPS=${trans_per_sec} ISOLATED_TRANSACTIONS=${chained_trans} + &{mapping} = BuiltIn.Create_Dictionary + ... SECONDS=${seconds} + ... TPS=${trans_per_sec} + ... ISOLATED_TRANSACTIONS=${chained_trans} TemplatedRequests.Post_As_Xml_Templated ${PRODUCE_TRANSACTIONS_DIR} mapping=${mapping} session=${session} Create_Prefix_Shard - [Arguments] ${member_index} ${prefix} ${replicas} [Documentation] Create prefix based shard. ${replicas} is a list of cluster node indexes, taken e.g. from ClusterManagement.List_Indices_Or_All. + [Arguments] ${member_index} ${prefix} ${replicas} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - ${replicas_str} BuiltIn.Set_Variable ${EMPTY} + ${replicas_str} = BuiltIn.Set_Variable ${EMPTY} FOR ${replica} IN @{replicas} - ${replicas_str} BuiltIn.Set_Variable ${replicas_str}member-${replica} + ${replicas_str} = BuiltIn.Set_Variable ${replicas_str}member-${replica} END - &{mapping} BuiltIn.Create_Dictionary PREFIX=${prefix} REPLICAS=${replicas_str} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${CREATE_PREFIX_SHARD_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary PREFIX=${prefix} REPLICAS=${replicas_str} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${CREATE_PREFIX_SHARD_DIR} + ... mapping=${mapping} + ... session=${session} Remove_Prefix_Shard - [Arguments] ${member_index} ${prefix} [Documentation] Remove prefix based shard. + [Arguments] ${member_index} ${prefix} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary PREFIX=${prefix} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${REMOVE_PREFIX_SHARD_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary PREFIX=${prefix} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${REMOVE_PREFIX_SHARD_DIR} + ... mapping=${mapping} + ... session=${session} Become_Prefix_Leader - [Arguments] ${member_index} ${shard_name} [Documentation] Given node ask to become a shard leader. + [Arguments] ${member_index} ${shard_name} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary SHARD_NAME=${shard_name} ID=prefix-0 - ${text} = TemplatedRequests.Post_As_Xml_Templated ${BECOME_PREFIX_LEADER_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary SHARD_NAME=${shard_name} ID=prefix-0 + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${BECOME_PREFIX_LEADER_DIR} + ... mapping=${mapping} + ... session=${session} Subscribe_Dtcl - [Arguments] ${member_index} [Documentation] Subscribe a listener for data changes. Invoke subscribe-dtcl rpc. + [Arguments] ${member_index} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} TemplatedRequests.Post_As_Xml_Templated ${SUBSCRIBE_DTCL_DIR} session=${session} Unsubscribe_Dtcl - [Arguments] ${member_index} [Documentation] Invoke unsubscribe-dtcl rpc, return copy-matches field as boolean. + [Arguments] ${member_index} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} ${text} = TemplatedRequests.Post_As_Xml_Templated ${UNSUBSCRIBE_DTCL_DIR} session=${session} BuiltIn.Run_Keyword_And_Return MdsalLowLevel__Parse_Matches ${text} Unsubscribe_Dtcl_No_Tx - [Arguments] ${member_index} [Documentation] Unsubscribe a listener from the data changes. Expect success no notifications received. Return boolean status. + [Arguments] ${member_index} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${UNSUBSCRIBE_DTCL_DIR} session=${session} additional_allowed_status_codes=${INTERNAL_SERVER_ERROR} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${UNSUBSCRIBE_DTCL_DIR} + ... session=${session} + ... additional_allowed_status_codes=${INTERNAL_SERVER_ERROR} BuiltIn.Run_Keyword_And_Return MdsalLowLevel__Parse_Maybe_No_Tx ${text} Subscribe_Ddtl - [Arguments] ${member_index} [Documentation] Subscribe DOMDataTreeListener to listen for the data changes. + [Arguments] ${member_index} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} TemplatedRequests.Post_As_Xml_Templated ${SUBSCRIBE_DDTL_DIR} session=${session} Unsubscribe_Ddtl - [Arguments] ${member_index} [Documentation] Invoke unsubscribe-ddtl rpc, return copy-matches field as boolean. + [Arguments] ${member_index} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} ${text} = TemplatedRequests.Post_As_Xml_Templated ${UNSUBSCRIBE_DDTL_DIR} session=${session} BuiltIn.Run_Keyword_And_Return MdsalLowLevel__Parse_Matches ${text} Unsubscribe_Ddtl_No_Tx - [Arguments] ${member_index} [Documentation] Unsubscribe a listener from the data changes. Expect success no notifications received. Return boolean status. + [Arguments] ${member_index} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${UNSUBSCRIBE_DDTL_DIR} session=${session} additional_allowed_status_codes=${INTERNAL_SERVER_ERROR} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${UNSUBSCRIBE_DDTL_DIR} + ... session=${session} + ... additional_allowed_status_codes=${INTERNAL_SERVER_ERROR} BuiltIn.Run_Keyword_And_Return MdsalLowLevel__Parse_Maybe_No_Tx ${text} MdsalLowLevel__Parse_Matches - [Arguments] ${text} [Documentation] Interpret the \${text} as XML response to an unsubscribe call and return copy-matches as boolean. + [Arguments] ${text} ${xml} = XML.Parse_Xml ${text} ${matches} = XML.Get_Element_Text ${xml} xpath=copy-matches ${matches} = BuiltIn.Convert_To_Boolean ${matches} - BuiltIn.Return_From_Keyword ${matches} + RETURN ${matches} MdsalLowLevel__Parse_Maybe_No_Tx - [Arguments] ${text} [Documentation] Attempt to parse the \${text} as successful unsubscribe. If that fails, extract the error message and expect no notifications. + [Arguments] ${text} ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error MdsalLowLevel__Parse_Matches ${text} - BuiltIn.Return_From_Keyword_If "${status}" == "PASS" ${message} + IF "${status}" == "PASS" RETURN ${message} ${xml} = XML.Parse_Xml ${text} ${message} = XML.Get_Element_Text ${xml} xpath=error/error-message - ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error BuiltIn.Should_Contain ${message} listener has not received - BuiltIn.Return_From_Keyword_If "${status}" == "PASS" ${TRUE} - [Return] ${FALSE} + ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error + ... BuiltIn.Should_Contain + ... ${message} + ... listener has not received + IF "${status}" == "PASS" RETURN ${TRUE} + RETURN ${FALSE} Start_Publish_Notifications - [Arguments] ${member_index} ${gid} ${seconds} ${notif_per_sec} [Documentation] Start publishing notifications by invoking publish-notifications rpc. + [Arguments] ${member_index} ${gid} ${seconds} ${notif_per_sec} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary ID=${gid} DURATION=${seconds} RATE=${notif_per_sec} - TemplatedRequests.Post_As_Xml_Templated ${START_PUBLISH_NOTIFICATIONS_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary ID=${gid} DURATION=${seconds} RATE=${notif_per_sec} + TemplatedRequests.Post_As_Xml_Templated + ... ${START_PUBLISH_NOTIFICATIONS_DIR} + ... mapping=${mapping} + ... session=${session} Check_Publish_Notifications - [Arguments] ${member_index} ${gid} [Documentation] Publishing notifications check by invoking check-publish-notifications rpc. Return publising process state details. + [Arguments] ${member_index} ${gid} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary ID=${gid} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${CHECK_PUBLISH_NOTIFICATIONS_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary ID=${gid} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${CHECK_PUBLISH_NOTIFICATIONS_DIR} + ... mapping=${mapping} + ... session=${session} ${xml} = XML.Parse_Xml ${text} ${active} = XML.Get_Element_Text ${xml} xpath=active ${active} = BuiltIn.Convert_To_Boolean ${active} - ${status} ${publish_count}= BuiltIn.Run_Keyword_And_Ignore_Error XML.Get_Element_Text ${xml} xpath=publish-count - BuiltIn.Run_Keyword_If """${status}""" == """FAIL""" and """${publish_count}""" != """No element matching 'publish-count' found.""" BuiltIn.Fail ${publish_count} - ${publish_count} BuiltIn.Set_Variable_If """${status}""" == """FAIL""" ${EMPTY} ${publish_count} - ${status} ${last_error}= BuiltIn.Run_Keyword_And_Ignore_Error XML.Get_Element_Text ${xml} xpath=last-error - BuiltIn.Run_Keyword_If """${status}""" == """FAIL""" and """${last_error}""" != """No element matching 'last-error' found.""" BuiltIn.Fail ${last_error} - ${last_error} BuiltIn.Set_Variable_If """${status}""" == """FAIL""" ${EMPTY} ${last_error} - BuiltIn.Return_From_Keyword ${active} ${publish_count} ${last_error} + ${status} ${publish_count} = BuiltIn.Run_Keyword_And_Ignore_Error + ... XML.Get_Element_Text + ... ${xml} + ... xpath=publish-count + IF """${status}""" == """FAIL""" and """${publish_count}""" != """No element matching 'publish-count' found.""" + BuiltIn.Fail ${publish_count} + END + ${publish_count} = BuiltIn.Set_Variable_If """${status}""" == """FAIL""" ${EMPTY} ${publish_count} + ${status} ${last_error} = BuiltIn.Run_Keyword_And_Ignore_Error + ... XML.Get_Element_Text + ... ${xml} + ... xpath=last-error + IF """${status}""" == """FAIL""" and """${last_error}""" != """No element matching 'last-error' found.""" + BuiltIn.Fail ${last_error} + END + ${last_error} = BuiltIn.Set_Variable_If """${status}""" == """FAIL""" ${EMPTY} ${last_error} + RETURN ${active} ${publish_count} ${last_error} Subscribe_Ynl - [Arguments] ${member_index} ${gid} [Documentation] Subscribe listener for the notifications with identifier ${gid}. + [Arguments] ${member_index} ${gid} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary ID=${gid} + &{mapping} = BuiltIn.Create_Dictionary ID=${gid} TemplatedRequests.Post_As_Xml_Templated ${SUBSCRIBE_YNL_DIR} mapping=${mapping} session=${session} Unsubscribe_Ynl - [Arguments] ${member_index} ${gid} [Documentation] Unsubscribe listener for the ${gid} identifier. Return statistics of the publishing process. + [Arguments] ${member_index} ${gid} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary ID=${gid} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${UNSUBSCRIBE_YNL_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary ID=${gid} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${UNSUBSCRIBE_YNL_DIR} + ... mapping=${mapping} + ... session=${session} ${xml} = XML.Parse_Xml ${text} ${all_not} = XML.Get_Element_Text ${xml} xpath=all-not ${id_not} = XML.Get_Element_Text ${xml} xpath=id-not ${err_not} = XML.Get_Element_Text ${xml} xpath=err-not ${local_number} = XML.Get_Element_Text ${xml} xpath=local-number - BuiltIn.Return_From_Keyword ${all_not} ${id_not} ${err_not} ${local_number} + RETURN ${all_not} ${id_not} ${err_not} ${local_number} Register_Bound_Constant - [Arguments] ${member_index} ${context} ${constant} [Documentation] Invoke register-bound-constant rpc and register get-contexted-constant rpc. The argument ${context} is only the string part ... of the whole instance identifier. + [Arguments] ${member_index} ${context} ${constant} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary CONTEXT=${context} CONSTANT=${constant} - ${text} = TemplatedRequests.Post_As_Xml_Templated ${REGISTER_BOUND_CONSTANT_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary CONTEXT=${context} CONSTANT=${constant} + ${text} = TemplatedRequests.Post_As_Xml_Templated + ... ${REGISTER_BOUND_CONSTANT_DIR} + ... mapping=${mapping} + ... session=${session} Unregister_Bound_Constant - [Arguments] ${member_index} ${context} [Documentation] Invoke unregister-bound-constant rpc and unregister get-contexted-constant rpc. The argument ${context} is only the string part ... of the whole instance identifier. + [Arguments] ${member_index} ${context} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary CONTEXT=${context} - TemplatedRequests.Post_As_Xml_Templated ${UNREGISTER_BOUND_CONSTANT_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary CONTEXT=${context} + TemplatedRequests.Post_As_Xml_Templated + ... ${UNREGISTER_BOUND_CONSTANT_DIR} + ... mapping=${mapping} + ... session=${session} Shutdown_Shard_Replica - [Arguments] ${member_index} ${shard_name} [Documentation] Invoke shutdown-shard-replica rpc. + [Arguments] ${member_index} ${shard_name} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary SHARD_NAME=${shard_name} - TemplatedRequests.Post_As_Xml_Templated ${SHUTDOWN_SHARD_REPLICA_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary SHARD_NAME=${shard_name} + TemplatedRequests.Post_As_Xml_Templated + ... ${SHUTDOWN_SHARD_REPLICA_DIR} + ... mapping=${mapping} + ... session=${session} Shutdown_Prefix_Shard_Replica - [Arguments] ${member_index} ${shard_prefix} [Documentation] Invoke shutdown-prefix-shard-replica rpc. + [Arguments] ${member_index} ${shard_prefix} ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${member_index} - &{mapping} BuiltIn.Create_Dictionary PREFIX=${shard_prefix} - TemplatedRequests.Post_As_Xml_Templated ${SHUTDOWN_PREFIX_SHARD_REPLICA_DIR} mapping=${mapping} session=${session} + &{mapping} = BuiltIn.Create_Dictionary PREFIX=${shard_prefix} + TemplatedRequests.Post_As_Xml_Templated + ... ${SHUTDOWN_PREFIX_SHARD_REPLICA_DIR} + ... mapping=${mapping} + ... session=${session} diff --git a/csit/libraries/MininetKeywords.robot b/csit/libraries/MininetKeywords.robot index ebe41e16e7..8f8305a33e 100644 --- a/csit/libraries/MininetKeywords.robot +++ b/csit/libraries/MininetKeywords.robot @@ -1,48 +1,52 @@ *** Settings *** -Documentation Mininet library. This library is useful for tests using mininet tool to simulate devices. -Library SSHLibrary -Resource SSHKeywords.robot -Resource Utils.robot -Resource OVSDB.robot -Resource ClusterManagement.robot -Variables ../variables/Variables.py +Documentation Mininet library. This library is useful for tests using mininet tool to simulate devices. + +Library SSHLibrary +Resource SSHKeywords.robot +Resource Utils.robot +Resource OVSDB.robot +Resource ClusterManagement.robot +Variables ../variables/Variables.py + *** Variables *** -${switch_private_key} switch.key -${switch_certificate} switch.crt -${controller_ca_list} cachain.crt -${topology_file} create_fullymesh.py -${topology_file_path} MininetTopo/${topology_file} +${switch_private_key} switch.key +${switch_certificate} switch.crt +${controller_ca_list} cachain.crt +${topology_file} create_fullymesh.py +${topology_file_path} MininetTopo/${topology_file} + *** Keywords *** Start Mininet Single Controller + [Documentation] Start Mininet with custom topology and connect to controller. [Arguments] ${mininet}=${TOOLS_SYSTEM_IP} ${controller}=${ODL_SYSTEM_IP} ${options}=--topo tree,1 ${custom}=${EMPTY} ${ofversion}=13 ${ofport}=${ODL_OF_PORT} ... ${timeout}=${DEFAULT_TIMEOUT} - [Documentation] Start Mininet with custom topology and connect to controller. Log Clear any existing mininet Utils.Clean Mininet System ${mininet} ${mininet_conn_id}= SSHKeywords.Open_Connection_To_Tools_System ip_address=${mininet} timeout=${timeout} Set Suite Variable ${mininet_conn_id} - Run Keyword If '${custom}' != '${EMPTY}' Put File ${custom} + IF '${custom}' != '${EMPTY}' Put File ${custom} Log Start mininet ${options} to ${controller} - SSHLibrary.Write sudo mn --controller 'remote,ip=${controller},port=${ofport}' ${options} --switch ovsk,protocols=OpenFlow${ofversion} + SSHLibrary.Write + ... sudo mn --controller 'remote,ip=${controller},port=${ofport}' ${options} --switch ovsk,protocols=OpenFlow${ofversion} SSHLibrary.Read Until mininet> Log Check OVS configuratiom SSHLibrary.Write sh ovs-vsctl show SSHLibrary.Read Until mininet> - [Return] ${mininet_conn_id} + RETURN ${mininet_conn_id} Start Mininet Multiple Controllers + [Documentation] Start Mininet with custom topology and connect to list of controllers in ${controller_index_list} or all if no list is provided. [Arguments] ${mininet}=${TOOLS_SYSTEM_IP} ${controller_index_list}=${EMPTY} ${options}=--topo tree,1 ${custom}=${EMPTY} ${ofversion}=13 ${ofport}=${ODL_OF_PORT} ... ${protocol}=tcp ${timeout}=${DEFAULT_TIMEOUT} - [Documentation] Start Mininet with custom topology and connect to list of controllers in ${controller_index_list} or all if no list is provided. - ${index_list} = ClusterManagement.List Indices Or All given_list=${controller_index_list} + ${index_list}= ClusterManagement.List Indices Or All given_list=${controller_index_list} Log Clear any existing mininet Utils.Clean Mininet System ${mininet} ${mininet_conn_id}= SSHKeywords.Open_Connection_To_Tools_System ip_address=${mininet} timeout=${timeout} Set Suite Variable ${mininet_conn_id} - Run Keyword If '${custom}' != '${EMPTY}' Put File ${custom} - Run Keyword If '${protocol}' == 'ssl' Install Certificates In Mininet + IF '${custom}' != '${EMPTY}' Put File ${custom} + IF '${protocol}' == 'ssl' Install Certificates In Mininet Log Start mininet ${options} SSHLibrary.Write sudo mn ${options} SSHLibrary.Read Until mininet> @@ -54,12 +58,14 @@ Start Mininet Multiple Controllers END Log Open extra SSH connection to configure the OVS bridges SSHKeywords.Open_Connection_To_Tools_System ip_address=${mininet} timeout=${timeout} - ${num_bridges} SSHLibrary.Execute Command sudo ovs-vsctl show | grep Bridge | wc -l + ${num_bridges}= SSHLibrary.Execute Command sudo ovs-vsctl show | grep Bridge | wc -l ${num_bridges}= Convert To Integer ${num_bridges} ${bridges}= Create List FOR ${i} IN RANGE 1 ${num_bridges+1} - ${bridge}= SSHLibrary.Execute Command sudo ovs-vsctl show | grep Bridge | cut -c 12- | sort | head -${i} | tail -1 - SSHLibrary.Execute Command sudo ovs-vsctl del-controller ${bridge} && sudo ovs-vsctl set bridge ${bridge} protocols=OpenFlow${ofversion} + ${bridge}= SSHLibrary.Execute Command + ... sudo ovs-vsctl show | grep Bridge | cut -c 12- | sort | head -${i} | tail -1 + SSHLibrary.Execute Command + ... sudo ovs-vsctl del-controller ${bridge} && sudo ovs-vsctl set bridge ${bridge} protocols=OpenFlow${ofversion} Collections.Append To List ${bridges} ${bridge} END Log Configure OVS controllers ${controller_opt} in all bridges @@ -70,25 +76,36 @@ Start Mininet Multiple Controllers ${output}= SSHLibrary.Execute Command sudo ovs-vsctl show Log ${output} SSHLibrary.Close Connection - [Return] ${mininet_conn_id} + RETURN ${mininet_conn_id} Start Mininet Multiple Hosts - [Arguments] ${hosts} ${mininet}=${TOOLS_SYSTEM_IP} ${controller}=${ODL_SYSTEM_IP} ${ofversion}=13 ${ofport}=${ODL_OF_PORT} ${mininet_timeout}=${DEFAULT_TIMEOUT} [Documentation] Start mininet 1 switch with ${hosts} hosts attached. + [Arguments] ${hosts} ${mininet}=${TOOLS_SYSTEM_IP} ${controller}=${ODL_SYSTEM_IP} ${ofversion}=13 ${ofport}=${ODL_OF_PORT} ${mininet_timeout}=${DEFAULT_TIMEOUT} Log Start Mininet Linear - MininetKeywords.StartMininet Single Controller options=--topo single,${hosts} --mac ofversion=${ofversion} ofport=${ofport} timeout=${mininet_timeout} + MininetKeywords.StartMininet Single Controller + ... options=--topo single,${hosts} --mac + ... ofversion=${ofversion} + ... ofport=${ofport} + ... timeout=${mininet_timeout} Start Mininet Linear - [Arguments] ${switches} ${mininet}=${TOOLS_SYSTEM_IP} ${controller}=${ODL_SYSTEM_IP} ${ofversion}=13 ${ofport}=${ODL_OF_PORT} ${mininet_timeout}=${DEFAULT_TIMEOUT} [Documentation] Start mininet linear topology with ${switches} nodes. + [Arguments] ${switches} ${mininet}=${TOOLS_SYSTEM_IP} ${controller}=${ODL_SYSTEM_IP} ${ofversion}=13 ${ofport}=${ODL_OF_PORT} ${mininet_timeout}=${DEFAULT_TIMEOUT} Log Start Mininet Linear - MininetKeywords.StartMininet Single Controller options=--topo linear,${switches} ofversion=${ofversion} ofport=${ofport} timeout=${mininet_timeout} + MininetKeywords.StartMininet Single Controller + ... options=--topo linear,${switches} + ... ofversion=${ofversion} + ... ofport=${ofport} + ... timeout=${mininet_timeout} Start Mininet Full Mesh + [Documentation] Start a custom mininet topology. [Arguments] ${switches} ${mininet}=${TOOLS_SYSTEM_IP} ${controller}=${ODL_SYSTEM_IP} ${ofversion}=13 ${ofport}=${ODL_OF_PORT} ${hosts}=0 ... ${mininet_timeout}=${DEFAULT_TIMEOUT} - [Documentation] Start a custom mininet topology. - ${mininet_conn_id}= SSHLibrary.Open Connection ${mininet} prompt=${TOOLS_SYSTEM_PROMPT} timeout=${mininet_timeout} + ${mininet_conn_id}= SSHLibrary.Open Connection + ... ${mininet} + ... prompt=${TOOLS_SYSTEM_PROMPT} + ... timeout=${mininet_timeout} Set Suite Variable ${mininet_conn_id} SSHKeywords.Flexible_Mininet_Login Log Copying ${topology_file_path} file to Mininet VM and Creating Full Mesh topology @@ -96,7 +113,8 @@ Start Mininet Full Mesh SSHLibrary.Write python ${topology_file} ${switches} ${hosts} 00:00:00:00:00:00 10.0.0.0 SSHLibrary.Read Until ${TOOLS_SYSTEM_PROMPT} Log Start Mininet Full Mesh - SSHLibrary.Write sudo mn --controller=remote,ip=${controller},port=${ofport} --custom switch.py --topo demotopo --switch ovsk,protocols=OpenFlow${ofversion} + SSHLibrary.Write + ... sudo mn --controller=remote,ip=${controller},port=${ofport} --custom switch.py --topo demotopo --switch ovsk,protocols=OpenFlow${ofversion} SSHLibrary.Read Until mininet> Log Check OVS configuratiom SSHLibrary.Write sh ovs-vsctl show @@ -105,101 +123,116 @@ Start Mininet Full Mesh Should Not Contain ${output} database connection failed Send Mininet Command - [Arguments] ${mininet_conn}=${EMPTY} ${cmd}=help [Documentation] Sends Command ${cmd} to Mininet session ${mininet_conn} and returns read buffer response. - Run Keyword If """${mininet_conn}""" != "" SSHLibrary.Switch Connection ${mininet_conn} + [Arguments] ${mininet_conn}=${EMPTY} ${cmd}=help + IF """${mininet_conn}""" != "" + SSHLibrary.Switch Connection ${mininet_conn} + END SSHLibrary.Write ${cmd} ${output}= SSHLibrary.Read Until mininet> - [Return] ${output} + RETURN ${output} Send Mininet Command Multiple Sessions - [Arguments] ${mininet_conn_list} ${cmd}=help [Documentation] Sends Command ${cmd} to Mininet sessions in ${mininet_conn_list} and returns list of read buffer responses. + [Arguments] ${mininet_conn_list} ${cmd}=help ${output_list}= Create List FOR ${mininet_conn} IN @{mininet_conn_list} ${output}= Utils.Send Mininet Command ${mininet_conn} ${cmd} Collections.Append To List ${output_list} ${output} END - [Return] ${output_list} + RETURN ${output_list} Stop Mininet And Exit - [Arguments] ${mininet_conn}=${EMPTY} [Documentation] Stops Mininet and exits session ${mininet_conn} - Run Keyword If """${mininet_conn}""" != "" SSHLibrary.Switch Connection ${mininet_conn} + [Arguments] ${mininet_conn}=${EMPTY} + IF """${mininet_conn}""" != "" + SSHLibrary.Switch Connection ${mininet_conn} + END SSHLibrary.Write exit SSHLibrary.Read Until ${TOOLS_SYSTEM_PROMPT} SSHLibrary.Close Connection Stop Mininet And Exit Multiple Sessions - [Arguments] ${mininet_conn_list} [Documentation] Stops Mininet and exits sessions in ${mininet_conn_list}. + [Arguments] ${mininet_conn_list} FOR ${mininet_conn} IN @{mininet_conn_list} MininetKeywords.Stop Mininet And Exit ${mininet_conn} END Disconnect Cluster Mininet - [Arguments] ${action}=break ${member_index_list}=${EMPTY} [Documentation] Break and restore controller to mininet connection via iptables. - ${index_list} = ClusterManagement.List_Indices_Or_All given_list=${member_index_list} + [Arguments] ${action}=break ${member_index_list}=${EMPTY} + ${index_list}= ClusterManagement.List_Indices_Or_All given_list=${member_index_list} FOR ${index} IN @{index_list} - ${rule} = BuiltIn.Set Variable OUTPUT -p all --source ${ODL_SYSTEM_${index}_IP} --destination ${TOOLS_SYSTEM_IP} -j DROP - ${command} = BuiltIn.Set Variable If '${action}'=='restore' sudo /sbin/iptables -D ${rule} sudo /sbin/iptables -I ${rule} + ${rule}= BuiltIn.Set Variable + ... OUTPUT -p all --source ${ODL_SYSTEM_${index}_IP} --destination ${TOOLS_SYSTEM_IP} -j DROP + ${command}= BuiltIn.Set Variable If + ... '${action}'=='restore' + ... sudo /sbin/iptables -D ${rule} + ... sudo /sbin/iptables -I ${rule} Log To Console ${ODL_SYSTEM_${index}_IP} Utils.Run Command On Controller ${ODL_SYSTEM_${index}_IP} cmd=${command} - ${command} = BuiltIn.Set Variable sudo /sbin/iptables -L -n - ${output} = Utils.Run Command On Controller cmd=${command} + ${command}= BuiltIn.Set Variable sudo /sbin/iptables -L -n + ${output}= Utils.Run Command On Controller cmd=${command} BuiltIn.Log ${output} END Verify Aggregate Flow From Mininet Session - [Arguments] ${mininet_conn}=${EMPTY} ${flow_count}=0 ${time_out}=0s [Documentation] Verify flow count per switch - Wait Until Keyword Succeeds ${time_out} 2s MininetKeywords.Check Flows In Mininet ${mininet_conn} ${flow_count} + [Arguments] ${mininet_conn}=${EMPTY} ${flow_count}=0 ${time_out}=0s + Wait Until Keyword Succeeds + ... ${time_out} + ... 2s + ... MininetKeywords.Check Flows In Mininet + ... ${mininet_conn} + ... ${flow_count} Check Flows In Mininet - [Arguments] ${mininet_conn}=${EMPTY} ${flow_count}=0 [Documentation] Sync with mininet to match exact number of flows - Run Keyword If """${mininet_conn}""" != "" SSHLibrary.Switch Connection ${mininet_conn} - ${cmd} = Set Variable dpctl dump-aggregate -O OpenFlow13 + [Arguments] ${mininet_conn}=${EMPTY} ${flow_count}=0 + IF """${mininet_conn}""" != "" + SSHLibrary.Switch Connection ${mininet_conn} + END + ${cmd}= Set Variable dpctl dump-aggregate -O OpenFlow13 ${output}= MininetKeywords.Send Mininet Command ${mininet_conn} ${cmd} ${flows}= String.Get RegExp Matches ${output} (?<=flow_count\=).*?(?=\r) ${total_flows}= BuiltIn.Evaluate sum(map(int, ${flows})) Should Be Equal As Numbers ${total_flows} ${flow_count} Verify Mininet Ping - [Arguments] ${host1} ${host2} [Documentation] Send ping from mininet and verify connectivity. + [Arguments] ${host1} ${host2} SSHLibrary.Write ${host1} ping -w 3 ${host2} ${result}= SSHLibrary.Read Until mininet> Should Contain ${result} 64 bytes Verify Mininet No Ping - [Arguments] ${host1} ${host2} [Documentation] Send ping from mininet and verify no conectivity. + [Arguments] ${host1} ${host2} SSHLibrary.Write ${host1} ping -w 3 ${host2} ${result}= SSHLibrary.Read Until mininet> Should Contain ${result} 100% packet loss Ping All Hosts - [Arguments] @{host_list} [Documentation] Do one round of ping from one host to all other hosts in mininet. ... Note that a single ping failure will exit the loop and return a non zero value. + [Arguments] @{host_list} ${source}= Get From List ${host_list} ${0} FOR ${h} IN @{host_list} ${status}= Ping Two Hosts ${source} ${h} 1 - Exit For Loop If ${status}!=${0} + IF ${status}!=${0} BREAK END - [Return] ${status} + RETURN ${status} Ping Two Hosts - [Arguments] ${host1} ${host2} ${pingcount}=2 [Documentation] Ping between mininet hosts. Must be used only after a mininet session is in place. ... Returns non zero value if there is 100% packet loss. + [Arguments] ${host1} ${host2} ${pingcount}=2 SSHLibrary.Write ${host1} ping -c ${pingcount} ${host2} ${out}= SSHLibrary.Read Until mininet> ${ret}= String.Get Lines Matching Regexp ${out} .*100% packet loss.* ${len}= Get Length ${ret} - [Return] ${len} + RETURN ${len} Get Mininet Hosts [Documentation] Get all the hosts from mininet @@ -209,9 +242,11 @@ Get Mininet Hosts @{words}= String.Split String ${out} ${SPACE} FOR ${item} IN @{words} ${h}= String.Get Lines Matching Regexp ${item} h[0-9]* - Run Keyword If '${h}' != '${EMPTY}' Collections.Append To List ${host_list} ${h} + IF '${h}' != '${EMPTY}' + Collections.Append To List ${host_list} ${h} + END END - [Return] ${host_list} + RETURN ${host_list} Install Certificates In Mininet [Documentation] Copy and install certificates in simulator. @@ -220,7 +255,9 @@ Install Certificates In Mininet SSHLibrary.Put File ${CURDIR}/tls/${switch_certificate} . SSHLibrary.Put File ${CURDIR}/tls/${controller_ca_list} . Comment Install Certificates - SSHLibrary.Execute Command sudo mv ${switch_private_key} /etc/openvswitch && sudo mv ${switch_certificate} /etc/openvswitch && sudo mv ${controller_ca_list} /etc/openvswitch - SSHLibrary.Execute Command sudo ovs-vsctl set-ssl /etc/openvswitch/${switch_private_key} /etc/openvswitch/${switch_certificate} /etc/openvswitch/${controller_ca_list} + SSHLibrary.Execute Command + ... sudo mv ${switch_private_key} /etc/openvswitch && sudo mv ${switch_certificate} /etc/openvswitch && sudo mv ${controller_ca_list} /etc/openvswitch + SSHLibrary.Execute Command + ... sudo ovs-vsctl set-ssl /etc/openvswitch/${switch_private_key} /etc/openvswitch/${switch_certificate} /etc/openvswitch/${controller_ca_list} ${std_out}= SSHLibrary.Execute Command sudo ovs-vsctl get-ssl Log ${std_out} diff --git a/csit/libraries/NetconfCallHome.robot b/csit/libraries/NetconfCallHome.robot index 48233be4f0..af86f10ec5 100644 --- a/csit/libraries/NetconfCallHome.robot +++ b/csit/libraries/NetconfCallHome.robot @@ -1,26 +1,30 @@ *** Settings *** -Library SSHLibrary -Library RequestsLibrary -Resource SSHKeywords.robot -Resource ../variables/Variables.robot +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 -${global_config_url} /restconf/config/odl-netconf-callhome-server:netconf-callhome-server/global/credentials -${netconf_keystore_url} /rests/operations/netconf-keystore +${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 +${global_config_url} /restconf/config/odl-netconf-callhome-server:netconf-callhome-server/global/credentials +${netconf_keystore_url} /rests/operations/netconf-keystore ${netconf_keystore_data_url} /rests/data/netconf-keystore:keystore -${substring1} "netconf-node-topology:connection-status":"connected" -${substring2} "node-id":"netopeer2" -${substring3} "netconf-node-topology:available-capabilities" +${substring1} "netconf-node-topology:connection-status":"connected" +${substring2} "node-id":"netopeer2" +${substring3} "netconf-node-topology:available-capabilities" + *** Keywords *** Check Device status - [Arguments] ${status} ${id}=netopeer2 [Documentation] Checks the operational device status. + [Arguments] ${status} ${id}=netopeer2 @{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}" + IF '${status}'=='FAILED_NOT_ALLOWED' or '${status}'=='FAILED_AUTH_FAILURE' + Remove Values From List ${expectedValues} "unique-id":"${id}" + END Utils.Check For Elements At URI ${device_status} ${expectedValues} Apply SSH-based Call-Home configuration @@ -45,41 +49,73 @@ Generate certificates for TLS configuration ${stdout} SSHLibrary.Execute Command rm -rf ./certs && mkdir ./certs SSHLibrary.Put File ${CURDIR}/../variables/netconf/callhome/x509_v3.cfg ./x509_v3.cfg ${stdout} SSHLibrary.Execute Command openssl genrsa -out ./certs/ca.key 2048 - ${stdout} SSHLibrary.Execute Command openssl req -x509 -new -extensions v3_ca -nodes -key ./certs/ca.key -sha256 -days 365 -subj "/C=US/ST=CA/L=Netopeer/O=netopeerCA/CN=netopeerCA" -out ./certs/ca.pem + ${stdout} SSHLibrary.Execute Command + ... openssl req -x509 -new -extensions v3_ca -nodes -key ./certs/ca.key -sha256 -days 365 -subj "/C=US/ST=CA/L=Netopeer/O=netopeerCA/CN=netopeerCA" -out ./certs/ca.pem ${stdout} SSHLibrary.Execute Command openssl genrsa -out ./certs/server.key 2048 - ${stdout} SSHLibrary.Execute Command openssl req -new -sha256 -key ./certs/server.key -subj "/C=US/ST=CA/L=Netopeer/O=Netopeer2/CN=netopeer2-server" -out ./certs/server.csr - ${stdout} SSHLibrary.Execute Command openssl x509 -req -in ./certs/server.csr -CA ./certs/ca.pem -CAkey ./certs/ca.key -CAcreateserial -extfile x509_v3.cfg -out ./certs/server.crt -days 365 -sha256 + ${stdout} SSHLibrary.Execute Command + ... openssl req -new -sha256 -key ./certs/server.key -subj "/C=US/ST=CA/L=Netopeer/O=Netopeer2/CN=netopeer2-server" -out ./certs/server.csr + ${stdout} SSHLibrary.Execute Command + ... openssl x509 -req -in ./certs/server.csr -CA ./certs/ca.pem -CAkey ./certs/ca.key -CAcreateserial -extfile x509_v3.cfg -out ./certs/server.crt -days 365 -sha256 ${stdout} SSHLibrary.Execute Command openssl rsa -in ./certs/server.key -pubout > ./certs/server.pub ${stdout} SSHLibrary.Execute Command openssl genrsa -out ./certs/client.key 2048 - ${stdout} SSHLibrary.Execute Command openssl req -new -sha256 -key ./certs/client.key -subj "/C=US/ST=CA/L=Netopeer/O=Netopeer2/CN=netopeer2-client" -out ./certs/client.csr - ${stdout} SSHLibrary.Execute Command openssl x509 -req -in ./certs/client.csr -CA ./certs/ca.pem -CAkey ./certs/ca.key -CAcreateserial -extfile x509_v3.cfg -out ./certs/client.crt -days 1024 -sha256 + ${stdout} SSHLibrary.Execute Command + ... openssl req -new -sha256 -key ./certs/client.key -subj "/C=US/ST=CA/L=Netopeer/O=Netopeer2/CN=netopeer2-client" -out ./certs/client.csr + ${stdout} SSHLibrary.Execute Command + ... openssl x509 -req -in ./certs/client.csr -CA ./certs/ca.pem -CAkey ./certs/ca.key -CAcreateserial -extfile x509_v3.cfg -out ./certs/client.crt -days 1024 -sha256 ${stdout} SSHLibrary.Execute Command mv ./certs ./configuration-files/certs Register keys and certificates in ODL controller [Documentation] Register pre-configured netopeer2 certificates and key in ODL-netconf keystore - ${base64-client-key} ${stderr} SSHLibrary.Execute_Command openssl enc -base64 -A -in ./configuration-files/certs/client.key return_stdout=True return_stderr=True + ${base64-client-key} ${stderr} SSHLibrary.Execute_Command + ... openssl enc -base64 -A -in ./configuration-files/certs/client.key + ... return_stdout=True + ... return_stderr=True ${template} OperatingSystem.Get File ${ADD_KEYSTORE_ENTRY_REQ} ${body} Replace String ${template} {base64-client-key} ${base64-client-key} - ${resp} RequestsLibrary.Post Request session ${netconf_keystore_url}:add-keystore-entry data=${body} headers=${HEADERS} + ${resp} RequestsLibrary.Post Request + ... session + ... ${netconf_keystore_url}:add-keystore-entry + ... data=${body} + ... headers=${HEADERS} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} - ${client-key} ${stderr} SSHLibrary.Execute_Command sed -u '1d; $d' ./configuration-files/certs/client.key | sed -z 's!\\n!\\\\n!g' return_stdout=True return_stderr=True - ${certificate-chain} ${stderr} SSHLibrary.Execute_Command sed -u '1d; $d' ./configuration-files/certs/client.crt | sed -z 's!\\n!\\\\n!g' return_stdout=True return_stderr=True + ${client-key} ${stderr} SSHLibrary.Execute_Command + ... sed -u '1d; $d' ./configuration-files/certs/client.key | sed -z 's!\\n!\\\\n!g' + ... return_stdout=True + ... return_stderr=True + ${certificate-chain} ${stderr} SSHLibrary.Execute_Command + ... sed -u '1d; $d' ./configuration-files/certs/client.crt | sed -z 's!\\n!\\\\n!g' + ... return_stdout=True + ... return_stderr=True ${template} OperatingSystem.Get File ${ADD_PRIVATE_KEY_REQ} ${body} Replace String ${template} {client-key} ${client-key} ${body} Replace String ${body} {certificate-chain} ${certificate-chain} - ${resp} RequestsLibrary.Post Request session ${netconf_keystore_url}:add-private-key data=${body} headers=${HEADERS} + ${resp} RequestsLibrary.Post Request + ... session + ... ${netconf_keystore_url}:add-private-key + ... data=${body} + ... headers=${HEADERS} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} - ${ca-certificate} ${stderr} SSHLibrary.Execute_Command sed -u '1d; $d' ./configuration-files/certs/ca.pem | sed -z 's!\\n!\\\\n!g' return_stdout=True return_stderr=True - ${device-certificate} ${stderr} SSHLibrary.Execute_Command sed -u '1d; $d' ./configuration-files/certs/server.crt | sed -z 's!\\n!\\\\n!g' return_stdout=True return_stderr=True + ${ca-certificate} ${stderr} SSHLibrary.Execute_Command + ... sed -u '1d; $d' ./configuration-files/certs/ca.pem | sed -z 's!\\n!\\\\n!g' + ... return_stdout=True + ... return_stderr=True + ${device-certificate} ${stderr} SSHLibrary.Execute_Command + ... sed -u '1d; $d' ./configuration-files/certs/server.crt | sed -z 's!\\n!\\\\n!g' + ... return_stdout=True + ... return_stderr=True ${template} OperatingSystem.Get File ${ADD_TRUSTED_CERTIFICATE} ${body} Replace String ${template} {ca-certificate} ${ca-certificate} ${body} Replace String ${body} {device-certificate} ${device-certificate} - ${resp} RequestsLibrary.Post Request session ${netconf_keystore_url}:add-trusted-certificate data=${body} headers=${HEADERS} + ${resp} RequestsLibrary.Post Request + ... session + ... ${netconf_keystore_url}:add-trusted-certificate + ... data=${body} + ... headers=${HEADERS} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Register global credentials for SSH call-home devices (APIv1) - [Arguments] ${username} ${password} [Documentation] Set global credentials for SSH call-home devices + [Arguments] ${username} ${password} ${template} OperatingSystem.Get File ${CREATE_GLOBAL_CREDENTIALS_REQ} ${body} Replace String ${template} {username} ${username} ${body} Replace String ${body} {password} ${password} @@ -87,10 +123,13 @@ Register global credentials for SSH call-home devices (APIv1) Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Register SSH call-home device in ODL controller (APIv1) - [Arguments] ${device_name} ${hostkey} ${username}=${EMPTY} ${password}=${EMPTY} [Documentation] Registration call-home device with SSH transport - Run Keyword If '${username}' == '${EMPTY}' or '${password}' == '${EMPTY}' Get create device request without credentials template (APIv1) - ... ELSE Get create device request template (APIv1) + [Arguments] ${device_name} ${hostkey} ${username}=${EMPTY} ${password}=${EMPTY} + IF '${username}' == '${EMPTY}' or '${password}' == '${EMPTY}' + Get create device request without credentials template (APIv1) + ELSE + Get create device request template (APIv1) + END ${body} Replace String ${template} {device_name} ${device_name} ${body} Replace String ${body} {username} ${username} ${body} Replace String ${body} {password} ${password} @@ -107,10 +146,13 @@ Get create device request without credentials template (APIv1) Set Test Variable ${template} Register SSH call-home device in ODL controller (APIv2) - [Arguments] ${device_name} ${hostkey} ${username}=${EMPTY} ${password}=${EMPTY} [Documentation] Registration call-home device with SSH transport using latest models - Run Keyword If '${username}' == '${EMPTY}' or '${password}' == '${EMPTY}' Get create device request without credentials template (APIv2) - ... ELSE Get create device request template (APIv2) + [Arguments] ${device_name} ${hostkey} ${username}=${EMPTY} ${password}=${EMPTY} + IF '${username}' == '${EMPTY}' or '${password}' == '${EMPTY}' + Get create device request without credentials template (APIv2) + ELSE + Get create device request template (APIv2) + END ${body} Replace String ${template} {device_name} ${device_name} ${body} Replace String ${body} {username} ${username} ${body} Replace String ${body} {password} ${password} @@ -127,8 +169,8 @@ Get create device request without credentials template (APIv2) Set Test Variable ${template} Register TLS call-home device in ODL controller (APIv2) - [Arguments] ${device_name} ${key_id} ${certificate_id} [Documentation] Registration call-home device with TLS transport + [Arguments] ${device_name} ${key_id} ${certificate_id} ${template} OperatingSystem.Get File ${CREATE_TLS_DEVICE_REQ} ${body} Replace String ${template} {device_name} ${device_name} ${body} Replace String ${body} {key_id} ${key_id} @@ -138,23 +180,36 @@ Register TLS call-home device in ODL controller (APIv2) Pull Netopeer2 Docker Image [Documentation] Pulls the netopeer image from the docker repository. - ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker pull sysrepo/sysrepo-netopeer2:latest return_stdout=True return_stderr=True + ${stdout} ${stderr} ${rc} SSHLibrary.Execute Command + ... docker pull sysrepo/sysrepo-netopeer2:latest + ... return_stdout=True + ... return_stderr=True ... return_rc=True - ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker images return_stdout=True return_stderr=True + ${stdout} ${stderr} ${rc} SSHLibrary.Execute Command + ... docker images + ... return_stdout=True + ... return_stderr=True ... return_rc=True Install Docker Compose on tools system [Documentation] Install docker-compose on tools system. - ${netopeer_conn_id} = SSHKeywords.Open_Connection_To_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 + 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 + ${stdout} ${stderr} ${rc} SSHLibrary.Execute Command + ... pip uninstall docker-compose + ... return_stdout=True + ... return_stderr=True ... return_rc=True Test Setup @@ -167,16 +222,25 @@ Test Setup Test Teardown [Documentation] Tears down the docker running netopeer and deletes entry from the whitelist. - ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker-compose logs return_stdout=True return_stderr=True + ${stdout} ${stderr} ${rc} SSHLibrary.Execute Command + ... docker-compose logs + ... return_stdout=True + ... return_stderr=True ... return_rc=True Log ${stdout} - ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command docker-compose down return_stdout=True return_stderr=True + ${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 + ${stdout} ${stderr} ${rc} SSHLibrary.Execute Command + ... docker ps -a + ... return_stdout=True + ... return_stderr=True ... return_rc=True SSHLibrary.Execute_Command rm -rf ./configuration-files - ${resp} = RequestsLibrary.Delete_Request session ${whitelist} - ${resp} = RequestsLibrary.Delete_Request session ${netconf_keystore_data_url} + ${resp} RequestsLibrary.Delete_Request session ${whitelist} + ${resp} RequestsLibrary.Delete_Request session ${netconf_keystore_data_url} Suite Setup [Documentation] Get the suite ready for callhome test cases. @@ -190,15 +254,33 @@ Suite Setup SSHLibrary.Execute_Command sed -i -e 's/NETCONF_CH_TLS/4335/g' docker-compose.yaml ${netconf_mount_expected_values} Create list ${substring1} ${substring2} ${substring3} Set Suite Variable ${netconf_mount_expected_values} - Set Suite Variable ${CREATE_SSH_DEVICE_REQ_V1} ${CURDIR}/../variables/netconf/callhome/json/apiv1/create_device.json - Set Suite Variable ${CREATE_SSH_DEVICE_REQ_V1_HOST_KEY_ONLY} ${CURDIR}/../variables/netconf/callhome/json/apiv1/create_device_hostkey_only.json - Set Suite Variable ${CREATE_GLOBAL_CREDENTIALS_REQ} ${CURDIR}/../variables/netconf/callhome/json/apiv1/create_global_credentials.json - Set Suite Variable ${CREATE_SSH_DEVICE_REQ_V2} ${CURDIR}/../variables/netconf/callhome/json/apiv2/create_ssh_device.json - Set Suite Variable ${CREATE_SSH_DEVICE_REQ_V2_HOST_KEY_ONLY} ${CURDIR}/../variables/netconf/callhome/json/apiv2/create_device_hostkey_only.json - Set Suite Variable ${CREATE_TLS_DEVICE_REQ} ${CURDIR}/../variables/netconf/callhome/json/apiv2/create_tls_device.json - Set Suite Variable ${ADD_KEYSTORE_ENTRY_REQ} ${CURDIR}/../variables/netconf/callhome/json/apiv2/add_keystore_entry.json - Set Suite Variable ${ADD_PRIVATE_KEY_REQ} ${CURDIR}/../variables/netconf/callhome/json/apiv2/add_private_key.json - Set Suite Variable ${ADD_TRUSTED_CERTIFICATE} ${CURDIR}/../variables/netconf/callhome/json/apiv2/add_trusted_certificate.json + Set Suite Variable + ... ${CREATE_SSH_DEVICE_REQ_V1} + ... ${CURDIR}/../variables/netconf/callhome/json/apiv1/create_device.json + Set Suite Variable + ... ${CREATE_SSH_DEVICE_REQ_V1_HOST_KEY_ONLY} + ... ${CURDIR}/../variables/netconf/callhome/json/apiv1/create_device_hostkey_only.json + Set Suite Variable + ... ${CREATE_GLOBAL_CREDENTIALS_REQ} + ... ${CURDIR}/../variables/netconf/callhome/json/apiv1/create_global_credentials.json + Set Suite Variable + ... ${CREATE_SSH_DEVICE_REQ_V2} + ... ${CURDIR}/../variables/netconf/callhome/json/apiv2/create_ssh_device.json + Set Suite Variable + ... ${CREATE_SSH_DEVICE_REQ_V2_HOST_KEY_ONLY} + ... ${CURDIR}/../variables/netconf/callhome/json/apiv2/create_device_hostkey_only.json + Set Suite Variable + ... ${CREATE_TLS_DEVICE_REQ} + ... ${CURDIR}/../variables/netconf/callhome/json/apiv2/create_tls_device.json + Set Suite Variable + ... ${ADD_KEYSTORE_ENTRY_REQ} + ... ${CURDIR}/../variables/netconf/callhome/json/apiv2/add_keystore_entry.json + Set Suite Variable + ... ${ADD_PRIVATE_KEY_REQ} + ... ${CURDIR}/../variables/netconf/callhome/json/apiv2/add_private_key.json + Set Suite Variable + ... ${ADD_TRUSTED_CERTIFICATE} + ... ${CURDIR}/../variables/netconf/callhome/json/apiv2/add_trusted_certificate.json Suite Teardown [Documentation] Tearing down the setup. diff --git a/csit/libraries/NetconfKeywords.robot b/csit/libraries/NetconfKeywords.robot index 868d09f6e0..c4887a0c82 100644 --- a/csit/libraries/NetconfKeywords.robot +++ b/csit/libraries/NetconfKeywords.robot @@ -1,153 +1,195 @@ *** Settings *** -Documentation Perform complex operations on netconf. +Documentation Perform complex operations on netconf. ... -... Copyright (c) 2015,2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2015,2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... This library encapsulates a bunch of somewhat complex and commonly used -... netconf operations into reusable keywords to make writing netconf -... test suites easier. +... This library encapsulates a bunch of somewhat complex and commonly used +... netconf operations into reusable keywords to make writing netconf +... test suites easier. ... -... TODO: RemoteBash.robot contains logic which could be reused here. -Library Collections -Library DateTime -Library RequestsLibrary -Library SSHLibrary -Resource NexusKeywords.robot -Resource Restconf.robot -Resource SSHKeywords.robot -Resource TemplatedRequests.robot -Resource Utils.robot -Resource RemoteBash.robot +... TODO: RemoteBash.robot contains logic which could be reused here. + +Library Collections +Library DateTime +Library RequestsLibrary +Library SSHLibrary +Resource NexusKeywords.robot +Resource Restconf.robot +Resource SSHKeywords.robot +Resource TemplatedRequests.robot +Resource Utils.robot +Resource RemoteBash.robot + *** Variables *** -${MAX_HEAP} 1G -${TESTTOOL_DEFAULT_JAVA_OPTIONS} -Xmx${MAX_HEAP} -Djava.security.egd=file:/dev/./urandom -${DIRECTORY_WITH_DEVICE_TEMPLATES} ${CURDIR}/../variables/netconf/device -${FIRST_TESTTOOL_PORT} 17830 -${BASE_NETCONF_DEVICE_PORT} 17830 -${DEVICE_NAME_BASE} netconf-scaling-device -${TESTTOOL_BOOT_TIMEOUT} 60s -${ENABLE_NETCONF_TEST_TIMEOUT} ${ENABLE_GLOBAL_TEST_DEADLINES} -${SSE_CFG_FILE} ${WORKSPACE}/${BUNDLEFOLDER}/etc/org.opendaylight.restconf.nb.rfc8040.cfg +${MAX_HEAP} 1G +${TESTTOOL_DEFAULT_JAVA_OPTIONS} -Xmx${MAX_HEAP} -Djava.security.egd=file:/dev/./urandom +${DIRECTORY_WITH_DEVICE_TEMPLATES} ${CURDIR}/../variables/netconf/device +${FIRST_TESTTOOL_PORT} 17830 +${BASE_NETCONF_DEVICE_PORT} 17830 +${DEVICE_NAME_BASE} netconf-scaling-device +${TESTTOOL_BOOT_TIMEOUT} 60s +${ENABLE_NETCONF_TEST_TIMEOUT} ${ENABLE_GLOBAL_TEST_DEADLINES} +${SSE_CFG_FILE} ${WORKSPACE}/${BUNDLEFOLDER}/etc/org.opendaylight.restconf.nb.rfc8040.cfg + *** Keywords *** Setup_NetconfKeywords - [Arguments] ${create_session_for_templated_requests}=True [Documentation] Setup the environment for the other keywords of this Resource to work properly. + [Arguments] ${create_session_for_templated_requests}=True ${tmp}= BuiltIn.Create_Dictionary BuiltIn.Set_Suite_Variable ${NetconfKeywords__mounted_device_types} ${tmp} - BuiltIn.Run_Keyword_If ${create_session_for_templated_requests} TemplatedRequests.Create_Default_Session timeout=2 + IF ${create_session_for_templated_requests} + TemplatedRequests.Create_Default_Session timeout=2 + END NexusKeywords.Initialize_Artifact_Deployment_And_Usage Configure_Device_In_Netconf + [Documentation] Tell Netconf about the specified device so it can add it into its configuration. [Arguments] ${device_name} ${device_type}=default ${device_port}=${FIRST_TESTTOOL_PORT} ${device_address}=${TOOLS_SYSTEM_IP} ${device_user}=admin ${device_password}=topsecret ... ${device_key}=device-key ${session}=default ${schema_directory}=/tmp/schema ${http_timeout}=${EMPTY} ${http_method}=put - [Documentation] Tell Netconf about the specified device so it can add it into its configuration. - ${mapping}= BuiltIn.Create_dictionary DEVICE_IP=${device_address} DEVICE_NAME=${device_name} DEVICE_PORT=${device_port} DEVICE_USER=${device_user} DEVICE_PASSWORD=${device_password} - ... DEVICE_KEY=${device_key} SCHEMA_DIRECTORY=${schema_directory} + ${mapping}= BuiltIn.Create_dictionary + ... DEVICE_IP=${device_address} + ... DEVICE_NAME=${device_name} + ... DEVICE_PORT=${device_port} + ... DEVICE_USER=${device_user} + ... DEVICE_PASSWORD=${device_password} + ... DEVICE_KEY=${device_key} + ... SCHEMA_DIRECTORY=${schema_directory} # TODO: Is it possible to use &{kwargs} as a mapping directly? - Run Keyword if '${http_method}'=='post' TemplatedRequests.Post_As_Xml_Templated folder=${DIRECTORY_WITH_DEVICE_TEMPLATES}${/}${device_type} mapping=${mapping} session=${session} http_timeout=${http_timeout} - ... ELSE TemplatedRequests.Put_As_Xml_Templated folder=${DIRECTORY_WITH_DEVICE_TEMPLATES}${/}${device_type} mapping=${mapping} session=${session} http_timeout=${http_timeout} + IF '${http_method}'=='post' + TemplatedRequests.Post_As_Xml_Templated + ... folder=${DIRECTORY_WITH_DEVICE_TEMPLATES}${/}${device_type} + ... mapping=${mapping} + ... session=${session} + ... http_timeout=${http_timeout} + ELSE + TemplatedRequests.Put_As_Xml_Templated + ... folder=${DIRECTORY_WITH_DEVICE_TEMPLATES}${/}${device_type} + ... mapping=${mapping} + ... session=${session} + ... http_timeout=${http_timeout} + END Collections.Set_To_Dictionary ${NetconfKeywords__mounted_device_types} ${device_name} ${device_type} Configure_Device - [Arguments] ${current_name} ${log_response}=True [Documentation] Operation for configuring the device. + [Arguments] ${current_name} ${log_response}=True KarafKeywords.Log_Message_To_Controller_Karaf Configuring device ${current_name} to Netconf Configure_Device_In_Netconf ${current_name} device_type=${device_type} device_port=${current_port} KarafKeywords.Log_Message_To_Controller_Karaf Device ${current_name} configured Configure_Device_And_Verify - [Arguments] ${current_name} ${log_response}=True [Documentation] Operation for configuring the device in the Netconf subsystem and connecting to it. + [Arguments] ${current_name} ${log_response}=True Configure_Device ${current_name} ${log_response} KarafKeywords.Log_Message_To_Controller_Karaf Waiting for device ${current_name} to connect Wait_Device_Connected ${current_name} period=0.5s log_response=${log_response} KarafKeywords.Log_Message_To_Controller_Karaf Device ${current_name} connected Count_Netconf_Connectors_For_Device - [Arguments] ${device_name} ${session}=default [Documentation] Count all instances of the specified device in the Netconf topology (usually 0 or 1). + [Arguments] ${device_name} ${session}=default # FIXME: This no longer counts netconf connectors, it counts "device instances in Netconf topology". # This keyword should be renamed but without an automatic keyword naming standards checker this is # potentially destabilizing change so right now it is as FIXME. Proposed new name: # Count_Device_Instances_In_Netconf_Topology - ${uri} = Restconf.Generate URI network-topology:network-topology operational + ${uri}= Restconf.Generate URI network-topology:network-topology operational ${mounts}= TemplatedRequests.Get_As_Json_From_Uri ${uri} session=${session} Builtin.Log ${mounts} ${actual_count}= Builtin.Evaluate len('''${mounts}'''.split('"node-id": "${device_name}"'))-1 - Builtin.Return_From_Keyword ${actual_count} + RETURN ${actual_count} Wait_Connected - [Arguments] ${current_name} ${log_response}=True [Documentation] Operation for waiting until the device is connected. + [Arguments] ${current_name} ${log_response}=True KarafKeywords.Log_Message_To_Controller_Karaf Waiting for device ${current_name} to connect Wait_Device_Connected ${current_name} period=0.5s timeout=300s log_response=${log_response} KarafKeywords.Log_Message_To_Controller_Karaf Device ${current_name} connected Check_Device_Has_No_Netconf_Connector - [Arguments] ${device_name} ${session}=default [Documentation] Check that there are no instances of the specified device in the Netconf topology. + [Arguments] ${device_name} ${session}=default # FIXME: Similarlt to "Count_Netconf_Connectors_For_Device", this does not check whether the device has # no netconf connector but whether the device is present in the netconf topology or not. Rename, proposed # new name: Check_Device_Not_Present_In_Netconf_Topology - ${count} Count_Netconf_Connectors_For_Device ${device_name} session=${session} + ${count}= Count_Netconf_Connectors_For_Device ${device_name} session=${session} Builtin.Should_Be_Equal_As_Strings ${count} 0 Check_Device_Completely_Gone - [Arguments] ${device_name} ${session}=default ${log_response}=True [Documentation] Check that the specified device has no Netconf connectors nor associated data. + [Arguments] ${device_name} ${session}=default ${log_response}=True Check_Device_Has_No_Netconf_Connector ${device_name} session=${session} - ${uri} = Restconf.Generate URI network-topology:network-topology config topology=topology-netconf node=${device_name} + ${uri}= Restconf.Generate URI + ... network-topology:network-topology + ... config + ... topology=topology-netconf + ... node=${device_name} Utils.No Content From URI ${session} ${uri} Check_Device_Connected - [Arguments] ${device_name} ${session}=default ${log_response}=True [Documentation] Check that the specified device is accessible from Netconf. - ${uri} = Restconf.Generate URI network-topology:network-topology operational topology=topology-netconf node=${device_name} - ${device_status}= TemplatedRequests.Get_As_Json_From_Uri ${uri} session=${session} log_response=${log_response} + [Arguments] ${device_name} ${session}=default ${log_response}=True + ${uri}= Restconf.Generate URI + ... network-topology:network-topology + ... operational + ... topology=topology-netconf + ... node=${device_name} + ${device_status}= TemplatedRequests.Get_As_Json_From_Uri + ... ${uri} + ... session=${session} + ... log_response=${log_response} Builtin.Should_Contain ${device_status} "netconf-node-topology:connection-status": "connected" Wait_Device_Connected - [Arguments] ${device_name} ${timeout}=20s ${period}=1s ${session}=default ${log_response}=True [Documentation] Wait for the device to become connected. ... It is more readable to use this keyword in a test case than to put the whole WUKS below into it. - BuiltIn.Wait_Until_Keyword_Succeeds ${timeout} ${period} Check_Device_Connected ${device_name} session=${session} log_response=${log_response} + [Arguments] ${device_name} ${timeout}=20s ${period}=1s ${session}=default ${log_response}=True + BuiltIn.Wait_Until_Keyword_Succeeds + ... ${timeout} + ... ${period} + ... Check_Device_Connected + ... ${device_name} + ... session=${session} + ... log_response=${log_response} Remove_Device_From_Netconf - [Arguments] ${device_name} ${session}=default ${location}=location [Documentation] Tell Netconf to deconfigure the specified device + [Arguments] ${device_name} ${session}=default ${location}=location ${device_type}= Collections.Pop_From_Dictionary ${NetconfKeywords__mounted_device_types} ${device_name} ${template_as_string}= BuiltIn.Create_Dictionary DEVICE_NAME=${device_name} - TemplatedRequests.Delete_Templated ${DIRECTORY_WITH_DEVICE_TEMPLATES}${/}${device_type} ${template_as_string} session=${session} location=${location} + TemplatedRequests.Delete_Templated + ... ${DIRECTORY_WITH_DEVICE_TEMPLATES}${/}${device_type} + ... ${template_as_string} + ... session=${session} + ... location=${location} Deconfigure_Device - [Arguments] ${current_name} ${log_response}=True [Documentation] Operation for deconfiguring the device. + [Arguments] ${current_name} ${log_response}=True KarafKeywords.Log_Message_To_Controller_Karaf Deconfiguring device ${current_name} Remove_Device_From_Netconf ${current_name} KarafKeywords.Log_Message_To_Controller_Karaf Device ${current_name} deconfigured Deconfigure_Device_And_Verify - [Arguments] ${current_name} ${log_response}=True [Documentation] Operation for deconfiguring the device from Netconf. + [Arguments] ${current_name} ${log_response}=True Deconfigure_Device ${current_name} ${log_response} Check_Device_Deconfigured ${current_name} Check_Device_Deconfigured - [Arguments] ${current_name} ${log_response}=True [Documentation] Operation for making sure the device is really deconfigured. + [Arguments] ${current_name} ${log_response}=True KarafKeywords.Log_Message_To_Controller_Karaf Waiting for device ${current_name} to disappear Wait_Device_Fully_Removed ${current_name} period=0.5s timeout=120s KarafKeywords.Log_Message_To_Controller_Karaf Device ${current_name} removed Wait_Device_Fully_Removed - [Arguments] ${device_name} ${timeout}=10s ${period}=1s ${session}=default ${log_response}=True [Documentation] Wait until all netconf connectors for the device with the given name disappear. ... Call of Remove_Device_From_Netconf returns before netconf gets ... around deleting the device's connector. To ensure the device is @@ -156,10 +198,16 @@ Wait_Device_Fully_Removed ... is not made before using this keyword, the wait will fail. ... Using this keyword is more readable than putting the WUKS below ... into a test case. - BuiltIn.Wait_Until_Keyword_Succeeds ${timeout} ${period} Check_Device_Completely_Gone ${device_name} session=${session} log_response=${log_response} + [Arguments] ${device_name} ${timeout}=10s ${period}=1s ${session}=default ${log_response}=True + BuiltIn.Wait_Until_Keyword_Succeeds + ... ${timeout} + ... ${period} + ... Check_Device_Completely_Gone + ... ${device_name} + ... session=${session} + ... log_response=${log_response} NetconfKeywords__Deploy_Additional_Schemas - [Arguments] ${schemas} [Documentation] Internal keyword for Install_And_Start_TestTool ... This deploys the additional schemas if any and returns a ... command line argument to be added to the testtool commandline @@ -168,6 +216,7 @@ NetconfKeywords__Deploy_Additional_Schemas ... unreadable as the actions are quite different in the two ... possibilities (additional schemas present versus no additional ... schemas present), therefore a separate keyword is used. + [Arguments] ${schemas} # Make sure there is no schemas directory on the remote machine. A # previous test suite might have left some debris there and that might # lead to spurious failures, so it is better to make sure we start with a @@ -178,24 +227,24 @@ NetconfKeywords__Deploy_Additional_Schemas BuiltIn.Log ${response} # Drop out of the keyword, returning no command line argument when there # are no additional schemas to deploy. - BuiltIn.Return_From_Keyword_If '${schemas}' == 'none' ${EMPTY} + IF '${schemas}' == 'none' RETURN ${EMPTY} # Deploy the additional schemas into a standard directory on the remote # machine and construct a command line argument pointing to that # directory from the point of view of the process running on that # machine. SSHLibrary.Put_Directory ${schemas} destination=./schemas SSHLibrary.List_Directory ./schemas - [Return] --schemas-dir ./schemas + RETURN --schemas-dir ./schemas NetconfKeywords__Deploy_Custom_RPC - [Arguments] ${rpc_config} [Documentation] Internal keyword for Install_And_Start_TestTool ... This deploys the optional custom rpc file. ... Drop out of the keyword, returning no command line argument when there ... is no rpc file to deploy. - BuiltIn.Return_From_Keyword_If '${rpc_config}' == 'none' ${EMPTY} + [Arguments] ${rpc_config} + IF '${rpc_config}' == 'none' RETURN ${EMPTY} SSHKeywords.Copy_File_To_Tools_System ${TOOLS_SYSTEM_1_IP} ${rpc_config} /tmp - [Return] --rpc-config /tmp/customaction.xml + RETURN --rpc-config /tmp/customaction.xml NetconfKeywords__Check_Device_Is_Up [Arguments] ${last-port} @@ -208,24 +257,25 @@ NetconfKeywords__Wait_Device_Is_Up_And_Running BuiltIn.Wait_Until_Keyword_Succeeds ${TESTTOOL_BOOT_TIMEOUT} 1s Check_Device_Up_And_Running ${number} Install_And_Start_Testtool + [Documentation] Install and run testtool. [Arguments] ${device-count}=10 ${debug}=true ${schemas}=none ${rpc_config}=none ${tool_options}=${EMPTY} ${java_options}=${TESTTOOL_DEFAULT_JAVA_OPTIONS} ... ${mdsal}=true ${log_response}=True - [Documentation] Install and run testtool. ${filename}= NexusKeywords.Deploy_Test_Tool netconf netconf-testtool Start_Testtool ${filename} ${device-count} ${debug} ${schemas} ${rpc_config} ${tool_options} ... ${java_options} ${mdsal} log_response=${log_response} Start_Testtool - [Arguments] ${filename} ${device-count}=10 ${debug}=true ${schemas}=none ${rpc_config}=none ${tool_options}=${EMPTY} - ... ${java_options}=${TESTTOOL_DEFAULT_JAVA_OPTIONS} ${mdsal}=true ${log_response}=True [Documentation] Arrange to collect tool's output into a log file. ... Will use specific ${schemas} unless argument resolves to 'none', ... which signifies that there are no additional schemas to be deployed. ... If so the directory for the additional schemas is deleted on the ... remote machine and the additional schemas argument is left out. + [Arguments] ${filename} ${device-count}=10 ${debug}=true ${schemas}=none ${rpc_config}=none ${tool_options}=${EMPTY} + ... ${java_options}=${TESTTOOL_DEFAULT_JAVA_OPTIONS} ${mdsal}=true ${log_response}=True ${schemas_option}= NetconfKeywords__Deploy_Additional_Schemas ${schemas} ${rpc_config_option}= NetconfKeywords__Deploy_Custom_RPC ${rpc_config} - ${command}= NexusKeywords.Compose_Full_Java_Command ${java_options} -jar ${filename} ${tool_options} --device-count ${device-count} --debug ${debug} ${schemas_option} ${rpc_config_option} --md-sal ${mdsal} + ${command}= NexusKeywords.Compose_Full_Java_Command + ... ${java_options} -jar ${filename} ${tool_options} --device-count ${device-count} --debug ${debug} ${schemas_option} ${rpc_config_option} --md-sal ${mdsal} BuiltIn.Log Running testtool: ${command} ${logfile}= Utils.Get_Log_File_Name testtool BuiltIn.Set_Suite_Variable ${testtool_log} ${logfile} @@ -236,8 +286,8 @@ Start_Testtool Perform_Operation_On_Each_Device NetconfKeywords__Wait_Device_Is_Up_And_Running log_response=${log_response} Check_Device_Up_And_Running - [Arguments] ${device-number} [Documentation] Query netstat on remote machine whether testtool device with the specified number has its port open and fail if not. + [Arguments] ${device-number} ${device-port}= BuiltIn.Evaluate ${FIRST_TESTTOOL_PORT}+${device-number}-1 NetconfKeywords__Check_Device_Is_Up ${device-port} @@ -253,10 +303,10 @@ Stop_Testtool NetconfKeywords__Check_Netconf_Test_Timeout_Not_Expired [Arguments] ${deadline_Date} - BuiltIn.Return_From_Keyword_If not ${ENABLE_NETCONF_TEST_TIMEOUT} + IF not ${ENABLE_NETCONF_TEST_TIMEOUT} RETURN ${current_Date}= DateTime.Get_Current_Date ${ellapsed_seconds}= DateTime.Subtract_Date_From_Date ${deadline_Date} ${current_Date} - BuiltIn.Run_Keyword_If ${ellapsed_seconds}<0 Fail The global time out period expired + IF ${ellapsed_seconds}<0 Fail The global time out period expired NetconfKeywords__Perform_Operation_With_Checking_On_Next_Device [Arguments] ${operation} ${deadline_Date} ${log_response}=True @@ -271,13 +321,18 @@ Perform_Operation_On_Each_Device ${current_Date}= DateTime.Get_Current_Date ${deadline_Date}= DateTime.Add_Time_To_Date ${current_Date} ${timeout} BuiltIn.Set_Suite_Variable ${current_port} ${BASE_NETCONF_DEVICE_PORT} - BuiltIn.Repeat_Keyword ${count} times NetconfKeywords__Perform_Operation_With_Checking_On_Next_Device ${operation} ${deadline_Date} log_response=${log_response} + BuiltIn.Repeat_Keyword + ... ${count} times + ... NetconfKeywords__Perform_Operation_With_Checking_On_Next_Device + ... ${operation} + ... ${deadline_Date} + ... log_response=${log_response} Disable SSE On Controller - [Arguments] ${controller_ip} [Documentation] Sets the config for using SSE (Server Side Events) to false. Note that ... this keyword only changes the config. A controller restart is needed for the config to ... to take effect. + [Arguments] ${controller_ip} SSHLibrary.Open Connection ${controller_ip} Login With Public Key ${ODL_SYSTEM_USER} ${USER_HOME}/.ssh/${SSH_KEY} any ${cmd}= Set Variable echo "use-sse=false" > ${SSE_CFG_FILE} @@ -285,10 +340,10 @@ Disable SSE On Controller SSHLibrary.Close Connection Enable SSE On Controller - [Arguments] ${controller_ip} [Documentation] Sets the config for using SSE (Server Side Events) to true. Note that ... this keyword only changes the config. A controller restart is needed for the config to ... to take effect. + [Arguments] ${controller_ip} SSHLibrary.Open Connection ${controller_ip} Login With Public Key ${ODL_SYSTEM_USER} ${USER_HOME}/.ssh/${SSH_KEY} any ${cmd}= Set Variable echo "use-sse=true" > ${SSE_CFG_FILE} diff --git a/csit/libraries/NettyReplication.robot b/csit/libraries/NettyReplication.robot index a907b58832..a02dd4990e 100644 --- a/csit/libraries/NettyReplication.robot +++ b/csit/libraries/NettyReplication.robot @@ -1,55 +1,80 @@ *** Settings *** -Documentation Netty replication library. This library can be used to setup and teardown netty replication connections. -Resource KarafKeywords.robot -Resource ClusterManagement.robot +Documentation Netty replication library. This library can be used to setup and teardown netty replication connections. + +Resource KarafKeywords.robot +Resource ClusterManagement.robot + *** Variables *** -${DEFAULT_NETTY_SOURCE_NODE_INDEX} ${1} -@{DEFAULT_NETTY_SINK_NODE_INDEXES} ${2} +${DEFAULT_NETTY_SOURCE_NODE_INDEX} ${1} +@{DEFAULT_NETTY_SINK_NODE_INDEXES} ${2} + *** Keywords *** Setup_Netty_Replication - [Arguments] ${source_member_index}=${DEFAULT_NETTY_SOURCE_NODE_INDEX} ${sink_members_indexes}=${DEFAULT_NETTY_SINK_NODE_INDEXES} [Documentation] Set up netty replication connections betwean source and sinks. + [Arguments] ${source_member_index}=${DEFAULT_NETTY_SOURCE_NODE_INDEX} ${sink_members_indexes}=${DEFAULT_NETTY_SINK_NODE_INDEXES} Open_Source_Connection ${source_member_index} FOR ${sink_member_index} IN @{sink_members_indexes} Open_Sink_Connection ${sink_member_index} source_member_index=${source_member_index} END Teardown_Netty_Replication - [Arguments] ${source_member_index}=${DEFAULT_NETTY_SOURCE_NODE_INDEX} ${sink_members_indexes}=${DEFAULT_NETTY_SINK_NODE_INDEXES} [Documentation] Tear down netty replication connections betwean source and sinks. + [Arguments] ${source_member_index}=${DEFAULT_NETTY_SOURCE_NODE_INDEX} ${sink_members_indexes}=${DEFAULT_NETTY_SINK_NODE_INDEXES} Close_Source_Connection ${source_member_index} FOR ${sink_member_index} IN @{sink_members_indexes} Close_Sink_Connection ${sink_member_index} END Open_Source_Connection - [Arguments] ${source_member_index}=${DEFAULT_NETTY_SOURCE_NODE_INDEX} [Documentation] Open source part of netty replicate connection on specific node. - KarafKeywords.Execute_Controller_Karaf_Command_On_Background config:edit org.opendaylight.mdsal.replicate.netty.source member_index=${source_member_index} - KarafKeywords.Execute_Controller_Karaf_Command_On_Background config:property-set enabled true member_index=${source_member_index} - KarafKeywords.Execute_Controller_Karaf_Command_On_Background config:update member_index=${source_member_index} + [Arguments] ${source_member_index}=${DEFAULT_NETTY_SOURCE_NODE_INDEX} + KarafKeywords.Execute_Controller_Karaf_Command_On_Background + ... config:edit org.opendaylight.mdsal.replicate.netty.source + ... member_index=${source_member_index} + KarafKeywords.Execute_Controller_Karaf_Command_On_Background + ... config:property-set enabled true + ... member_index=${source_member_index} + KarafKeywords.Execute_Controller_Karaf_Command_On_Background + ... config:update + ... member_index=${source_member_index} Close_Source_Connection - [Arguments] ${source_member_index}=${DEFAULT_NETTY_SOURCE_NODE_INDEX} [Documentation] Close source part of netty replicate connection on specific node. - KarafKeywords.Execute_Controller_Karaf_Command_On_Background config:edit org.opendaylight.mdsal.replicate.netty.source member_index=${source_member_index} - KarafKeywords.Execute_Controller_Karaf_Command_On_Background config:property-set enabled false member_index=${source_member_index} - KarafKeywords.Execute_Controller_Karaf_Command_On_Background config:update member_index=${source_member_index} + [Arguments] ${source_member_index}=${DEFAULT_NETTY_SOURCE_NODE_INDEX} + KarafKeywords.Execute_Controller_Karaf_Command_On_Background + ... config:edit org.opendaylight.mdsal.replicate.netty.source + ... member_index=${source_member_index} + KarafKeywords.Execute_Controller_Karaf_Command_On_Background + ... config:property-set enabled false + ... member_index=${source_member_index} + KarafKeywords.Execute_Controller_Karaf_Command_On_Background + ... config:update + ... member_index=${source_member_index} Open_Sink_Connection - [Arguments] ${sink_member_index}=@{DEFAULT_NETTY_SINK_NODE_INDEXES}[0] ${source_member_index}=${DEFAULT_NETTY_SOURCE_NODE_INDEX} [Documentation] Open sink part of netty replicate connection on specific node. + [Arguments] ${sink_member_index}=@{DEFAULT_NETTY_SINK_NODE_INDEXES}[0] ${source_member_index}=${DEFAULT_NETTY_SOURCE_NODE_INDEX} ${replicate_source_ip}= ClusterManagement.Resolve_Ip_Address_For_Member ${source_member_index} - KarafKeywords.Execute_Controller_Karaf_Command_On_Background config:edit org.opendaylight.mdsal.replicate.netty.sink member_index=${sink_member_index} - KarafKeywords.Execute_Controller_Karaf_Command_On_Background config:property-set enabled true member_index=${sink_member_index} - KarafKeywords.Execute_Controller_Karaf_Command_On_Background config:property-set source-host ${replicate_source_ip} member_index=${sink_member_index} + KarafKeywords.Execute_Controller_Karaf_Command_On_Background + ... config:edit org.opendaylight.mdsal.replicate.netty.sink + ... member_index=${sink_member_index} + KarafKeywords.Execute_Controller_Karaf_Command_On_Background + ... config:property-set enabled true + ... member_index=${sink_member_index} + KarafKeywords.Execute_Controller_Karaf_Command_On_Background + ... config:property-set source-host ${replicate_source_ip} + ... member_index=${sink_member_index} KarafKeywords.Execute_Controller_Karaf_Command_On_Background config:update member_index=${sink_member_index} Close_Sink_Connection - [Arguments] ${sink_member_index}=@{DEFAULT_NETTY_SINK_NODE_INDEXES}[0] [Documentation] Close sink part of netty replicate connection on specific node. - KarafKeywords.Execute_Controller_Karaf_Command_On_Background config:edit org.opendaylight.mdsal.replicate.netty.sink member_index=${sink_member_index} - KarafKeywords.Execute_Controller_Karaf_Command_On_Background config:property-set enabled false member_index=${sink_member_index} + [Arguments] ${sink_member_index}=@{DEFAULT_NETTY_SINK_NODE_INDEXES}[0] + KarafKeywords.Execute_Controller_Karaf_Command_On_Background + ... config:edit org.opendaylight.mdsal.replicate.netty.sink + ... member_index=${sink_member_index} + KarafKeywords.Execute_Controller_Karaf_Command_On_Background + ... config:property-set enabled false + ... member_index=${sink_member_index} KarafKeywords.Execute_Controller_Karaf_Command_On_Background config:update member_index=${sink_member_index} diff --git a/csit/libraries/NexusKeywords.robot b/csit/libraries/NexusKeywords.robot index 7db65e6a63..fb9ac4cfbb 100644 --- a/csit/libraries/NexusKeywords.robot +++ b/csit/libraries/NexusKeywords.robot @@ -1,76 +1,89 @@ *** Settings *** -Documentation Nexus repository access keywords, and supporting Java and Maven handling. +Documentation Nexus repository access keywords, and supporting Java and Maven handling. ... -... Copyright (c) 2015,2016 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2015,2016 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... This library encapsulates a bunch of somewhat complex and commonly used -... Nexus operations into reusable keywords to make writing test suites easier. +... This library encapsulates a bunch of somewhat complex and commonly used +... Nexus operations into reusable keywords to make writing test suites easier. ... -... Currently, Java version detection is incorporated so that Java tools can be run reliably. -... Also, suport for installing and running Maven is added, as that needs the Java detection. -... TODO: Move Java detection and Maven to a separate Resource, or rename this Resource. -Library Collections -Library OperatingSystem -Library SSHLibrary -Library String -Library XML -Library Collections -Library RequestsLibrary -Resource ${CURDIR}/CompareStream.robot -Resource ${CURDIR}/SSHKeywords.robot -Resource ${CURDIR}/Utils.robot +... Currently, Java version detection is incorporated so that Java tools can be run reliably. +... Also, suport for installing and running Maven is added, as that needs the Java detection. +... TODO: Move Java detection and Maven to a separate Resource, or rename this Resource. + +Library Collections +Library OperatingSystem +Library SSHLibrary +Library String +Library XML +Library Collections +Library RequestsLibrary +Resource ${CURDIR}/CompareStream.robot +Resource ${CURDIR}/SSHKeywords.robot +Resource ${CURDIR}/Utils.robot + *** Variables *** -&{COMPONENT_MAPPING} netconf=netconf-impl bgpcep=pcep-impl carpeople=clustering-it-model yangtools=yang-data-impl bindingv1=mdsal-binding-generator-impl odl-micro=odlmicro-impl +&{COMPONENT_MAPPING} +... netconf=netconf-impl +... bgpcep=pcep-impl +... carpeople=clustering-it-model +... yangtools=yang-data-impl +... bindingv1=mdsal-binding-generator-impl +... odl-micro=odlmicro-impl @{RELEASE_INTEGRATED_COMPONENTS} mdsal odlparent yangtools carpeople netconf bgpcep -${JDKVERSION} None -${JAVA_8_HOME_CENTOS} /usr/lib/jvm/java-1.8.0 -${JAVA_8_HOME_UBUNTU} /usr/lib/jvm/java-8-openjdk-amd64 -${JAVA_11_HOME_CENTOS} /usr/lib/jvm/java-11-openjdk -${JAVA_11_HOME_UBUNTU} /usr/lib/jvm/java-11-openjdk-amd64 -${JAVA_17_HOME_CENTOS} /usr/lib/jvm/java-17-openjdk -${JAVA_17_HOME_UBUNTU} /usr/lib/jvm/java-17-openjdk-amd64 -${JAVA_OPTIONS} -Xmx2560m # Note that '-Xmx=3g' is wrong syntax. Also 3GB heap may not fit in 4GB RAM. +${JDKVERSION} None +${JAVA_8_HOME_CENTOS} /usr/lib/jvm/java-1.8.0 +${JAVA_8_HOME_UBUNTU} /usr/lib/jvm/java-8-openjdk-amd64 +${JAVA_11_HOME_CENTOS} /usr/lib/jvm/java-11-openjdk +${JAVA_11_HOME_UBUNTU} /usr/lib/jvm/java-11-openjdk-amd64 +${JAVA_17_HOME_CENTOS} /usr/lib/jvm/java-17-openjdk +${JAVA_17_HOME_UBUNTU} /usr/lib/jvm/java-17-openjdk-amd64 +# Note that '-Xmx=3g' is wrong syntax. Also 3GB heap may not fit in 4GB RAM. +${JAVA_OPTIONS} +... -Xmx2560m ${MAVEN_DEFAULT_OUTPUT_FILENAME} default_maven.log -${MAVEN_OPTIONS} -Pq -Djenkins -${MAVEN_REPOSITORY_PATH} /tmp/r -${MAVEN_SETTINGS_URL} https://raw.githubusercontent.com/opendaylight/odlparent/master/settings.xml -${MAVEN_VERSION} 3.3.9 -${NEXUS_FALLBACK_URL} ${NEXUSURL_PREFIX}/content/repositories/opendaylight.snapshot -${NEXUS_RELEASE_BASE_URL} https://nexus.opendaylight.org/content/repositories/opendaylight.release -${NEXUS_RELEASES_URL} ${NEXUS_RELEASE_BASE_URL}/org/opendaylight/integration/karaf +${MAVEN_OPTIONS} -Pq -Djenkins +${MAVEN_REPOSITORY_PATH} /tmp/r +${MAVEN_SETTINGS_URL} https://raw.githubusercontent.com/opendaylight/odlparent/master/settings.xml +${MAVEN_VERSION} 3.3.9 +${NEXUS_FALLBACK_URL} ${NEXUSURL_PREFIX}/content/repositories/opendaylight.snapshot +${NEXUS_RELEASE_BASE_URL} https://nexus.opendaylight.org/content/repositories/opendaylight.release +${NEXUS_RELEASES_URL} ${NEXUS_RELEASE_BASE_URL}/org/opendaylight/integration/karaf + *** Keywords *** Initialize_Artifact_Deployment_And_Usage - [Arguments] ${tools_system_connect}=True [Documentation] Places search utility to ODL system, which will be needed for version detection. ... By default also initialize a SSH connection to Tools system, ... as following Keywords assume a working connection towards target system. + [Arguments] ${tools_system_connect}=True # Connect to the ODL machine. ${odl} = SSHKeywords.Open_Connection_To_ODL_System # Deploy the search tool. SSHLibrary.Put_File ${CURDIR}/../../tools/deployment/search.sh SSHLibrary.Close_Connection # Optionally connect to the Tools System machine. - BuiltIn.Return_From_Keyword_If not (${tools_system_connect}) # the argument may be a convoluted Python expression + IF not (${tools_system_connect}) RETURN SSHKeywords.Open_Connection_To_Tools_System NexusKeywords__Get_Items_To_Look_At - [Arguments] ${component} [Documentation] Get a list of items that might contain the version number that we are looking for. ... ... &{COMPONENT_MAPPING} is the centralized place to maintain the mapping ... from a stream independent component nickname to the list of artifact names to search for. - Collections.Dictionary_Should_Contain_Key ${COMPONENT_MAPPING} ${component} Component not supported by NexusKeywords version detection: ${component} + [Arguments] ${component} + Collections.Dictionary_Should_Contain_Key + ... ${COMPONENT_MAPPING} + ... ${component} + ... Component not supported by NexusKeywords version detection: ${component} BuiltIn.Run_Keyword_And_Return Collections.Get_From_Dictionary ${COMPONENT_MAPPING} ${component} NexusKeywords__Detect_Version_To_Pull - [Arguments] ${component} [Documentation] Determine the exact Nexus directory to be used as a source for a particular test tool ... Figure out what version of the tool needs to be pulled out of the ... Nexus by looking at the version directory of the subsystem from @@ -80,28 +93,35 @@ NexusKeywords__Detect_Version_To_Pull ... I also don't want to depend on maven-metadata-local.xml and other ... bits and pieces of ODL distribution which are not required for ODL ... to function properly. + [Arguments] ${component} ${itemlist} = NexusKeywords__Get_Items_To_Look_At ${component} ${current_ssh_connection} = SSHLibrary.Get Connection SSHKeywords.Open_Connection_To_ODL_System - ${version} ${result} = SSHLibrary.Execute_Command sh search.sh ${WORKSPACE}/${BUNDLEFOLDER}/system ${itemlist} return_rc=True + ${version} ${result} = SSHLibrary.Execute_Command + ... sh search.sh ${WORKSPACE}/${BUNDLEFOLDER}/system ${itemlist} + ... return_rc=True SSHLibrary.Close_Connection SSHKeywords.Restore Current SSH Connection From Index ${current_ssh_connection.index} BuiltIn.Log ${version} - BuiltIn.Run_Keyword_If ${result}!=0 BuiltIn.Fail Component "${component}": searching for "${itemlist}" found no version, cannot locate test tool. + IF ${result}!=0 + BuiltIn.Fail + ... Component "${component}": searching for "${itemlist}" found no version, cannot locate test tool. + END ${version} ${location} = String.Split_String ${version} max_split=1 - [Return] ${version} ${location} + RETURN ${version} ${location} Deploy_From_Url - [Arguments] ${url} [Documentation] On active SSH conenction execute download ${url} command, log output, check RC and return file name. + [Arguments] ${url} ${filename} = String.Fetch_From_Right ${url} / ${response} ${result} = SSHLibrary.Execute_Command wget -q -N '${url}' 2>&1 return_rc=True BuiltIn.Log ${response} - BuiltIn.Run_Keyword_If ${result} != 0 BuiltIn.Fail File ${filename} could not be downloaded from ${url} - [Return] ${filename} + IF ${result} != 0 + BuiltIn.Fail File ${filename} could not be downloaded from ${url} + END + RETURN ${filename} Deploy_Artifact - [Arguments] ${component} ${artifact} ${name_prefix}=${artifact}- ${name_suffix}=-executable.jar ${fallback_url}=${NEXUS_FALLBACK_URL} ${explicit_url}=${EMPTY} ${build_version}=${EMPTY} ${build_location}=${EMPTY} [Documentation] Deploy the specified artifact from Nexus to the cwd of the machine to which the active SSHLibrary connection points. ... ${component} is a name part of an artifact present in system/ of ODl installation with the same version as ${artifact} should have. ... Must have ${BUNDLE_URL} variable set to the URL from which the @@ -110,6 +130,7 @@ Deploy_Artifact ... construction job. If this is detected to ne be the case, fallback URL is used. ... If ${explicit_url} is non-empty, Deploy_From_Utrl is called instead. ... TODO: Allow deploying to a specific directory, we have SSHKeywords.Execute_Command_At_Cwd_Should_Pass now. + [Arguments] ${component} ${artifact} ${name_prefix}=${artifact}- ${name_suffix}=-executable.jar ${fallback_url}=${NEXUS_FALLBACK_URL} ${explicit_url}=${EMPTY} ${build_version}=${EMPTY} ${build_location}=${EMPTY} BuiltIn.Run_Keyword_And_Return_If """${explicit_url}""" != "" Deploy_From_Url ${explicit_url} ${urlbase} = String.Fetch_From_Left ${BUNDLE_URL} /org/opendaylight # If the BUNDLE_URL points somewhere else (perhaps *patch-test* job in Jenkins), @@ -117,23 +138,49 @@ Deploy_Artifact # If we are working with a "release integrated" project, we always will want to look for # a released version, not in the snapshots ${urlbase} = BuiltIn.Set_Variable_If '${urlbase}' != '${BUNDLE_URL}' ${urlbase} ${fallback_url} - CompareStream.Run_Keyword_If_At_Most_Magnesium Collections.Remove_Values_From_List ${RELEASE_INTEGRATED_COMPONENTS} carpeople - CompareStream.Run_Keyword_If_At_Most_Aluminium Collections.Remove_Values_From_List ${RELEASE_INTEGRATED_COMPONENTS} netconf - CompareStream.Run_Keyword_If_At_Most_Silicon Collections.Remove_Values_From_List ${RELEASE_INTEGRATED_COMPONENTS} bgpcep - ${version} ${location} = BuiltIn.Run_Keyword_If '${build_version}'=='${EMPTY}' NexusKeywords__Detect_Version_To_Pull ${component} - ... ELSE BuiltIn.Set_Variable ${build_version} ${build_location} - BuiltIn.Run_Keyword_If 'SNAPSHOT' in '${version}' Collections.Remove_Values_From_List ${RELEASE_INTEGRATED_COMPONENTS} netconf bgpcep + CompareStream.Run_Keyword_If_At_Most_Magnesium + ... Collections.Remove_Values_From_List + ... ${RELEASE_INTEGRATED_COMPONENTS} + ... carpeople + CompareStream.Run_Keyword_If_At_Most_Aluminium + ... Collections.Remove_Values_From_List + ... ${RELEASE_INTEGRATED_COMPONENTS} + ... netconf + CompareStream.Run_Keyword_If_At_Most_Silicon + ... Collections.Remove_Values_From_List + ... ${RELEASE_INTEGRATED_COMPONENTS} + ... bgpcep + IF '${build_version}'=='${EMPTY}' + ${version} ${location} = NexusKeywords__Detect_Version_To_Pull ${component} + ELSE + ${version} ${location} = BuiltIn.Set_Variable ${build_version} ${build_location} + END + IF 'SNAPSHOT' in '${version}' + Collections.Remove_Values_From_List ${RELEASE_INTEGRATED_COMPONENTS} netconf bgpcep + END # check if the bundle url is pointing to a staging artifact # when we are pointing at a staged artifact we need to use the staging repo instead of release/snapshot artifacts - ${is_staged} = BuiltIn.Set_Variable_If "opendaylight.release" not in '${urlbase}' and "opendaylight.snapshot" not in '${urlbase}' "TRUE" "FALSE" + ${is_staged} = BuiltIn.Set_Variable_If + ... "opendaylight.release" not in '${urlbase}' and "opendaylight.snapshot" not in '${urlbase}' + ... "TRUE" + ... "FALSE" # if we have a staged artifact we need to use the urlbase given to us in the job params - ${is_mri_component} = BuiltIn.Set_Variable_If '${component}' in ${RELEASE_INTEGRATED_COMPONENTS} "TRUE" "FALSE" - ${urlbase} = BuiltIn.Set_Variable_If ${is_mri_component} == "TRUE" and ${is_staged} == "FALSE" ${NEXUS_RELEASE_BASE_URL} ${urlbase} + ${is_mri_component} = BuiltIn.Set_Variable_If + ... '${component}' in ${RELEASE_INTEGRATED_COMPONENTS} + ... "TRUE" + ... "FALSE" + ${urlbase} = BuiltIn.Set_Variable_If + ... ${is_mri_component} == "TRUE" and ${is_staged} == "FALSE" + ... ${NEXUS_RELEASE_BASE_URL} + ... ${urlbase} # TODO: Use RequestsLibrary and String instead of curl and bash utilities? ${url} = BuiltIn.Set_Variable ${urlbase}/${location}/${artifact}/${version} # TODO: Review SSHKeywords for current best keywords to call. ${metadata} = SSHKeywords.Execute_Command_Should_Pass curl -L ${url}/maven-metadata.xml - ${status} ${namepart} = BuiltIn.Run_Keyword_And_Ignore_Error SSHKeywords.Execute_Command_Should_Pass echo "${metadata}" | grep value | head -n 1 | cut -d '>' -f 2 | cut -d '<' -f 1 stderr_must_be_empty=${True} + ${status} ${namepart} = BuiltIn.Run_Keyword_And_Ignore_Error + ... SSHKeywords.Execute_Command_Should_Pass + ... echo "${metadata}" | grep value | head -n 1 | cut -d '>' -f 2 | cut -d '<' -f 1 + ... stderr_must_be_empty=${True} ${length} = BuiltIn.Get_Length ${namepart} ${namepart} = BuiltIn.Set_Variable_If "${status}" != "PASS" or ${length} == 0 ${version} ${namepart} ${filename} = BuiltIn.Set_Variable ${name_prefix}${namepart}${name_suffix} @@ -141,15 +188,17 @@ Deploy_Artifact ${url} = BuiltIn.Set_Variable ${url}/${filename} ${response} ${result} = SSHLibrary.Execute_Command wget -q -N '${url}' 2>&1 return_rc=True BuiltIn.Log ${response} - BuiltIn.Return_From_Keyword_If ${result} == 0 ${filename} + IF ${result} == 0 RETURN ${filename} # staged autorelease for non-mri project might not contain the artifact we need so we need to fallback to grabbing it from the release repo ${release_url} = String.Replace_String_Using_Regexp ${url} autorelease-[0-9]{4} opendaylight.release ${response} ${result} = SSHLibrary.Execute_Command wget -q -N '${release_url}' 2>&1 return_rc=True - BuiltIn.Run_Keyword_If ${result} != 0 BuiltIn.Fail Artifact "${artifact}" in component "${component}" could not be downloaded from ${release_url} nor ${url} - [Return] ${filename} + IF ${result} != 0 + BuiltIn.Fail + ... Artifact "${artifact}" in component "${component}" could not be downloaded from ${release_url} nor ${url} + END + RETURN ${filename} Deploy_Test_Tool - [Arguments] ${component} ${artifact} ${suffix}=executable ${fallback_url}=${NEXUS_FALLBACK_URL} ${explicit_url}=${EMPTY} ${build_version}=${EMPTY} ${build_location}=${EMPTY} [Documentation] Deploy a test tool. ... The test tools have naming convention of the form ... "/some/dir/somewhere//--${suffix}.jar" @@ -158,52 +207,75 @@ Deploy_Test_Tool ... keyword calculates ${name_prefix} and ${name_suffix} for ... "Deploy_Artifact" and then calls "Deploy_Artifact" to do the real ... work of deploying the artifact. + [Arguments] ${component} ${artifact} ${suffix}=executable ${fallback_url}=${NEXUS_FALLBACK_URL} ${explicit_url}=${EMPTY} ${build_version}=${EMPTY} ${build_location}=${EMPTY} ${name_prefix} = BuiltIn.Set_Variable ${artifact}- ${extension} = BuiltIn.Set_Variable_If '${component}'=='odl-micro' tar jar ${name_suffix} = BuiltIn.Set_Variable_If "${suffix}" != "" -${suffix}.${extension} .${extension} - ${filename} = Deploy_Artifact ${component} ${artifact} ${name_prefix} ${name_suffix} ${fallback_url} - ... ${explicit_url} ${build_version} ${build_location} - [Return] ${filename} + ${filename} = Deploy_Artifact + ... ${component} + ... ${artifact} + ... ${name_prefix} + ... ${name_suffix} + ... ${fallback_url} + ... ${explicit_url} + ... ${build_version} + ... ${build_location} + RETURN ${filename} Install_And_Start_Java_Artifact - [Arguments] ${component} ${artifact} ${suffix}=executable ${tool_options}=${EMPTY} ${java_options}=${EMPTY} ${openjdk}=${JDKVERSION} - ... ${fallback_url}=${NEXUS_FALLBACK_URL} ${explicit_url}=${EMPTY} [Documentation] Deploy the artifact, assign name for log file, figure out java command, write the command to active SSH connection and return the log name. ... This keyword does not examine whether the artifact was started successfully or whether is still running upon return. + [Arguments] ${component} ${artifact} ${suffix}=executable ${tool_options}=${EMPTY} ${java_options}=${EMPTY} ${openjdk}=${JDKVERSION} + ... ${fallback_url}=${NEXUS_FALLBACK_URL} ${explicit_url}=${EMPTY} # TODO: Unify this keyword with what NexusKeywords.Install_And_Start_Testtool does. - ${actual_java_options} = BuiltIn.Set_Variable_If """${java_options}""" != "" ${java_options} ${JAVA_OPTIONS} + ${actual_java_options} = BuiltIn.Set_Variable_If + ... """${java_options}""" != "" + ... ${java_options} + ... ${JAVA_OPTIONS} ${filename} = Deploy_Test_Tool ${component} ${artifact} ${suffix} ${fallback_url} ${explicit_url} ${command} = Compose_Full_Java_Command ${actual_java_options} -jar ${filename} ${tool_options} ${logfile} = Utils.Get_Log_File_Name ${artifact} SSHLibrary.Write ${command} >${logfile} 2>&1 - [Return] ${logfile} + RETURN ${logfile} Compose_Dilemma_Filepath - [Arguments] ${default_path} ${specific_path} [Documentation] Query active SSH connection, return specific path if it exists else default path. + [Arguments] ${default_path} ${specific_path} ${out} ${rc} = SSHLibrary.Execute_Command ls -lA ${specific_path} 2>&1 return_rc=True - BuiltIn.Return_From_Keyword_If ${rc} == 0 ${specific_path} - BuiltIn.Return_From_Keyword ${default_path} + IF ${rc} == 0 RETURN ${specific_path} + RETURN ${default_path} Compose_Base_Java_Command - [Arguments] ${openjdk}=${JDKVERSION} [Documentation] Return string suitable for launching Java programs over SSHLibrary, depending on JRE version needed. ... This requires that the SSH connection on which the command is going to be used is active as it is needed for querying files. ... Commands composed for one SSH connection shall not be reused on other SSH connections as the two connections may have different Java setups. ... Not directly related to Nexus, but versioned Java tools may need this. + [Arguments] ${openjdk}=${JDKVERSION} # Check whether the user set the override and return it if yes. - BuiltIn.Run_Keyword_And_Return_If """${openjdk}""" == "openjdk8" Compose_Dilemma_Filepath ${JAVA_8_HOME_CENTOS}/bin/java ${JAVA_8_HOME_UBUNTU}/bin/java - BuiltIn.Run_Keyword_And_Return_If """${openjdk}""" == "openjdk11" Compose_Dilemma_Filepath ${JAVA_11_HOME_CENTOS}/bin/java ${JAVA_11_HOME_UBUNTU}/bin/java - BuiltIn.Run_Keyword_And_Return_If """${openjdk}""" == "openjdk17" Compose_Dilemma_Filepath ${JAVA_17_HOME_CENTOS}/bin/java ${JAVA_17_HOME_UBUNTU}/bin/java + BuiltIn.Run_Keyword_And_Return_If + ... """${openjdk}""" == "openjdk8" + ... Compose_Dilemma_Filepath + ... ${JAVA_8_HOME_CENTOS}/bin/java + ... ${JAVA_8_HOME_UBUNTU}/bin/java + BuiltIn.Run_Keyword_And_Return_If + ... """${openjdk}""" == "openjdk11" + ... Compose_Dilemma_Filepath + ... ${JAVA_11_HOME_CENTOS}/bin/java + ... ${JAVA_11_HOME_UBUNTU}/bin/java + BuiltIn.Run_Keyword_And_Return_If + ... """${openjdk}""" == "openjdk17" + ... Compose_Dilemma_Filepath + ... ${JAVA_17_HOME_CENTOS}/bin/java + ... ${JAVA_17_HOME_UBUNTU}/bin/java # Attempt to call plain "java" command directly. If it works, return it. ${out} ${rc} = SSHLibrary.Execute_Command java -version 2>&1 return_rc=True - BuiltIn.Return_From_Keyword_If ${rc} == 0 java + IF ${rc} == 0 RETURN java # Query the virtual machine for the JAVA_HOME environment variable and # use it to assemble a (hopefully) working command. If that worked out, # return the result. ${java} = SSHLibrary.Execute_Command echo $JAVA_HOME/bin/java 2>&1 ${out} ${rc} = SSHLibrary.Execute_Command ${java} -version 2>&1 return_rc=True - BuiltIn.Return_From_Keyword_If ${rc} == 0 ${java} + IF ${rc} == 0 RETURN ${java} # There are bizzare test environment setups where the (correct) JAVA_HOME # is set in the VM where Robot is running but not in the VM where the # tools are supposed to run (usually because these two are really one @@ -214,118 +286,140 @@ Compose_Base_Java_Command ${JAVA_HOME} = OperatingSystem.Get_Environment_Variable JAVA_HOME ${EMPTY} ${java} = BuiltIn.Set_Variable_If """${JAVA_HOME}"""!="" ${JAVA_HOME}/bin/java false ${out} ${rc} = SSHLibrary.Execute_Command ${java} -version 2>&1 return_rc=True - BuiltIn.Return_From_Keyword_If ${rc} == 0 ${java} + IF ${rc} == 0 RETURN ${java} # Nothing works, most likely java is not installed at all on the target # machine or it is hopelesly lost. Bail out with a helpful message # telling the user how to make it accessible for the script. - BuiltIn.Fail Unable to find Java; specify \${JDKVERSION}, put it to your PATH or set JAVA_HOME environment variable. + BuiltIn.Fail + ... Unable to find Java; specify \${JDKVERSION}, put it to your PATH or set JAVA_HOME environment variable. Compose_Full_Java_Command - [Arguments] ${options} ${openjdk}=${JDKVERSION} [Documentation] Return full Bash command to run Java with given options. ... This requires that the SSH connection on which the command is going to be used is active as it is needed for querying files. ... The options may include JVM options, application command line arguments, Bash redirects and other constructs. + [Arguments] ${options} ${openjdk}=${JDKVERSION} ${base_command} = Compose_Base_Java_Command openjdk=${openjdk} ${full_command} = BuiltIn.Set_Variable ${base_command} ${options} BuiltIn.Log ${full_command} - [Return] ${full_command} + RETURN ${full_command} Compose_Java_Home - [Arguments] ${openjdk}=${JDKVERSION} [Documentation] Compose base java command and strip trailing "/bin/java". + [Arguments] ${openjdk}=${JDKVERSION} ${java_command} = Compose_Base_Java_Command - ${java_home} ${bin} ${java} = String.Split_String_From_Right ${java_command} separator=/ max_split=2 - [Return] ${java_home} + ${java_home} ${bin} ${java} = String.Split_String_From_Right + ... ${java_command} + ... separator=/ + ... max_split=2 + RETURN ${java_home} Install_Maven_Bare - [Arguments] ${maven_version}=3.3.9 ${openjdk}=${JDKVERSION} [Documentation] Download and unpack Maven, prepare launch command with proper Java version and download settings file. ... This Keyword requires an active SSH connection to target machine. ... This Keyword sets global variables, so that suites can reuse existing installation. ... This Keyword can only place Maven (and settings) to remote current working directory. ... This Keyword does not perform any initial or final cleanup. + [Arguments] ${maven_version}=3.3.9 ${openjdk}=${JDKVERSION} # Avoid multiple initialization by several downstream libraries. ${installed_version} = BuiltIn.Get_Variable_Value \${Maven__installed_version} None - BuiltIn.Return_From_Keyword_If """${installed_version}""" == """${maven_version}""" + IF """${installed_version}""" == """${maven_version}""" RETURN BuiltIn.Set_Global_Variable \${Maven__installed_version} ${maven_version} BuiltIn.Set_Global_Variable \${maven_directory} apache-maven-${maven_version} SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -rf '${maven_directory}' ${maven_archive_filename} = BuiltIn.Set_Variable ${maven_directory}-bin.tar.gz - ${maven_download_url} = BuiltIn.Set_Variable http://www-us.apache.org/dist/maven/maven-3/${maven_version}/binaries/${maven_archive_filename} + ${maven_download_url} = BuiltIn.Set_Variable + ... http://www-us.apache.org/dist/maven/maven-3/${maven_version}/binaries/${maven_archive_filename} SSHKeywords.Execute_Command_At_Cwd_Should_Pass wget -N '${maven_download_url}' stderr_must_be_empty=False SSHKeywords.Execute_Command_At_Cwd_Should_Pass tar xvf '${maven_archive_filename}' ${java_home} = NexusKeywords.Compose_Java_Home openjdk=${openjdk} - BuiltIn.Set_Global_Variable \${maven_bash_command} export JAVA_HOME='${java_home}' && export MAVEN_OPTS='${JAVA_OPTIONS}' && ./${maven_directory}/bin/mvn + BuiltIn.Set_Global_Variable + ... \${maven_bash_command} + ... export JAVA_HOME='${java_home}' && export MAVEN_OPTS='${JAVA_OPTIONS}' && ./${maven_directory}/bin/mvn # TODO: Get settings files from Jenkins settings provider, somehow. - SSHKeywords.Execute_Command_At_Cwd_Should_Pass wget '${MAVEN_SETTINGS_URL}' -O settings.xml stderr_must_be_empty=False + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... wget '${MAVEN_SETTINGS_URL}' -O settings.xml + ... stderr_must_be_empty=False Install_Maven - [Arguments] ${maven_version}=3.3.9 ${openjdk}=${JDKVERSION} ${branch}=${EMPTY} ${patches}=${EMPTY} [Documentation] Install Maven. ... Depending on arguments, perform a multipatch build to populate local Maven repository with patched artifacts. + [Arguments] ${maven_version}=3.3.9 ${openjdk}=${JDKVERSION} ${branch}=${EMPTY} ${patches}=${EMPTY} Install_Maven_Bare maven_version=${maven_version} openjdk=${openjdk} - BuiltIn.Return_From_Keyword_If """${patches}""" == "" No post-install build requested. - BuiltIn.Run_Keyword_If """${branch}""" == "" BuiltIn.Fail BRANCH needs to be specified for multipatch builds. + IF """${patches}""" == "" RETURN No post-install build requested. + IF """${branch}""" == "" + BuiltIn.Fail BRANCH needs to be specified for multipatch builds. + END ${script_name} = BuiltIn.Set_Variable include-raw-integration-multipatch-distribution-test.sh - ${script_url} = BuiltIn.Set_Variable https://raw.githubusercontent.com/opendaylight/releng-builder/master/jjb/integration/${script_name} + ${script_url} = BuiltIn.Set_Variable + ... https://raw.githubusercontent.com/opendaylight/releng-builder/master/jjb/integration/${script_name} SSHKeywords.Execute_Command_At_Cwd_Should_Pass wget -N '${script_url}' stderr_must_be_empty=False - SSHKeywords.Execute_Command_At_Cwd_Should_Pass export WORKSPACE='${WORKSPACE}' && export BRANCH='${branch}' && export PATCHES_TO_BUILD='${patches}' && bash '${script_name}' stderr_must_be_empty=False + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... export WORKSPACE='${WORKSPACE}' && export BRANCH='${branch}' && export PATCHES_TO_BUILD='${patches}' && bash '${script_name}' + ... stderr_must_be_empty=False Run_Maven pom_file=${WORKSPACE}/patch_tester/pom.xml Run_Maven - [Arguments] ${pom_file}=pom.xml ${log_file}=${MAVEN_DEFAULT_OUTPUT_FILENAME} [Documentation] Determine arguments to use and call mvn command against given pom file. + [Arguments] ${pom_file}=pom.xml ${log_file}=${MAVEN_DEFAULT_OUTPUT_FILENAME} SSHKeywords.Execute_Command_At_Cwd_Should_Pass mkdir -p '${MAVEN_REPOSITORY_PATH}' - ${maven_repository_options} = BuiltIn.Set_Variable -Dmaven.repo.local=${MAVEN_REPOSITORY_PATH} -Dorg.ops4j.pax.url.mvn.localRepository=${MAVEN_REPOSITORY_PATH} - SSHKeywords.Execute_Command_At_Cwd_Should_Pass ${maven_bash_command} clean install dependency:tree -V -B -DoutputFile=dependency_tree.log -s './settings.xml' -f '${pom_file}' ${MAVEN_OPTIONS} ${maven_repository_options} > '${log_file}' + ${maven_repository_options} = BuiltIn.Set_Variable + ... -Dmaven.repo.local=${MAVEN_REPOSITORY_PATH} -Dorg.ops4j.pax.url.mvn.localRepository=${MAVEN_REPOSITORY_PATH} + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... ${maven_bash_command} clean install dependency:tree -V -B -DoutputFile=dependency_tree.log -s './settings.xml' -f '${pom_file}' ${MAVEN_OPTIONS} ${maven_repository_options} > '${log_file}' Get_ODL_Versions_From_Nexus [Documentation] Returns name of last release found on nexus and list of all versions. RequestsLibrary.Create_Session nexus ${NEXUS_RELEASES_URL} verify=${TRUE} - ${uri}= BuiltIn.Set_Variable maven-metadata.xml - ${response}= RequestsLibrary.Get_Request nexus ${uri} + ${uri} = BuiltIn.Set_Variable maven-metadata.xml + ${response} = RequestsLibrary.Get_Request nexus ${uri} BuiltIn.Log ${response.text} - ${root}= XML.Parse_XML ${response.text} - ${element}= XML.Get_Element ${root} versioning/latest - ${latest}= BuiltIn.Set_Variable ${element.text} + ${root} = XML.Parse_XML ${response.text} + ${element} = XML.Get_Element ${root} versioning/latest + ${latest} = BuiltIn.Set_Variable ${element.text} BuiltIn.Log ${latest} - @{elements}= XML.Get_Elements ${root} .//version - ${versions}= BuiltIn.Create_List + @{elements} = XML.Get_Elements ${root} .//version + ${versions} = BuiltIn.Create_List FOR ${element} IN @{elements} - BuiltIn.Run_Keyword_If 'Carbon' not in $element.text Collections.Append_To_List ${versions} ${element.text} + IF 'Carbon' not in $element.text + Collections.Append_To_List ${versions} ${element.text} + END END Collections.Sort_List ${versions} BuiltIn.Log_Many @{versions} - [Return] ${latest} @{versions} + RETURN ${latest} @{versions} Get_Latest_ODL_Release_From_Nexus [Documentation] Returns name of last release found on nexus - ${latest} @{versions}= Get_ODL_Versions_From_Nexus - [Return] ${latest} + ${latest} @{versions} = Get_ODL_Versions_From_Nexus + RETURN ${latest} Get_Latest_ODL_Stream_Release - [Arguments] ${stream}=latest [Documentation] Returns name for last release for specified stream. - ${latest} @{versions}= Get_ODL_Versions_From_Nexus - BuiltIn.Return_From_Keyword_If '${stream}'=='latest' ${latest} - ${latest_version}= BuiltIn.Set_Variable xxx + [Arguments] ${stream}=latest + ${latest} @{versions} = Get_ODL_Versions_From_Nexus + IF '${stream}'=='latest' RETURN ${latest} + ${latest_version} = BuiltIn.Set_Variable xxx FOR ${version} IN @{versions} - ${latest_version}= BuiltIn.Set_Variable_If '${stream}'.title() in '${version}' ${version} ${latest_version} + ${latest_version} = BuiltIn.Set_Variable_If + ... '${stream}'.title() in '${version}' + ... ${version} + ... ${latest_version} + END + IF '${latest_version}'=='xxx' + BuiltIn.Fail Could not find latest release for stream ${stream} END - BuiltIn.Run_Keyword_If '${latest_version}'=='xxx' BuiltIn.Fail Could not find latest release for stream ${stream} BuiltIn.Log ${latest_version} - [Return] ${latest_version} + RETURN ${latest_version} Get_Latest_ODL_Stream_Release_URL - [Arguments] ${stream}=latest ${format}=.zip [Documentation] Returns URL for last release for specified stream. Default format is .zip. - ${latest_version}= Get_Latest_ODL_Stream_Release ${stream} - ${url}= BuiltIn.Set_Variable ${NEXUS_RELEASES_URL}/${latest_version}/karaf-${latest_version}${format} + [Arguments] ${stream}=latest ${format}=.zip + ${latest_version} = Get_Latest_ODL_Stream_Release ${stream} + ${url} = BuiltIn.Set_Variable ${NEXUS_RELEASES_URL}/${latest_version}/karaf-${latest_version}${format} BuiltIn.Log ${url} - [Return] ${url} + RETURN ${url} Get_Latest_ODL_Previous_Stream_Release - [Arguments] ${stream}=${ODL_STREAM} [Documentation] Returns name for last release for previous stream of specified stream. ... Note: If specified stream is not found on nexus, then it is taken as new one (not released yet). ... So in this case, latest release version is return. @@ -339,22 +433,28 @@ Get_Latest_ODL_Previous_Stream_Release ... version is found from the list. The CompareStream.robot library keeps a mapping of major version ... numbers to the global variable ${ODL_STREAM} so that is used to ensure we get a major version that is ... older than the current running major version. - ${latest} @{versions}= Get_ODL_Versions_From_Nexus - ${current_version}= BuiltIn.Set_Variable ${Stream_dict}[${ODL_STREAM}].0 - ${latest_version}= BuiltIn.Set_Variable 0.0 + [Arguments] ${stream}=${ODL_STREAM} + ${latest} @{versions} = Get_ODL_Versions_From_Nexus + ${current_version} = BuiltIn.Set_Variable ${Stream_dict}[${ODL_STREAM}].0 + ${latest_version} = BuiltIn.Set_Variable 0.0 FOR ${version} IN @{versions} ${version} = String.Replace String Using Regexp ${version} ^0\. ${EMPTY} - ${latest_version}= Set Variable If ${version} > ${latest_version} and ${version} < ${current_version} ${version} ${latest_version} + ${latest_version} = Set Variable If + ... ${version} > ${latest_version} and ${version} < ${current_version} + ... ${version} + ... ${latest_version} + END + ${latest_version} = Set Variable 0.${latest_version} + IF '${latest_version}'=='0.0.0' + BuiltIn.Fail Could not find latest previous release for stream ${stream} END - ${latest_version}= Set Variable 0.${latest_version} - BuiltIn.Run_Keyword_If '${latest_version}'=='0.0.0' BuiltIn.Fail Could not find latest previous release for stream ${stream} BuiltIn.Log ${latest_version} - [Return] ${latest_version} + RETURN ${latest_version} Get_Latest_ODL_Previous_Stream_Release_URL - [Arguments] ${stream}=${ODL_STREAM} ${format}=.zip [Documentation] Returns URL for last release for previous stream of specified stream. Default format is .zip. - ${latest_version}= Get_Latest_ODL_Previous_Stream_Release ${stream} - ${url}= BuiltIn.Set_Variable ${NEXUS_RELEASES_URL}/${latest_version}/karaf-${latest_version}${format} + [Arguments] ${stream}=${ODL_STREAM} ${format}=.zip + ${latest_version} = Get_Latest_ODL_Previous_Stream_Release ${stream} + ${url} = BuiltIn.Set_Variable ${NEXUS_RELEASES_URL}/${latest_version}/karaf-${latest_version}${format} BuiltIn.Log ${url} - [Return] ${url} + RETURN ${url} diff --git a/csit/libraries/ODLMicroKeywords.robot b/csit/libraries/ODLMicroKeywords.robot index f1a7222250..fcb6866395 100644 --- a/csit/libraries/ODLMicroKeywords.robot +++ b/csit/libraries/ODLMicroKeywords.robot @@ -1,14 +1,14 @@ *** Settings *** -Documentation A test suite which contains keywords of ODL micro which are used commonly. -Library Collections -Library OperatingSystem -Library SSHLibrary -Library String -Library XML -Library Collections -Library RequestsLibrary +Documentation A test suite which contains keywords of ODL micro which are used commonly. + +Library Collections +Library OperatingSystem +Library SSHLibrary +Library String +Library XML +Library Collections +Library RequestsLibrary -*** Variables *** *** Keywords *** Download ODL Micro @@ -17,7 +17,13 @@ Download ODL Micro SSHLibrary.Set_Client_Configuration timeout=10s SSHLibrary.Set_Client_Configuration prompt=${ODL_SYSTEM_PROMPT} SSHKeywords.Flexible_SSH_Login ${ODL_SYSTEM_USER} ${ODL_SYSTEM_PASSWORD} delay=4s - ${file_name} = NexusKeywords.Deploy_Test_Tool odl-micro micro-netconf micro ${BASE_URL} build_version=${ODL_MICRO_VERSION} build_location=org/opendaylight/odlmicro + ${file_name} = NexusKeywords.Deploy_Test_Tool + ... odl-micro + ... micro-netconf + ... micro + ... ${BASE_URL} + ... build_version=${ODL_MICRO_VERSION} + ... build_location=org/opendaylight/odlmicro BuiltIn.Set_Suite_Variable ${FILENAME} ${filename} Run ODL Micro @@ -27,14 +33,16 @@ Run ODL Micro SSHLibrary.Write cd ${ODL_MICRO_WORKSPACE}/micro-netconf-${ODL_MICRO_VERSION} ${response} = SSHLibrary.Execute_Command ls BuiltIn.Log ${response} - ${command} = NexusKeywords.Compose_Full_Java_Command -Xms128M -Xmx2048m -XX:+UnlockDiagnosticVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -Dcom.sun.management.jmxremote -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom -cp "etc/initial/:lib/*" org.opendaylight.netconf.micro.NetconfMain > /tmp/odlmicro.log 2>&1 + ${command} = NexusKeywords.Compose_Full_Java_Command + ... -Xms128M -Xmx2048m -XX:+UnlockDiagnosticVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -Dcom.sun.management.jmxremote -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom -cp "etc/initial/:lib/*" org.opendaylight.netconf.micro.NetconfMain > /tmp/odlmicro.log 2>&1 BuiltIn.Log ${command} SSHLibrary.Write ${command} Get pid [Arguments] ${process_name} - ${pid} = SSHLibrary.Execute Command ps -fu ${ODL_SYSTEM_USER} | grep "${process_name}" | grep -v "grep" | awk '{print $2}' - [Return] ${pid} + ${pid} = SSHLibrary.Execute Command + ... ps -fu ${ODL_SYSTEM_USER} | grep "${process_name}" | grep -v "grep" | awk '{print $2}' + RETURN ${pid} Check netstat [Arguments] ${portno} ${session}=ODL_Micro_instance @@ -48,13 +56,15 @@ Check Process Stats SSHLibrary.Set_Client_Configuration timeout=10s SSHLibrary.Set_Client_Configuration prompt=${ODL_SYSTEM_PROMPT} SSHKeywords.Flexible_SSH_Login ${ODL_SYSTEM_USER} ${ODL_SYSTEM_PASSWORD} delay=4s - ${mock_pid} Get pid ${process_name} - BuiltIn.Run_Keyword_If '${mock_pid}' == '${EMPTY}' BuiltIn.Fail No ${process_name} process is running + ${mock_pid} = Get pid ${process_name} + IF '${mock_pid}' == '${EMPTY}' + BuiltIn.Fail No ${process_name} process is running + END Kill process [Arguments] ${process_name} ${ssh_alias}=ODL_Micro_instance SSHLibrary.Switch_Connection ${ssh_alias} - ${mock_pid} Get pid ${process_name} + ${mock_pid} = Get pid ${process_name} SSHLibrary.Execute_Command kill -9 ${mock_pid} Download Netconf Testtool @@ -63,11 +73,23 @@ Download Netconf Testtool SSHLibrary.Set_Client_Configuration timeout=10s SSHLibrary.Set_Client_Configuration prompt=${TOOLS_SYSTEM_PROMPT} SSHKeywords.Flexible_SSH_Login ${TOOLS_SYSTEM_USER} ${TOOLS_SYSTEM_PASSWORD} delay=4s - ${file_name} = NexusKeywords.Deploy_Test_Tool netconf netconf-testtool build_version=${NETCONF_TESTTOOL_VERSION} build_location=org/opendaylight/netconf + ${file_name} = NexusKeywords.Deploy_Test_Tool + ... netconf + ... netconf-testtool + ... build_version=${NETCONF_TESTTOOL_VERSION} + ... build_location=org/opendaylight/netconf Set Global Variable ${NETCONF_FILENAME} ${filename} - ${file_name} = NexusKeywords.Deploy_Test_Tool netconf netconf-testtool rest-perf-client build_version=${NETCONF_TESTTOOL_VERSION} build_location=org/opendaylight/netconf + ${file_name} = NexusKeywords.Deploy_Test_Tool + ... netconf + ... netconf-testtool + ... rest-perf-client + ... build_version=${NETCONF_TESTTOOL_VERSION} + ... build_location=org/opendaylight/netconf Set Global Variable ${RESTPERF_FILENAME} ${filename} Run Netconf Testtool [Arguments] ${ssh_alias}=Netconf_System - NetconfKeywords.Start_Testtool ${NETCONF_FILENAME} device-count=1 schemas=${CURDIR}/../variables/netconf/CRUD/schemas + NetconfKeywords.Start_Testtool + ... ${NETCONF_FILENAME} + ... device-count=1 + ... schemas=${CURDIR}/../variables/netconf/CRUD/schemas diff --git a/csit/libraries/ODLTools.robot b/csit/libraries/ODLTools.robot index de9c8d2436..ae983f4047 100644 --- a/csit/libraries/ODLTools.robot +++ b/csit/libraries/ODLTools.robot @@ -1,7 +1,9 @@ *** Settings *** -Documentation Robot wrapper around ODLTools. -Library OperatingSystem -Resource ../variables/Variables.robot +Documentation Robot wrapper around ODLTools. + +Library OperatingSystem +Resource ../variables/Variables.robot + *** Keywords *** Version @@ -10,46 +12,50 @@ Version ${rc} ${output} = OperatingSystem.Run And Return Rc And Output ${cmd} BuiltIn.Log rc: ${rc}, output: ${output} BuiltIn.Should Be True '${rc}' == '0' - [Return] ${output} + RETURN ${output} Get EOS - [Arguments] ${node_ip}=${ODL_SYSTEM_IP} ${port}=${RESTCONFPORT} ${test_name}=${SUITE_NAME}.${TEST_NAME} [Documentation] Get the various ODL entity ownership information + [Arguments] ${node_ip}=${ODL_SYSTEM_IP} ${port}=${RESTCONFPORT} ${test_name}=${SUITE_NAME}.${TEST_NAME} ${dstdir} = Get Path ${test_name} - ${cmd} = BuiltIn.Set Variable odltools netvirt show eos -i ${node_ip} -t ${port} -u ${ODL_RESTCONF_USER} -w ${ODL_RESTCONF_PASSWORD} --path ${dstdir} + ${cmd} = BuiltIn.Set Variable + ... odltools netvirt show eos -i ${node_ip} -t ${port} -u ${ODL_RESTCONF_USER} -w ${ODL_RESTCONF_PASSWORD} --path ${dstdir} ${rc} ${output} = OperatingSystem.Run And Return Rc And Output ${cmd} BuiltIn.Log rc: ${rc}, output: ${output} BuiltIn.Should Be True '${rc}' == '0' - [Return] ${output} + RETURN ${output} Get Cluster Info - [Arguments] ${port}=${RESTCONFPORT} [Documentation] Get ODL Cluster related information like transaction counts, commit rates, etc. + [Arguments] ${port}=${RESTCONFPORT} FOR ${i} IN RANGE ${NUM_ODL_SYSTEM} - ${cmd} = BuiltIn.Set Variable odltools netvirt show cluster-info -i ${ODL_SYSTEM_${i+1}_IP} -t ${port} -u ${ODL_RESTCONF_USER} -w ${ODL_RESTCONF_PASSWORD} + ${cmd} = BuiltIn.Set Variable + ... odltools netvirt show cluster-info -i ${ODL_SYSTEM_${i+1}_IP} -t ${port} -u ${ODL_RESTCONF_USER} -w ${ODL_RESTCONF_PASSWORD} ${output} = OperatingSystem.Run ${cmd} BuiltIn.Log output: ${output} END Analyze Tunnels - [Arguments] ${node_ip}=${ODL_SYSTEM_IP} ${port}=${RESTCONFPORT} ${test_name}=${SUITE_NAME}.${TEST_NAME} [Documentation] Analyze Tunnel Mesh creation for any errors and log results + [Arguments] ${node_ip}=${ODL_SYSTEM_IP} ${port}=${RESTCONFPORT} ${test_name}=${SUITE_NAME}.${TEST_NAME} ${dstdir} = Get Path ${test_name} - ${cmd} = BuiltIn.Set Variable odltools netvirt analyze tunnels -i ${node_ip} -t ${port} -u ${ODL_RESTCONF_USER} -w ${ODL_RESTCONF_PASSWORD} --path ${dstdir} + ${cmd} = BuiltIn.Set Variable + ... odltools netvirt analyze tunnels -i ${node_ip} -t ${port} -u ${ODL_RESTCONF_USER} -w ${ODL_RESTCONF_PASSWORD} --path ${dstdir} ${rc} ${output} = OperatingSystem.Run And Return Rc And Output ${cmd} BuiltIn.Log rc: ${rc}, output: ${output} BuiltIn.Should Be True '${rc}' == '0' - [Return] ${output} + RETURN ${output} Get All - [Arguments] ${node_ip}=${ODL_SYSTEM_IP} ${port}=${RESTCONFPORT} ${test_name}=${SUITE_NAME}.${TEST_NAME} [Documentation] Get all results provided by ODLTools + [Arguments] ${node_ip}=${ODL_SYSTEM_IP} ${port}=${RESTCONFPORT} ${test_name}=${SUITE_NAME}.${TEST_NAME} ODLTools.Get Cluster Info BuiltIn.run Keyword And Ignore Error ODLTools.Get EOS ${node_ip} test_name=${test_name} BuiltIn.run Keyword And Ignore Error ODLTools.Analyze Tunnels ${node_ip} test_name=${test_name} Get Path - [Arguments] ${test_name}=${SUITE_NAME}.${TEST_NAME} [Documentation] Get odltools path for a given test case - ${tmpdir} = BuiltIn.Evaluate """${test_name}""".replace(" ","_").replace("/","_").replace(".","_").replace("(","_").replace(")","_") - [Return] /tmp/${tmpdir} + [Arguments] ${test_name}=${SUITE_NAME}.${TEST_NAME} + ${tmpdir} = BuiltIn.Evaluate + ... """${test_name}""".replace(" ","_").replace("/","_").replace(".","_").replace("(","_").replace(")","_") + RETURN /tmp/${tmpdir} diff --git a/csit/libraries/OVSDB.robot b/csit/libraries/OVSDB.robot index be3d13b975..b36aea3631 100644 --- a/csit/libraries/OVSDB.robot +++ b/csit/libraries/OVSDB.robot @@ -1,27 +1,32 @@ *** Settings *** -Library Collections -Library ipaddress -Library OperatingSystem -Library RequestsLibrary -Library SSHLibrary -Library String -Resource ClusterManagement.robot -Resource Utils.robot -Resource ${CURDIR}/TemplatedRequests.robot -Resource ../variables/Variables.robot -Resource ../variables/ovsdb/Variables.robot -Resource ../variables/netvirt/Variables.robot +Library Collections +Library ipaddress +Library OperatingSystem +Library RequestsLibrary +Library SSHLibrary +Library String +Resource ClusterManagement.robot +Resource Utils.robot +Resource ${CURDIR}/TemplatedRequests.robot +Resource ../variables/Variables.robot +Resource ../variables/ovsdb/Variables.robot +Resource ../variables/netvirt/Variables.robot + *** Variables *** -${OVSDB_CONFIG_DIR} ${CURDIR}/../variables/ovsdb +${OVSDB_CONFIG_DIR} ${CURDIR}/../variables/ovsdb + *** Keywords *** Log Request [Arguments] ${resp_content} - ${resp_json} = BuiltIn.Run Keyword If '''${resp_content}''' != '${EMPTY}' RequestsLibrary.To Json ${resp_content} pretty_print=True - ... ELSE BuiltIn.Set Variable ${EMPTY} + IF '''${resp_content}''' != '${EMPTY}' + ${resp_json} = RequestsLibrary.To Json ${resp_content} pretty_print=True + ELSE + ${resp_json} = BuiltIn.Set Variable ${EMPTY} + END BuiltIn.Log ${resp_json} - [Return] ${resp_json} + RETURN ${resp_json} Create OVSDB Node [Arguments] ${node_ip} ${port}=${OVSDB_NODE_PORT} @@ -36,8 +41,8 @@ Create OVSDB Node BuiltIn.Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Connect To Ovsdb Node - [Arguments] ${node_ip} ${port}=${OVSDB_NODE_PORT} [Documentation] This will Initiate the connection to OVSDB node from controller + [Arguments] ${node_ip} ${port}=${OVSDB_NODE_PORT} ${body} = OperatingSystem.Get File ${OVSDB_CONFIG_DIR}/connect.json ${body} = String.Replace String ${body} 127.0.0.1 ${node_ip} ${body} = String.Replace String ${body} 61644 ${port} @@ -49,14 +54,14 @@ Connect To Ovsdb Node BuiltIn.Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Disconnect From Ovsdb Node - [Arguments] ${node_ip} ${port}=${OVSDB_NODE_PORT} [Documentation] This request will disconnect the OVSDB node from the controller + [Arguments] ${node_ip} ${port}=${OVSDB_NODE_PORT} ${resp} = RequestsLibrary.Delete Request session ${RFC8040_SOUTHBOUND_NODE_API}${node_ip}%3A${port} BuiltIn.Should Be Equal As Strings ${resp.status_code} 204 Add Bridge To Ovsdb Node - [Arguments] ${node_id} ${node_ip} ${bridge} ${datapath_id} ${port}=${OVSDB_NODE_PORT} [Documentation] This will create a bridge and add it to the OVSDB node. + [Arguments] ${node_id} ${node_ip} ${bridge} ${datapath_id} ${port}=${OVSDB_NODE_PORT} ${body} = OperatingSystem.Get File ${OVSDB_CONFIG_DIR}/create_bridge.json ${body} = String.Replace String ${body} ovsdb://127.0.0.1:61644 ovsdb://${node_id} ${body} = String.Replace String ${body} tcp:127.0.0.1:6633 tcp:${ODL_SYSTEM_IP}:6633 @@ -73,16 +78,18 @@ Add Bridge To Ovsdb Node BuiltIn.Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Delete Bridge From Ovsdb Node - [Arguments] ${node_id} ${bridge} [Documentation] This request will delete the bridge node from the OVSDB - ${resp} = RequestsLibrary.Delete Request session ${RFC8040_SOUTHBOUND_NODE_API}${node_id}%2Fbridge%2F${bridge} + [Arguments] ${node_id} ${bridge} + ${resp} = RequestsLibrary.Delete Request + ... session + ... ${RFC8040_SOUTHBOUND_NODE_API}${node_id}%2Fbridge%2F${bridge} BuiltIn.Should Be Equal As Strings ${resp.status_code} 204 Add Termination Point - [Arguments] ${node_id} ${bridge} ${tp_name} ${remote_ip}=${TOOLS_SYSTEM_IP} [Documentation] Using the json data body file as a template, a REST config request is made to ... create a termination-point ${tp_name} on ${bridge} for the given ${node_id}. The ports ... remote-ip defaults to ${TOOLS_SYSTEM_IP} + [Arguments] ${node_id} ${bridge} ${tp_name} ${remote_ip}=${TOOLS_SYSTEM_IP} ${body} = OperatingSystem.Get File ${OVSDB_CONFIG_DIR}/create_port.json ${body} = String.Replace String ${body} 192.168.0.21 ${remote_ip} ${body} = String.Replace String ${body} vxlanport ${tp_name} @@ -92,32 +99,36 @@ Add Termination Point BuiltIn.Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Add Vxlan To Bridge - [Arguments] ${node_ip} ${bridge} ${vxlan_port} ${remote_ip} ${port}=${OVSDB_NODE_PORT} [Documentation] This request will create vxlan port for vxlan tunnel and attach it to the specific bridge + [Arguments] ${node_ip} ${bridge} ${vxlan_port} ${remote_ip} ${port}=${OVSDB_NODE_PORT} OVSDB.Add Termination Point ${node_ip}:${port} ${bridge} ${vxlan_port} ${remote_ip} Verify OVS Reports Connected - [Arguments] ${tools_system}=${TOOLS_SYSTEM_IP} [Documentation] Uses "vsctl show" to check for string "is_connected" + [Arguments] ${tools_system}=${TOOLS_SYSTEM_IP} ${output} = Verify Ovs-vsctl Output show is_connected ${tools_system} - [Return] ${output} + RETURN ${output} Verify Ovs-vsctl Output - [Arguments] ${vsctl_args} ${expected_output} ${ovs_system}=${TOOLS_SYSTEM_IP} ${should_match}=True [Documentation] A wrapper keyword to make it easier to validate ovs-vsctl output, and gives an easy ... way to check this output in a WUKS. The argument ${should_match} can control if the match should ... exist (True} or not (False) or don't care (anything but True or False). ${should_match} is True by default + [Arguments] ${vsctl_args} ${expected_output} ${ovs_system}=${TOOLS_SYSTEM_IP} ${should_match}=True ${output} = Utils.Run Command On Mininet ${ovs_system} sudo ovs-vsctl ${vsctl_args} BuiltIn.Log ${output} - BuiltIn.Run Keyword If "${should_match}" == "True" BuiltIn.Should Contain ${output} ${expected_output} - BuiltIn.Run Keyword If "${should_match}" == "False" BuiltIn.Should Not Contain ${output} ${expected_output} - [Return] ${output} + IF "${should_match}" == "True" + BuiltIn.Should Contain ${output} ${expected_output} + END + IF "${should_match}" == "False" + BuiltIn.Should Not Contain ${output} ${expected_output} + END + RETURN ${output} Get OVSDB UUID - [Arguments] ${ovs_system_ip}=${TOOLS_SYSTEM_IP} ${controller_http_session}=session [Documentation] Queries the topology in the operational datastore and searches for the node that has ... the ${ovs_system_ip} argument as the "remote-ip". If found, the value returned will be the value of ... node-id stripped of "ovsdb://uuid/". If not found, ${EMPTY} will be returned. + [Arguments] ${ovs_system_ip}=${TOOLS_SYSTEM_IP} ${controller_http_session}=session ${uuid} = Set Variable ${EMPTY} ${resp} = RequestsLibrary.Get Request ${controller_http_session} ${RFC8040_OPERATIONAL_TOPO_OVSDB1_API} OVSDB.Log Request ${resp.text} @@ -132,25 +143,33 @@ Get OVSDB UUID FOR ${node} IN @{node_list} ${node_id} = Collections.Get From Dictionary ${node} node-id ${node_uuid} = String.Replace String ${node_id} ovsdb://uuid/ ${EMPTY} - ${status} ${connection_info} = BuiltIn.Run Keyword And Ignore Error Collections.Get From Dictionary ${node} ovsdb:connection-info - ${status} ${remote_ip} = BuiltIn.Run Keyword And Ignore Error Collections.Get From Dictionary ${connection_info} remote-ip + ${status} ${connection_info} = BuiltIn.Run Keyword And Ignore Error + ... Collections.Get From Dictionary + ... ${node} + ... ovsdb:connection-info + ${status} ${remote_ip} = BuiltIn.Run Keyword And Ignore Error + ... Collections.Get From Dictionary + ... ${connection_info} + ... remote-ip ${uuid} = Set Variable If '${remote_ip}' == '${ovs_system_ip}' ${node_uuid} ${uuid} END - [Return] ${uuid} + RETURN ${uuid} Collect OVSDB Debugs - [Arguments] ${switch}=${INTEGRATION_BRIDGE} [Documentation] Used to log useful test debugs for OVSDB related system tests. + [Arguments] ${switch}=${INTEGRATION_BRIDGE} ${output} = Utils.Run Command On Mininet ${TOOLS_SYSTEM_IP} sudo ovs-vsctl show BuiltIn.Log ${output} - ${output} = Utils.Run Command On Mininet ${TOOLS_SYSTEM_IP} sudo ovs-ofctl -O OpenFlow13 dump-flows ${switch} | cut -d',' -f3- + ${output} = Utils.Run Command On Mininet + ... ${TOOLS_SYSTEM_IP} + ... sudo ovs-ofctl -O OpenFlow13 dump-flows ${switch} | cut -d',' -f3- BuiltIn.Log ${output} Clean OVSDB Test Environment - [Arguments] ${tools_system}=${TOOLS_SYSTEM_IP} [Documentation] General Use Keyword attempting to sanitize test environment for OVSDB related ... tests. Not every step will always be neccessary, but should not cause any problems for ... any new ovsdb test suites. + [Arguments] ${tools_system}=${TOOLS_SYSTEM_IP} Utils.Clean Mininet System ${tools_system} Utils.Run Command On Mininet ${tools_system} sudo ovs-vsctl del-manager Utils.Run Command On Mininet ${tools_system} sudo /usr/share/openvswitch/scripts/ovs-ctl stop @@ -158,27 +177,29 @@ Clean OVSDB Test Environment Utils.Run Command On Mininet ${tools_system} sudo /usr/share/openvswitch/scripts/ovs-ctl start Restart OVSDB - [Arguments] ${ovs_ip} [Documentation] Restart the OVS node without cleaning the current configuration. + [Arguments] ${ovs_ip} ${output} = Utils.Run Command On Mininet ${ovs_ip} sudo systemctl restart openvswitch BuiltIn.Log ${output} Set Controller In OVS Bridge - [Arguments] ${tools_system} ${bridge} ${controller_opt} ${ofversion}=13 [Documentation] Sets controller for the OVS bridge ${bridge} using ${controller_opt} and OF version ${ofversion}. - Utils.Run Command On Mininet ${tools_system} sudo ovs-vsctl set bridge ${bridge} protocols=OpenFlow${ofversion} + [Arguments] ${tools_system} ${bridge} ${controller_opt} ${ofversion}=13 + Utils.Run Command On Mininet + ... ${tools_system} + ... sudo ovs-vsctl set bridge ${bridge} protocols=OpenFlow${ofversion} Utils.Run Command On Mininet ${tools_system} sudo ovs-vsctl set-controller ${bridge} ${controller_opt} Check OVS OpenFlow Connections - [Arguments] ${tools_system} ${of_connections} [Documentation] Check OVS instance with IP ${tools_system} has ${of_connections} OpenFlow connections. + [Arguments] ${tools_system} ${of_connections} ${output} = Utils.Run Command On Mininet ${tools_system} sudo ovs-vsctl show BuiltIn.Log ${output} BuiltIn.Should Contain X Times ${output} is_connected ${of_connections} Add Multiple Managers to OVS - [Arguments] ${tools_system}=${TOOLS_SYSTEM_IP} ${controller_index_list}=${EMPTY} ${ovs_mgr_port}=6640 [Documentation] Connect OVS to the list of controllers in the ${controller_index_list} or all if no list is provided. + [Arguments] ${tools_system}=${TOOLS_SYSTEM_IP} ${controller_index_list}=${EMPTY} ${ovs_mgr_port}=6640 ${index_list} = ClusterManagement.List Indices Or All given_list=${controller_index_list} Utils.Clean Mininet System ${tools_system} ${ovs_opt} = BuiltIn.Set Variable @@ -191,61 +212,73 @@ Add Multiple Managers to OVS BuiltIn.Log ${output} ${controller_index} = Collections.Get_From_List ${index_list} 0 ${session} = ClusterManagement.Resolve_Http_Session_For_Member member_index=${controller_index} - ${ovsdb_uuid} = BuiltIn.Wait Until Keyword Succeeds 30s 2s OVSDB.Get OVSDB UUID controller_http_session=${session} - [Return] ${ovsdb_uuid} + ${ovsdb_uuid} = BuiltIn.Wait Until Keyword Succeeds + ... 30s + ... 2s + ... OVSDB.Get OVSDB UUID + ... controller_http_session=${session} + RETURN ${ovsdb_uuid} Get DPID - [Arguments] ${ip} [Documentation] Returns the dpnid from the system at the given ip address using ovs-ofctl assuming br-int is present. - ${output} = Utils.Run Command On Remote System ${ip} sudo ovs-ofctl show -O Openflow13 ${INTEGRATION_BRIDGE} | head -1 | awk -F "dpid:" '{print $2}' + [Arguments] ${ip} + ${output} = Utils.Run Command On Remote System + ... ${ip} + ... sudo ovs-ofctl show -O Openflow13 ${INTEGRATION_BRIDGE} | head -1 | awk -F "dpid:" '{print $2}' ${dpnid} = BuiltIn.Convert To Integer ${output} 16 BuiltIn.Log ${dpnid} - [Return] ${dpnid} + RETURN ${dpnid} Get Subnet - [Arguments] ${ip} [Documentation] Return the subnet from the system at the given ip address and interface + [Arguments] ${ip} ${output} = Utils.Run Command On Remote System ${ip} /usr/sbin/ip addr show | grep ${ip} | cut -d' ' -f6 ${interface} = ipaddress.ip_interface ${output} ${network} = BuiltIn.Set Variable ${interface.network.__str__()} - [Return] ${network} + RETURN ${network} Get Ethernet Adapter - [Arguments] ${ip} [Documentation] Returns the ethernet adapter name from the system at the given ip address using ip addr show. - ${adapter} = Utils.Run Command On Remote System ${ip} /usr/sbin/ip addr show | grep ${ip} | cut -d " " -f 11 + [Arguments] ${ip} + ${adapter} = Utils.Run Command On Remote System + ... ${ip} + ... /usr/sbin/ip addr show | grep ${ip} | cut -d " " -f 11 BuiltIn.Log ${adapter} - [Return] ${adapter} + RETURN ${adapter} Get Default Gateway - [Arguments] ${ip} [Documentation] Returns the default gateway at the given ip address using route command. - ${gateway} = Utils.Run Command On Remote System ${ip} /usr/sbin/route -n | grep '^0.0.0.0' | cut -d " " -f 10 + [Arguments] ${ip} + ${gateway} = Utils.Run Command On Remote System + ... ${ip} + ... /usr/sbin/route -n | grep '^0.0.0.0' | cut -d " " -f 10 BuiltIn.Log ${gateway} - [Return] ${gateway} + RETURN ${gateway} Get Port Number - [Arguments] ${subportid} ${ip_addr} [Documentation] Get the port number for the given sub-port id - ${command} = Set Variable sudo ovs-ofctl -O OpenFlow13 show ${INTEGRATION_BRIDGE} | grep ${subportid} | awk '{print$1}' + [Arguments] ${subportid} ${ip_addr} + ${command} = Set Variable + ... sudo ovs-ofctl -O OpenFlow13 show ${INTEGRATION_BRIDGE} | grep ${subportid} | awk '{print$1}' BuiltIn.Log sudo ovs-ofctl -O OpenFlow13 show ${INTEGRATION_BRIDGE} | grep ${subportid} | awk '{print$1}' ${output} = Utils.Run Command On Remote System ${ip_addr} ${command} ${port_number} = BuiltIn.Should Match Regexp ${output} [0-9]+ - [Return] ${port_number} + RETURN ${port_number} Get Port Metadata - [Arguments] ${ip_addr} ${port} [Documentation] Get the Metadata for a given port - ${cmd} = Set Variable sudo ovs-ofctl dump-flows -O Openflow13 ${INTEGRATION_BRIDGE} | grep table=0 | grep in_port=${port} + [Arguments] ${ip_addr} ${port} + ${cmd} = Set Variable + ... sudo ovs-ofctl dump-flows -O Openflow13 ${INTEGRATION_BRIDGE} | grep table=0 | grep in_port=${port} ${output} = Utils.Run Command On Remote System ${ip_addr} ${cmd} @{list_any_matches} = String.Get_Regexp_Matches ${output} metadata:(\\w{12}) 1 ${metadata} = Builtin.Convert To String @{list_any_matches} ${output} = String.Get Substring ${metadata} 2 - [Return] ${output} + RETURN ${output} Log Config And Operational Topology [Documentation] For debugging purposes, this will log both config and operational topo data stores - ${resp} RequestsLibrary.Get Request session ${RFC8040_CONFIG_TOPO_API} + ${resp} = RequestsLibrary.Get Request session ${RFC8040_CONFIG_TOPO_API} OVSDB.Log Request ${resp.text} ${resp} = RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_TOPO_API} OVSDB.Log Request ${resp.text} @@ -253,14 +286,14 @@ Log Config And Operational Topology Config and Operational Topology Should Be Empty [Documentation] This will check that only the expected output is there for both operational and config ... topology data stores. Empty probably means that only ovsdb:1 is there. - ${config_resp} RequestsLibrary.Get Request session ${RFC8040_CONFIG_TOPO_API} - ${operational_resp} RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_TOPO_API} + ${config_resp} = RequestsLibrary.Get Request session ${RFC8040_CONFIG_TOPO_API} + ${operational_resp} = RequestsLibrary.Get Request session ${RFC8040_OPERATIONAL_TOPO_API} BuiltIn.Should Contain ${config_resp.text} {"topology-id":"ovsdb:1"} BuiltIn.Should Contain ${operational_resp.text} {"topology-id":"ovsdb:1"} Modify Multi Port Body - [Arguments] ${ovs_1_port_name} ${ovs_2_port_name} ${bridge} [Documentation] Updates two port names for the given ${bridge} in config store + [Arguments] ${ovs_1_port_name} ${ovs_2_port_name} ${bridge} ${body} = OperatingSystem.Get File ${OVSDB_CONFIG_DIR}/bug_7414/create_multiple_ports.json ${ovs_1_ovsdb_uuid} = Get OVSDB UUID ${TOOLS_SYSTEM_IP} ${ovs_2_ovsdb_uuid} = Get OVSDB UUID ${TOOLS_SYSTEM_2_IP} @@ -278,7 +311,7 @@ Modify Multi Port Body ${resp} = RequestsLibrary.Put Request session ${uri} data=${body} OVSDB.Log Request ${resp.text} BuiltIn.Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} - [Return] ${body} + RETURN ${body} Create Qos [Arguments] ${qos} @@ -313,37 +346,56 @@ Update Qos BuiltIn.Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Create Qos Linked Queue - ${body} OperatingSystem.Get File ${OVSDB_CONFIG_DIR}/bug_7160/create_qoslinkedqueue.json - ${resp} RequestsLibrary.Put Request session ${RFC8040_SOUTHBOUND_NODE_HOST1_API} data=${body} + ${body} = OperatingSystem.Get File ${OVSDB_CONFIG_DIR}/bug_7160/create_qoslinkedqueue.json + ${resp} = RequestsLibrary.Put Request session ${RFC8040_SOUTHBOUND_NODE_HOST1_API} data=${body} OVSDB.Log Request ${resp.text} BuiltIn.Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Add OVS Logging - [Arguments] ${conn_id} [Documentation] Add higher levels of OVS logging + [Arguments] ${conn_id} SSHLibrary.Switch Connection ${conn_id} - @{modules} = BuiltIn.Create List bridge:file:dbg connmgr:file:dbg inband:file:dbg ofp_actions:file:dbg ofp_errors:file:dbg - ... ofp_msgs:file:dbg ovsdb_error:file:dbg rconn:file:dbg tunnel:file:dbg vconn:file:dbg + @{modules} = BuiltIn.Create List + ... bridge:file:dbg + ... connmgr:file:dbg + ... inband:file:dbg + ... ofp_actions:file:dbg + ... ofp_errors:file:dbg + ... ofp_msgs:file:dbg + ... ovsdb_error:file:dbg + ... rconn:file:dbg + ... tunnel:file:dbg + ... vconn:file:dbg FOR ${module} IN @{modules} - Utils.Write Commands Until Expected Prompt sudo ovs-appctl --target ovs-vswitchd vlog/set ${module} ${DEFAULT_LINUX_PROMPT_STRICT} + Utils.Write Commands Until Expected Prompt + ... sudo ovs-appctl --target ovs-vswitchd vlog/set ${module} + ... ${DEFAULT_LINUX_PROMPT_STRICT} END - Utils.Write Commands Until Expected Prompt sudo ovs-appctl --target ovs-vswitchd vlog/list ${DEFAULT_LINUX_PROMPT_STRICT} + Utils.Write Commands Until Expected Prompt + ... sudo ovs-appctl --target ovs-vswitchd vlog/list + ... ${DEFAULT_LINUX_PROMPT_STRICT} Reset OVS Logging - [Arguments] ${conn_id} [Documentation] Reset the OVS logging + [Arguments] ${conn_id} SSHLibrary.Switch Connection ${conn_id} - ${output} = Utils.Write Commands Until Expected Prompt sudo ovs-appctl --target ovs-vswitchd vlog/set :file:info ${DEFAULT_LINUX_PROMPT_STRICT} + ${output} = Utils.Write Commands Until Expected Prompt + ... sudo ovs-appctl --target ovs-vswitchd vlog/set :file:info + ... ${DEFAULT_LINUX_PROMPT_STRICT} Suite Setup SetupUtils.Setup_Utils_For_Setup_And_Teardown KarafKeywords.Open Controller Karaf Console On Background - RequestsLibrary.Create Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} auth=${AUTH} headers=${HEADERS} + RequestsLibrary.Create Session + ... session + ... http://${ODL_SYSTEM_IP}:${RESTCONFPORT} + ... auth=${AUTH} + ... headers=${HEADERS} OVSDB.Log Config And Operational Topology Suite Teardown - [Arguments] ${uris}=@{EMPTY} [Documentation] Cleans up test environment, close existing sessions. + [Arguments] ${uris}=@{EMPTY} OVSDB.Clean OVSDB Test Environment ${TOOLS_SYSTEM_IP} FOR ${uri} IN @{uris} RequestsLibrary.Delete Request session ${uri} @@ -353,26 +405,34 @@ Suite Teardown RequestsLibrary.Delete All Sessions Get DumpFlows And Ovsconfig - [Arguments] ${conn_id} ${bridge} [Documentation] Get the OvsConfig and Flow entries from OVS + [Arguments] ${conn_id} ${bridge} SSHLibrary.Switch Connection ${conn_id} Write Commands Until Expected Prompt sudo ovs-vsctl show ${DEFAULT_LINUX_PROMPT_STRICT} Write Commands Until Expected Prompt sudo ovs-vsctl list Open_vSwitch ${DEFAULT_LINUX_PROMPT_STRICT} - Write Commands Until Expected Prompt sudo ovs-ofctl show ${bridge} -OOpenFlow13 ${DEFAULT_LINUX_PROMPT_STRICT} - Write Commands Until Expected Prompt sudo ovs-ofctl dump-flows ${bridge} -OOpenFlow13 ${DEFAULT_LINUX_PROMPT_STRICT} - Write Commands Until Expected Prompt sudo ovs-ofctl dump-groups ${bridge} -OOpenFlow13 ${DEFAULT_LINUX_PROMPT_STRICT} - Write Commands Until Expected Prompt sudo ovs-ofctl dump-group-stats ${bridge} -OOpenFlow13 ${DEFAULT_LINUX_PROMPT_STRICT} + Write Commands Until Expected Prompt + ... sudo ovs-ofctl show ${bridge} -OOpenFlow13 + ... ${DEFAULT_LINUX_PROMPT_STRICT} + Write Commands Until Expected Prompt + ... sudo ovs-ofctl dump-flows ${bridge} -OOpenFlow13 + ... ${DEFAULT_LINUX_PROMPT_STRICT} + Write Commands Until Expected Prompt + ... sudo ovs-ofctl dump-groups ${bridge} -OOpenFlow13 + ... ${DEFAULT_LINUX_PROMPT_STRICT} + Write Commands Until Expected Prompt + ... sudo ovs-ofctl dump-group-stats ${bridge} -OOpenFlow13 + ... ${DEFAULT_LINUX_PROMPT_STRICT} Write Commands Until Expected Prompt sudo ovs-vsctl list interface ${DEFAULT_LINUX_PROMPT_STRICT} Start OVS - [Arguments] ${ovs_ip} [Documentation] start the OVS node. + [Arguments] ${ovs_ip} ${output} = Utils.Run Command On Mininet ${ovs_ip} sudo /usr/share/openvswitch/scripts/ovs-ctl start BuiltIn.Log ${output} Stop OVS - [Arguments] ${ovs_ip} [Documentation] Stop the OVS node. + [Arguments] ${ovs_ip} ${output} = Utils.Run Command On Mininet ${ovs_ip} sudo /usr/share/openvswitch/scripts/ovs-ctl stop BuiltIn.Log ${output} @@ -380,37 +440,37 @@ Get Bridge Data [Documentation] This keyword returns first bridge name and UUID from list of bridges. ${result} = SSHLibrary.Execute Command sudo ovs-vsctl show ${uuid} = String.Get Line ${result} 0 - ${line} ${bridge_name} Builtin.Should Match Regexp ${result} Bridge ([\\w-]+) - [Return] ${uuid} ${bridge_name} + ${line} ${bridge_name} = Builtin.Should Match Regexp ${result} Bridge ([\\w-]+) + RETURN ${uuid} ${bridge_name} Delete OVS Controller - [Arguments] ${ovs_ip} ${bridge}=${INTEGRATION_BRIDGE} [Documentation] Delete controller from OVS + [Arguments] ${ovs_ip} ${bridge}=${INTEGRATION_BRIDGE} ${del_ctr} = Utils.Run Command On Remote System ${ovs_ip} sudo ovs-vsctl del-controller ${bridge} BuiltIn.Log ${del_ctr} Delete OVS Manager - [Arguments] ${ovs_ip} [Documentation] Delete manager from OVS + [Arguments] ${ovs_ip} ${del_mgr} = Utils.Run Command On Remote System ${ovs_ip} sudo ovs-vsctl del-manager BuiltIn.Log ${del_mgr} Delete Groups On Bridge - [Arguments] ${ovs_ip} ${br}=${INTEGRATION_BRIDGE} [Documentation] Delete OVS groups from ${br} + [Arguments] ${ovs_ip} ${br}=${INTEGRATION_BRIDGE} ${del_grp} = Utils.Run Command On Remote System ${ovs_ip} sudo ovs-ofctl -O Openflow13 del-groups ${br} BuiltIn.Log ${del_grp} Get Ports From Bridge By Type - [Arguments] ${ovs_ip} ${br} ${type} [Documentation] Get ${type} ports for a bridge ${br} on node ${ovs_ip}. + [Arguments] ${ovs_ip} ${br} ${type} ${ports} = Utils.Run Command On Remote System ${ovs_ip} sudo ovs-vsctl list-ports ${br} | grep "${type}" ${ports_list} = String.Split to lines ${ports} - [Return] ${ports_list} + RETURN ${ports_list} Delete Ports On Bridge By Type - [Arguments] ${ovs_ip} ${br} ${type} [Documentation] List all ports of ${br} and delete ${type} ports + [Arguments] ${ovs_ip} ${br} ${type} ${ports_present} = Get Ports From Bridge By Type ${ovs_ip} ${br} ${type} FOR ${port} IN @{ports_present} ${del-ports} = Utils.Run Command On Remote System ${ovs_ip} sudo ovs-vsctl del-port ${br} ${port} @@ -420,67 +480,129 @@ Delete Ports On Bridge By Type BuiltIn.Log ${ports_present_after_delete} Get Tunnel Id And Packet Count - [Arguments] ${conn_id} ${table_id} ${tun_id} ${mac}="" [Documentation] Get tunnel id and packet count from specified table id ... Using regex get the n_packet and the tunnel_id from the table flow. + [Arguments] ${conn_id} ${table_id} ${tun_id} ${mac}="" ${tun_id} = BuiltIn.Convert To Hex ${tun_id} prefix=0x lowercase=yes - ${cmd} = BuiltIn.Run Keyword If "${table_id}" == "${INTERNAL_TUNNEL_TABLE}" BuiltIn.Set Variable sudo ovs-ofctl dump-flows br-int -OOpenFlow13 | grep table=${table_id} | grep ${mac} | grep tun_id=${tun_id} | grep goto_table:${ELAN_DMACTABLE} - ... ELSE BuiltIn.Set Variable sudo ovs-ofctl dump-flows br-int -OOpenFlow13 | grep table=${table_id} | grep ${mac} + IF "${table_id}" == "${INTERNAL_TUNNEL_TABLE}" + ${cmd} = BuiltIn.Set Variable + ... sudo ovs-ofctl dump-flows br-int -OOpenFlow13 | grep table=${table_id} | grep ${mac} | grep tun_id=${tun_id} | grep goto_table:${ELAN_DMACTABLE} + ELSE + ${cmd} = BuiltIn.Set Variable + ... sudo ovs-ofctl dump-flows br-int -OOpenFlow13 | grep table=${table_id} | grep ${mac} + END SSHLibrary.Switch Connection ${conn_id} ${output} = Utils.Write Commands Until Expected Prompt ${cmd} ${DEFAULT_LINUX_PROMPT_STRICT} - @{list}= Split to lines ${output} + @{list} = Split to lines ${output} ${output} = Set Variable ${list}[0] - ${output} = String.Get Regexp Matches ${output} n_packets=([0-9]+),.*set_field:(0x[0-9a-z]+)|n_packets=([0-9]+),.*tun_id=(0x[0-9a-z]+) 1 2 3 + ${output} = String.Get Regexp Matches + ... ${output} + ... n_packets=([0-9]+),.*set_field:(0x[0-9a-z]+)|n_packets=([0-9]+),.*tun_id=(0x[0-9a-z]+) + ... 1 + ... 2 + ... 3 ... 4 ${output} = BuiltIn.Set Variable ${output}[0] - ${output} Convert To List ${output} - ${packet_count} ${tunnel_id} = BuiltIn.Run Keyword If "${table_id}" == "${ELAN_DMACTABLE}" BuiltIn.Set Variable ${output}[0] ${output}[1] - ... ELSE IF "${table_id}" == "${INTERNAL_TUNNEL_TABLE}" BuiltIn.Set Variable ${output}[2] ${output}[3] - ... ELSE IF "${table_id}" == "${L3_TABLE}" BuiltIn.Set Variable ${output}[0] ${output}[1] + ${output} = Convert To List ${output} + IF "${table_id}" == "${ELAN_DMACTABLE}" + ${packet_count} ${tunnel_id} = BuiltIn.Set Variable ${output}[0] ${output}[1] + ELSE IF "${table_id}" == "${INTERNAL_TUNNEL_TABLE}" + ${packet_count} ${tunnel_id} = BuiltIn.Set Variable ${output}[2] ${output}[3] + ELSE IF "${table_id}" == "${L3_TABLE}" + ${packet_count} ${tunnel_id} = BuiltIn.Set Variable ${output}[0] ${output}[1] + ELSE + ${packet_count} ${tunnel_id} = Set Variable ${None} ${None} + END ${tunnel_id} = Convert To Integer ${tunnel_id} 16 - [Return] ${tunnel_id} ${packet_count} + RETURN ${tunnel_id} ${packet_count} Verify Dump Flows For Specific Table - [Arguments] ${compute_ip} ${table_num} ${flag} ${additional_args}=${EMPTY} @{matching_paras} [Documentation] To Verify flows are present for the corresponding table Number - ${flow_output} = Utils.Run Command On Remote System ${compute_ip} sudo ovs-ofctl -O OpenFlow13 dump-flows ${INTEGRATION_BRIDGE}|grep table=${table_num} ${additional_args} + [Arguments] ${compute_ip} ${table_num} ${flag} ${additional_args}=${EMPTY} @{matching_paras} + ${flow_output} = Utils.Run Command On Remote System + ... ${compute_ip} + ... sudo ovs-ofctl -O OpenFlow13 dump-flows ${INTEGRATION_BRIDGE}|grep table=${table_num} ${additional_args} Log ${flow_output} FOR ${matching_str} IN @{matching_paras} - BuiltIn.Run Keyword If ${flag}==True BuiltIn.Should Contain ${flow_output} ${matching_str} - ... ELSE BuiltIn.Should Not Contain ${flow_output} ${matching_str} + IF ${flag}==True + BuiltIn.Should Contain ${flow_output} ${matching_str} + ELSE + BuiltIn.Should Not Contain ${flow_output} ${matching_str} + END END Verify Vni Segmentation Id and Tunnel Id + [Documentation] Get tunnel id and packet count from specified table id and destination port mac address [Arguments] ${port1} ${port2} ${net1} ${net2} ${vm1_ip} ${vm2_ip} ... ${ip}="" - [Documentation] Get tunnel id and packet count from specified table id and destination port mac address ${port_mac1} = OpenStackOperations.Get Port Mac ${port1} ${port_mac2} = OpenStackOperations.Get Port Mac ${port2} ${segmentation_id1} = OpenStackOperations.Get Network Segmentation Id ${net1} ${segmentation_id2} = OpenStackOperations.Get Network Segmentation Id ${net2} - ${egress_tun_id} ${before_count_egress_port1} = OVSDB.Get Tunnel Id And Packet Count ${OS_CMP1_CONN_ID} ${L3_TABLE} tun_id=${segmentation_id2} mac=${port_mac2} + ${egress_tun_id} ${before_count_egress_port1} = OVSDB.Get Tunnel Id And Packet Count + ... ${OS_CMP1_CONN_ID} + ... ${L3_TABLE} + ... tun_id=${segmentation_id2} + ... mac=${port_mac2} BuiltIn.Should Be Equal As Numbers ${segmentation_id2} ${egress_tun_id} - ${egress_tun_id} ${before_count_egress_port2} = OVSDB.Get Tunnel Id And Packet Count ${OS_CMP2_CONN_ID} ${L3_TABLE} tun_id=${segmentation_id1} mac=${port_mac1} + ${egress_tun_id} ${before_count_egress_port2} = OVSDB.Get Tunnel Id And Packet Count + ... ${OS_CMP2_CONN_ID} + ... ${L3_TABLE} + ... tun_id=${segmentation_id1} + ... mac=${port_mac1} BuiltIn.Should Be Equal As Numbers ${segmentation_id1} ${egress_tun_id} - ${ingress_tun_id} ${before_count_ingress_port1} = OVSDB.Get Tunnel Id And Packet Count ${OS_CMP1_CONN_ID} ${INTERNAL_TUNNEL_TABLE} tun_id=${segmentation_id1} + ${ingress_tun_id} ${before_count_ingress_port1} = OVSDB.Get Tunnel Id And Packet Count + ... ${OS_CMP1_CONN_ID} + ... ${INTERNAL_TUNNEL_TABLE} + ... tun_id=${segmentation_id1} BuiltIn.Should Be Equal As Numbers ${segmentation_id1} ${ingress_tun_id} - ${ingress_tun_id} ${before_count_ingress_port2} = OVSDB.Get Tunnel Id And Packet Count ${OS_CMP2_CONN_ID} ${INTERNAL_TUNNEL_TABLE} tun_id=${segmentation_id2} + ${ingress_tun_id} ${before_count_ingress_port2} = OVSDB.Get Tunnel Id And Packet Count + ... ${OS_CMP2_CONN_ID} + ... ${INTERNAL_TUNNEL_TABLE} + ... tun_id=${segmentation_id2} BuiltIn.Should Be Equal As Numbers ${segmentation_id2} ${ingress_tun_id} - ${ping_cmd} = BuiltIn.Run Keyword If '${ip}'=='ipv4' BuiltIn.Set Variable ping -c ${DEFAULT_PING_COUNT} ${vm2_ip} - ... ELSE BuiltIn.Set Variable ping6 -c ${DEFAULT_PING_COUNT} ${vm2_ip} + IF '${ip}'=='ipv4' + ${ping_cmd} = BuiltIn.Set Variable ping -c ${DEFAULT_PING_COUNT} ${vm2_ip} + ELSE + ${ping_cmd} = BuiltIn.Set Variable ping6 -c ${DEFAULT_PING_COUNT} ${vm2_ip} + END ${output} = OpenStackOperations.Execute Command on VM Instance ${net1} ${vm1_ip} ${ping_cmd} BuiltIn.Should Contain ${output} 64 bytes - BuiltIn.Wait Until Keyword Succeeds 60s 5s OVSDB.Verify Vni Packet Count After Traffic ${before_count_egress_port1} ${before_count_egress_port2} ${before_count_ingress_port1} - ... ${before_count_ingress_port2} ${segmentation_id1} ${segmentation_id2} ${port_mac1} ${port_mac2} + BuiltIn.Wait Until Keyword Succeeds + ... 60s + ... 5s + ... OVSDB.Verify Vni Packet Count After Traffic + ... ${before_count_egress_port1} + ... ${before_count_egress_port2} + ... ${before_count_ingress_port1} + ... ${before_count_ingress_port2} + ... ${segmentation_id1} + ... ${segmentation_id2} + ... ${port_mac1} + ... ${port_mac2} Verify Vni Packet Count After Traffic + [Documentation] Verify the packet count after the traffic sent [Arguments] ${before_count_egress_port1} ${before_count_egress_port2} ${before_count_ingress_port1} ${before_count_ingress_port2} ${segmentation_id1} ${segmentation_id2} ... ${port_mac1} ${port_mac2} - [Documentation] Verify the packet count after the traffic sent - ${tun_id} ${after_count_egress_port2} = OVSDB.Get Tunnel Id And Packet Count ${OS_CMP2_CONN_ID} ${L3_TABLE} tun_id=${segmentation_id1} mac=${port_mac1} - ${tun_id} ${after_count_ingress_port2} = OVSDB.Get Tunnel Id And Packet Count ${OS_CMP2_CONN_ID} ${INTERNAL_TUNNEL_TABLE} tun_id=${segmentation_id2} - ${tun_id} ${after_count_egress_port1} = OVSDB.Get Tunnel Id And Packet Count ${OS_CMP1_CONN_ID} ${L3_TABLE} tun_id=${segmentation_id2} mac=${port_mac2} - ${tun_id} ${after_count_ingress_port1} = OVSDB.Get Tunnel Id And Packet Count ${OS_CMP1_CONN_ID} ${INTERNAL_TUNNEL_TABLE} tun_id=${segmentation_id1} + ${tun_id} ${after_count_egress_port2} = OVSDB.Get Tunnel Id And Packet Count + ... ${OS_CMP2_CONN_ID} + ... ${L3_TABLE} + ... tun_id=${segmentation_id1} + ... mac=${port_mac1} + ${tun_id} ${after_count_ingress_port2} = OVSDB.Get Tunnel Id And Packet Count + ... ${OS_CMP2_CONN_ID} + ... ${INTERNAL_TUNNEL_TABLE} + ... tun_id=${segmentation_id2} + ${tun_id} ${after_count_egress_port1} = OVSDB.Get Tunnel Id And Packet Count + ... ${OS_CMP1_CONN_ID} + ... ${L3_TABLE} + ... tun_id=${segmentation_id2} + ... mac=${port_mac2} + ${tun_id} ${after_count_ingress_port1} = OVSDB.Get Tunnel Id And Packet Count + ... ${OS_CMP1_CONN_ID} + ... ${INTERNAL_TUNNEL_TABLE} + ... tun_id=${segmentation_id1} ${diff_count_egress_port1} = BuiltIn.Evaluate ${after_count_egress_port1} - ${before_count_egress_port1} ${diff_count_ingress_port1} = BuiltIn.Evaluate ${after_count_ingress_port1} - ${before_count_ingress_port1} ${diff_count_egress_port2} = BuiltIn.Evaluate ${after_count_egress_port2} - ${before_count_egress_port2} @@ -491,22 +613,26 @@ Verify Vni Packet Count After Traffic BuiltIn.Should Be True ${diff_count_ingress_port2} >= ${DEFAULT_PING_COUNT} Get Flow Entries On Node - [Arguments] ${conn_id} ${switch}=${INTEGRATION_BRIDGE} [Documentation] Return flow entries on the given Node. + [Arguments] ${conn_id} ${switch}=${INTEGRATION_BRIDGE} SSHLibrary.Switch Connection ${conn_id} - ${output} = Utils.Write Commands Until Expected Prompt sudo ovs-ofctl -O OpenFlow13 dump-flows ${switch} ${DEFAULT_LINUX_PROMPT_STRICT} + ${output} = Utils.Write Commands Until Expected Prompt + ... sudo ovs-ofctl -O OpenFlow13 dump-flows ${switch} + ... ${DEFAULT_LINUX_PROMPT_STRICT} BuiltIn.Log ${output} - [Return] ${output} + RETURN ${output} Verify Ovsdb State - [Arguments] ${dpn_ip} ${state}=ACTIVE [Documentation] Verify ovsdb state for the given DPN - ${output} = Utils.Run Command On Remote System And Log ${dpn_ip} sudo ovsdb-client dump -f list Open_vSwitch Controller | grep state + [Arguments] ${dpn_ip} ${state}=ACTIVE + ${output} = Utils.Run Command On Remote System And Log + ... ${dpn_ip} + ... sudo ovsdb-client dump -f list Open_vSwitch Controller | grep state BuiltIn.Log ${output} BuiltIn.Should Contain ${output} state=${state} Verify Flows Are Present On Node - [Arguments] ${conn_id} ${match} [Documentation] Verify Flows Are Present On The Given Node + [Arguments] ${conn_id} ${match} ${output} = OVSDB.Get Flow Entries On Node ${conn_id} BuiltIn.Should Contain ${output} ${match} diff --git a/csit/libraries/OcpAgentKeywords.robot b/csit/libraries/OcpAgentKeywords.robot index 60615c08aa..46326cdb41 100644 --- a/csit/libraries/OcpAgentKeywords.robot +++ b/csit/libraries/OcpAgentKeywords.robot @@ -1,16 +1,21 @@ *** Settings *** -Documentation OCP agent library. This library is useful for tests using ocp agent tool to simulate RRH devices. -Library SSHLibrary -Resource SSHKeywords.robot -Resource OVSDB.robot -Variables ../variables/Variables.py +Documentation OCP agent library. This library is useful for tests using ocp agent tool to simulate RRH devices. + +Library SSHLibrary +Resource SSHKeywords.robot +Resource OVSDB.robot +Variables ../variables/Variables.py + *** Keywords *** Install Agent - [Arguments] ${mininet}=${TOOLS_SYSTEM_IP} ${controller}=${ODL_SYSTEM_IP} [Documentation] Start Agent with custom topology and connect to controller. + [Arguments] ${mininet}=${TOOLS_SYSTEM_IP} ${controller}=${ODL_SYSTEM_IP} Log Clear any existing Agent - ${conn_id}= SSHLibrary.Open Connection ${mininet} prompt=${TOOLS_SYSTEM_PROMPT} timeout=${DEFAULT_TIMEOUT} + ${conn_id}= SSHLibrary.Open Connection + ... ${mininet} + ... prompt=${TOOLS_SYSTEM_PROMPT} + ... timeout=${DEFAULT_TIMEOUT} Set Suite Variable ${conn_id} SSHKeywords.Flexible Mininet Login SSHLibrary.Write rm -rf /tmp/agent @@ -24,30 +29,38 @@ Install Agent Close Connection Start Emulator Single - [Arguments] ${mininet}=${TOOLS_SYSTEM_IP} ${controller}=${ODL_SYSTEM_IP} ${vendorID}=TST ${serialNumber}=100 [Documentation] Start Agent with custom topology and connect to controller. - ${mininet_conn_id}= SSHLibrary.Open Connection ${mininet} prompt=${TOOLS_SYSTEM_PROMPT} timeout=${DEFAULT_TIMEOUT} + [Arguments] ${mininet}=${TOOLS_SYSTEM_IP} ${controller}=${ODL_SYSTEM_IP} ${vendorID}=TST ${serialNumber}=100 + ${mininet_conn_id}= SSHLibrary.Open Connection + ... ${mininet} + ... prompt=${TOOLS_SYSTEM_PROMPT} + ... timeout=${DEFAULT_TIMEOUT} Set Suite Variable ${mininet_conn_id} SSHKeywords.Flexible Mininet Login - SSHLibrary.Write java -cp /tmp/agent/simple-agent/src/main/java/ org.opendaylight.ocpplugin.OcpAgent ${controller} 1033 ${vendorID} ${serialNumber} + SSHLibrary.Write + ... java -cp /tmp/agent/simple-agent/src/main/java/ org.opendaylight.ocpplugin.OcpAgent ${controller} 1033 ${vendorID} ${serialNumber} SSHLibrary.Read Until getParamResp - [Return] ${mininet_conn_id} + RETURN ${mininet_conn_id} Start Emulator Multiple - [Arguments] ${mininet}=${TOOLS_SYSTEM_IP} ${controller}=${ODL_SYSTEM_IP} ${vendorID}=TST ${number}=100 [Documentation] Start Agent with custom topology and connect to controller. - ${mininet_conn_id}= SSHLibrary.Open Connection ${mininet} prompt=${TOOLS_SYSTEM_PROMPT} timeout=${DEFAULT_TIMEOUT} + [Arguments] ${mininet}=${TOOLS_SYSTEM_IP} ${controller}=${ODL_SYSTEM_IP} ${vendorID}=TST ${number}=100 + ${mininet_conn_id}= SSHLibrary.Open Connection + ... ${mininet} + ... prompt=${TOOLS_SYSTEM_PROMPT} + ... timeout=${DEFAULT_TIMEOUT} Set Suite Variable ${mininet_conn_id} SSHKeywords.Flexible Mininet Login FOR ${NODE_NUM} IN RANGE 1 ${number} - SSHLibrary.Write java -cp /tmp/agent/simple-agent/src/main/java/ org.opendaylight.ocpplugin.OcpAgent ${controller} 1033 ${vendorID} ${NODE_NUM} & + SSHLibrary.Write + ... java -cp /tmp/agent/simple-agent/src/main/java/ org.opendaylight.ocpplugin.OcpAgent ${controller} 1033 ${vendorID} ${NODE_NUM} & SSHLibrary.Read Until getParamResp END - [Return] ${mininet_conn_id} + RETURN ${mininet_conn_id} Stop Emulator And Exit - [Arguments] ${mininet_conn_id} [Documentation] Stops Agent and exits session ${mininet_conn_id} + [Arguments] ${mininet_conn_id} SSHLibrary.Switch Connection ${mininet_conn_id} SSHLibrary.Write pkill -f OcpAgent Close Connection diff --git a/csit/libraries/OpenStackOperations.robot b/csit/libraries/OpenStackOperations.robot index a89820d170..83889add71 100644 --- a/csit/libraries/OpenStackOperations.robot +++ b/csit/libraries/OpenStackOperations.robot @@ -1,100 +1,113 @@ *** Settings *** -Documentation Openstack library. This library is useful for tests to create network, subnet, router and vm instances -Library Collections -Library Process -Library OperatingSystem -Library RequestsLibrary -Library SSHLibrary -Library String -Resource DataModels.robot -Resource DevstackUtils.robot -Resource KarafKeywords.robot -Resource L2GatewayOperations.robot -Resource ODLTools.robot -Resource OVSDB.robot -Resource SetupUtils.robot -Resource SSHKeywords.robot -Resource Tcpdump.robot -Resource Utils.robot -Resource ../variables/Variables.robot -Resource ../variables/openflowplugin/Variables.robot -Resource ../variables/netvirt/Variables.robot -Variables ../variables/netvirt/Modules.py +Documentation Openstack library. This library is useful for tests to create network, subnet, router and vm instances + +Library Collections +Library Process +Library OperatingSystem +Library RequestsLibrary +Library SSHLibrary +Library String +Resource DataModels.robot +Resource DevstackUtils.robot +Resource KarafKeywords.robot +Resource L2GatewayOperations.robot +Resource ODLTools.robot +Resource OVSDB.robot +Resource SetupUtils.robot +Resource SSHKeywords.robot +Resource Tcpdump.robot +Resource Utils.robot +Resource ../variables/Variables.robot +Resource ../variables/openflowplugin/Variables.robot +Resource ../variables/netvirt/Variables.robot +Variables ../variables/netvirt/Modules.py + *** Variables *** -@{VALIDATION_KEYWORDS} Verify Services Verify Expected Default Tunnels Verify Expected Default Tables On Nodes -${VALIDATION_FILE} /tmp/validations.txt +@{VALIDATION_KEYWORDS} +... Verify Services +... Verify Expected Default Tunnels +... Verify Expected Default Tables On Nodes +${VALIDATION_FILE} /tmp/validations.txt + *** Keywords *** Get Tenant ID From Security Group [Documentation] Returns tenant ID by reading it from existing default security-group. ${output} = OpenStack CLI openstack security group show default | grep "| tenant_id" | awk '{print $4}' - [Return] ${output} + RETURN ${output} Get Tenant ID From Network - [Arguments] ${network_uuid} [Documentation] Returns tenant ID by reading it from existing network. - ${resp} = TemplatedRequests.Get_From_Uri uri=${CONFIG_API}/neutron:neutron/networks/network/${network_uuid}/ accept=${ACCEPT_EMPTY} session=session + [Arguments] ${network_uuid} + ${resp} = TemplatedRequests.Get_From_Uri + ... uri=${CONFIG_API}/neutron:neutron/networks/network/${network_uuid}/ + ... accept=${ACCEPT_EMPTY} + ... session=session ${temp_vars} = BuiltIn.Set Variable ['network'][0]['tenant-id'] ${tenant_id} = Utils.Extract Value From Content ${resp} ${temp_vars} - [Return] ${tenant_id} + RETURN ${tenant_id} Create Network - [Arguments] ${network_name} ${additional_args}=${EMPTY} ${verbose}=TRUE [Documentation] Create Network with openstack request. + [Arguments] ${network_name} ${additional_args}=${EMPTY} ${verbose}=TRUE ${output} = OpenStack CLI openstack network create ${network_name} ${additional_args} - [Return] ${output} + RETURN ${output} Create Multiple Networks - [Arguments] @{name_of_networks} [Documentation] Create required number of networks and return a list of the resulting network ids + [Arguments] @{name_of_networks} ${net_list_ids} = BuiltIn.Create List @{EMPTY} FOR ${net} IN @{name_of_networks} ${output} = OpenStackOperations.Create Network ${net} ${net_id} = Get Regexp Matches ${output} ${REGEX_UUID} Collections.Append To List ${net_list_ids} ${net_id} END - [Return] @{net_list_ids} + RETURN @{net_list_ids} Update Network - [Arguments] ${network_name} ${additional_args}=${EMPTY} [Documentation] Update Network with neutron request. + [Arguments] ${network_name} ${additional_args}=${EMPTY} ${output} = OpenStack CLI openstack network set ${network_name} ${additional_args} - [Return] ${output} + RETURN ${output} Show Network - [Arguments] ${network_name} [Documentation] Show Network with neutron request. + [Arguments] ${network_name} ${output} = OpenStack CLI openstack network show ${network_name} - [Return] ${output} + RETURN ${output} List Networks [Documentation] List networks and return output with neutron client. ${output} = OpenStack CLI openstack network list - [Return] ${output} + RETURN ${output} List Subnets [Documentation] List subnets and return output with neutron client. ${output} = OpenStack CLI openstack subnet list - [Return] ${output} + RETURN ${output} Delete Network - [Arguments] ${network_name} [Documentation] Delete Network with neutron request. + [Arguments] ${network_name} ${output} = OpenStack CLI openstack network delete ${network_name} Create SubNet - [Arguments] ${network_name} ${subnet_name} ${range_ip} ${additional_args}=${EMPTY} [Documentation] Create SubNet for the Network with neutron request. - ${output} = OpenStack CLI openstack subnet create --network ${network_name} --subnet-range ${range_ip} ${subnet_name} ${additional_args} + [Arguments] ${network_name} ${subnet_name} ${range_ip} ${additional_args}=${EMPTY} + ${output} = OpenStack CLI + ... openstack subnet create --network ${network_name} --subnet-range ${range_ip} ${subnet_name} ${additional_args} Create Multiple Subnets - [Arguments] ${network_names} ${subnet_names} ${subnet_cidr} [Documentation] Create required number of subnets for previously created networks and return subnet id + [Arguments] ${network_names} ${subnet_names} ${subnet_cidr} ${number_of_networks} = BuiltIn.Get Length ${network_names} @{subnet_id_list} = BuiltIn.Create List @{EMPTY} FOR ${index} IN RANGE ${number_of_networks} - OpenStackOperations.Create SubNet ${network_names[${index}]} ${subnet_names[${index}]} ${subnet_cidr[${index}]} + OpenStackOperations.Create SubNet + ... ${network_names[${index}]} + ... ${subnet_names[${index}]} + ... ${subnet_cidr[${index}]} END ${sub_list} = OpenStackOperations.List Subnets FOR ${index} IN RANGE ${number_of_networks} @@ -102,172 +115,193 @@ Create Multiple Subnets ${subnet_id} = OpenStackOperations.Get Subnet Id ${subnet_names[${index}]} Collections.Append To List ${subnet_id_list} ${subnet_id} END - [Return] @{subnet_id_list} + RETURN @{subnet_id_list} Update SubNet - [Arguments] ${subnet_name} ${additional_args}=${EMPTY} [Documentation] Update subnet with openstack subnet set request. + [Arguments] ${subnet_name} ${additional_args}=${EMPTY} ${output} = OpenStack CLI openstack subnet set ${subnet_name} ${additional_args} - [Return] ${output} + RETURN ${output} Unset SubNet - [Arguments] ${subnet_name} ${additional_args}=${EMPTY} [Documentation] Update subnet with openstack subnet unset request + [Arguments] ${subnet_name} ${additional_args}=${EMPTY} ${output} = OpenStack CLI openstack subnet unset ${subnet_name} ${additional_args} - [Return] ${output} + RETURN ${output} Show SubNet - [Arguments] ${subnet_name} [Documentation] Show subnet with neutron request. + [Arguments] ${subnet_name} ${output} = OpenStack CLI openstack subnet show ${subnet_name} - [Return] ${output} + RETURN ${output} Create Port - [Arguments] ${network_name} ${port_name} ${sg}=default ${additional_args}=${EMPTY} ${allowed_address_pairs}=${EMPTY} [Documentation] Create Port with neutron request. + [Arguments] ${network_name} ${port_name} ${sg}=default ${additional_args}=${EMPTY} ${allowed_address_pairs}=${EMPTY} # if allowed_address_pairs is not empty we need to create the arguments to pass to the port create command. They are # in a different format with the neutron vs openstack cli. ${address_pair_length} = BuiltIn.Get Length ${allowed_address_pairs} ${allowed_pairs_argv} = BuiltIn.Set Variable ${EMPTY} - ${allowed_pairs_argv} = BuiltIn.Set Variable If '${address_pair_length}'=='2' --allowed-address ip-address=${allowed_address_pairs}[0] --allowed-address ip-address=${allowed_address_pairs}[1] ${allowed_pairs_argv} - ${output} = OpenStack CLI openstack port create --network ${network_name} ${port_name} --security-group ${sg} ${additional_args} ${allowed_pairs_argv} + ${allowed_pairs_argv} = BuiltIn.Set Variable If + ... '${address_pair_length}'=='2' + ... --allowed-address ip-address=${allowed_address_pairs}[0] --allowed-address ip-address=${allowed_address_pairs}[1] + ... ${allowed_pairs_argv} + ${output} = OpenStack CLI + ... openstack port create --network ${network_name} ${port_name} --security-group ${sg} ${additional_args} ${allowed_pairs_argv} Update Port - [Arguments] ${port_name} ${additional_args}=${EMPTY} [Documentation] Update port with neutron request. + [Arguments] ${port_name} ${additional_args}=${EMPTY} ${output} = OpenStack CLI openstack port set ${port_name} ${additional_args} - [Return] ${output} + RETURN ${output} Show Port - [Arguments] ${port_name} [Documentation] Show port with neutron request. + [Arguments] ${port_name} ${output} = OpenStack CLI openstack port show ${port_name} - [Return] ${output} + RETURN ${output} Delete Port - [Arguments] ${port_name} [Documentation] Delete Port with neutron request. + [Arguments] ${port_name} ${output} = OpenStack CLI openstack port delete ${port_name} List Ports [Documentation] List ports and return output with neutron client. ${output} = OpenStack CLI openstack port list - [Return] ${output} + RETURN ${output} List Nova VMs [Documentation] List VMs and return output with nova client. ${output} = OpenStack CLI openstack server list --all-projects - [Return] ${output} + RETURN ${output} Create And Associate Floating IPs - [Arguments] ${external_net} @{vm_list} [Documentation] Create and associate floating IPs to VMs with nova request + [Arguments] ${external_net} @{vm_list} ${ip_list} = BuiltIn.Create List @{EMPTY} FOR ${vm} IN @{vm_list} ${output} = OpenStack CLI openstack floating ip create ${external_net} @{ip} = String.Get Regexp Matches ${output} [0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3} ${ip_length} = BuiltIn.Get Length ${ip} - BuiltIn.Run Keyword If ${ip_length}>0 Collections.Append To List ${ip_list} ${ip}[0] - ... ELSE Collections.Append To List ${ip_list} None - ${vm_ip} = OpenStack CLI openstack server show ${vm} | grep "addresses" | awk '{print $4}' | cut -d"=" -f 2 - ${port_id} = OpenStack CLI openstack port list | grep "ip_address='${vm_ip}'" | awk '{print $2}' | cut -d"=" -f 2 - ${output} = BuiltIn.Run Keyword If '${OPENSTACK_BRANCH}' == 'stable/rocky' OpenStack CLI openstack floating ip set --port ${port_id} ${ip}[0] - ... ELSE OpenStack CLI openstack server add floating ip ${vm} ${ip}[0] + IF ${ip_length}>0 + Collections.Append To List ${ip_list} ${ip}[0] + ELSE + Collections.Append To List ${ip_list} None + END + ${vm_ip} = OpenStack CLI + ... openstack server show ${vm} | grep "addresses" | awk '{print $4}' | cut -d"=" -f 2 + ${port_id} = OpenStack CLI + ... openstack port list | grep "ip_address='${vm_ip}'" | awk '{print $2}' | cut -d"=" -f 2 + IF '${OPENSTACK_BRANCH}' == 'stable/rocky' + ${output} = OpenStack CLI openstack floating ip set --port ${port_id} ${ip}[0] + ELSE + ${output} = OpenStack CLI openstack server add floating ip ${vm} ${ip}[0] + END END - [Return] ${ip_list} + RETURN ${ip_list} Remove Floating Ip From Vm - [Arguments] ${vm_name} ${fip} [Documentation] Remove the Floating IP From VM Instance - ${vm_ip} = OpenStack CLI openstack server show ${vm_name} | grep "addresses" | awk '{print $4}' | cut -d"=" -f 2 - ${port_id} = OpenStack CLI openstack port list | grep "ip_address='${vm_ip}'" | awk '{print $2}' | cut -d"=" -f 2 - ${output} = BuiltIn.Run Keyword If '${OPENSTACK_BRANCH}' == 'stable/rocky' OpenStack CLI openstack floating ip unset --port ${port_id} ${fip} - ... ELSE OpenStack CLI openstack server remove floating ip ${vm_name} ${fip} + [Arguments] ${vm_name} ${fip} + ${vm_ip} = OpenStack CLI + ... openstack server show ${vm_name} | grep "addresses" | awk '{print $4}' | cut -d"=" -f 2 + ${port_id} = OpenStack CLI + ... openstack port list | grep "ip_address='${vm_ip}'" | awk '{print $2}' | cut -d"=" -f 2 + IF '${OPENSTACK_BRANCH}' == 'stable/rocky' + ${output} = OpenStack CLI openstack floating ip unset --port ${port_id} ${fip} + ELSE + ${output} = OpenStack CLI openstack server remove floating ip ${vm_name} ${fip} + END Delete Floating IP - [Arguments] ${fip} [Documentation] Delete floating ip with neutron request. + [Arguments] ${fip} ${output} = OpenStack CLI openstack floating ip delete ${fip} Delete SubNet - [Arguments] ${subnet} [Documentation] Delete SubNet for the Network with neutron request. + [Arguments] ${subnet} ${output} = OpenStack CLI openstack subnet delete ${subnet} Delete Vm Instance - [Arguments] ${vm_name} [Documentation] Delete Vm instances using instance names. + [Arguments] ${vm_name} ${output} = OpenStack CLI openstack server delete ${vm_name} Get Net Id - [Arguments] ${network_name} [Documentation] Retrieve the net id for the given network name to create specific vm instance + [Arguments] ${network_name} ${output} = OpenStack CLI openstack network list | grep "${network_name}" | awk '{print $2}' ${splitted_output} = String.Split String ${output} ${EMPTY} ${net_id} = Collections.Get from List ${splitted_output} 0 - [Return] ${net_id} + RETURN ${net_id} Get Subnet Id - [Arguments] ${subnet_name} [Documentation] Retrieve the subnet id for the given subnet name + [Arguments] ${subnet_name} ${output} = OpenStack CLI openstack subnet show "${subnet_name}" | grep " id " | awk '{print $4}' ${splitted_output} = String.Split String ${output} ${EMPTY} ${subnet_id} = Collections.Get from List ${splitted_output} 0 - [Return] ${subnet_id} + RETURN ${subnet_id} Get Port Id - [Arguments] ${port_name} [Documentation] Retrieve the port id for the given port name to attach specific vm instance to a particular port + [Arguments] ${port_name} ${output} = OpenStack CLI openstack port list | grep "${port_name}" | awk '{print $2}' ${splitted_output} = String.Split String ${output} ${EMPTY} ${port_id} = Collections.Get from List ${splitted_output} 0 - [Return] ${port_id} + RETURN ${port_id} Get Sub Port Id - [Arguments] ${portname} [Documentation] Retrieve the first 10 chars of the UUID for the given port name + [Arguments] ${portname} ${port_id} = OpenStackOperations.Get Port Id ${portname} ${output} = String.Get Regexp Matches ${port_id} \\w{8}-\\w{2} ${subport_id} = Collections.Get from List ${output} 0 - [Return] ${subport_id} + RETURN ${subport_id} Get Router Id - [Arguments] ${router1} [Documentation] Retrieve the router id for the given router name + [Arguments] ${router1} ${output} = OpenStack CLI openstack router show "${router1}" |awk '/ id / {print $4}' ${splitted_output} = String.Split String ${output} ${EMPTY} ${router_id} = Collections.Get from List ${splitted_output} 0 - [Return] ${router_id} + RETURN ${router_id} Get VMs OVS Port Number - [Arguments] ${ip_address} ${portname} [Documentation] Get the port number for given portname + [Arguments] ${ip_address} ${portname} ${subportid} = OpenStackOperations.Get Sub Port Id ${portname} ${vm_port_number} = OVSDB.Get Port Number ${subportid} ${ip_address} - [Return] ${vm_port_number} + RETURN ${vm_port_number} Add New Image From Url - [Arguments] ${image_url} ${image_name} [Documentation] To add new qcow2 images for testing. + [Arguments] ${image_url} ${image_name} ${rc} ${output} = OperatingSystem.Run And Return Rc And Output wget ${image_url} -O /tmp/new_image.qcow2 BuiltIn.Log ${output} BuiltIn.Should Be True '${rc}' == '0' - ${output} = OpenStack CLI openstack image create ${image_name} --file /tmp/new_image.qcow2 --disk-format qcow2 --container-format bare --public + ${output} = OpenStack CLI + ... openstack image create ${image_name} --file /tmp/new_image.qcow2 --disk-format qcow2 --container-format bare --public Create Flavor - [Arguments] ${flavor_name} ${ram_in_mb} ${disk_in_gb} ${ncpu}=1 [Documentation] To create new flavors for instance deployment and testing - ${output} = OpenStack CLI openstack flavor create ${flavor_name} --ram ${ram_in_mb} --disk ${disk_in_gb} --vcpus ${ncpu} + [Arguments] ${flavor_name} ${ram_in_mb} ${disk_in_gb} ${ncpu}=1 + ${output} = OpenStack CLI + ... openstack flavor create ${flavor_name} --ram ${ram_in_mb} --disk ${disk_in_gb} --vcpus ${ncpu} Create Keypair - [Arguments] ${keyname} ${public_key_file} [Documentation] To add keypairs to Openstack that can be used when ssh to instances using publickey authentication + [Arguments] ${keyname} ${public_key_file} ${output} = OpenStack CLI openstack keypair create ${keyname} --public-key ${public_key_file} Generate And Add Keypair - [Arguments] ${keyname} ${keyfilename} [Documentation] To generate keypair using ssh-keygen and add them to Openstack - ${result} = Process.Run Process ssh-keygen -b 2048 -t rsa -f ${JENKINS_WORKSPACE}/${keyfilename} -q -N "" shell=True + [Arguments] ${keyname} ${keyfilename} + ${result} = Process.Run Process + ... ssh-keygen -b 2048 -t rsa -f ${JENKINS_WORKSPACE}/${keyfilename} -q -N "" + ... shell=True BuiltIn.Log ${result.stdout} BuiltIn.Log ${result.stderr} BuiltIn.Should Be True '${result.rc}' == '0' @@ -276,92 +310,104 @@ Generate And Add Keypair SSHLibrary.Put_File ${JENKINS_WORKSPACE}/${keyfilename} /tmp Create Vm Instances - [Arguments] ${net_name} ${vm_instance_names} ${image}=${EMPTY} ${flavor}=m1.nano ${sg}=default ${min}=1 [Documentation] Create X Vm Instance with the net id of the Netowrk. + [Arguments] ${net_name} ${vm_instance_names} ${image}=${EMPTY} ${flavor}=m1.nano ${sg}=default ${min}=1 .. ${max}=1 - ${image} BuiltIn.Set Variable If "${image}"=="${EMPTY}" ${CIRROS_${OPENSTACK_BRANCH}} ${image} + ${image} = BuiltIn.Set Variable If "${image}"=="${EMPTY}" ${CIRROS_${OPENSTACK_BRANCH}} ${image} ${net_id} = OpenStackOperations.Get Net Id ${net_name} FOR ${vm} IN @{vm_instance_names} - ${output} = OpenStack CLI openstack server create --image ${image} --flavor ${flavor} --nic net-id=${net_id} ${vm} --security-group ${sg} --min ${min} --max ${max} + ${output} = OpenStack CLI + ... openstack server create --image ${image} --flavor ${flavor} --nic net-id=${net_id} ${vm} --security-group ${sg} --min ${min} --max ${max} END Create Vm Instance On Compute Node - [Arguments] ${net_name} ${vm_name} ${node_hostname} ${image}=${EMPTY} ${flavor}=m1.nano ${sg}=default [Documentation] Create a VM instance on a specific compute node. + [Arguments] ${net_name} ${vm_name} ${node_hostname} ${image}=${EMPTY} ${flavor}=m1.nano ${sg}=default ${image} = BuiltIn.Set Variable If "${image}"=="${EMPTY}" ${CIRROS_${OPENSTACK_BRANCH}} ${image} ${net_id} = OpenStackOperations.Get Net Id ${net_name} - ${output} = OpenStack CLI openstack server create ${vm_name} --image ${image} --flavor ${flavor} --nic net-id=${net_id} --security-group ${sg} --availability-zone nova:${node_hostname} + ${output} = OpenStack CLI + ... openstack server create ${vm_name} --image ${image} --flavor ${flavor} --nic net-id=${net_id} --security-group ${sg} --availability-zone nova:${node_hostname} Create Vm Instance With Port - [Arguments] ${port_name} ${vm_instance_name} ${image}=${EMPTY} ${flavor}=m1.nano ${sg}=default [Documentation] Create One VM instance using given ${port_name} and for given ${compute_node} + [Arguments] ${port_name} ${vm_instance_name} ${image}=${EMPTY} ${flavor}=m1.nano ${sg}=default ${image} = BuiltIn.Set Variable If "${image}"=="${EMPTY}" ${CIRROS_${OPENSTACK_BRANCH}} ${image} - ${output} = OpenStack CLI openstack server create --image ${image} --flavor ${flavor} --port ${port_name} --security-group ${sg} ${vm_instance_name} + ${output} = OpenStack CLI + ... openstack server create --image ${image} --flavor ${flavor} --port ${port_name} --security-group ${sg} ${vm_instance_name} Create Vm Instance With Ports And Key On Compute Node + [Documentation] Create One VM instance using given ${port1_name} and ${port2_name} with keyname for ssh and also on a specific compute node [Arguments] ${port1_name} ${port2_name} ${vm_instance_name} ${node_hostname} ${image}=${EMPTY} ${flavor}=m1.nano ... ${sg}=default ${keyname}=${EMPTY} - [Documentation] Create One VM instance using given ${port1_name} and ${port2_name} with keyname for ssh and also on a specific compute node - ${image} BuiltIn.Set Variable If "${image}"=="${EMPTY}" ${CIRROS_${OPENSTACK_BRANCH}} ${image} - ${output} = OpenStack CLI openstack server create --image ${image} --flavor ${flavor} --port ${port1_name} --port ${port2_name} ${vm_instance_name} --security-group ${sg} --availability-zone nova:${node_hostname} --key-name ${keyname} + ${image} = BuiltIn.Set Variable If "${image}"=="${EMPTY}" ${CIRROS_${OPENSTACK_BRANCH}} ${image} + ${output} = OpenStack CLI + ... openstack server create --image ${image} --flavor ${flavor} --port ${port1_name} --port ${port2_name} ${vm_instance_name} --security-group ${sg} --availability-zone nova:${node_hostname} --key-name ${keyname} Create Vm Instance With Port On Compute Node - [Arguments] ${port_name} ${vm_instance_name} ${node_hostname} ${image}=${EMPTY} ${flavor}=m1.nano ${sg}=default [Documentation] Create One VM instance using given ${port_name} and for given ${node_hostname} + [Arguments] ${port_name} ${vm_instance_name} ${node_hostname} ${image}=${EMPTY} ${flavor}=m1.nano ${sg}=default ${image} = BuiltIn.Set Variable If "${image}"=="${EMPTY}" ${CIRROS_${OPENSTACK_BRANCH}} ${image} - ${output} = OpenStack CLI openstack server create --image ${image} --flavor ${flavor} --port ${port_name} --security-group ${sg} --availability-zone nova:${node_hostname} ${vm_instance_name} + ${output} = OpenStack CLI + ... openstack server create --image ${image} --flavor ${flavor} --port ${port_name} --security-group ${sg} --availability-zone nova:${node_hostname} ${vm_instance_name} Remove Security Group From Vm Instance - [Arguments] ${vm_instance_name} ${security_group} [Documentation] Delete the Security Group from the VM Instance. + [Arguments] ${vm_instance_name} ${security_group} ${output} = OpenStack CLI openstack server remove security group ${vm_instance_name} ${security_group} Create Vm Instance With Ports On Compute Node + [Documentation] Create One VM instance using given ${port1_name}, ${port2_name} and for given ${node_hostname} with no keys (cirros like) [Arguments] ${port1_name} ${port2_name} ${vm_instance_name} ${node_hostname} ${image}=${EMPTY} ${flavor}=m1.nano ... ${sg}=default - [Documentation] Create One VM instance using given ${port1_name}, ${port2_name} and for given ${node_hostname} with no keys (cirros like) ${image} = BuiltIn.Set Variable If "${image}"=="${EMPTY}" ${CIRROS_${OPENSTACK_BRANCH}} ${image} ${port1_id} = OpenStackOperations.Get Port Id ${port1_name} ${port2_id} = OpenStackOperations.Get Port Id ${port2_name} - ${output} = OpenStack CLI openstack server create --image ${image} --flavor ${flavor} --nic port-id=${port1_id} --nic port-id=${port2_id} --security-group ${sg} --availability-zone nova:${node_hostname} ${vm_instance_name} + ${output} = OpenStack CLI + ... openstack server create --image ${image} --flavor ${flavor} --nic port-id=${port1_id} --nic port-id=${port2_id} --security-group ${sg} --availability-zone nova:${node_hostname} ${vm_instance_name} Get Hypervisor Hostname From IP - [Arguments] ${hypervisor_ip} [Documentation] Returns the hostname found for the given IP address if it's listed in hypervisor list. For debuggability ... the full listing is logged first, then followed by a grep | cut to focus on the actual hostname to return + [Arguments] ${hypervisor_ip} ${output} = OpenStack CLI openstack hypervisor list ${hostname} = OpenStack CLI openstack hypervisor list -f value | grep "${hypervisor_ip} " | cut -d" " -f 2 - [Return] ${hostname} + RETURN ${hostname} Create Nano Flavor [Documentation] Create a nano flavor ${output} = OpenStack CLI openstack flavor create m1.nano --id auto --ram 64 --disk 0 --vcpus 1 Verify VM Is ACTIVE - [Arguments] ${vm_name} [Documentation] Run these commands to check whether the created vm instance is active or not. + [Arguments] ${vm_name} OpenStack CLI openstack server show ${vm_name} ${output} = OpenStack CLI openstack server show ${vm_name} | grep OS-EXT-STS:vm_state BuiltIn.Should Contain ${output} active Poll VM Is ACTIVE - [Arguments] ${vm_name} ${retry}=600s ${retry_interval}=30s [Documentation] Run these commands to check whether the created vm instance is active or not. - BuiltIn.Wait Until Keyword Succeeds ${retry} ${retry_interval} OpenStackOperations.Verify VM Is ACTIVE ${vm_name} + [Arguments] ${vm_name} ${retry}=600s ${retry_interval}=30s + BuiltIn.Wait Until Keyword Succeeds + ... ${retry} + ... ${retry_interval} + ... OpenStackOperations.Verify VM Is ACTIVE + ... ${vm_name} Get Match - [Arguments] ${text} ${regexp} ${index}=0 [Documentation] Wrapper around String.Get Regexp Matches to return None if not found or the first match if found. + [Arguments] ${text} ${regexp} ${index}=0 @{matches} = String.Get Regexp Matches ${text} ${regexp} ${matches_length} = BuiltIn.Get Length ${matches} BuiltIn.Set Suite Variable ${OS_MATCH} None - BuiltIn.Run Keyword If ${matches_length} > ${index} BuiltIn.Set Suite Variable ${OS_MATCH} ${matches}[${index}] - [Return] ${OS_MATCH} + IF ${matches_length} > ${index} + BuiltIn.Set Suite Variable ${OS_MATCH} ${matches}[${index}] + END + RETURN ${OS_MATCH} Get VM IP - [Arguments] ${fail_on_none} ${vm} [Documentation] Get the vm ip address and nameserver by scraping the vm's console log. ... Get VM IP returns three values: [0] the vm IP, [1] the DHCP IP and [2] the vm console log. + [Arguments] ${fail_on_none} ${vm} ${vm_console_output} = OpenStack CLI With No Log openstack console log show ${vm} ${vm_ip} = BuiltIn.Set Variable None ${dhcp_ip} = BuiltIn.Set Variable None @@ -369,132 +415,173 @@ Get VM IP ${vm_ip} = OpenStackOperations.Get Match ${match} ${REGEX_IPV4} 0 ${match} = OpenStackOperations.Get Match ${vm_console_output} ${REGEX_IPROUTE} ${dhcp_ip} = OpenStackOperations.Get Match ${match} ${REGEX_IPV4} 1 - BuiltIn.Run Keyword If '${fail_on_none}' == 'true' BuiltIn.Should Not Contain ${vm_ip} None - BuiltIn.Run Keyword If '${fail_on_none}' == 'true' BuiltIn.Should Not Contain ${dhcp_ip} None - [Return] ${vm_ip} ${dhcp_ip} ${vm_console_output} + IF '${fail_on_none}' == 'true' + BuiltIn.Should Not Contain ${vm_ip} None + END + IF '${fail_on_none}' == 'true' + BuiltIn.Should Not Contain ${dhcp_ip} None + END + RETURN ${vm_ip} ${dhcp_ip} ${vm_console_output} Verify If Instance Is Arpingable From DHCP Namespace - [Arguments] ${net_name} ${mac} ${ip} [Documentation] Get the Port IP and check the arp -a from DHCP NS to ensure that the VM's have been assigned IP's + [Arguments] ${net_name} ${mac} ${ip} OpenStackOperations.Get ControlNode Connection ${net_id} = OpenStackOperations.Get Net Id ${net_name} - ${output} = Utils.Write Commands Until Expected Prompt sudo ip netns exec qdhcp-${net_id} arping ${ip} -c3 ${DEFAULT_LINUX_PROMPT_STRICT} timeout=60s + ${output} = Utils.Write Commands Until Expected Prompt + ... sudo ip netns exec qdhcp-${net_id} arping ${ip} -c3 + ... ${DEFAULT_LINUX_PROMPT_STRICT} + ... timeout=60s ${mac_uppercase} = String.Convert To Upper Case ${mac} BuiltIn.Should Contain ${output} [${mac_uppercase}] Check If Instance Is Ready For Ssh Login Using PublicKey - [Arguments] ${net_name} ${vm_ip} ${user}=centos ${idfile}=/tmp/odlkey ${console}=cirros [Documentation] Ensure the VM is reachable from ssh as tests would require. This keyword will use publickey authentication - ${output} = Execute Command on VM Instance with PublicKey Auth ${net_name} ${vm_ip} ifconfig user=${user} idfile=${idfile} + [Arguments] ${net_name} ${vm_ip} ${user}=centos ${idfile}=/tmp/odlkey ${console}=cirros + ${output} = Execute Command on VM Instance with PublicKey Auth + ... ${net_name} + ... ${vm_ip} + ... ifconfig + ... user=${user} + ... idfile=${idfile} ... console=${console} BuiltIn.Should Contain ${output} ${vm_ip} Check If Instance Is Ready For Ssh Login Using Password - [Arguments] ${net_name} ${vm_ip} ${user}=cirros ${password}=${EMPTY} ${console}=cirros [Documentation] Ensure the VM is reachable from ssh as tests would require. This keyword will use password authentication - ${password} BuiltIn.Set Variable If "${password}"=="${EMPTY}" ${PASSWORD_CIRROS_${OPENSTACK_BRANCH}} + [Arguments] ${net_name} ${vm_ip} ${user}=cirros ${password}=${EMPTY} ${console}=cirros + ${password} = BuiltIn.Set Variable If "${password}"=="${EMPTY}" ${PASSWORD_CIRROS_${OPENSTACK_BRANCH}} ${output} = Execute Command on VM Instance ${net_name} ${vm_ip} ifconfig ${user} ${password} ... console=${console} BuiltIn.Should Contain ${output} ${vm_ip} Get VM IPs - [Arguments] @{vms} [Documentation] Get the instance IP addresses and nameserver address for the list of given vms. ... First poll for the vm instance to be in the active state, then poll for the vm ip address and nameserver. ... Get VM IPs returns two things: [0] a list of the ips for the vms passed to this keyword (may contain values ... of None) and [1] the dhcp ip address found in the last vm checked. ... TODO: there is a potential issue for a caller that passes in VMs belonging to different networks that ... may have different dhcp server addresses. Not sure what TODO about that, but noting it here for reference. - @{vm_ips} BuiltIn.Create List @{EMPTY} + [Arguments] @{vms} + @{vm_ips} = BuiltIn.Create List @{EMPTY} FOR ${vm} IN @{vms} OpenStackOperations.Poll VM Is ACTIVE ${vm} - ${status} ${ips_and_console_log} BuiltIn.Run Keyword And Ignore Error BuiltIn.Wait Until Keyword Succeeds 180s 15s - ... OpenStackOperations.Get VM IP true ${vm} + ${status} ${ips_and_console_log} = BuiltIn.Run Keyword And Ignore Error + ... BuiltIn.Wait Until Keyword Succeeds + ... 180s + ... 15s + ... OpenStackOperations.Get VM IP + ... true + ... ${vm} # If there is trouble with Get VM IP, the status will be FAIL and the return value will be a string of what went # wrong. We need to handle both the PASS and FAIL cases. In the FAIL case we know we wont have access to the # console log, as it would not be returned; so we need to grab it again to log it. We also can append 'None' to # the vm ip list if status is FAIL. - BuiltIn.Run Keyword If "${status}" == "PASS" BuiltIn.Log ${ips_and_console_log[2]} - BuiltIn.Run Keyword If "${status}" == "PASS" Collections.Append To List ${vm_ips} ${ips_and_console_log[0]} - BuiltIn.Run Keyword If "${status}" == "FAIL" Collections.Append To List ${vm_ips} None - ${vm_console_output} = BuiltIn.Run Keyword If "${status}" == "FAIL" OpenStack CLI openstack console log show ${vm} - BuiltIn.Run Keyword If "${status}" == "FAIL" BuiltIn.Log ${vm_console_output} + IF "${status}" == "PASS" BuiltIn.Log ${ips_and_console_log[2]} + IF "${status}" == "PASS" + Collections.Append To List ${vm_ips} ${ips_and_console_log[0]} + END + IF "${status}" == "FAIL" + Collections.Append To List ${vm_ips} None + END + IF "${status}" == "FAIL" + ${vm_console_output} = OpenStack CLI openstack console log show ${vm} + ELSE + ${vm_console_output} = Set Variable ${None} + END + IF "${status}" == "FAIL" BuiltIn.Log ${vm_console_output} END OpenStackOperations.Copy DHCP Files From Control Node - [Return] @{vm_ips} ${ips_and_console_log[1]} + RETURN @{vm_ips} ${ips_and_console_log[1]} Get All VM IP Addresses - [Arguments] ${conn_id} ${vm_name} [Documentation] Show information of a given two port VM and grep for two ip address. VM name should be sent as arguments. + [Arguments] ${conn_id} ${vm_name} SSHLibrary.Switch Connection ${conn_id} ${cmd} = BuiltIn.Set Variable openstack server show ${vm_name} ${output} = OpenStackOperations.OpenStack CLI ${cmd} BuiltIn.Log ${output} ${address_output} = OpenStackOperations.OpenStack CLI ${cmd} | grep "addresses" | awk '{print $4$5}' @{vm_ips} = String.Get Regexp Matches ${address_output} ${REGEX_IPV4} - [Return] @{vm_ips} + RETURN @{vm_ips} Get Subnet Gateway Ip - [Arguments] ${subnet_name} [Documentation] Show information of a subnet and grep for subnet gateway ip address - ${output} = OpenStackOperations.OpenStack CLI openstack subnet show ${subnet_name} | grep gateway_ip | awk '{print $4}' + [Arguments] ${subnet_name} + ${output} = OpenStackOperations.OpenStack CLI + ... openstack subnet show ${subnet_name} | grep gateway_ip | awk '{print $4}' ${splitted_output} = String.Split String ${output} ${EMPTY} ${matches} = Collections.Get Matches ${splitted_output} regexp=(\\d\.)+ ${subnet_gateway_ip} = String.Strip String ${matches[0]} characters=',' - [Return] ${subnet_gateway_ip} + RETURN ${subnet_gateway_ip} Collect VM IPv6 SLAAC Addresses - [Arguments] ${fail_on_none} ${vm_list} ${network} ${subnet} [Documentation] For each VM parse output of "openstack server show" to get its IPv6 address from Neutron DB. ... Then try to connect to each VM by SSH and execute there "ip -6 a" command. This double-check allows to ... obtain and compare IP info (Neutron DB vs dnsmasque/ODL DHCP) and to test L2 connectivity as well. ... Returns an empty list if no IPv6 addresses found or if SSH connection fails. ... Otherwise, returns a list of IPv6 addresses. + [Arguments] ${fail_on_none} ${vm_list} ${network} ${subnet} ${ipv6_list} = BuiltIn.Create List @{EMPTY} FOR ${vm} IN @{vm_list} ${output} = OpenStack CLI openstack server show ${vm} -f shell ${pattern} = String.Replace String ${subnet} ::/64 (:[a-f0-9]{,4}){,4} @{vm_ipv6} = String.Get Regexp Matches ${output} ${pattern} ${vm_ip_length} = BuiltIn.Get Length ${vm_ipv6}[0] - ${ipv6_data_from_vm} = BuiltIn.Run Keyword If ${vm_ip_length}>0 OpenStackOperations.Execute Command on VM Instance ${network} ${vm_ipv6[0]} - ... ip -6 a + IF ${vm_ip_length}>0 + ${ipv6_data_from_vm} = OpenStackOperations.Execute Command on VM Instance + ... ${network} + ... ${vm_ipv6[0]} + ... ip -6 a + ELSE + ${ipv6_data_from_vm} = Set Variable ${None} + END @{ipv6} = String.Get Regexp Matches ${ipv6_data_from_vm} ${pattern} - ${ipv6_addr_list_length} BuiltIn.Get Length @{ipv6} - BuiltIn.Run Keyword If ${ipv6_addr_list_length}>0 Collections.Append To List ${ipv6_list} ${ipv6[0]} - ... ELSE Collections.Append To List ${ipv6_list} None + ${ipv6_addr_list_length} = BuiltIn.Get Length @{ipv6} + IF ${ipv6_addr_list_length}>0 + Collections.Append To List ${ipv6_list} ${ipv6[0]} + ELSE + Collections.Append To List ${ipv6_list} None + END END - [Return] ${ipv6_list} + RETURN ${ipv6_list} View Vm Console - [Arguments] ${vm_instance_names} [Documentation] View Console log of the created vm instances using nova show. + [Arguments] ${vm_instance_names} FOR ${vm} IN @{vm_instance_names} ${output} = OpenStack CLI openstack server show ${vm} ${output} = OpenStack CLI openstack console log show ${vm} END Ping Vm From DHCP Namespace - [Arguments] ${net_name} ${vm_ip} [Documentation] Reach all Vm Instance with the net id of the Netowrk. + [Arguments] ${net_name} ${vm_ip} OpenStackOperations.Get ControlNode Connection ${net_id} = OpenStackOperations.Get Net Id ${net_name} - ${output} = DevstackUtils.Write Commands Until Prompt And Log sudo ip netns exec qdhcp-${net_id} ping -c 3 ${vm_ip} 20s + ${output} = DevstackUtils.Write Commands Until Prompt And Log + ... sudo ip netns exec qdhcp-${net_id} ping -c 3 ${vm_ip} + ... 20s BuiltIn.Should Contain ${output} 64 bytes Ping From DHCP Should Not Succeed - [Arguments] ${net_name} ${vm_ip} [Documentation] Should Not Reach Vm Instance with the net id of the Netowrk. - Return From Keyword If "skip_if_${SECURITY_GROUP_MODE}" in @{TEST_TAGS} + [Arguments] ${net_name} ${vm_ip} + IF "skip_if_${SECURITY_GROUP_MODE}" in @{TEST_TAGS} RETURN OpenStackOperations.Get ControlNode Connection ${net_id} = OpenStackOperations.Get Net Id ${net_name} - ${output} = DevstackUtils.Write Commands Until Prompt And Log sudo ip netns exec qdhcp-${net_id} ping -c 3 ${vm_ip} 20s + ${output} = DevstackUtils.Write Commands Until Prompt And Log + ... sudo ip netns exec qdhcp-${net_id} ping -c 3 ${vm_ip} + ... 20s BuiltIn.Should Not Contain ${output} 64 bytes Ping Vm From Control Node - [Arguments] ${vm_floating_ip} ${additional_args}=${EMPTY} [Documentation] Ping VM floating IP from control node + [Arguments] ${vm_floating_ip} ${additional_args}=${EMPTY} OpenStackOperations.Get ControlNode Connection - ${output} = DevstackUtils.Write Commands Until Prompt And Log ping ${additional_args} -c 3 ${vm_floating_ip} 20s + ${output} = DevstackUtils.Write Commands Until Prompt And Log + ... ping ${additional_args} -c 3 ${vm_floating_ip} + ... 20s BuiltIn.Should Contain ${output} 64 bytes Curl Metadata Server @@ -508,31 +595,36 @@ Close Vm Instance ${output} = DevstackUtils.Write Commands Until Prompt And Log exit Check If Console Is VmInstance - [Arguments] ${console}=cirros [Documentation] Check if the session has been able to login to the VM instance + [Arguments] ${console}=cirros ${output} = Utils.Write Commands Until Expected Prompt id ${OS_SYSTEM_PROMPT} BuiltIn.Should Contain ${output} ${console} Exit From Vm Console - [Arguments] ${console}=cirros [Documentation] Check if the session has been able to login to the VM instance and exit the instance - ${rcode} = BuiltIn.Run Keyword And Return Status OpenStackOperations.Check If Console Is VmInstance ${console} - BuiltIn.Run Keyword If ${rcode} DevstackUtils.Write Commands Until Prompt exit + [Arguments] ${console}=cirros + ${rcode} = BuiltIn.Run Keyword And Return Status + ... OpenStackOperations.Check If Console Is VmInstance + ... ${console} + IF ${rcode} DevstackUtils.Write Commands Until Prompt exit Check Ping - [Arguments] ${ip_address} ${ttl}=64 ${ping_tries}=3 [Documentation] Run Ping command on the IP available as argument + [Arguments] ${ip_address} ${ttl}=64 ${ping_tries}=3 ${ethertype} = String.Get Regexp Matches ${ip_address} ${IP_REGEX} ${ping} = BuiltIn.Set Variable If ${ethertype} ping ping6 - ${cmd} = BuiltIn.Set Variable rc=0; for count in `seq 1 ${ping_tries}`; do ${ping} -W1 -t${ttl} -c5 ${ip_address}; rc=$?; if [ $rc -eq 0 ]; then break; fi; done; echo ping_rc=$rc + ${cmd} = BuiltIn.Set Variable + ... rc=0; for count in `seq 1 ${ping_tries}`; do ${ping} -W1 -t${ttl} -c5 ${ip_address}; rc=$?; if [ $rc -eq 0 ]; then break; fi; done; echo ping_rc=$rc ${output} = Utils.Write Commands Until Expected Regexp ${cmd} ping_rc=\\d+ 120 BuiltIn.Log output: ${output} BuiltIn.Should Contain ${output} 64 bytes Check No Ping - [Arguments] ${ip_address} ${ttl}=64 [Documentation] Run Ping command to the IP given as argument, executing 3 times and expecting NOT to see "64 bytes" - ${output} = Utils.Write Commands Until Expected Prompt ping -t ${ttl} -c 3 ${ip_address} ${OS_SYSTEM_PROMPT} + [Arguments] ${ip_address} ${ttl}=64 + ${output} = Utils.Write Commands Until Expected Prompt + ... ping -t ${ttl} -c 3 ${ip_address} + ... ${OS_SYSTEM_PROMPT} BuiltIn.Should Not Contain ${output} 64 bytes Check Metadata Access @@ -541,74 +633,121 @@ Check Metadata Access BuiltIn.Should Contain ${output} 200 Execute Command on VM Instance + [Documentation] Login to the vm instance using ssh in the network, executes a command inside the VM and returns the ouput. [Arguments] ${net_name} ${vm_ip} ${cmd} ${user}=cirros ${password}=${EMPTY} ${cmd_timeout}=30s ... ${console}=cirros - [Documentation] Login to the vm instance using ssh in the network, executes a command inside the VM and returns the ouput. - ${password} BuiltIn.Set Variable If "${password}"=="${EMPTY}" ${PASSWORD_CIRROS_${OPENSTACK_BRANCH}} + ${password} = BuiltIn.Set Variable If "${password}"=="${EMPTY}" ${PASSWORD_CIRROS_${OPENSTACK_BRANCH}} OpenStackOperations.Get ControlNode Connection ${net_id} = OpenStackOperations.Get Net Id ${net_name} - ${output} = Utils.Write Commands Until Expected Prompt sudo ip netns exec qdhcp-${net_id} ssh ${user}@${vm_ip} -o MACs=hmac-sha1 -o ConnectTimeout=5 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o PreferredAuthentications=password password: + ${output} = Utils.Write Commands Until Expected Prompt + ... sudo ip netns exec qdhcp-${net_id} ssh ${user}@${vm_ip} -o MACs=hmac-sha1 -o ConnectTimeout=5 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o PreferredAuthentications=password + ... password: ${output} = Utils.Write Commands Until Expected Prompt ${password} ${OS_SYSTEM_PROMPT} - ${rcode} = BuiltIn.Run Keyword And Return Status OpenStackOperations.Check If Console Is VmInstance ${console} - ${output} = BuiltIn.Run Keyword If ${rcode} Utils.Write Commands Until Expected Prompt ${cmd} ${OS_SYSTEM_PROMPT} timeout=${cmd_timeout} + ${rcode} = BuiltIn.Run Keyword And Return Status + ... OpenStackOperations.Check If Console Is VmInstance + ... ${console} + IF ${rcode} + ${output} = Utils.Write Commands Until Expected Prompt + ... ${cmd} + ... ${OS_SYSTEM_PROMPT} + ... timeout=${cmd_timeout} + ELSE + ${output} = Set Variable ${None} + END + RETURN ${output} [Teardown] Exit From Vm Console ${console} - [Return] ${output} Execute Command on VM Instance With PublicKey Auth - [Arguments] ${net_name} ${vm_ip} ${cmd} ${user}=centos ${idfile}=/tmp/odlkey ${console}=cirros [Documentation] Login to the vm instance using ssh publickey in the network, executes a command inside the VM and returns the ouput. + [Arguments] ${net_name} ${vm_ip} ${cmd} ${user}=centos ${idfile}=/tmp/odlkey ${console}=cirros OpenStackOperations.Get ControlNode Connection ${net_id} = OpenStackOperations.Get Net Id ${net_name} - ${output} = Utils.Write Commands Until Expected Prompt sudo ip netns exec qdhcp-${net_id} ssh -i ${idfile} ${user}@${vm_ip} -o MACs=hmac-sha1 -o ConnectTimeout=5 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o PreferredAuthentications=publickey prompt=${OS_SYSTEM_PROMPT} timeout=60s - ${rcode} = BuiltIn.Run Keyword And Return Status OpenStackOperations.Check If Console Is VmInstance ${console} - ${output} = BuiltIn.Run Keyword If ${rcode} Utils.Write Commands Until Expected Prompt ${cmd} ${OS_SYSTEM_PROMPT} + ${output} = Utils.Write Commands Until Expected Prompt + ... sudo ip netns exec qdhcp-${net_id} ssh -i ${idfile} ${user}@${vm_ip} -o MACs=hmac-sha1 -o ConnectTimeout=5 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o PreferredAuthentications=publickey + ... prompt=${OS_SYSTEM_PROMPT} + ... timeout=60s + ${rcode} = BuiltIn.Run Keyword And Return Status + ... OpenStackOperations.Check If Console Is VmInstance + ... ${console} + IF ${rcode} + ${output} = Utils.Write Commands Until Expected Prompt ${cmd} ${OS_SYSTEM_PROMPT} + ELSE + ${output} = Set Variable ${None} + END + RETURN ${output} [Teardown] Exit From Vm Console ${console} - [Return] ${output} Copy File To VM Instance With PublicKey Auth - [Arguments] ${net_name} ${vm_ip} ${file_to_copy} ${user}=centos ${idfile}=/tmp/odlkey [Documentation] Login to the vm instance using ssh publickey in the network, executes a command inside the VM and returns the ouput. + [Arguments] ${net_name} ${vm_ip} ${file_to_copy} ${user}=centos ${idfile}=/tmp/odlkey OpenStackOperations.Get ControlNode Connection ${net_id} = OpenStackOperations.Get Net Id ${net_name} - ${rc} = SSHLibrary.Execute Command sudo ip netns exec qdhcp-${net_id} scp -i ${idfile} -o MACs=hmac-sha1 -o ConnectTimeout=5 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o PreferredAuthentications=publickey ${file_to_copy} ${user}@${vm_ip}:/tmp/ return_stdout=False return_rc=True + ${rc} = SSHLibrary.Execute Command + ... sudo ip netns exec qdhcp-${net_id} scp -i ${idfile} -o MACs=hmac-sha1 -o ConnectTimeout=5 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o PreferredAuthentications=publickey ${file_to_copy} ${user}@${vm_ip}:/tmp/ + ... return_stdout=False + ... return_rc=True BuiltIn.Should Be True '${rc}' == '0' Test Operations From Vm Instance + [Documentation] Login to the vm instance using ssh in the network. [Arguments] ${net_name} ${src_ip} ${dest_ips} ${user}=cirros ${password}=${EMPTY} ${ttl}=64 ... ${ping_should_succeed}=True ${check_metadata}=True ${console}=cirros ${ping_tries}=3 - [Documentation] Login to the vm instance using ssh in the network. - ${password} BuiltIn.Set Variable If "${password}"=="${EMPTY}" ${PASSWORD_CIRROS_${OPENSTACK_BRANCH}} + ${password} = BuiltIn.Set Variable If "${password}"=="${EMPTY}" ${PASSWORD_CIRROS_${OPENSTACK_BRANCH}} OpenStackOperations.Get ControlNode Connection ${net_id} = OpenStackOperations.Get Net Id ${net_name} - ${output} = Utils.Write Commands Until Expected Prompt sudo ip netns exec qdhcp-${net_id} ssh -o MACs=hmac-sha1 -o ConnectTimeout=5 -o StrictHostKeyChecking=no ${user}@${src_ip} -o UserKnownHostsFile=/dev/null password: 10s + ${output} = Utils.Write Commands Until Expected Prompt + ... sudo ip netns exec qdhcp-${net_id} ssh -o MACs=hmac-sha1 -o ConnectTimeout=5 -o StrictHostKeyChecking=no ${user}@${src_ip} -o UserKnownHostsFile=/dev/null + ... password: + ... 10s ${output} = Utils.Write Commands Until Expected Prompt ${password} ${OS_SYSTEM_PROMPT} - ${rcode} = BuiltIn.Run Keyword And Return Status OpenStackOperations.Check If Console Is VmInstance ${console} - BuiltIn.Run Keyword If ${rcode} Utils.Write Commands Until Expected Prompt ifconfig ${OS_SYSTEM_PROMPT} - BuiltIn.Run Keyword If ${rcode} Utils.Write Commands Until Expected Prompt route -n ${OS_SYSTEM_PROMPT} - BuiltIn.Run Keyword If ${rcode} Utils.Write Commands Until Expected Prompt route -A inet6 ${OS_SYSTEM_PROMPT} - BuiltIn.Run Keyword If ${rcode} Utils.Write Commands Until Expected Prompt arp -an ${OS_SYSTEM_PROMPT} - BuiltIn.Run Keyword If ${rcode} Utils.Write Commands Until Expected Prompt ip -f inet6 neigh show ${OS_SYSTEM_PROMPT} + ${rcode} = BuiltIn.Run Keyword And Return Status + ... OpenStackOperations.Check If Console Is VmInstance + ... ${console} + IF ${rcode} + Utils.Write Commands Until Expected Prompt ifconfig ${OS_SYSTEM_PROMPT} + END + IF ${rcode} + Utils.Write Commands Until Expected Prompt route -n ${OS_SYSTEM_PROMPT} + END + IF ${rcode} + Utils.Write Commands Until Expected Prompt route -A inet6 ${OS_SYSTEM_PROMPT} + END + IF ${rcode} + Utils.Write Commands Until Expected Prompt arp -an ${OS_SYSTEM_PROMPT} + END + IF ${rcode} + Utils.Write Commands Until Expected Prompt ip -f inet6 neigh show ${OS_SYSTEM_PROMPT} + END FOR ${dest_ip} IN @{dest_ips} ${string_empty} = BuiltIn.Run Keyword And Return Status Should Be Empty ${dest_ip} - BuiltIn.Run Keyword If ${string_empty} Continue For Loop - BuiltIn.Run Keyword If ${rcode} and "${ping_should_succeed}" == "True" OpenStackOperations.Check Ping ${dest_ip} ttl=${ttl} ping_tries=${ping_tries} - ... ELSE OpenStackOperations.Check No Ping ${dest_ip} ttl=${ttl} + IF ${string_empty} CONTINUE + IF ${rcode} and "${ping_should_succeed}" == "True" + OpenStackOperations.Check Ping ${dest_ip} ttl=${ttl} ping_tries=${ping_tries} + ELSE + OpenStackOperations.Check No Ping ${dest_ip} ttl=${ttl} + END END ${ethertype} = String.Get Regexp Matches ${src_ip} ${IP_REGEX} - BuiltIn.Run Keyword If ${rcode} and "${check_metadata}" and ${ethertype} == "True" OpenStackOperations.Check Metadata Access + IF ${rcode} and "${check_metadata}" and ${ethertype} == "True" + OpenStackOperations.Check Metadata Access + END [Teardown] Exit From Vm Console ${console} Test Netcat Operations From Vm Instance + [Documentation] Use Netcat to test TCP/UDP connections to the controller [Arguments] ${net_name} ${vm_ip} ${dest_ip} ${additional_args}=${EMPTY} ${port}=12345 ${user}=cirros ... ${password}=${EMPTY} - [Documentation] Use Netcat to test TCP/UDP connections to the controller - ${password} BuiltIn.Set Variable If "${password}"=="${EMPTY}" ${PASSWORD_CIRROS_${OPENSTACK_BRANCH}} - ${client_data} BuiltIn.Set Variable Test Client Data - ${server_data} BuiltIn.Set Variable Test Server Data + ${password} = BuiltIn.Set Variable If "${password}"=="${EMPTY}" ${PASSWORD_CIRROS_${OPENSTACK_BRANCH}} + ${client_data} = BuiltIn.Set Variable Test Client Data + ${server_data} = BuiltIn.Set Variable Test Server Data OpenStackOperations.Get ControlNode Connection - ${output} = DevstackUtils.Write Commands Until Prompt And Log ( ( echo "${server_data}" | sudo timeout 60 nc -l ${additional_args} ${port} ) & ) + ${output} = DevstackUtils.Write Commands Until Prompt And Log + ... ( ( echo "${server_data}" | sudo timeout 60 nc -l ${additional_args} ${port} ) & ) ${output} = DevstackUtils.Write Commands Until Prompt And Log sudo netstat -nlap | grep ${port} - ${nc_output} = OpenStackOperations.Execute Command on VM Instance ${net_name} ${vm_ip} sudo echo "${client_data}" | nc -v -w 5 ${additional_args} ${dest_ip} ${port} + ${nc_output} = OpenStackOperations.Execute Command on VM Instance + ... ${net_name} + ... ${vm_ip} + ... sudo echo "${client_data}" | nc -v -w 5 ${additional_args} ${dest_ip} ${port} BuiltIn.Log ${output} ${output} = OpenStackOperations.Execute Command on VM Instance ${net_name} ${vm_ip} sudo route -n BuiltIn.Log ${output} @@ -617,88 +756,107 @@ Test Netcat Operations From Vm Instance BuiltIn.Should Match Regexp ${nc_output} ${server_data} Ping Other Instances - [Arguments] ${list_of_external_dst_ips} ${console}=cirros [Documentation] Check reachability with other network's instances. - ${rcode} = BuiltIn.Run Keyword And Return Status OpenStackOperations.Check If Console Is VmInstance ${console} + [Arguments] ${list_of_external_dst_ips} ${console}=cirros + ${rcode} = BuiltIn.Run Keyword And Return Status + ... OpenStackOperations.Check If Console Is VmInstance + ... ${console} FOR ${dest_ip} IN @{list_of_external_dst_ips} OpenStackOperations.Check Ping ${dest_ip} END Create Router - [Arguments] ${router_name} [Documentation] Create Router and Add Interface to the subnets. + [Arguments] ${router_name} ${output} = OpenStack CLI openstack router create ${router_name} List Routers [Documentation] List Routers and return output with neutron client. ${output} = OpenStack CLI openstack router list -f value - [Return] ${output} + RETURN ${output} Add Router Interface [Arguments] ${router_name} ${interface_name} ${output} = OpenStack CLI openstack router add subnet ${router_name} ${interface_name} Show Router Interface - [Arguments] ${router_name} [Documentation] List Routers interface associated with given Router and return output with neutron client. + [Arguments] ${router_name} ${output} = OpenStack CLI openstack port list --router ${router_name} -f value - [Return] ${output} + RETURN ${output} Add Router Gateway [Arguments] ${router_name} ${external_network_name} ${additional_args}=${EMPTY} - ${output} = OpenStack CLI openstack router set ${router_name} --external-gateway ${external_network_name} ${additional_args} + ${output} = OpenStack CLI + ... openstack router set ${router_name} --external-gateway ${external_network_name} ${additional_args} Remove Interface - [Arguments] ${router_name} ${interface_name} [Documentation] Remove Interface to the subnets. + [Arguments] ${router_name} ${interface_name} ${output} = OpenStack CLI openstack router remove subnet ${router_name} ${interface_name} Remove Gateway - [Arguments] ${router_name} [Documentation] Remove external gateway from the router. + [Arguments] ${router_name} ${output} = OpenStack CLI openstack router unset ${router_name} --external-gateway Update Router - [Arguments] ${router_name} ${cmd} [Documentation] Update the router with the command. Router name and command should be passed as argument. + [Arguments] ${router_name} ${cmd} ${output} = OpenStack CLI openstack router set ${router_name} ${cmd} Show Router - [Arguments] ${router_name} ${additional_args}=${EMPTY} [Documentation] Show information of a given router. Router name and optional fields should be sent as arguments. + [Arguments] ${router_name} ${additional_args}=${EMPTY} ${output} = OpenStack CLI openstack router show ${router_name} ${additional_args} - [Return] ${output} + RETURN ${output} Delete Router - [Arguments] ${router_name} [Documentation] Delete Router and Interface to the subnets. + [Arguments] ${router_name} ${output} = OpenStack CLI openstack router delete ${router_name} Get DumpFlows And Ovsconfig - [Arguments] ${conn_id} [Documentation] Get the OvsConfig and Flow entries from OVS from the Openstack Node + [Arguments] ${conn_id} SSHLibrary.Switch Connection ${conn_id} Utils.Write Commands Until Expected Prompt ip -o link ${DEFAULT_LINUX_PROMPT_STRICT} Utils.Write Commands Until Expected Prompt ip -o addr ${DEFAULT_LINUX_PROMPT_STRICT} Utils.Write Commands Until Expected Prompt ip route ${DEFAULT_LINUX_PROMPT_STRICT} Utils.Write Commands Until Expected Prompt arp -an ${DEFAULT_LINUX_PROMPT_STRICT} - ${nslist} = Utils.Write Commands Until Expected Prompt ip netns list | awk '{print $1}' ${DEFAULT_LINUX_PROMPT_STRICT} - @{lines} Split To Lines ${nslist} end=-1 + ${nslist} = Utils.Write Commands Until Expected Prompt + ... ip netns list | awk '{print $1}' + ... ${DEFAULT_LINUX_PROMPT_STRICT} + @{lines} = Split To Lines ${nslist} end=-1 FOR ${line} IN @{lines} - Utils.Write Commands Until Expected Prompt sudo ip netns exec ${line} ip -o link ${DEFAULT_LINUX_PROMPT_STRICT} - Utils.Write Commands Until Expected Prompt sudo ip netns exec ${line} ip -o addr ${DEFAULT_LINUX_PROMPT_STRICT} - Utils.Write Commands Until Expected Prompt sudo ip netns exec ${line} ip route ${DEFAULT_LINUX_PROMPT_STRICT} + Utils.Write Commands Until Expected Prompt + ... sudo ip netns exec ${line} ip -o link + ... ${DEFAULT_LINUX_PROMPT_STRICT} + Utils.Write Commands Until Expected Prompt + ... sudo ip netns exec ${line} ip -o addr + ... ${DEFAULT_LINUX_PROMPT_STRICT} + Utils.Write Commands Until Expected Prompt + ... sudo ip netns exec ${line} ip route + ... ${DEFAULT_LINUX_PROMPT_STRICT} END Utils.Write Commands Until Expected Prompt sudo ovs-vsctl show ${DEFAULT_LINUX_PROMPT_STRICT} Utils.Write Commands Until Expected Prompt sudo ovs-vsctl list Open_vSwitch ${DEFAULT_LINUX_PROMPT_STRICT} - Utils.Write Commands Until Expected Prompt sudo ovs-ofctl show ${INTEGRATION_BRIDGE} -OOpenFlow13 ${DEFAULT_LINUX_PROMPT_STRICT} - Utils.Write Commands Until Expected Prompt sudo ovs-ofctl dump-flows ${INTEGRATION_BRIDGE} -OOpenFlow13 ${DEFAULT_LINUX_PROMPT_STRICT} - Utils.Write Commands Until Expected Prompt sudo ovs-ofctl dump-groups ${INTEGRATION_BRIDGE} -OOpenFlow13 ${DEFAULT_LINUX_PROMPT_STRICT} - Utils.Write Commands Until Expected Prompt sudo ovs-ofctl dump-group-stats ${INTEGRATION_BRIDGE} -OOpenFlow13 ${DEFAULT_LINUX_PROMPT_STRICT} + Utils.Write Commands Until Expected Prompt + ... sudo ovs-ofctl show ${INTEGRATION_BRIDGE} -OOpenFlow13 + ... ${DEFAULT_LINUX_PROMPT_STRICT} + Utils.Write Commands Until Expected Prompt + ... sudo ovs-ofctl dump-flows ${INTEGRATION_BRIDGE} -OOpenFlow13 + ... ${DEFAULT_LINUX_PROMPT_STRICT} + Utils.Write Commands Until Expected Prompt + ... sudo ovs-ofctl dump-groups ${INTEGRATION_BRIDGE} -OOpenFlow13 + ... ${DEFAULT_LINUX_PROMPT_STRICT} + Utils.Write Commands Until Expected Prompt + ... sudo ovs-ofctl dump-group-stats ${INTEGRATION_BRIDGE} -OOpenFlow13 + ... ${DEFAULT_LINUX_PROMPT_STRICT} Get ControlNode Connection SSHLibrary.Switch Connection ${OS_CNTL_CONN_ID} - [Return] ${OS_CNTL_CONN_ID} + RETURN ${OS_CNTL_CONN_ID} Get OvsDebugInfo [Documentation] Get the OvsConfig and Flow entries from all Openstack nodes @@ -713,7 +871,10 @@ Get Test Teardown Debugs BuiltIn.Run Keyword And Ignore Error DataModels.Get Model Dump ${HA_PROXY_IP} ${netvirt_data_models} KarafKeywords.Fail If Exceptions Found During Test ${test_name} fail=${fail} FOR ${i} IN RANGE ${NUM_ODL_SYSTEM} - BuiltIn.Run Keyword And Ignore Error Issue_Command_On_Karaf_Console trace:transactions ${ODL_SYSTEM_${i+1}_IP} + BuiltIn.Run Keyword And Ignore Error + ... Issue_Command_On_Karaf_Console + ... trace:transactions + ... ${ODL_SYSTEM_${i+1}_IP} END Get Suite Debugs @@ -724,8 +885,8 @@ Get Test Teardown Debugs For SFC BuiltIn.Run Keyword And Ignore Error DataModels.Get Model Dump ${HA_PROXY_IP} ${netvirt_sfc_data_models} Show Debugs - [Arguments] @{vm_indices} [Documentation] Run these commands for debugging, it can list state of VM instances and ip information in control node + [Arguments] @{vm_indices} OpenStackOperations.Get ControlNode Connection ${output} = DevstackUtils.Write Commands Until Prompt And Log sudo ip netns list FOR ${index} IN @{vm_indices} @@ -743,84 +904,146 @@ List Security Groups [Documentation] Logging keyword to display all security groups using the openstack cli. Assumes openstack ... credentials are already sourced ${output} = OpenStack CLI openstack security group list - [Return] ${output} + RETURN ${output} Neutron Security Group Show - [Arguments] ${SecurityGroupRuleName} [Documentation] Displays the neutron security group configurations that belongs to a given neutron security group name + [Arguments] ${SecurityGroupRuleName} ${output} = OpenStack CLI openstack security group show ${SecurityGroupRuleName} - [Return] ${output} + RETURN ${output} Neutron Port Show - [Arguments] ${PortName} [Documentation] Display the port configuration that belong to a given neutron port + [Arguments] ${PortName} ${output} = OpenStack CLI openstack port show ${PortName} - [Return] ${output} + RETURN ${output} Neutron Security Group Create - [Arguments] ${SecurityGroupName} ${additional_args}=${EMPTY} [Documentation] Create a security group with specified name ,description & protocol value according to security group template + [Arguments] ${SecurityGroupName} ${additional_args}=${EMPTY} OpenStackOperations.Get ControlNode Connection ${output} = OpenStack CLI openstack security group create ${SecurityGroupName} ${additional_args} ${sgp_id} = BuiltIn.Should Match Regexp ${output} ${REGEX_UUID} - [Return] ${output} ${sgp_id} + RETURN ${output} ${sgp_id} Neutron Security Group Update - [Arguments] ${SecurityGroupName} ${additional_args}=${EMPTY} [Documentation] Updating security groups + [Arguments] ${SecurityGroupName} ${additional_args}=${EMPTY} ${output} = OpenStack CLI openstack security group set ${SecurityGroupName} ${additional_args} - [Return] ${output} + RETURN ${output} Delete SecurityGroup - [Arguments] ${sg_name} [Documentation] Delete Security group + [Arguments] ${sg_name} ${output} = OpenStack CLI openstack security group delete ${sg_name} Neutron Security Group Rule Create - [Arguments] ${Security_group_name} &{Kwargs} [Documentation] Creates neutron security rule with Openstack CLI with or without optional params, here security group name is mandatory args, rule with optional params can be created by passing the optional args values ex: direction=${INGRESS_EGRESS}, Then these optional params are BuiltIn.Catenated with mandatory args, example of usage: "OpenStack Neutron Security Group Rule Create ${SGP_SSH} direction=${RULE_PARAMS[0]} ethertype=${RULE_PARAMS[1]} ..." - BuiltIn.Run Keyword If ${Kwargs} BuiltIn.Log ${Kwargs} - ${description} BuiltIn.Run Keyword If ${Kwargs} Collections.Pop From Dictionary ${Kwargs} description default=${None} - ${direction} BuiltIn.Run Keyword If ${Kwargs} Collections.Pop From Dictionary ${Kwargs} direction default=${None} - ${ethertype} BuiltIn.Run Keyword If ${Kwargs} Collections.Pop From Dictionary ${Kwargs} ethertype default=${None} - ${port_range_max} BuiltIn.Run Keyword If ${Kwargs} Collections.Pop From Dictionary ${Kwargs} port_range_max default=${None} - ${port_range_min} BuiltIn.Run Keyword If ${Kwargs} Collections.Pop From Dictionary ${Kwargs} port_range_min default=${None} - ${protocol} BuiltIn.Run Keyword If ${Kwargs} Collections.Pop From Dictionary ${Kwargs} protocol default=${None} - ${remote_group_id} BuiltIn.Run Keyword If ${Kwargs} Collections.Pop From Dictionary ${Kwargs} remote_group_id default=${None} - ${remote_ip_prefix} BuiltIn.Run Keyword If ${Kwargs} Collections.Pop From Dictionary ${Kwargs} remote_ip_prefix default=${None} - ${remote_ip} BuiltIn.Run Keyword If ${Kwargs} Collections.Pop From Dictionary ${Kwargs} remote_ip default=${None} + [Arguments] ${Security_group_name} &{Kwargs} + IF ${Kwargs} BuiltIn.Log ${Kwargs} + IF ${Kwargs} + ${description} = Collections.Pop From Dictionary ${Kwargs} description default=${None} + ELSE + ${description} = Set Variable ${None} + END + IF ${Kwargs} + ${direction} = Collections.Pop From Dictionary ${Kwargs} direction default=${None} + ELSE + ${direction} = Set Variable ${None} + END + IF ${Kwargs} + ${ethertype} = Collections.Pop From Dictionary ${Kwargs} ethertype default=${None} + ELSE + ${ethertype} = Set Variable ${None} + END + IF ${Kwargs} + ${port_range_max} = Collections.Pop From Dictionary ${Kwargs} port_range_max default=${None} + ELSE + ${port_range_max} = Set Variable ${None} + END + IF ${Kwargs} + ${port_range_min} = Collections.Pop From Dictionary ${Kwargs} port_range_min default=${None} + ELSE + ${port_range_min} = Set Variable ${None} + END + IF ${Kwargs} + ${protocol} = Collections.Pop From Dictionary ${Kwargs} protocol default=${None} + ELSE + ${protocol} = Set Variable ${None} + END + IF ${Kwargs} + ${remote_group_id} = Collections.Pop From Dictionary ${Kwargs} remote_group_id default=${None} + ELSE + ${remote_group_id} = Set Variable ${None} + END + IF ${Kwargs} + ${remote_ip_prefix} = Collections.Pop From Dictionary ${Kwargs} remote_ip_prefix default=${None} + ELSE + ${remote_ip_prefix} = Set Variable ${None} + END + IF ${Kwargs} + ${remote_ip} = Collections.Pop From Dictionary ${Kwargs} remote_ip default=${None} + ELSE + ${remote_ip} = Set Variable ${None} + END ${cmd} = BuiltIn.Set Variable openstack security group rule create ${Security_group_name} - ${cmd} = BuiltIn.Run Keyword If '${description}'!='None' BuiltIn.Catenate ${cmd} --description ${description} - ... ELSE BuiltIn.Catenate ${cmd} - ${cmd} = BuiltIn.Run Keyword If '${direction}'!='None' BuiltIn.Catenate ${cmd} --${direction} - ... ELSE BuiltIn.Catenate ${cmd} - ${cmd} = BuiltIn.Run Keyword If '${ethertype}'!='None' BuiltIn.Catenate ${cmd} --ethertype ${ethertype} - ... ELSE BuiltIn.Catenate ${cmd} - ${cmd} = BuiltIn.Run Keyword If '${port_range_min}'!='None' and '${port_range_max}'!='None' BuiltIn.Catenate ${cmd} --dst-port ${port_range_min}:${port_range_max} - ... ELSE IF '${port_range_max}'!='None' BuiltIn.Catenate ${cmd} --dst-port ${port_range_max} - ... ELSE IF '${port_range_min}'!='None' BuiltIn.Catenate ${cmd} --dst-port ${port_range_min} - ... ELSE BuiltIn.Catenate ${cmd} - ${cmd} = BuiltIn.Run Keyword If '${protocol}'!='None' BuiltIn.Catenate ${cmd} --protocol ${protocol} - ... ELSE BuiltIn.Catenate ${cmd} - ${cmd} = BuiltIn.Run Keyword If '${remote_group_id}'!='None' BuiltIn.Catenate ${cmd} --remote-group ${remote_group_id} - ... ELSE BuiltIn.Catenate ${cmd} - ${cmd} = BuiltIn.Run Keyword If '${remote_ip_prefix}'!='None' BuiltIn.Catenate ${cmd} --src-ip ${remote_ip_prefix} - ... ELSE BuiltIn.Catenate ${cmd} - ${cmd} = BuiltIn.Run Keyword If '${remote_ip}'!='None' BuiltIn.Catenate ${cmd} --remote-ip ${remote_ip} - ... ELSE BuiltIn.Catenate ${cmd} + IF '${description}'!='None' + ${cmd} = BuiltIn.Catenate ${cmd} --description ${description} + ELSE + ${cmd} = BuiltIn.Catenate ${cmd} + END + IF '${direction}'!='None' + ${cmd} = BuiltIn.Catenate ${cmd} --${direction} + ELSE + ${cmd} = BuiltIn.Catenate ${cmd} + END + IF '${ethertype}'!='None' + ${cmd} = BuiltIn.Catenate ${cmd} --ethertype ${ethertype} + ELSE + ${cmd} = BuiltIn.Catenate ${cmd} + END + IF '${port_range_min}'!='None' and '${port_range_max}'!='None' + ${cmd} = BuiltIn.Catenate ${cmd} --dst-port ${port_range_min}:${port_range_max} + ELSE IF '${port_range_max}'!='None' + ${cmd} = BuiltIn.Catenate ${cmd} --dst-port ${port_range_max} + ELSE IF '${port_range_min}'!='None' + ${cmd} = BuiltIn.Catenate ${cmd} --dst-port ${port_range_min} + ELSE + ${cmd} = BuiltIn.Catenate ${cmd} + END + IF '${protocol}'!='None' + ${cmd} = BuiltIn.Catenate ${cmd} --protocol ${protocol} + ELSE + ${cmd} = BuiltIn.Catenate ${cmd} + END + IF '${remote_group_id}'!='None' + ${cmd} = BuiltIn.Catenate ${cmd} --remote-group ${remote_group_id} + ELSE + ${cmd} = BuiltIn.Catenate ${cmd} + END + IF '${remote_ip_prefix}'!='None' + ${cmd} = BuiltIn.Catenate ${cmd} --src-ip ${remote_ip_prefix} + ELSE + ${cmd} = BuiltIn.Catenate ${cmd} + END + IF '${remote_ip}'!='None' + ${cmd} = BuiltIn.Catenate ${cmd} --remote-ip ${remote_ip} + ELSE + ${cmd} = BuiltIn.Catenate ${cmd} + END ${output} = OpenStack CLI ${cmd} ${rule_id} = BuiltIn.Should Match Regexp ${output} ${REGEX_UUID} - [Return] ${output} ${rule_id} + RETURN ${output} ${rule_id} Security Group Create Without Default Security Rules - [Arguments] ${sg_name} ${additional_args}=${EMPTY} [Documentation] Create Neutron Security Group with no default rules, using specified name and optional arguments. + [Arguments] ${sg_name} ${additional_args}=${EMPTY} OpenStackOperations.Neutron Security Group Create ${sg_name} ${additional_args} Delete All Security Group Rules ${sg_name} Delete All Security Group Rules - [Arguments] ${sg_name} [Documentation] Delete all security rules from a specified security group + [Arguments] ${sg_name} ${sg_rules_output} = OpenStack CLI openstack security group rule list ${sg_name} -cID -fvalue @{sg_rules} = String.Split String ${sg_rules_output} \n FOR ${rule} IN @{sg_rules} @@ -828,282 +1051,388 @@ Delete All Security Group Rules END Create Allow All SecurityGroup - [Arguments] ${sg_name} ${ether_type}=IPv4 ${dual}=False [Documentation] Allow all TCP/UDP/ICMP packets for this suite + [Arguments] ${sg_name} ${ether_type}=IPv4 ${dual}=False OpenStackOperations.Neutron Security Group Create ${sg_name} - OpenStackOperations.Neutron Security Group Rule Create ${sg_name} direction=ingress ethertype=${ether_type} port_range_max=65535 port_range_min=1 protocol=tcp - OpenStackOperations.Neutron Security Group Rule Create ${sg_name} direction=egress ethertype=${ether_type} port_range_max=65535 port_range_min=1 protocol=tcp - OpenStackOperations.Neutron Security Group Rule Create ${sg_name} direction=ingress ethertype=${ether_type} protocol=icmp - OpenStackOperations.Neutron Security Group Rule Create ${sg_name} direction=egress ethertype=${ether_type} protocol=icmp - OpenStackOperations.Neutron Security Group Rule Create ${sg_name} direction=ingress ethertype=${ether_type} port_range_max=65535 port_range_min=1 protocol=udp - OpenStackOperations.Neutron Security Group Rule Create ${sg_name} direction=egress ethertype=${ether_type} port_range_max=65535 port_range_min=1 protocol=udp - BuiltIn.Run Keyword If "${dual}"=="True" Run Keywords OpenStackOperations.Neutron Security Group Rule Create ${sg_name} direction=ingress ethertype=IPv6 - ... port_range_max=65535 port_range_min=1 protocol=tcp - ... AND OpenStackOperations.Neutron Security Group Rule Create ${sg_name} direction=egress ethertype=IPv6 port_range_max=65535 - ... port_range_min=1 protocol=tcp - ... AND OpenStackOperations.Neutron Security Group Rule Create ${sg_name} direction=ingress ethertype=IPv6 protocol=icmp - ... AND OpenStackOperations.Neutron Security Group Rule Create ${sg_name} direction=egress ethertype=IPv6 protocol=icmp - ... AND OpenStackOperations.Neutron Security Group Rule Create ${sg_name} direction=ingress ethertype=IPv6 port_range_max=65535 - ... port_range_min=1 protocol=udp - ... AND OpenStackOperations.Neutron Security Group Rule Create ${sg_name} direction=egress ethertype=IPv6 port_range_max=65535 - ... port_range_min=1 protocol=udp + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg_name} + ... direction=ingress + ... ethertype=${ether_type} + ... port_range_max=65535 + ... port_range_min=1 + ... protocol=tcp + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg_name} + ... direction=egress + ... ethertype=${ether_type} + ... port_range_max=65535 + ... port_range_min=1 + ... protocol=tcp + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg_name} + ... direction=ingress + ... ethertype=${ether_type} + ... protocol=icmp + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg_name} + ... direction=egress + ... ethertype=${ether_type} + ... protocol=icmp + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg_name} + ... direction=ingress + ... ethertype=${ether_type} + ... port_range_max=65535 + ... port_range_min=1 + ... protocol=udp + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg_name} + ... direction=egress + ... ethertype=${ether_type} + ... port_range_max=65535 + ... port_range_min=1 + ... protocol=udp + IF "${dual}"=="True" + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg_name} + ... direction=ingress + ... ethertype=IPv6 + ... port_range_max=65535 + ... port_range_min=1 + ... protocol=tcp + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg_name} + ... direction=egress + ... ethertype=IPv6 + ... port_range_max=65535 + ... port_range_min=1 + ... protocol=tcp + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg_name} + ... direction=ingress + ... ethertype=IPv6 + ... protocol=icmp + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg_name} + ... direction=egress + ... ethertype=IPv6 + ... protocol=icmp + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg_name} + ... direction=ingress + ... ethertype=IPv6 + ... port_range_max=65535 + ... port_range_min=1 + ... protocol=udp + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg_name} + ... direction=egress + ... ethertype=IPv6 + ... port_range_max=65535 + ... port_range_min=1 + ... protocol=udp + END Create Neutron Port With Additional Params - [Arguments] ${network_name} ${port_name} ${additional_args}=${EMPTY} [Documentation] Create Port With given additional parameters - ${rc} ${output} = OperatingSystem.Run And Return Rc And Output neutron -v port-create ${network_name} --name ${port_name} ${additional_args} + [Arguments] ${network_name} ${port_name} ${additional_args}=${EMPTY} + ${rc} ${output} = OperatingSystem.Run And Return Rc And Output + ... neutron -v port-create ${network_name} --name ${port_name} ${additional_args} BuiltIn.Log ${output} BuiltIn.Should Be True '${rc}' == '0' ${port_id} = BuiltIn.Should Match Regexp ${OUTPUT} ${REGEX_UUID} - [Return] ${OUTPUT} ${port_id} + RETURN ${OUTPUT} ${port_id} Get Ports MacAddr - [Arguments] ${ports} [Documentation] Retrieve the port MacAddr for the given list of port name and return the MAC address list. - ${macs} BuiltIn.Create List + [Arguments] ${ports} + ${macs} = BuiltIn.Create List FOR ${port} IN @{ports} ${mac} = OpenStackOperations.Get Port Mac ${port} Collections.Append To List ${macs} ${mac} END - [Return] ${macs} + RETURN ${macs} Get Port Ip - [Arguments] ${port_name} [Documentation] Keyword would return the IP of the ${port_name} received. + [Arguments] ${port_name} ${output} = OpenStack CLI openstack port list | grep "${port_name}" | awk -F\\' '{print $2}' ${splitted_output} = String.Split String ${output} ${EMPTY} ${port_ip} = Collections.Get from List ${splitted_output} 0 - [Return] ${port_ip} + RETURN ${port_ip} Get Port Mac - [Arguments] ${port_name} [Documentation] Keyword would return the MAC ID of the ${port_name} received. + [Arguments] ${port_name} ${output} = OpenStack CLI openstack port show ${port_name} | grep mac_address | awk '{print $4}' ${splitted_output} = String.Split String ${output} ${EMPTY} ${port_mac} = Collections.Get from List ${splitted_output} 0 - [Return] ${port_mac} + RETURN ${port_mac} Get Port Mac Address From Ip - [Arguments] ${ip} [Documentation] Retrieve the mac address for a port that matches any given ip. + [Arguments] ${ip} ${output} = OpenStack CLI openstack port list | grep -w ${ip} | awk '{print $5}' ${splitted_output} = String.Split String ${output} ${EMPTY} ${mac_addr} = Collections.Get from List ${splitted_output} 0 - [Return] ${mac_addr} + RETURN ${mac_addr} Create L2Gateway - [Arguments] ${bridge_name} ${intf_name} ${gw_name} [Documentation] Keyword to create an L2 Gateway ${gw_name} for bridge ${bridge_name} connected to interface ${intf_name} (Using Neutron CLI). - ${rc} ${l2gw_output} = OperatingSystem.Run And Return Rc And Output ${L2GW_CREATE} name=${bridge_name},interface_names=${intf_name} ${gw_name} + [Arguments] ${bridge_name} ${intf_name} ${gw_name} + ${rc} ${l2gw_output} = OperatingSystem.Run And Return Rc And Output + ... ${L2GW_CREATE} name=${bridge_name},interface_names=${intf_name} ${gw_name} BuiltIn.Log ${l2gw_output} - [Return] ${l2gw_output} + RETURN ${l2gw_output} Update L2Gateway - [Arguments] ${bridge_name} ${gw_name} ${intf_name_1} ${intf_name_2} [Documentation] Keyword to add {intf_name_list} to an existing L2 Gateway ${gw_name} (Using Neutron CLI). - ${rc} ${l2gw_output}= Run And Return Rc And Output ${L2GW_UPDATE} name=${bridge_name},interface_names="${intf_name_1};${intf_name_2}" ${gw_name} + [Arguments] ${bridge_name} ${gw_name} ${intf_name_1} ${intf_name_2} + ${rc} ${l2gw_output} = Run And Return Rc And Output + ... ${L2GW_UPDATE} name=${bridge_name},interface_names="${intf_name_1};${intf_name_2}" ${gw_name} Log ${l2gw_output} - [Return] ${l2gw_output} + RETURN ${l2gw_output} Create L2Gateway Connection - [Arguments] ${gw_name} ${net_name} [Documentation] Keyword would create a new L2 Gateway Connection for ${gw_name} to ${net_name} (Using Neutron CLI). - ${rc} ${l2gw_output} = OperatingSystem.Run And Return Rc And Output ${L2GW_CONN_CREATE} ${gw_name} ${net_name} + [Arguments] ${gw_name} ${net_name} + ${rc} ${l2gw_output} = OperatingSystem.Run And Return Rc And Output + ... ${L2GW_CONN_CREATE} ${gw_name} ${net_name} BuiltIn.Log ${l2gw_output} BuiltIn.Should Be True '${rc}' == '0' - [Return] ${l2gw_output} + RETURN ${l2gw_output} Get All L2Gateway [Documentation] Keyword to return all the L2 Gateways available (Using Neutron CLI). ${rc} ${output} = OperatingSystem.Run And Return Rc And Output ${L2GW_GET_YAML} BuiltIn.Should Be True '${rc}' == '0' - [Return] ${output} + RETURN ${output} Get All L2Gateway Connection [Documentation] Keyword to return all the L2 Gateway connections available (Using Neutron CLI). ${rc} ${output} = OperatingSystem.Run And Return Rc And Output ${L2GW_GET_CONN_YAML} BuiltIn.Should Be True '${rc}' == '0' - [Return] ${output} + RETURN ${output} Get L2Gateway - [Arguments] ${gw_id} [Documentation] Keyword to check if the ${gw_id} is available in the L2 Gateway list (Using Neutron CLI). + [Arguments] ${gw_id} ${rc} ${output} = OperatingSystem.Run And Return Rc And Output ${L2GW_SHOW} ${gw_id} BuiltIn.Log ${output} BuiltIn.Should Be True '${rc}' == '0' - [Return] ${output} + RETURN ${output} Get L2gw Id - [Arguments] ${l2gw_name} [Documentation] Keyword to retrieve the L2 Gateway ID for the ${l2gw_name} (Using Neutron CLI). - ${rc} ${output} = OperatingSystem.Run And Return Rc And Output ${L2GW_GET} | grep "${l2gw_name}" | awk '{print $2}' + [Arguments] ${l2gw_name} + ${rc} ${output} = OperatingSystem.Run And Return Rc And Output + ... ${L2GW_GET} | grep "${l2gw_name}" | awk '{print $2}' BuiltIn.Log ${output} BuiltIn.Should Be True '${rc}' == '0' ${splitted_output} = String.Split String ${output} ${EMPTY} ${l2gw_id} = Collections.Get from List ${splitted_output} 0 - [Return] ${l2gw_id} + RETURN ${l2gw_id} Get L2gw Connection Id - [Arguments] ${l2gw_name} [Documentation] Keyword to retrieve the L2 Gateway Connection ID for the ${l2gw_name} (Using Neutron CLI). + [Arguments] ${l2gw_name} ${l2gw_id} = OpenStackOperations.Get L2gw Id ${l2gw_name} - ${rc} ${output} = OperatingSystem.Run And Return Rc And Output ${L2GW_GET_CONN} | grep "${l2gw_id}" | awk '{print $2}' + ${rc} ${output} = OperatingSystem.Run And Return Rc And Output + ... ${L2GW_GET_CONN} | grep "${l2gw_id}" | awk '{print $2}' BuiltIn.Should Be True '${rc}' == '0' ${splitted_output} = String.Split String ${output} ${EMPTY} ${splitted_output} = String.Split String ${output} ${EMPTY} ${l2gw_conn_id} = Collections.Get from List ${splitted_output} 0 - [Return] ${l2gw_conn_id} + RETURN ${l2gw_conn_id} Neutron Port List Rest [Documentation] Keyword to get all ports details in Neutron (Using REST). ${resp} = RequestsLibrary.Get Request session ${PORT_URL} BuiltIn.Log ${resp.text} BuiltIn.Should Be Equal As Strings ${resp.status_code} 200 - [Return] ${resp.text} + RETURN ${resp.text} Get Neutron Port Rest - [Arguments] ${port_id} [Documentation] Keyword to get the specific port details in Neutron (Using REST). + [Arguments] ${port_id} ${resp} = RequestsLibrary.Get Request session ${CONFIG_API}/${GET_PORT_URL}/${port_id} BuiltIn.Log ${resp.text} BuiltIn.Should Be Equal As Strings ${resp.status_code} 200 - [Return] ${resp.text} + RETURN ${resp.text} Update Port Rest - [Arguments] ${port_id} ${json_data} [Documentation] Keyword to update ${port_id} with json data received in ${json_data} (Using REST). + [Arguments] ${port_id} ${json_data} BuiltIn.Log ${json_data} ${resp} = RequestsLibrary.Put Request session ${CONFIG_API}/${GET_PORT_URL}/${port_id} ${json_data} BuiltIn.Log ${resp.text} BuiltIn.Should Be Equal As Strings ${resp.status_code} 200 - [Return] ${resp.text} + RETURN ${resp.text} Get Neutron Network Rest - [Arguments] ${net_id} [Documentation] Keyword to get the specific network details in Neutron (Using REST). + [Arguments] ${net_id} ${resp} = RequestsLibrary.Get Request session ${NETWORK_URL}/network/${net_id} BuiltIn.Log ${resp.text} BuiltIn.Should Be Equal As Strings ${resp.status_code} 200 - [Return] ${resp.text} + RETURN ${resp.text} Create And Configure Security Group - [Arguments] ${sg-name} [Documentation] Create Security Group with given name, and default allow rules for TCP/UDP/ICMP protocols. + [Arguments] ${sg-name} OpenStackOperations.Neutron Security Group Create ${sg-name} - OpenStackOperations.Neutron Security Group Rule Create ${sg-name} direction=ingress port_range_max=65535 port_range_min=1 protocol=tcp remote_ip_prefix=0.0.0.0/0 - OpenStackOperations.Neutron Security Group Rule Create ${sg-name} direction=egress port_range_max=65535 port_range_min=1 protocol=tcp remote_ip_prefix=0.0.0.0/0 - OpenStackOperations.Neutron Security Group Rule Create ${sg-name} direction=ingress protocol=icmp remote_ip_prefix=0.0.0.0/0 - OpenStackOperations.Neutron Security Group Rule Create ${sg-name} direction=egress protocol=icmp remote_ip_prefix=0.0.0.0/0 - OpenStackOperations.Neutron Security Group Rule Create ${sg-name} direction=ingress port_range_max=65535 port_range_min=1 protocol=udp remote_ip_prefix=0.0.0.0/0 - OpenStackOperations.Neutron Security Group Rule Create ${sg-name} direction=egress port_range_max=65535 port_range_min=1 protocol=udp remote_ip_prefix=0.0.0.0/0 + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg-name} + ... direction=ingress + ... port_range_max=65535 + ... port_range_min=1 + ... protocol=tcp + ... remote_ip_prefix=0.0.0.0/0 + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg-name} + ... direction=egress + ... port_range_max=65535 + ... port_range_min=1 + ... protocol=tcp + ... remote_ip_prefix=0.0.0.0/0 + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg-name} + ... direction=ingress + ... protocol=icmp + ... remote_ip_prefix=0.0.0.0/0 + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg-name} + ... direction=egress + ... protocol=icmp + ... remote_ip_prefix=0.0.0.0/0 + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg-name} + ... direction=ingress + ... port_range_max=65535 + ... port_range_min=1 + ... protocol=udp + ... remote_ip_prefix=0.0.0.0/0 + OpenStackOperations.Neutron Security Group Rule Create + ... ${sg-name} + ... direction=egress + ... port_range_max=65535 + ... port_range_min=1 + ... protocol=udp + ... remote_ip_prefix=0.0.0.0/0 Add Security Group To VM - [Arguments] ${vm} ${sg} [Documentation] Add the security group provided to the given VM. + [Arguments] ${vm} ${sg} ${output} = OpenStack CLI openstack server add security group ${vm} ${sg} Remove Security Group From VM - [Arguments] ${vm} ${sg} [Documentation] Remove the security group provided to the given VM. + [Arguments] ${vm} ${sg} OpenStackOperations.Get ControlNode Connection ${output} = OpenStack CLI openstack server remove security group ${vm} ${sg} Create SFC Flow Classifier - [Arguments] ${name} ${src_ip} ${dest_ip} ${protocol} ${neutron_src_port} ${args}=${EMPTY} [Documentation] Create a flow classifier for SFC - ${output} = OpenStack CLI openstack sfc flow classifier create --ethertype IPv4 --source-ip-prefix ${src_ip}/32 --destination-ip-prefix ${dest_ip}/32 --protocol ${protocol} --logical-source-port ${neutron_src_port} ${args} ${name} + [Arguments] ${name} ${src_ip} ${dest_ip} ${protocol} ${neutron_src_port} ${args}=${EMPTY} + ${output} = OpenStack CLI + ... openstack sfc flow classifier create --ethertype IPv4 --source-ip-prefix ${src_ip}/32 --destination-ip-prefix ${dest_ip}/32 --protocol ${protocol} --logical-source-port ${neutron_src_port} ${args} ${name} BuiltIn.Should Contain ${output} ${name} - [Return] ${output} + RETURN ${output} Delete SFC Flow Classifier - [Arguments] ${name} [Documentation] Delete a SFC flow classifier + [Arguments] ${name} ${output} = OpenStack CLI openstack sfc flow classifier delete ${name} - [Return] ${output} + RETURN ${output} Create SFC Port Pair - [Arguments] ${name} ${port_in} ${port_out} [Documentation] Creates a neutron port pair for SFC + [Arguments] ${name} ${port_in} ${port_out} ${output} = OpenStack CLI openstack sfc port pair create --ingress=${port_in} --egress=${port_out} ${name} BuiltIn.Should Contain ${output} ${name} - [Return] ${output} + RETURN ${output} Delete SFC Port Pair - [Arguments] ${name} [Documentation] Delete a SFC port pair + [Arguments] ${name} ${output} = OpenStack CLI openstack sfc port pair delete ${name} - [Return] ${output} + RETURN ${output} Create SFC Port Pair Group - [Arguments] ${name} ${port_pair} [Documentation] Creates a port pair group with a single port pair for SFC + [Arguments] ${name} ${port_pair} ${output} = OpenStack CLI openstack sfc port pair group create --port-pair ${port_pair} ${name} BuiltIn.Should Contain ${output} ${name} - [Return] ${output} + RETURN ${output} Create SFC Port Pair Group With Two Pairs - [Arguments] ${name} ${port_pair1} ${port_pair2} [Documentation] Creates a port pair group with two port pairs for SFC - ${output} = OpenStack CLI openstack sfc port pair group create --port-pair ${port_pair1} --port-pair ${port_pair2} ${name} + [Arguments] ${name} ${port_pair1} ${port_pair2} + ${output} = OpenStack CLI + ... openstack sfc port pair group create --port-pair ${port_pair1} --port-pair ${port_pair2} ${name} BuiltIn.Should Contain ${output} ${name} - [Return] ${output} + RETURN ${output} Delete SFC Port Pair Group - [Arguments] ${name} [Documentation] Delete a SFC port pair group + [Arguments] ${name} OpenStackOperations.Get ControlNode Connection ${output} = OpenStack CLI openstack sfc port pair group delete ${name} - [Return] ${output} + RETURN ${output} Create SFC Port Chain - [Arguments] ${name} ${args}=${EMPTY} [Documentation] Creates a port pair chain with two port groups and a singel classifier. + [Arguments] ${name} ${args}=${EMPTY} ${output} = OpenStack CLI openstack sfc port chain create ${name} ${args} BuiltIn.Should Contain ${output} ${name} - [Return] ${output} + RETURN ${output} Update SFC Port Chain With A New Flow Classifier - [Arguments] ${name} ${fc} [Documentation] Adds a Flow Classifier to a Port Chain + [Arguments] ${name} ${fc} ${output} = OpenStack CLI openstack sfc port chain set ${name} --flow-classifier ${fc} - [Return] ${output} + RETURN ${output} Update SFC Port Chain Removing A Flow Classifier - [Arguments] ${name} ${fc} [Documentation] Adds a Flow Classifier to a Port Chain + [Arguments] ${name} ${fc} ${output} = OpenStack CLI openstack sfc port chain unset ${name} --flow-classifier ${fc} - [Return] ${output} + RETURN ${output} Delete SFC Port Chain - [Arguments] ${name} [Documentation] Delete a SFC port chain + [Arguments] ${name} ${output} = OpenStack CLI openstack sfc port chain delete ${name} - [Return] ${output} + RETURN ${output} Reboot Nova VM - [Arguments] ${vm_name} [Documentation] Reboot NOVA VM + [Arguments] ${vm_name} ${output} = OpenStack CLI openstack server reboot --wait ${vm_name} BuiltIn.Wait Until Keyword Succeeds 35s 10s OpenStackOperations.Verify VM Is ACTIVE ${vm_name} Remove RSA Key From KnownHosts - [Arguments] ${vm_ip} [Documentation] Remove RSA + [Arguments] ${vm_ip} OpenStackOperations.Get ControlNode Connection ${output} = DevstackUtils.Write Commands Until Prompt And Log sudo cat /root/.ssh/known_hosts 30s - ${output} = DevstackUtils.Write Commands Until Prompt And Log sudo ssh-keygen -f "/root/.ssh/known_hosts" -R ${vm_ip} 30s + ${output} = DevstackUtils.Write Commands Until Prompt And Log + ... sudo ssh-keygen -f "/root/.ssh/known_hosts" -R ${vm_ip} + ... 30s ${output} = DevstackUtils.Write Commands Until Prompt sudo cat "/root/.ssh/known_hosts" 30s Wait For Routes To Propogate - [Arguments] ${networks} ${subnets} [Documentation] Check propagated routes + [Arguments] ${networks} ${subnets} OpenStackOperations.Get ControlNode Connection FOR ${INDEX} IN RANGE 0 1 ${net_id} = OpenStackOperations.Get Net Id ${networks}[${INDEX}] ${is_ipv6} = String.Get Regexp Matches ${subnets}[${INDEX}] ${IP6_REGEX} ${length} = BuiltIn.Get Length ${is_ipv6} ${cmd} = BuiltIn.Set Variable If ${length} == 0 ip route ip -6 route - ${output} = Utils.Write Commands Until Expected Prompt sudo ip netns exec qdhcp-${net_id} ${cmd} ${DEFAULT_LINUX_PROMPT_STRICT} + ${output} = Utils.Write Commands Until Expected Prompt + ... sudo ip netns exec qdhcp-${net_id} ${cmd} + ... ${DEFAULT_LINUX_PROMPT_STRICT} BuiltIn.Should Contain ${output} ${subnets}[${INDEX}] END @@ -1134,29 +1463,29 @@ OpenStack List All END OpenStack CLI Get List - [Arguments] ${cmd} [Documentation] Return a json list from the output of an OpenStack command. + [Arguments] ${cmd} @{list} = BuiltIn.Create List ${json} = OpenStack CLI ${cmd} @{list} = RequestsLibrary.To Json ${json} BuiltIn.Log ${list} - [Return] @{list} + RETURN @{list} OpenStack CLI - [Arguments] ${cmd} [Documentation] Run the given OpenStack ${cmd} and log the output. + [Arguments] ${cmd} ${result} = Process.Run Process ${cmd} shell=True BuiltIn.Log ${result.stdout} BuiltIn.Log ${result.stderr} BuiltIn.Should Be True '${result.rc}' == '0' - [Return] ${result.stdout} + RETURN ${result.stdout} OpenStack CLI With No Log - [Arguments] ${cmd} [Documentation] Run the given OpenStack ${cmd} and do not log the output. + [Arguments] ${cmd} ${result} = Process.Run Process ${cmd} shell=True BuiltIn.Should Be True '${result.rc}' == '0' - [Return] ${result.stdout} + RETURN ${result.stdout} OpenStack Cleanup All [Documentation] Cleanup all Openstack resources with best effort. The keyword will query for all resources @@ -1185,30 +1514,41 @@ OpenStack Cleanup All END @{security_groups} = OpenStack CLI Get List openstack security group list -f json FOR ${security_group} IN @{security_groups} - BuiltIn.Run Keyword If "${security_group['Name']}" != "default" BuiltIn.Run Keyword And Ignore Error Delete SecurityGroup ${security_group['ID']} + IF "${security_group['Name']}" != "default" + BuiltIn.Run Keyword And Ignore Error Delete SecurityGroup ${security_group['ID']} + END END OpenStack List All Cleanup Router - [Arguments] ${id} [Documentation] Delete a router, but first remove any interfaces or gateways so that the delete will be successful. + [Arguments] ${id} @{ports} = OpenStack CLI Get List openstack port list --router ${id} -f json --long FOR ${port} IN @{ports} ${subnet_id} = OpenStackOperations.Get Match ${port['Fixed IP Addresses']} ${REGEX_UUID} 0 - BuiltIn.Run Keyword If "${port['Device Owner']}" == "network:router_gateway" BuiltIn.Run Keyword And Ignore Error Remove Gateway ${id} - BuiltIn.Run Keyword If "${port['Device Owner']}" == "network:router_interface" BuiltIn.Run Keyword And Ignore Error Remove Interface ${id} ${subnet_id} + IF "${port['Device Owner']}" == "network:router_gateway" + BuiltIn.Run Keyword And Ignore Error Remove Gateway ${id} + END + IF "${port['Device Owner']}" == "network:router_interface" + BuiltIn.Run Keyword And Ignore Error Remove Interface ${id} ${subnet_id} + END END BuiltIn.Run Keyword And Ignore Error Delete Router ${id} OpenStack Suite Setup [Documentation] Wrapper teardown keyword that can be used in any suite running in an openstack environement SetupUtils.Setup_Utils_For_Setup_And_Teardown - @{loggers} = BuiltIn.Create List org.apache.karaf.shell.support.ShellUtil org.apache.sshd.server.session.ServerSessionImpl + @{loggers} = BuiltIn.Create List + ... org.apache.karaf.shell.support.ShellUtil + ... org.apache.sshd.server.session.ServerSessionImpl Setuputils.Setup_Logging_For_Debug_Purposes_On_List_Or_All OFF ${loggers} DevstackUtils.Devstack Suite Setup - @{tcpdump_port_6653_conn_ids} = OpenStackOperations.Start Packet Capture On Nodes tcpdump_port_6653 port 6653 @{OS_ALL_IPS} + @{tcpdump_port_6653_conn_ids} = OpenStackOperations.Start Packet Capture On Nodes + ... tcpdump_port_6653 + ... port 6653 + ... @{OS_ALL_IPS} BuiltIn.Set Suite Variable @{tcpdump_port_6653_conn_ids} - BuiltIn.Run Keyword If "${PRE_CLEAN_OPENSTACK_ALL}"=="True" OpenStack Cleanup All + IF "${PRE_CLEAN_OPENSTACK_ALL}"=="True" OpenStack Cleanup All OpenStackOperations.Add OVS Logging On All OpenStack Nodes Validate Deployment @@ -1233,16 +1573,20 @@ Validate Deployment Write To Validate File ----------------------------------------\n${SUITE_NAME}\n FOR ${keyword} IN @{VALIDATION_KEYWORDS} ${status} = Builtin.Run Keyword And Return Status ${keyword} - BuiltIn.Run Keyword If "${status}" == "FAIL" or "${status}" == "False" BuiltIn.Run Keywords Write To Validate File Failed: ${keyword} - ... AND BuiltIn.Fail - ... ELSE Write To Validate File Passed: ${keyword} + IF "${status}" == "FAIL" or "${status}" == "False" + BuiltIn.Run Keywords Write To Validate File Failed: ${keyword} AND BuiltIn.Fail + ELSE + Write To Validate File Passed: ${keyword} + END END Write To Validate File - [Arguments] ${msg} [Documentation] Write the given ${msg} to ${VALIDATION_FILE}. Create the file if not present. + [Arguments] ${msg} ${status} = BuiltIn.Run Keyword And Return Status OperatingSystem.File Should Exist ${VALIDATION_FILE} - BuiltIn.Run Keyword If "${status}" == "False" OperatingSystem.Create File ${VALIDATION_FILE} + IF "${status}" == "False" + OperatingSystem.Create File ${VALIDATION_FILE} + END OperatingSystem.Append To File ${VALIDATION_FILE} ${msg}\n Copy DHCP Files From Control Node @@ -1252,15 +1596,22 @@ Copy DHCP Files From Control Node ${dstdir} = BuiltIn.Set Variable /tmp/qdhcp/${suite_} OperatingSystem.Create Directory ${dstdir} OpenStackOperations.Get ControlNode Connection - BuiltIn.Run Keyword And Ignore Error SSHLibrary.Get Directory /opt/stack/data/neutron/dhcp ${dstdir} recursive=True + BuiltIn.Run Keyword And Ignore Error + ... SSHLibrary.Get Directory + ... /opt/stack/data/neutron/dhcp + ... ${dstdir} + ... recursive=True Is Feature Installed [Arguments] ${features}=none FOR ${feature} IN @{features} - ${status} ${output} BuiltIn.Run Keyword And Ignore Error BuiltIn.Should Contain ${CONTROLLERFEATURES} ${feature} - Return From Keyword If "${status}" == "PASS" True + ${status} ${output} = BuiltIn.Run Keyword And Ignore Error + ... BuiltIn.Should Contain + ... ${CONTROLLERFEATURES} + ... ${feature} + IF "${status}" == "PASS" RETURN True END - [Return] False + RETURN False Add OVS Logging On All OpenStack Nodes [Documentation] Add higher levels of OVS logging to all the OpenStack nodes @@ -1275,64 +1626,75 @@ Reset OVS Logging On All OpenStack Nodes END Start Packet Capture On Nodes - [Arguments] ${tag} ${filter} @{ips} [Documentation] Wrapper keyword around the TcpDump packet capture that is catered to the Openstack setup. ... The caller must pass the three arguments with a variable number of ips at the end, ... but ${EMPTY} can be used for the tag and filter. + [Arguments] ${tag} ${filter} @{ips} ${suite_} = BuiltIn.Evaluate """${SUITE_NAME}""".replace(" ","_").replace("/","_").replace(".","_") ${tag_} = BuiltIn.Catenate SEPARATOR=__ ${tag} ${suite_} @{conn_ids} = Tcpdump.Start Packet Capture on Nodes tag=${tag_} filter=${filter} ips=${ips} - [Return] @{conn_ids} + RETURN @{conn_ids} Stop Packet Capture On Nodes [Arguments] ${conn_ids}=@{EMPTY} Tcpdump.Stop Packet Capture on Nodes ${conn_ids} Server Live Migrate - [Arguments] ${vm_instance_name} [Documentation] Keyword for live migration of VM instance ... additional_agrs is to select particular migration(live/shared-migration/block-migration) ... if the additional_agrs is not given default migration(shared-migration) will happen + [Arguments] ${vm_instance_name} ${output} = OpenStackOperations.OpenStack CLI nova live-migration ${vm_instance_name} Get Hypervisor Host Of Vm - [Arguments] ${vm_name} [Documentation] Show server with neutron request. - ${output} = OpenStackOperations.OpenStack CLI openstack server show -f value -c OS-EXT-SRV-ATTR:host ${vm_name} - [Return] ${output} + [Arguments] ${vm_name} + ${output} = OpenStackOperations.OpenStack CLI + ... openstack server show -f value -c OS-EXT-SRV-ATTR:host ${vm_name} + RETURN ${output} Check If Migration Is Complete - [Arguments] ${vm_name} [Documentation] Show server and verify if task_state is not migrating + [Arguments] ${vm_name} ${output} = OpenStackOperations.OpenStack CLI openstack server show ${vm_name} | grep "OS-EXT-STS:task_state" BuiltIn.Should Not Contain ${output} migrating Modify OpenStack Configuration File - [Arguments] ${conn_id} ${file_name} ${section} ${key} ${value} [Documentation] Use crudini to modify any parameter in any Openstack configuration File + [Arguments] ${conn_id} ${file_name} ${section} ${key} ${value} SSHLibrary.Switch Connection ${conn_id} - ${output} ${rc} = SSHLibrary.Execute Command sudo crudini --verbose --set --inplace ${file_name} ${section} ${key} ${value} return_rc=True return_stdout=True + ${output} ${rc} = SSHLibrary.Execute Command + ... sudo crudini --verbose --set --inplace ${file_name} ${section} ${key} ${value} + ... return_rc=True + ... return_stdout=True BuiltIn.Log ${output} BuiltIn.Should Be True '${rc}' == '0' Restart DevStack Service - [Arguments] ${conn_id} ${service_name} [Documentation] Restart the Openstack Service + [Arguments] ${conn_id} ${service_name} SSHLibrary.Switch Connection ${conn_id} - ${output} ${rc} = SSHLibrary.Execute Command sudo systemctl restart devstack@${service_name}.service return_rc=True return_stdout=True + ${output} ${rc} = SSHLibrary.Execute Command + ... sudo systemctl restart devstack@${service_name}.service + ... return_rc=True + ... return_stdout=True BuiltIn.Log ${output} BuiltIn.Should Be True '${rc}' == '0' Get Network Segmentation Id - [Arguments] ${network_name} [Documentation] Returns network segmentation id for the given network name. + [Arguments] ${network_name} ${output} = OpenStack CLI openstack network show ${network_name} | grep segmentation_id | awk '{print $4}' @{list} = String.Split String ${output} - [Return] ${list}[0] + RETURN ${list}[0] Verify Services [Documentation] Verify if the services are operational - Wait Until Keyword Succeeds 60 2 ClusterManagement.Check Status Of Services Is OPERATIONAL @{NETVIRT_DIAG_SERVICES} + Wait Until Keyword Succeeds + ... 60 + ... 2 + ... ClusterManagement.Check Status Of Services Is OPERATIONAL + ... @{NETVIRT_DIAG_SERVICES} Verify Expected Default Tunnels [Documentation] Verify if the default tunnels are created. @@ -1341,69 +1703,84 @@ Verify Expected Default Tunnels ... added to odltools. ${check_feature_list} = BuiltIn.Create List odl-netvirt-sfc ${is_sfc_enabled} = OpenStackOperations.Is Feature Installed features=${check_feature_list} - BuiltIn.Return From Keyword If ${is_sfc_enabled} == ${True} ${True} - BuiltIn.Return From Keyword If ${OS_NODE_CNT} == ${1} ${True} + IF ${is_sfc_enabled} == ${True} RETURN ${True} + IF ${OS_NODE_CNT} == ${1} RETURN ${True} ${output} = ODLTools.Analyze Tunnels test_name=${SUITE_NAME}.Suite Setup BuiltIn.Should Contain ${output} All tunnels are up Verify Expected Default Tables On Nodes - [Arguments] ${node_ips}=@{OS_ALL_IPS} [Documentation] Verify if Default Table Entries are programmed on all Nodes + [Arguments] ${node_ips}=@{OS_ALL_IPS} ${resp} = RequestsLibrary.Get Request session ${RFC8040_CONFIG_NODES_API} Utils.Log Content ${resp.text} ${failed_node_list} = BuiltIn.Create List FOR ${node_ip} IN @{node_ips} ${failed_table_list} = Verify Expected Default Tables ${node_ip} ${failed_table_list_size} = BuiltIn.Get Length ${failed_table_list} - BuiltIn.Run Keyword If ${failed_table_list_size} > 0 Collections.Append To List ${failed_node_list} ${node_ip} + IF ${failed_table_list_size} > 0 + Collections.Append To List ${failed_node_list} ${node_ip} + END END Builtin.Should Be Empty ${failed_node_list} Verify Expected Default Tables - [Arguments] ${ovs_ip} [Documentation] Verify if Default Table Entries are programmed on specific Node - ${flow_dump} = Utils.Run Command On Remote System ${ovs_ip} sudo ovs-ofctl dump-flows ${INTEGRATION_BRIDGE} -OOpenFlow13 + [Arguments] ${ovs_ip} + ${flow_dump} = Utils.Run Command On Remote System + ... ${ovs_ip} + ... sudo ovs-ofctl dump-flows ${INTEGRATION_BRIDGE} -OOpenFlow13 BuiltIn.Log ${flow_dump} ${failed_table_list} = BuiltIn.Create List FOR ${table} IN @{DEFAULT_FLOW_TABLES} - ${rc} = Builtin.Run Keyword And Return Status Builtin.Should Not Match Regexp ${flow_dump} .*table=${table}.*priority=0 - BuiltIn.Run Keyword If ${rc} Collections.Append To List ${failed_table_list} ${table} + ${rc} = Builtin.Run Keyword And Return Status + ... Builtin.Should Not Match Regexp + ... ${flow_dump} + ... .*table=${table}.*priority=0 + IF ${rc} + Collections.Append To List ${failed_table_list} ${table} + END END - [Return] ${failed_table_list} + RETURN ${failed_table_list} Get Project Id - [Arguments] ${project_name} [Documentation] Returns project ID for the given project name. + [Arguments] ${project_name} ${project_id} = OpenStack CLI openstack project show ${project_name} -f value -c id - [Return] ${project_id} + RETURN ${project_id} Set Instance Quota For Project - [Arguments] ${num_instances} ${project_id} [Documentation] Set quota for the created instances using the specific project id. + [Arguments] ${num_instances} ${project_id} ${output} = OpenStack CLI openstack quota set --instances ${num_instances} ${project_id} - [Return] ${output} + RETURN ${output} Create Bgpvpn - [Arguments] ${vpnname} ${additional_args}=${EMPTY} [Documentation] Create Bgpvpn with neutron request. + [Arguments] ${vpnname} ${additional_args}=${EMPTY} ${output} = OpenStack CLI openstack bgpvpn create --name ${vpnname} ${additional_args} Get BgpVpn Id - [Arguments] ${vpnName} [Documentation] Retrieve the bgpvpn id for the given bgpvpn name + [Arguments] ${vpnName} ${output} = OpenStack CLI openstack bgpvpn show ${vpnName} | grep " ID" | awk '{print $4}' ${splitted_output} = String.Split String ${output} ${EMPTY} ${vpn_id} = Collections.Get from List ${splitted_output} 0 - [Return] ${vpn_id} + RETURN ${vpn_id} Configure_IP_On_Sub_Interface + [Documentation] Keyword for configuring specified IP on specified interface and the corresponding specified sub interface [Arguments] ${network_name} ${ip} ${vm_ip} ${mask} ${sub_interface_state}=${EMPTY} ${interface}=eth0 ... ${sub_interface_number}=1 - [Documentation] Keyword for configuring specified IP on specified interface and the corresponding specified sub interface - OpenStackOperations.Execute Command on VM Instance ${network_name} ${vm_ip} sudo ifconfig ${interface}:${sub_interface_number} ${ip} netmask ${mask} ${sub_interface_state} + OpenStackOperations.Execute Command on VM Instance + ... ${network_name} + ... ${vm_ip} + ... sudo ifconfig ${interface}:${sub_interface_number} ${ip} netmask ${mask} ${sub_interface_state} Verify_IP_Configured_On_Sub_Interface - [Arguments] ${network_name} ${ip} ${vm_ip} ${interface}=eth0 ${sub_interface_number}=1 [Documentation] Keyword for verifying specified IP on specified interface and the corresponding specified sub interface - ${resp} = OpenStackOperations.Execute Command on VM Instance ${network_name} ${vm_ip} sudo ifconfig ${interface}:${sub_interface_number} + [Arguments] ${network_name} ${ip} ${vm_ip} ${interface}=eth0 ${sub_interface_number}=1 + ${resp} = OpenStackOperations.Execute Command on VM Instance + ... ${network_name} + ... ${vm_ip} + ... sudo ifconfig ${interface}:${sub_interface_number} BuiltIn.Should Contain ${resp} ${ip} diff --git a/csit/libraries/OvsManager.robot b/csit/libraries/OvsManager.robot index 0edf59aade..bc4a80fb40 100644 --- a/csit/libraries/OvsManager.robot +++ b/csit/libraries/OvsManager.robot @@ -1,17 +1,20 @@ *** Settings *** -Documentation Library to provide ovsdb access to mininet topologies -Library SSHLibrary -Library ${CURDIR}/VsctlListParser.py -Library Collections +Documentation Library to provide ovsdb access to mininet topologies + +Library SSHLibrary +Library ${CURDIR}/VsctlListParser.py +Library Collections + *** Variables *** -${SH_BR_CMD} ovs-vsctl list Bridge -${SH_CNTL_CMD} ovs-vsctl list Controller -${SHOW_OVS_VERSION} sudo ovs-vsctl show | grep version -${GET_LOCAL_IP} sudo ovs-vsctl list Open_vSwitch | grep local_ip= -${ovs_switch_data} ${None} -${lprompt} mininet> -${lcmd_prefix} sh +${SH_BR_CMD} ovs-vsctl list Bridge +${SH_CNTL_CMD} ovs-vsctl list Controller +${SHOW_OVS_VERSION} sudo ovs-vsctl show | grep version +${GET_LOCAL_IP} sudo ovs-vsctl list Open_vSwitch | grep local_ip= +${ovs_switch_data} ${None} +${lprompt} mininet> +${lcmd_prefix} sh + *** Keywords *** Initialize If Shell Used @@ -20,8 +23,8 @@ Initialize If Shell Used BuiltIn.Set Suite variable ${lcmd_prefix} ${cmd_prefix} Get Ovsdb Data - [Arguments] ${prompt}=mininet> [Documentation] Gets ovs data and parse them. + [Arguments] ${prompt}=mininet> SSHLibrary.Write ${lcmd_prefix} ${SH_BR_CMD} ${brstdout}= SSHLibrary.Read_Until ${lprompt} Log ${brstdout} @@ -31,17 +34,17 @@ Get Ovsdb Data ${data} ${bridegs} ${controllers}= VsctlListParser.Parse ${brstdout} ${cntlstdout} BuiltIn.Log ${data} BuiltIn.Set Suite Variable ${ovs_switch_data} ${data} - BuiltIn.Return From Keyword ${data} + RETURN ${data} Get Controllers Uuid - [Arguments] ${switch} ${controller} ${update_data}=${False} [Documentation] Returns controllers uuid - Run Keyword If ${update_data}==${True} Get Ovsdb Data + [Arguments] ${switch} ${controller} ${update_data}=${False} + IF ${update_data}==${True} Get Ovsdb Data ${bridge}= Collections.Get From Dictionary ${ovs_switch_data} ${switch} ${cntls}= Collections.Get From Dictionary ${bridge} controller ${cntl}= Collections.Get From Dictionary ${cntls} ${controller} ${uuid}= Collections.Get From Dictionary ${cntl} _uuid - BuiltIn.Return From Keyword ${uuid} + RETURN ${uuid} Execute OvsVsctl Show Command [Documentation] Executes ovs-vsctl show command and returns stdout, no check nor change is performed @@ -50,15 +53,18 @@ Execute OvsVsctl Show Command Log ${output} Set Bridge Controllers - [Arguments] ${bridge} ${controllers} ${ofversion}=13 ${disconnected}=${False} [Documentation] Adds controller to the bridge + [Arguments] ${bridge} ${controllers} ${ofversion}=13 ${disconnected}=${False} ${cmd}= BuiltIn.Set Variable ${lcmd_prefix} ovs-vsctl set bridge ${bridge} protocols=OpenFlow${ofversion} SSHLibrary.Write ${cmd} ${output}= SSHLibrary.Read_Until ${lprompt} Log ${output} ${cmd}= BuiltIn.Set Variable ${lcmd_prefix} ovs-vsctl set-controller ${bridge} FOR ${cntl} IN @{controllers} - ${cmd}= BuiltIn.Set Variable If ${disconnected}==${False} ${cmd} tcp:${cntl}:6653 ${cmd} tcp:${cntl}:6654 + ${cmd}= BuiltIn.Set Variable If + ... ${disconnected}==${False} + ... ${cmd} tcp:${cntl}:6653 + ... ${cmd} tcp:${cntl}:6654 END BuiltIn.Log ${cmd} SSHLibrary.Write ${cmd} @@ -66,113 +72,131 @@ Set Bridge Controllers Log ${output} Disconnect Switch From Controller And Verify Disconnected - [Arguments] ${switch} ${controller} ${update_data}=${False} ${verify_disconnected}=${True} [Documentation] Disconnects the switch from the controller by setting the incorrect port - Run Keyword If ${update_data}==${True} Get Ovsdb Data + [Arguments] ${switch} ${controller} ${update_data}=${False} ${verify_disconnected}=${True} + IF ${update_data}==${True} Get Ovsdb Data ${uuid}= Get Controllers Uuid ${switch} ${controller} - ${cmd}= BuiltIn.Set Variable ${lcmd_prefix} ovs-vsctl set Controller ${uuid} target="tcp\\:${controller}\\:6654" + ${cmd}= BuiltIn.Set Variable + ... ${lcmd_prefix} ovs-vsctl set Controller ${uuid} target="tcp\\:${controller}\\:6654" SSHLibrary.Write ${cmd} ${output}= SSHLibrary.Read_Until ${lprompt} Log ${output} - Return From Keyword If ${verify_disconnected}==${False} - BuiltIn.Wait Until Keyword Succeeds 5x 2s Should Be Disconnected ${switch} ${controller} update_data=${True} + IF ${verify_disconnected}==${False} RETURN + BuiltIn.Wait Until Keyword Succeeds + ... 5x + ... 2s + ... Should Be Disconnected + ... ${switch} + ... ${controller} + ... update_data=${True} [Teardown] Execute OvsVsctl Show Command Reconnect Switch To Controller And Verify Connected - [Arguments] ${switch} ${controller} ${update_data}=${False} ${verify_connected}=${True} [Documentation] Reconnects the switch back to the controller by setting the correct port - Run Keyword If ${update_data}==${True} Get Ovsdb Data + [Arguments] ${switch} ${controller} ${update_data}=${False} ${verify_connected}=${True} + IF ${update_data}==${True} Get Ovsdb Data ${uuid}= Get Controllers Uuid ${switch} ${controller} - ${cmd}= BuiltIn.Set Variable ${lcmd_prefix} ovs-vsctl set Controller ${uuid} target="tcp\\:${controller}\\:6653" + ${cmd}= BuiltIn.Set Variable + ... ${lcmd_prefix} ovs-vsctl set Controller ${uuid} target="tcp\\:${controller}\\:6653" SSHLibrary.Write ${cmd} ${output}= SSHLibrary.Read_Until ${lprompt} Log ${output} - Return From Keyword If ${verify_connected}==${False} - BuiltIn.Wait Until Keyword Succeeds 5x 2s Should Be Connected ${switch} ${controller} update_data=${True} + IF ${verify_connected}==${False} RETURN + BuiltIn.Wait Until Keyword Succeeds + ... 5x + ... 2s + ... Should Be Connected + ... ${switch} + ... ${controller} + ... update_data=${True} [Teardown] Execute OvsVsctl Show Command Should Be Connected - [Arguments] ${switch} ${controller} ${update_data}=${False} [Documentation] Check if the switch is connected + [Arguments] ${switch} ${controller} ${update_data}=${False} ${connected}= OvsManager__Is_Connected ${switch} ${controller} update_data=${update_data} BuiltIn.Should Be True ${connected} Should Be Disconnected - [Arguments] ${switch} ${controller} ${update_data}=${False} [Documentation] Check if the switch is disconnected + [Arguments] ${switch} ${controller} ${update_data}=${False} ${connected}= OvsManager__Is_Connected ${switch} ${controller} update_data=${update_data} BuiltIn.Should Be Equal ${connected} ${False} OvsManager__Is_Connected - [Arguments] ${switch} ${controller} ${update_data}=${False} [Documentation] Return is_connected boolean value - Run Keyword If ${update_data}==${True} Get Ovsdb Data + [Arguments] ${switch} ${controller} ${update_data}=${False} + IF ${update_data}==${True} Get Ovsdb Data ${bridge}= Collections.Get From Dictionary ${ovs_switch_data} ${switch} ${cntls}= Collections.Get From Dictionary ${bridge} controller ${cntl}= Collections.Get From Dictionary ${cntls} ${controller} ${connected}= Collections.Get From Dictionary ${cntl} is_connected + RETURN ${connected} [Teardown] Execute OvsVsctl Show Command - [Return] ${connected} Should Be Master - [Arguments] ${switch} ${controller} ${update_data}=${False} [Documentation] Verifies the master role - ${role} Get Node Role ${switch} ${controller} update_data=${update_data} + [Arguments] ${switch} ${controller} ${update_data}=${False} + ${role}= Get Node Role ${switch} ${controller} update_data=${update_data} BuiltIn.Should Be Equal ${role} master Should Be Slave - [Arguments] ${switch} ${controller} ${update_data}=${False} [Documentation] Verifies the slave role - ${role} Get Node Role ${switch} ${controller} update_data=${update_data} + [Arguments] ${switch} ${controller} ${update_data}=${False} + ${role}= Get Node Role ${switch} ${controller} update_data=${update_data} BuiltIn.Should Be Equal ${role} slave Get Node Role - [Arguments] ${switch} ${controller} ${update_data}=${False} [Documentation] Returns the controllers role - Run Keyword If ${update_data}==${True} Get Ovsdb Data + [Arguments] ${switch} ${controller} ${update_data}=${False} + IF ${update_data}==${True} Get Ovsdb Data ${bridge}= Collections.Get From Dictionary ${ovs_switch_data} ${switch} ${cntls}= Collections.Get From Dictionary ${bridge} controller ${cntl}= Collections.Get From Dictionary ${cntls} ${controller} ${role}= Collections.Get From Dictionary ${cntl} role - Return From Keyword ${role} + RETURN ${role} Get Master Node - [Arguments] ${switch} ${update_data}=${False} [Documentation] Gets controller which is a master + [Arguments] ${switch} ${update_data}=${False} ${master}= BuiltIn.Set Variable ${None} - Run Keyword If ${update_data}==${True} Get Ovsdb Data + IF ${update_data}==${True} Get Ovsdb Data ${bridge}= Collections.Get From Dictionary ${ovs_switch_data} ${switch} ${cntls_dict}= Collections.Get From Dictionary ${bridge} controller ${cntls_items}= Collections.Get Dictionary Items ${cntls_dict} FOR ${key} ${value} IN @{cntls_items} Log ${key} : ${value} ${role}= Collections.Get From Dictionary ${value} role - Run Keyword If "${role}"=="master" BuiltIn.Should Be Equal ${master} ${None} + IF "${role}"=="master" + BuiltIn.Should Be Equal ${master} ${None} + END ${master}= BuiltIn.Set Variable If "${role}"=="master" ${key} ${master} END BuiltIn.Should Not Be Equal ${master} ${None} - Return From Keyword ${master} + RETURN ${master} Get Slave Nodes - [Arguments] ${switch} ${update_data}=${False} [Documentation] Returns a list of ips of slave nodes for particular switch + [Arguments] ${switch} ${update_data}=${False} ${slaves}= BuiltIn.Create List - Run Keyword If ${update_data}==${True} Get Ovsdb Data + IF ${update_data}==${True} Get Ovsdb Data ${bridge}= Collections.Get From Dictionary ${ovs_switch_data} ${switch} ${cntls_dict}= Collections.Get From Dictionary ${bridge} controller ${cntls_items}= Collections.Get Dictionary Items ${cntls_dict} FOR ${key} ${value} IN @{cntls_items} Log ${key} : ${value} ${role}= Collections.Get From Dictionary ${value} role - Run Keyword If "${role}"=="slave" Collections.Append To List ${slaves} ${key} + IF "${role}"=="slave" + Collections.Append To List ${slaves} ${key} + END END - Return From Keyword ${slaves} + RETURN ${slaves} Setup Clustered Controller For Switches - [Arguments] ${switches} ${controller_ips} ${verify_connected}=${False} [Documentation] The idea of this keyword is to setup clustered controller and to be more or less sure that the role is filled correctly. The problem is when ... more controllers are being set up at once, the role shown in Controller ovsdb table is not the same as we can see from wireshark traces. ... Now we set disconnected controllers and we will connect them expecting that the first connected controller will be master. + [Arguments] ${switches} ${controller_ips} ${verify_connected}=${False} FOR ${switch_name} IN @{switches} Set Bridge Controllers ${switch_name} ${controller_ips} disconnected=${True} # now we need to enable one node which will be master @@ -183,30 +207,35 @@ Setup Clustered Controller For Switches Reconnect Switch To Controller And Verify Connected ${switch_name} ${own} verify_connected=${False} # now we need to wait till master controllers are connected END - BuiltIn.Wait Until Keyword Succeeds 5x 2s OvsManager__Verify_Masters_Connected ${switches} update_data=${True} + BuiltIn.Wait Until Keyword Succeeds + ... 5x + ... 2s + ... OvsManager__Verify_Masters_Connected + ... ${switches} + ... update_data=${True} # now we can enable slaves OvsManager__Enable_Slaves ${switches} verify_connected=${verify_connected} OvsManager__Verify_Masters_Connected - [Arguments] ${switches} ${update_data}=${False} [Documentation] Private keyword, the existence of master means it is verified - Run Keyword If ${update_data}==${True} Get Ovsdb Data + [Arguments] ${switches} ${update_data}=${False} + IF ${update_data}==${True} Get Ovsdb Data FOR ${switch_name} IN @{switches} Get Master Node ${switch_name} END OvsManager__Enable_Slaves - [Arguments] ${switches} ${update_data}=${False} ${verify_connected}=${False} [Documentation] This is a private keyword to enable diconnected controllers - Run Keyword If ${update_data}==${True} Get Ovsdb Data + [Arguments] ${switches} ${update_data}=${False} ${verify_connected}=${False} + IF ${update_data}==${True} Get Ovsdb Data FOR ${switch_name} IN @{switches} OvsManager__Enable_Slaves_For_Switch ${switch_name} verify_connected=${verify_connected} END OvsManager__Enable_Slaves_For_Switch - [Arguments] ${switch} ${update_data}=${False} ${verify_connected}=${False} [Documentation] This is a private keyword, verification is not reliable yet, enables disconnected controllers - Run Keyword If ${update_data}==${True} Get Ovsdb Data + [Arguments] ${switch} ${update_data}=${False} ${verify_connected}=${False} + IF ${update_data}==${True} Get Ovsdb Data ${bridge}= Collections.Get From Dictionary ${ovs_switch_data} ${switch} ${cntls_dict}= Collections.Get From Dictionary ${bridge} controller ${cntls_items}= Collections.Get Dictionary Items ${cntls_dict} @@ -214,53 +243,62 @@ OvsManager__Enable_Slaves_For_Switch Log ${cntl_id} : ${cntl_value} ${role}= Collections.Get From Dictionary ${cntl_value} role ${connected}= Collections.Get From Dictionary ${cntl_value} is_connected - Run Keyword If ${connected}==${False} Reconnect Switch To Controller And Verify Connected ${switch} ${cntl_id} verify_connected=${verify_connected} + IF ${connected}==${False} + Reconnect Switch To Controller And Verify Connected + ... ${switch} + ... ${cntl_id} + ... verify_connected=${verify_connected} + END END Get Dump Flows Count - [Arguments] ${conn_id} ${acl_sr_table_id} ${port_mac}="" [Documentation] Count the number of dump flows for a given table id ... and grep with port_mac if provided - ${cmd} = BuiltIn.Set Variable sudo ovs-ofctl dump-flows br-int -OOpenFlow13 | grep table=${acl_sr_table_id} | grep ${port_mac} | wc -l + [Arguments] ${conn_id} ${acl_sr_table_id} ${port_mac}="" + ${cmd}= BuiltIn.Set Variable + ... sudo ovs-ofctl dump-flows br-int -OOpenFlow13 | grep table=${acl_sr_table_id} | grep ${port_mac} | wc -l SSHLibrary.Switch Connection ${conn_id} - ${output} = Utils.Write Commands Until Expected Prompt ${cmd} ${DEFAULT_LINUX_PROMPT_STRICT} - @{list} = String.Split String ${output} - [Return] ${list[0]} + ${output}= Utils.Write Commands Until Expected Prompt ${cmd} ${DEFAULT_LINUX_PROMPT_STRICT} + @{list}= String.Split String ${output} + RETURN ${list[0]} Get Packet Count From Table - [Arguments] ${system_ip} ${br_name} ${table_no} ${addtioanal_args}=${EMPTY} [Documentation] Return packet count for the specific table no. - ${flow_output} = Utils.Run Command On Remote System ${system_ip} sudo ovs-ofctl dump-flows -O Openflow13 ${br_name} | grep ${table_no} ${addtioanal_args} - @{output} = String.Split String ${flow_output} \r\n - ${flow} = Collections.Get From List ${output} 0 - ${packetcountlist} = String.Get Regexp Matches ${flow} n_packets=([0-9]+), 1 - ${packetcount} = Collections.Get From List ${packetcountlist} 0 - [Return] ${packetcount} + [Arguments] ${system_ip} ${br_name} ${table_no} ${addtioanal_args}=${EMPTY} + ${flow_output}= Utils.Run Command On Remote System + ... ${system_ip} + ... sudo ovs-ofctl dump-flows -O Openflow13 ${br_name} | grep ${table_no} ${addtioanal_args} + @{output}= String.Split String ${flow_output} \r\n + ${flow}= Collections.Get From List ${output} 0 + ${packetcountlist}= String.Get Regexp Matches ${flow} n_packets=([0-9]+), 1 + ${packetcount}= Collections.Get From List ${packetcountlist} 0 + RETURN ${packetcount} Get Packet Count In Table For IP - [Arguments] ${os_compute_ip} ${table_no} ${ip_address} ${additional_args}=${EMPTY} [Documentation] Capture packetcount for IP in Table - ${cmd} = BuiltIn.Set Variable sudo ovs-ofctl dump-flows br-int -OOpenFlow13 | grep table=${table_no} | grep ${ip_address} ${additional_args} - ${output} = Utils.Run Command On Remote System And Log ${os_compute_ip} ${cmd} - @{output_list} = String.Split String ${output} \r\n - ${flow} = Collections.Get From List ${output_list} 0 - ${packetcount_list} = String.Get Regexp Matches ${flow} n_packets=([0-9]+) 1 - ${count} = Collections.Get From List ${packetcount_list} 0 - [Return] ${count} + [Arguments] ${os_compute_ip} ${table_no} ${ip_address} ${additional_args}=${EMPTY} + ${cmd}= BuiltIn.Set Variable + ... sudo ovs-ofctl dump-flows br-int -OOpenFlow13 | grep table=${table_no} | grep ${ip_address} ${additional_args} + ${output}= Utils.Run Command On Remote System And Log ${os_compute_ip} ${cmd} + @{output_list}= String.Split String ${output} \r\n + ${flow}= Collections.Get From List ${output_list} 0 + ${packetcount_list}= String.Get Regexp Matches ${flow} n_packets=([0-9]+) 1 + ${count}= Collections.Get From List ${packetcount_list} 0 + RETURN ${count} Verify Ovs Version Greater Than Or Equal To - [Arguments] ${ovs_version} @{nodes} [Documentation] Get ovs version and verify greater than required version + [Arguments] ${ovs_version} @{nodes} FOR ${ip} IN @{nodes} - ${output} = Utils.Run Command On Remote System ${ip} ${SHOW_OVS_VERSION} - ${version} = String.Get Regexp Matches ${output} \[0-9].\[0-9] - ${result} = BuiltIn.Convert To Number ${version[0]} + ${output}= Utils.Run Command On Remote System ${ip} ${SHOW_OVS_VERSION} + ${version}= String.Get Regexp Matches ${output} \[0-9].\[0-9] + ${result}= BuiltIn.Convert To Number ${version[0]} BuiltIn.Should Be True ${result} >= ${ovs_version} END Get OVS Local Ip - [Arguments] ${ip} [Documentation] Get local ip of compute node ovsdb - ${cmd_output} = Utils.Run Command On Remote System ${ip} ${GET_LOCAL_IP} - ${localip} = String.Get Regexp Matches ${cmd_output} (\[0-9]+\.\[0-9]+\.\[0-9]+\.\[0-9]+) - [Return] ${localip}[0] + [Arguments] ${ip} + ${cmd_output}= Utils.Run Command On Remote System ${ip} ${GET_LOCAL_IP} + ${localip}= String.Get Regexp Matches ${cmd_output} (\[0-9]+\.\[0-9]+\.\[0-9]+\.\[0-9]+) + RETURN ${localip}[0] diff --git a/csit/libraries/PacketcableVersion.robot b/csit/libraries/PacketcableVersion.robot index 5db7c87f93..6bee18dcc7 100644 --- a/csit/libraries/PacketcableVersion.robot +++ b/csit/libraries/PacketcableVersion.robot @@ -1,6 +1,8 @@ *** Settings *** -Documentation This setup variable for Packetcable based on ODL version using resource CompareStream. -Resource ${CURDIR}/CompareStream.robot +Documentation This setup variable for Packetcable based on ODL version using resource CompareStream. + +Resource ${CURDIR}/CompareStream.robot + *** Keywords *** Init Variables diff --git a/csit/libraries/PcepOperations.robot b/csit/libraries/PcepOperations.robot index 43f3a73ed2..5b324bbfbc 100644 --- a/csit/libraries/PcepOperations.robot +++ b/csit/libraries/PcepOperations.robot @@ -1,27 +1,34 @@ *** Settings *** -Documentation Robot keyword library (Resource) for performing PCEP operations via restconf calls. +Documentation Robot keyword library (Resource) for performing PCEP operations via restconf calls. ... -... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... -... TODO: Remove all old keywords, update pcepuser.robot accordingly -... TODO: Add new KWs, update all pcep tests to use them. -Library RequestsLibrary -Library norm_json.py -Resource ../variables/Variables.robot -Resource TemplatedRequests.robot +... TODO: Remove all old keywords, update pcepuser.robot accordingly +... TODO: Add new KWs, update all pcep tests to use them. + +Library RequestsLibrary +Library norm_json.py +Resource ../variables/Variables.robot +Resource TemplatedRequests.robot + *** Variables *** -${PCEP_VAR_FOLDER} ${CURDIR}/../variables/tcpmd5user +${PCEP_VAR_FOLDER} ${CURDIR}/../variables/tcpmd5user + *** Keywords *** Setup_Pcep_Operations [Documentation] Creates Requests session to be used by subsequent keywords. # Do not append slash at the end uf URL, Requests would add another, resulting in error. - Create_Session pcep_session http://${ODL_SYSTEM_IP}:${RESTCONFPORT}/rests/operations headers=${HEADERS_XML} auth=${AUTH} + Create_Session + ... pcep_session + ... http://${ODL_SYSTEM_IP}:${RESTCONFPORT}/rests/operations + ... headers=${HEADERS_XML} + ... auth=${AUTH} Teardown_Pcep_Operations [Documentation] Teardown to pair with Setup (otherwise no-op). @@ -29,43 +36,44 @@ Teardown_Pcep_Operations # Delete_Session pcep_session Add_Xml_Lsp_Return_Json - [Arguments] ${xml_data} [Documentation] Instantiate LSP according to XML data and return response (json) text. + [Arguments] ${xml_data} # Also no slash here ${response}= Operate_Xml_Lsp_Return_Json network-topology-pcep:add-lsp ${xml_data} - [Return] ${response} + RETURN ${response} Update_Xml_Lsp_Return_Json - [Arguments] ${xml_data} [Documentation] Update LSP according to XML data and return response (json) text. + [Arguments] ${xml_data} # Also no slash here ${response}= Operate_Xml_Lsp_Return_Json network-topology-pcep:update-lsp ${xml_data} - [Return] ${response} + RETURN ${response} Remove_Xml_Lsp_Return_Json - [Arguments] ${xml_data} [Documentation] Remove LSP according to XML data and return response (json) text. + [Arguments] ${xml_data} # Also no slash here ${response}= Operate_Xml_Lsp_Return_Json network-topology-pcep:remove-lsp ${xml_data} - [Return] ${response} + RETURN ${response} Operate_Xml_Lsp_Return_Json - [Arguments] ${uri_part} ${xml_data} [Documentation] Post XML data to given pcep-operations URI, check status_code is 200 and return response text (JSON). + [Arguments] ${uri_part} ${xml_data} ${response}= RequestsLibrary.Post Request pcep_session ${uri_part} data=${xml_data} Log ${xml_data} Should Contain ${ALLOWED_STATUS_CODES} ${response.status_code} - [Return] ${response.text} + RETURN ${response.text} Pcep_Json_Is_Success - [Arguments] ${text} [Documentation] Given text should be equal to successfull json response. + [Arguments] ${text} Should_Be_Equal_As_Strings ${text} {"output":{}} Pcep_Json_Is_Refused - [Arguments] ${actual_raw} [Documentation] Given text should be equal to json response when device refuses tunnel removal. - ${expected_raw}= BuiltIn.Set_Variable {"network-topology-pcep:output":{"error":[{"error-object":{"ignore":false,"processing-rule":false,"type":19,"value":9}}],"failure":"failed"}} + [Arguments] ${actual_raw} + ${expected_raw}= BuiltIn.Set_Variable + ... {"network-topology-pcep:output":{"error":[{"error-object":{"ignore":false,"processing-rule":false,"type":19,"value":9}}],"failure":"failed"}} # TODO: Is that JSON worth referencing pcepuser variables from this library? ${expected_normalized}= norm_json.normalize_json_text ${expected_raw} ${actual_normalized}= norm_json.normalize_json_text ${actual_raw} @@ -73,7 +81,13 @@ Pcep_Json_Is_Refused # TODO: Would the diff approach be more useful? Pcep_Topology_Precondition - [Arguments] ${session} [Documentation] Compare current pcep-topology to empty one. ... Timeout is long enough to see that pcep is ready. - BuiltIn.Wait_Until_Keyword_Succeeds 300s 1s TemplatedRequests.Get_As_Json_Templated ${PCEP_VAR_FOLDER}/default_off session=${session} verify=True + [Arguments] ${session} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 300s + ... 1s + ... TemplatedRequests.Get_As_Json_Templated + ... ${PCEP_VAR_FOLDER}/default_off + ... session=${session} + ... verify=True diff --git a/csit/libraries/PrefixCounting.robot b/csit/libraries/PrefixCounting.robot index 3e0fc146b4..e5c494b2db 100644 --- a/csit/libraries/PrefixCounting.robot +++ b/csit/libraries/PrefixCounting.robot @@ -1,26 +1,29 @@ *** Settings *** -Documentation Robot keyword library (Resource) for common BGP actions concerned with counting prefixes. +Documentation Robot keyword library (Resource) for common BGP actions concerned with counting prefixes. ... -... Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... Currently, all keywords count prefixes only in ${topology}. -... Prefix is identified by simplistic regular expression on JSON data. +... Currently, all keywords count prefixes only in ${topology}. +... Prefix is identified by simplistic regular expression on JSON data. ... -... This resource assumes that RequestsLibrary has open a connection named "operational" -... which points to (an analogue of) http://:${RESTCONFPORT} -... or user has to provide a similar session. -Library RequestsLibrary -Resource ${CURDIR}/ShardStability.robot -Resource ${CURDIR}/WaitUtils.robot -Resource ${CURDIR}/ScalarClosures.robot +... This resource assumes that RequestsLibrary has open a connection named "operational" +... which points to (an analogue of) http://:${RESTCONFPORT} +... or user has to provide a similar session. + +Library RequestsLibrary +Resource ${CURDIR}/ShardStability.robot +Resource ${CURDIR}/WaitUtils.robot +Resource ${CURDIR}/ScalarClosures.robot + *** Variables *** -${PC_NW_TOPOLOGY} ${REST_API}/network-topology:network-topology/topology +${PC_NW_TOPOLOGY} ${REST_API}/network-topology:network-topology/topology + *** Keywords *** PC_Setup @@ -28,54 +31,78 @@ PC_Setup WaitUtils.WU_Setup # includes ScalarClosures.SC_Setup Get_Ipv4_Topology - [Arguments] ${session}=operational ${topology}=example-ipv4-topology [Documentation] GET the ${topology} data, check status is 200, return the topology data. ... ... Contrary to Utils.Get_Data_From_URI, this does not Log the (potentially huge) content. + [Arguments] ${session}=operational ${topology}=example-ipv4-topology ${response} = RequestsLibrary.Get_Request ${session} ${PC_NW_TOPOLOGY}=${topology}?content=nonconfig - Run_Keyword_If ${response.status_code} != 200 Fail Get on ${topology} returned status code ${response.status_code} with message: ${response.text} - [Return] ${response.text} + IF ${response.status_code} != 200 + Fail Get on ${topology} returned status code ${response.status_code} with message: ${response.text} + END + RETURN ${response.text} Get_Ipv4_Topology_Count - [Arguments] ${session}=operational ${topology}=example-ipv4-topology [Documentation] Get topology. If not fail, return number of prefixes in the topology. + [Arguments] ${session}=operational ${topology}=example-ipv4-topology ${topology} = Get_Ipv4_Topology session=${session} topology=${topology} # Triple quotes are precaution against formatted output. ${prefix_count} = Builtin.Evaluate len(re.findall('"prefix":"', '''${topology}''')) modules=re - [Return] ${prefix_count} + RETURN ${prefix_count} Get_Ipv4_Topology_Count_With_Shards_Check - [Arguments] ${shards_list} ${details_exp} ${session}=operational ${topology}=example-ipv4-topology [Documentation] Get topology after the shards stability check passes. If not fail, return number of prefixes in the topology. - ${details_actual}= ShardStability.Shards_Stability_Get_Details ${shards_list} http_timeout=125 + [Arguments] ${shards_list} ${details_exp} ${session}=operational ${topology}=example-ipv4-topology + ${details_actual} = ShardStability.Shards_Stability_Get_Details ${shards_list} http_timeout=125 ShardStability.Shards_Stability_Compare_Same ${details_actual} stateless_details=${details_exp} ${topology} = Get_Ipv4_Topology session=${session} topology=${topology} # Triple quotes are precaution against formatted output. ${prefix_count} = Builtin.Evaluate len(re.findall('"prefix":"', '''${topology}''')) modules=re - [Return] ${prefix_count} + RETURN ${prefix_count} Check_Ipv4_Topology_Count - [Arguments] ${expected_count} ${session}=operational ${topology}=example-ipv4-topology [Documentation] Check that the count of prefixes matches the expected count. Fails if it does not. In either case, collect garbage. - ${actual_count} = ScalarClosures.Run_Keyword_And_Collect_Garbage Get_Ipv4_Topology_Count session=${session} topology=${topology} + [Arguments] ${expected_count} ${session}=operational ${topology}=example-ipv4-topology + ${actual_count} = ScalarClosures.Run_Keyword_And_Collect_Garbage + ... Get_Ipv4_Topology_Count + ... session=${session} + ... topology=${topology} BuiltIn.Should_Be_Equal_As_Strings ${actual_count} ${expected_count} Check_Ipv4_Topology_Is_Empty - [Arguments] ${session}=operational ${topology}=example-ipv4-topology [Documentation] Example_Ipv4_Topology has to give status 200 with zero prefixes. ... ... Functional suites should use a more strict Keyword which tests for the whole JSON structure. + [Arguments] ${session}=operational ${topology}=example-ipv4-topology Check_Ipv4_Topology_Count 0 session=${session} topology=${topology} Wait_For_Ipv4_Topology_Prefixes_To_Become_Stable + [Documentation] Each ${period} get prefix count. When called with shard list, the check is done before the count is get. After ${repetitions} of stable different from ${excluded_count} within ${timeout}, Return validator output. Fail early on getter error. [Arguments] ${timeout}=60s ${period}=5s ${repetitions}=1 ${excluded_count}=-1 ${session}=operational ${topology}=example-ipv4-topology ... ${shards_list}=${EMPTY} ${shards_details}=${EMPTY} - [Documentation] Each ${period} get prefix count. When called with shard list, the check is done before the count is get. After ${repetitions} of stable different from ${excluded_count} within ${timeout}, Return validator output. Fail early on getter error. # This is very similar to ChangeCounter keyword, but attempt to extract common code would increase overall code size. - ${getter} = BuiltIn.Run_Keyword_If """${shards_list}"""=="""${EMPTY}""" ScalarClosures.Closure_From_Keyword_And_Arguments Get_Ipv4_Topology_Count session=${session} topology=${topology} - ... ELSE ScalarClosures.Closure_From_Keyword_And_Arguments Get_Ipv4_Topology_Count_With_Shards_Check ${shards_list} ${shards_details} session=${session} - ... topology=${topology} - ${validator} = ScalarClosures.Closure_From_Keyword_And_Arguments WaitUtils.Excluding_Stability_Safe_Stateful_Validator_As_Keyword state_holder data_holder excluded_value=${excluded_count} - ${result} = WaitUtils.Wait_For_Getter_Error_Or_Safe_Stateful_Validator_Consecutive_Success timeout=${timeout} period=${period} count=${repetitions} getter=${getter} safe_validator=${validator} + IF """${shards_list}"""=="""${EMPTY}""" + ${getter} = ScalarClosures.Closure_From_Keyword_And_Arguments + ... Get_Ipv4_Topology_Count + ... session=${session} + ... topology=${topology} + ELSE + ${getter} = ScalarClosures.Closure_From_Keyword_And_Arguments + ... Get_Ipv4_Topology_Count_With_Shards_Check + ... ${shards_list} + ... ${shards_details} + ... session=${session} + ... topology=${topology} + END + ${validator} = ScalarClosures.Closure_From_Keyword_And_Arguments + ... WaitUtils.Excluding_Stability_Safe_Stateful_Validator_As_Keyword + ... state_holder + ... data_holder + ... excluded_value=${excluded_count} + ${result} = WaitUtils.Wait_For_Getter_Error_Or_Safe_Stateful_Validator_Consecutive_Success + ... timeout=${timeout} + ... period=${period} + ... count=${repetitions} + ... getter=${getter} + ... safe_validator=${validator} ... initial_state=${excluded_count} - [Return] ${result} + RETURN ${result} diff --git a/csit/libraries/RemoteBash.robot b/csit/libraries/RemoteBash.robot index e6c022c015..b0d758f4e6 100644 --- a/csit/libraries/RemoteBash.robot +++ b/csit/libraries/RemoteBash.robot @@ -1,28 +1,30 @@ *** Settings *** -Documentation Resource for managing bash execution when SSHLibrary.Execute_Command is not enough. +Documentation Resource for managing bash execution when SSHLibrary.Execute_Command is not enough. ... -... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... There are many test tools that need to be started from bash, -... and then either waited upon or aborted. -... Typical hurdles are usage of virtualenv or preventing idle SSH sessions from closing down. -... This Resource contains keywords specifically for these situations, -... in order to avoid SSHKeywords growing too big. +... There are many test tools that need to be started from bash, +... and then either waited upon or aborted. +... Typical hurdles are usage of virtualenv or preventing idle SSH sessions from closing down. +... This Resource contains keywords specifically for these situations, +... in order to avoid SSHKeywords growing too big. ... -... Each keyword assumes There is a SSH session already esteablished and active, -... with properties such as timeout already configured. -... No keyword should close or switch away from that session, -... but the configured timeout may be changed if requested. +... Each keyword assumes There is a SSH session already esteablished and active, +... with properties such as timeout already configured. +... No keyword should close or switch away from that session, +... but the configured timeout may be changed if requested. ... -... TODO: Backport improvements from project-specific Resources, -... for example logging to generated filename from NetconfKeywords and NexusKeywords. -Library SSHLibrary -Resource ${CURDIR}/SSHKeywords.robot +... TODO: Backport improvements from project-specific Resources, +... for example logging to generated filename from NetconfKeywords and NexusKeywords. + +Library SSHLibrary +Resource ${CURDIR}/SSHKeywords.robot + *** Keywords *** Write_Bare_Ctrl_C @@ -38,10 +40,10 @@ Write_Bare_Ctrl_D SSHLibrary.Write_Bare ${ctrl_d} Flush_Read - [Arguments] ${delay}=1 [Documentation] Attempt to read excess data (probably just multiple prompts), ignoring failure. ... Log the data or error message. Return None. ... \${delay} parameter tunes how long a period of inactivity has to be to consider all excess data to be read. + [Arguments] ${delay}=1 ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error SSHLibrary.Read delay=${delay} BuiltIn.Log ${message} @@ -52,33 +54,33 @@ Abort_Execution ${text} = SSHLibrary.Read_Until_Prompt BuiltIn.Log ${text} Flush_Read - [Return] ${text} + RETURN ${text} RemoteBash__Wait_Iteration [Documentation] Send a newline and wait for prompt. On success, return the text before the prompt. ... The newline is there to avoid disconnection due to idling. SSHLibrary.Write ${EMPTY} ${text} = SSHLibrary.Read_Until_Prompt - [Return] ${text} + RETURN ${text} Wait_Without_Idle - [Arguments] ${timeout} ${refresh}=1s [Documentation] Wait until prompt, while sending newlines to avoid idling. ... Flush read and return the text before prompt. + [Arguments] ${timeout} ${refresh}=1s ${text} = Wait_Until_Keyword_Succeeds ${timeout} ${refresh} RemoteBash__Wait_Iteration Flush_Read - [Return] ${text} + RETURN ${text} Invoke_With_Timeout - [Arguments] ${command} ${timeout} [Documentation] Enter ${command}, wait until it finishes and return the output. ... If it does not finish within timeout, abort it and fail. ... In either case, flush read. + [Arguments] ${command} ${timeout} # TODO: Total duration is WUKS timeout plus RUP timeout. Should we do some computation? SSHLibrary.Write ${command} ${text} = Wait_Without_Idle ${timeout} + RETURN ${text} [Teardown] BuiltIn.Run_Keyword_If "${KEYWORD_STATUS}" != "PASS" Abort_Execution - [Return] ${text} RemoteBash__Log_Text_Before_Prompt [Documentation] Log text gathered by SSHLibrary.Read_Until_Prompt. @@ -90,12 +92,12 @@ Verify_Tool_Has_Not_Finished_Yet [Documentation] Try to read SSH to see prompt, but expect to see no prompt within SSHLibrary's timeout. ... Log any text seen, to help debug what happened when the tool exited early. ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error RemoteBash__Log_Text_Before_Prompt - BuiltIn.Return_From_Keyword_If "${status}" == "FAIL" + IF "${status}" == "FAIL" RETURN Builtin.Fail The prompt was seen but it was not expected yet. Check_Return_Code - [Arguments] ${expected_rc}=0 [Documentation] Get return code of the previous command, fail if it does not match the expectation.. + [Arguments] ${expected_rc}=0 SSHLibrary.Write echo \$? ${rc_and_prompt} = SSHLibrary.Read_Until_Prompt ${rc} = String.Fetch_From_Left ${rc_and_prompt} ${\n} diff --git a/csit/libraries/RestPerfClient.robot b/csit/libraries/RestPerfClient.robot index 5be9901fea..c8492eeef6 100644 --- a/csit/libraries/RestPerfClient.robot +++ b/csit/libraries/RestPerfClient.robot @@ -1,55 +1,61 @@ *** Settings *** -Documentation RestPerfClient handling singleton resource. +Documentation RestPerfClient handling singleton resource. ... -... Copyright (c) 2016,2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2016,2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... This singleton manages RestPerfClient invocation, tracks the log file -... produced by the invocation, allows the test suite to easily search this -... log file and collect it once done. +... This singleton manages RestPerfClient invocation, tracks the log file +... produced by the invocation, allows the test suite to easily search this +... log file and collect it once done. ... -... TODO: RemoteBash.robot contains logic which could be reused here. +... TODO: RemoteBash.robot contains logic which could be reused here. ... -... TODO: Currently only one RestPerfClient invocation running at a time is -... supported. Support for multiple concurrently running RestPerfClient -... invocations might be needed for example when performance testing cluster -... nodes. However no such suites are planned for now. +... TODO: Currently only one RestPerfClient invocation running at a time is +... supported. Support for multiple concurrently running RestPerfClient +... invocations might be needed for example when performance testing cluster +... nodes. However no such suites are planned for now. ... -... FIXME: There may be suites which want to use this Resource without -... NetconfKeywords, in which case NexusKeywords will not be initialized -... and Setup_Restperfclient will fail. Fixing this problem will require -... updating NexusKeywords initialization (which may break other suites) -... and currently all suites using this use also NetconfKeywords so this -... was postponed. Workaround for the problem: Initialize NexusKeywords -... manually before initializing this resource. -Library DateTime -Library SSHLibrary -Resource ${CURDIR}/NexusKeywords.robot -Resource ${CURDIR}/SetupUtils.robot -Resource ${CURDIR}/SSHKeywords.robot -Resource ${CURDIR}/Utils.robot -Resource ${CURDIR}/RemoteBash.robot +... FIXME: There may be suites which want to use this Resource without +... NetconfKeywords, in which case NexusKeywords will not be initialized +... and Setup_Restperfclient will fail. Fixing this problem will require +... updating NexusKeywords initialization (which may break other suites) +... and currently all suites using this use also NetconfKeywords so this +... was postponed. Workaround for the problem: Initialize NexusKeywords +... manually before initializing this resource. + +Library DateTime +Library SSHLibrary +Resource ${CURDIR}/NexusKeywords.robot +Resource ${CURDIR}/SetupUtils.robot +Resource ${CURDIR}/SSHKeywords.robot +Resource ${CURDIR}/Utils.robot +Resource ${CURDIR}/RemoteBash.robot + *** Variables *** ${RestPerfClient__restperfclientlog} ${EMPTY} + *** Keywords *** Setup_Restperfclient - [Arguments] ${build_version}=${EMPTY} ${build_location}=${EMPTY} [Documentation] Deploy RestPerfClient and determine the Java command to use to call it. ... Open a SSH connection through which the RestPerfClient will be ... invoked, deploy RestPerfClient and the data files it needs to do ... its work and initialize the internal state for the remaining ... keywords. + [Arguments] ${build_version}=${EMPTY} ${build_location}=${EMPTY} ${connection}= SSHKeywords.Open_Connection_To_Tools_System BuiltIn.Set_Suite_Variable ${RestPerfClient__restperfclient} ${connection} SSHLibrary.Put_File ${CURDIR}/../variables/netconf/RestPerfClient/request1.json - ${filename}= Run Keyword If '${IS_KARAF_APPL}' == 'False' Set Variable ${RESTPERF_FILENAME} - ... ELSE NexusKeywords.Deploy_Test_Tool netconf netconf-testtool rest-perf-client + IF '${IS_KARAF_APPL}' == 'False' + ${filename}= Set Variable ${RESTPERF_FILENAME} + ELSE + ${filename}= NexusKeywords.Deploy_Test_Tool netconf netconf-testtool rest-perf-client + END ${prefix}= NexusKeywords.Compose_Full_Java_Command -Xmx4G -jar ${filename} BuiltIn.Set_Suite_Variable ${RestPerfClient__restperfclient_invocation_command_prefix} ${prefix} @@ -73,12 +79,12 @@ Restperfclient__Invoke_With_Timeout Execute_Command_Passes cat ${RestPerfClient__restperfclientlog} Invoke_Restperfclient - [Arguments] ${timeout} ${url} ${testcase}=${EMPTY} ${ip}=${ODL_SYSTEM_IP} ${port}=${RESTCONFPORT} ${count}=${REQUEST_COUNT} - ... ${async}=false ${user}=${ODL_RESTCONF_USER} ${password}=${ODL_RESTCONF_PASSWORD} [Documentation] Invoke RestPerfClient on the specified URL with the specified timeout. ... Assemble the RestPerfClient invocation commad, setup the specified ... timeout for the SSH connection, invoke the assembled command and ... then check that RestPerfClient finished its run correctly. + [Arguments] ${timeout} ${url} ${testcase}=${EMPTY} ${ip}=${ODL_SYSTEM_IP} ${port}=${RESTCONFPORT} ${count}=${REQUEST_COUNT} + ... ${async}=false ${user}=${ODL_RESTCONF_USER} ${password}=${ODL_RESTCONF_PASSWORD} ${restperfclient_running}= Set_Variable False ${logname}= Utils.Get_Log_File_Name restperfclient ${testcase} BuiltIn.Set_Suite_Variable ${RestPerfClient__restperfclientlog} ${logname} @@ -101,11 +107,11 @@ Invoke_Restperfclient [Teardown] BuiltIn.Run_Keyword_If ${restperfclient_running} BuiltIn.Run_Keyword_And_Ignore_Error RestPerfClient__Kill Grep_Restperfclient_Log - [Arguments] ${pattern} [Documentation] Search for the specified string in the log file produced by latest invocation of RestPerfClient + [Arguments] ${pattern} BuiltIn.Should_Not_Be_Equal '${RestPerfClient__restperfclientlog}' '' ${result}= SSHLibrary.Execute_Command grep '${pattern}' ${RestPerfClient__restperfclientlog} - [Return] ${result} + RETURN ${result} Collect_From_Restperfclient [Documentation] Collect useful data produced by restperfclient diff --git a/csit/libraries/Restconf.robot b/csit/libraries/Restconf.robot index af93200271..ee8a55c265 100644 --- a/csit/libraries/Restconf.robot +++ b/csit/libraries/Restconf.robot @@ -1,28 +1,39 @@ -*** Settings *** - *** Variables *** ${USE_RFC8040} = False + *** Keywords *** Generate URI - [Arguments] ${identifier} ${datastore_flag}=config @{node_value_list} [Documentation] Returns the proper URI to use depending on if RFC8040 is to be used or not. Variable input ... error checking is done to ensure the ${USE_RFC8040} Flag is one of True or False and the ${datastore_flag} variable ... must be config, operational or rpc. @{node_value_list} is expected to be in the format of node=value. RFC8040 can ... use that as is with '=' delimiter, but older restconf URI will convert the '=' to a '/' - ${uri} = Run Keyword If "${USE_RFC8040}" == "True" Generate RFC8040 URI ${identifier} ${datastore_flag} @{node_value_list} - Return From Keyword If "${USE_RFC8040}" == "True" ${uri} - Run Keyword If "${USE_RFC8040}" != "False" Fail Invalid Value for RFC8040 Flag: ${USE_RFC8040} - Run Keyword If "${datastore_flag}"!="config" and "${datastore_flag}"!="operational" and "${datastore_flag}"!="rpc" Fail Invalid value for datastore: ${datastore_flag} - ${uri} = Run Keyword If "${datastore_flag}"=="config" Set Variable ${CONFIG_API}/${identifier} - ... ELSE IF "${datastore_flag}"=="operational" Set Variable ${OPERATIONAL_API}/${identifier} - ... ELSE Set Variable ${OPERATIONS_API}/${identifier} + [Arguments] ${identifier} ${datastore_flag}=config @{node_value_list} + IF "${USE_RFC8040}" == "True" + ${uri} = Generate RFC8040 URI ${identifier} ${datastore_flag} @{node_value_list} + ELSE + ${uri} = Set Variable ${None} + END + IF "${USE_RFC8040}" == "True" RETURN ${uri} + IF "${USE_RFC8040}" != "False" + Fail Invalid Value for RFC8040 Flag: ${USE_RFC8040} + END + IF "${datastore_flag}"!="config" and "${datastore_flag}"!="operational" and "${datastore_flag}"!="rpc" + Fail Invalid value for datastore: ${datastore_flag} + END + IF "${datastore_flag}"=="config" + ${uri} = Set Variable ${CONFIG_API}/${identifier} + ELSE IF "${datastore_flag}"=="operational" + ${uri} = Set Variable ${OPERATIONAL_API}/${identifier} + ELSE + ${uri} = Set Variable ${OPERATIONS_API}/${identifier} + END ${node_value_path} = Set Variable ${EMPTY} FOR ${nv} IN @{node_value_list} ${nv} = String.Replace String ${nv} = / ${node_value_path} = Set Variable ${node_value_path}/${nv} END - [Return] ${uri}${node_value_path} + RETURN ${uri}${node_value_path} Generate RFC8040 URI [Arguments] ${identifier} ${datastore_flag}=config @{node_value_list} @@ -30,7 +41,11 @@ Generate RFC8040 URI FOR ${nv} IN @{node_value_list} ${node_value_path} = Set Variable ${node_value_path}/${nv} END - ${uri} = Run Keyword If "${datastore_flag}" == "config" Set Variable rests/data/${identifier}${node_value_path}?content=config - ... ELSE IF "${datastore_flag}"=="operational" Set Variable rests/data/${identifier}${node_value_path}?content=nonconfig - ... ELSE Set Variable rests/operations/${identifier} - [Return] ${uri} + IF "${datastore_flag}" == "config" + ${uri} = Set Variable rests/data/${identifier}${node_value_path}?content=config + ELSE IF "${datastore_flag}"=="operational" + ${uri} = Set Variable rests/data/${identifier}${node_value_path}?content=nonconfig + ELSE + ${uri} = Set Variable rests/operations/${identifier} + END + RETURN ${uri} diff --git a/csit/libraries/SFC/DockerSfc.robot b/csit/libraries/SFC/DockerSfc.robot index 22f092a98b..b9fc200144 100644 --- a/csit/libraries/SFC/DockerSfc.robot +++ b/csit/libraries/SFC/DockerSfc.robot @@ -1,75 +1,107 @@ *** Settings *** -Library SSHLibrary -Resource ../../variables/netvirt/Variables.robot +Library SSHLibrary +Resource ../../variables/netvirt/Variables.robot -*** Variables *** *** Keywords *** Docker Ovs Start - [Arguments] ${nodes} ${guests} ${tunnel} ${odl_ip} ${log_file}=myFile2.log [Documentation] Run the docker-ovs.sh script with specific input arguments. Run ./docker-ovs.sh --help for more info. - ${result} SSHLibrary.Execute Command ./docker-ovs.sh spawn --nodes=${nodes} --guests=${guests} --tun=${tunnel} --odl=${odl_ip} > >(tee ${log_file}) 2> >(tee ${log_file}) return_stderr=True return_stdout=True return_rc=True + [Arguments] ${nodes} ${guests} ${tunnel} ${odl_ip} ${log_file}=myFile2.log + ${result} SSHLibrary.Execute Command + ... ./docker-ovs.sh spawn --nodes=${nodes} --guests=${guests} --tun=${tunnel} --odl=${odl_ip} > >(tee ${log_file}) 2> >(tee ${log_file}) + ... return_stderr=True + ... return_stdout=True + ... return_rc=True log ${result} Should be equal as integers ${result[2]} 0 Docker Ovs Clean - [Arguments] ${log_file}=myFile3.log [Documentation] Run the docker-ovs.sh script with --clean option to clean up all containers deployment. Run ./docker-ovs.sh --help for more info. - ${result} SSHLibrary.Execute Command ./docker-ovs.sh clean > >(tee ${log_file}) 2> >(tee ${log_file}) return_stderr=True return_stdout=True return_rc=True + [Arguments] ${log_file}=myFile3.log + ${result} SSHLibrary.Execute Command + ... ./docker-ovs.sh clean > >(tee ${log_file}) 2> >(tee ${log_file}) + ... return_stderr=True + ... return_stdout=True + ... return_rc=True log ${result} Should be equal as integers ${result[2]} 0 Get Docker Ids [Documentation] Execute command docker ps and retrieve the existing containers ids - ${output} ${rc} SSHLibrary.Execute Command sudo docker ps -q -a return_stdout=True return_stderr=False return_rc=True + ${output} ${rc} SSHLibrary.Execute Command + ... sudo docker ps -q -a + ... return_stdout=True + ... return_stderr=False + ... return_rc=True Should Be Equal As Numbers ${rc} 0 - [Return] ${output} + RETURN ${output} Get Docker Ids Formatted - [Arguments] ${format} [Documentation] Execute command docker ps with --format argument and retrieve the existing containers names - ${output} ${rc} SSHLibrary.Execute Command sudo docker ps -a --format ${format} return_stdout=True return_stderr=False return_rc=True + [Arguments] ${format} + ${output} ${rc} SSHLibrary.Execute Command + ... sudo docker ps -a --format ${format} + ... return_stdout=True + ... return_stderr=False + ... return_rc=True Should Be Equal As Numbers ${rc} 0 - [Return] ${output} + RETURN ${output} Get Docker Names As List [Documentation] Returns a list with the names of all running containers inside the tools system - ${docker_ps}= DockerSfc.Get Docker Ids Formatted "{{.Names}}" -f status=running - ${docker_name_list}= Split String ${docker_ps} \n - [Return] ${docker_name_list} + ${docker_ps} DockerSfc.Get Docker Ids Formatted "{{.Names}}" -f status=running + ${docker_name_list} Split String ${docker_ps} \n + RETURN ${docker_name_list} Get Docker IP - [Arguments] ${docker_name} [Documentation] Obtain the IP address from a given container - ${output} ${rc} SSHLibrary.Execute Command sudo docker inspect -f '{{.NetworkSettings.IPAddress }}' ${docker_name} return_stdout=True return_stderr=False return_rc=True + [Arguments] ${docker_name} + ${output} ${rc} SSHLibrary.Execute Command + ... sudo docker inspect -f '{{.NetworkSettings.IPAddress }}' ${docker_name} + ... return_stdout=True + ... return_stderr=False + ... return_rc=True Should Be Equal As Numbers ${rc} 0 - [Return] ${output} + RETURN ${output} Docker Exec - [Arguments] ${docker_name} ${command} ${return_contains}=${EMPTY} ${result_code}=0 [Documentation] Execute a command into a docker container. - ${output} ${rc} SSHLibrary.Execute Command sudo docker exec ${docker_name} ${command} return_stdout=True return_stderr=False return_rc=True - Run Keyword If '${return_contains}'!='${EMPTY}' Should Contain ${output} ${return_contains} + [Arguments] ${docker_name} ${command} ${return_contains}=${EMPTY} ${result_code}=0 + ${output} ${rc} SSHLibrary.Execute Command + ... sudo docker exec ${docker_name} ${command} + ... return_stdout=True + ... return_stderr=False + ... return_rc=True + IF '${return_contains}'!='${EMPTY}' + Should Contain ${output} ${return_contains} + END Should Be Equal As Numbers ${rc} ${result_code} - [Return] ${output} + RETURN ${output} Multiple Docker Exec - [Arguments] ${docker_name_list} ${command} ${return_contains}=${EMPTY} ${result_code}=0 [Documentation] Execute a command in a list of dockers and return all the outputs in a list - @{list_output}= Create List + [Arguments] ${docker_name_list} ${command} ${return_contains}=${EMPTY} ${result_code}=0 + @{list_output} Create List FOR ${docker_id} IN @{docker_name_list} - ${exec_output}= Docker Exec ${docker_id} ${command} ${return_contains} ${result_code} + ${exec_output} Docker Exec ${docker_id} ${command} ${return_contains} ${result_code} Append To List ${list_output} ${exec_output} END - [Return] ${list_output} + RETURN ${list_output} Get Flows In Docker Containers - ${docker_list}= DockerSfc.Get Docker Names As List - ${docker_flows} DockerSfc.Multiple Docker Exec ${docker_list} ovs-ofctl dump-flows -OOpenflow13 ${INTEGRATION_BRIDGE} OFPST_FLOW - [Return] ${docker_flows} + ${docker_list} DockerSfc.Get Docker Names As List + ${docker_flows} DockerSfc.Multiple Docker Exec + ... ${docker_list} + ... ovs-ofctl dump-flows -OOpenflow13 ${INTEGRATION_BRIDGE} + ... OFPST_FLOW + RETURN ${docker_flows} Get Docker Bridge Subnet [Documentation] Obtain the subnet used by docker bridge using the docker inspect tool - ${output} ${rc} SSHLibrary.Execute Command sudo docker network inspect bridge --format {{.IPAM.Config}} | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}[\/][0-9]{1,2}" return_stdout=True return_stderr=False return_rc=True + ${output} ${rc} SSHLibrary.Execute Command + ... sudo docker network inspect bridge --format {{.IPAM.Config}} | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}[\/][0-9]{1,2}" + ... return_stdout=True + ... return_stderr=False + ... return_rc=True Should Be Equal As Numbers ${rc} 0 - [Return] ${output} + RETURN ${output} diff --git a/csit/libraries/SFC/SfcKeywords.robot b/csit/libraries/SFC/SfcKeywords.robot index 5ebe41449a..6fb9919541 100644 --- a/csit/libraries/SFC/SfcKeywords.robot +++ b/csit/libraries/SFC/SfcKeywords.robot @@ -1,33 +1,33 @@ *** Settings *** -Documentation Common Keywords for the SFC Test suites. -Library Collections -Resource ../CompareStream.robot -Resource ../Utils.robot +Documentation Common Keywords for the SFC Test suites. + +Library Collections +Resource ../CompareStream.robot +Resource ../Utils.robot -*** Variables *** *** Keywords *** Get JSON Elements From URI [Arguments] ${uri} ${resp} = RequestsLibrary.Get Request session ${uri} - [Return] ${resp.json()} + RETURN ${resp.json()} Check Classifier Flows ${flowList} = DockerSfc.Get Flows In Docker Containers BuiltIn.log ${flowList} - ${expected_nsh_pop}= Set_Variable_If_At_Most oxygen *actions=pop_nsh* *actions=decap(),decap(),* - ${expected_nsh_push}= Set_Variable_If_At_Most oxygen *actions=push_nsh* *actions=encap(nsh* + ${expected_nsh_pop} = Set_Variable_If_At_Most oxygen *actions=pop_nsh* *actions=decap(),decap(),* + ${expected_nsh_push} = Set_Variable_If_At_Most oxygen *actions=push_nsh* *actions=encap(nsh* Collections.Should Contain Match ${flowList} ${expected_nsh_pop} Collections.Should Contain Match ${flowList} ${expected_nsh_push} Check Service Function Types Added - [Arguments] ${elements} [Documentation] Check that the service function types are updated with the service function names + [Arguments] ${elements} Utils.Check For Elements At URI ${SERVICE_FUNCTION_TYPES_URI} ${elements} Check Service Function Types Removed - [Arguments] ${elements} [Documentation] Check that the service function names are removed from the service function types + [Arguments] ${elements} Utils.Check For Elements Not At URI ${SERVICE_FUNCTION_TYPES_URI} ${elements} Check Empty Service Function Paths State @@ -35,25 +35,29 @@ Check Empty Service Function Paths State Utils.No Content From URI session ${SERVICE_FUNCTION_PATH_STATE_URI} Check Rendered Service Path Created - [Arguments] ${sfp_name} [Documentation] Check that the Rendered Service Path is created + [Arguments] ${sfp_name} ${sfp_name_elements_list} = BuiltIn.Create List ${sfp_name} Utils.Check For Elements At URI ${SERVICE_FUNCTION_PATHS_STATE_URI} ${sfp_name_elements_list} Check Rendered Service Path Deleted - [Arguments] ${sfp_name} [Documentation] Check that the Rendered Service Path is deleted + [Arguments] ${sfp_name} Utils.No Content From URI session ${SERVICE_FUNCTION_PATH_STATE_URI}/${sfp_name} Get Rendered Service Path Name - [Arguments] ${sfp_name} ${get_reverse}=False [Documentation] Given an SFP name, do a get on ${SERVICE_FUNCTION_PATH_STATE_URI} to get the RSP name + [Arguments] ${sfp_name} ${get_reverse}=False ${resp} = RequestsLibrary.Get Request session ${SERVICE_FUNCTION_PATH_STATE_URI}/${sfp_name} BuiltIn.Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} # should be like this: {"service-function-path-state":[{"name":"SFC1-100","sfp-rendered-service-path":[{"name":"SFC1-100-Path-183"}]}]} - ${sfp_rendered_service_path_list} = Collections.Get_From_Dictionary ${resp.json()} service-function-path-state + ${sfp_rendered_service_path_list} = Collections.Get_From_Dictionary + ... ${resp.json()} + ... service-function-path-state ${sfp_rendered_service_path_dict} = Collections.Get_From_List ${sfp_rendered_service_path_list} 0 - ${sfp_state_list} = Collections.Get_From_Dictionary ${sfp_rendered_service_path_dict} sfp-rendered-service-path + ${sfp_state_list} = Collections.Get_From_Dictionary + ... ${sfp_rendered_service_path_dict} + ... sfp-rendered-service-path ${list_length} = BuiltIn.Get Length ${sfp_state_list} # The "sfp-rendered-service-path" will only have 1 or 2 entries, depending on chain symmetry config. # The RSP name will be "-Path-" and the optional symmetric name will be -Path--Reverse" @@ -63,14 +67,19 @@ Get Rendered Service Path Name ${name} = Collections.Get_From_Dictionary ${rsp_name_dict} name @{matches} = String.Get Regexp Matches ${name} .*Reverse$ ${matches_length} = BuiltIn.Get Length ${matches} - ${value} = BuiltIn.Set Variable If "${get_reverse}" == "False" and 0 == ${matches_length} ${name} "${get_reverse}" == "True" and 0 < ${matches_length} ${name} - ... "${value}" != "None" ${value} + ${value} = BuiltIn.Set Variable If + ... "${get_reverse}" == "False" and 0 == ${matches_length} + ... ${name} + ... "${get_reverse}" == "True" and 0 < ${matches_length} + ... ${name} + ... "${value}" != "None" + ... ${value} END - [Return] ${value} + RETURN ${value} Create Sfp And Wait For Rsp Creation - [Arguments] ${sfp_file_name} [Documentation] Given an SFP name, create it and wait for the associated RSPs to be created + [Arguments] ${sfp_file_name} Utils.Add Elements To URI From File And Verify ${SERVICE_FUNCTION_PATHS_URI} ${sfp_file_name} ${sfp_dict} = Utils.Json Parse From File ${sfp_file_name} ${sfps} = Collections.Get_From_Dictionary ${sfp_dict} service-function-paths @@ -80,16 +89,24 @@ Create Sfp And Wait For Rsp Creation FOR ${i} IN RANGE ${list_length} ${sfp_entry_dict} = Collections.Get From List ${sfp_json_list} ${i} ${sfp_name} = Collections.Get_From_Dictionary ${sfp_entry_dict} name - ${status} ${symmetric} = BuiltIn.Run Keyword And Ignore Error Collections.Get_From_Dictionary ${sfp_entry_dict} symmetric + ${status} ${symmetric} = BuiltIn.Run Keyword And Ignore Error + ... Collections.Get_From_Dictionary + ... ${sfp_entry_dict} + ... symmetric ${symmetric} = BuiltIn.Set Variable If "${status}" == "FAIL" False ${symmetric} ${num_names} = BuiltIn.Set Variable If "${symmetric}" == "False" 2 3 - BuiltIn.Wait Until Keyword Succeeds 60s 2s Utils.Check For Specific Number Of Elements At URI ${SERVICE_FUNCTION_PATH_STATE_URI}/${sfp_name} name + BuiltIn.Wait Until Keyword Succeeds + ... 60s + ... 2s + ... Utils.Check For Specific Number Of Elements At URI + ... ${SERVICE_FUNCTION_PATH_STATE_URI}/${sfp_name} + ... name ... ${num_names} END Delete Sfp And Wait For Rsps Deletion - [Arguments] ${sfp_name} [Documentation] Given an SFP name, delete it and wait for the associated SFP state and RSPs to be deleted + [Arguments] ${sfp_name} Utils.Remove All Elements At URI And Verify ${SERVICE_FUNCTION_PATH_URI}/${sfp_name} BuiltIn.Wait Until Keyword Succeeds 60s 2s Check Rendered Service Path Deleted ${sfp_name} @@ -100,7 +117,7 @@ Delete All Sfps And Wait For Rsps Deletion Switch Ips In Json Files [Arguments] ${json_dir} ${container_names} - ${normalized_dir}= OperatingSystem.Normalize Path ${json_dir}/*.json + ${normalized_dir} = OperatingSystem.Normalize Path ${json_dir}/*.json FOR ${cont_name} IN @{container_names} ${cont_ip} = Get Docker IP ${cont_name} OperatingSystem.Run sudo sed -i 's/${cont_name}/${cont_ip}/g' ${normalized_dir} diff --git a/csit/libraries/SSHKeywords.robot b/csit/libraries/SSHKeywords.robot index 7042e7dcfe..c2073d5347 100644 --- a/csit/libraries/SSHKeywords.robot +++ b/csit/libraries/SSHKeywords.robot @@ -1,43 +1,48 @@ *** Settings *** -Documentation Resource enhancing SSHLibrary with Keywords used in multiple suites. +Documentation Resource enhancing SSHLibrary with Keywords used in multiple suites. ... -... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... Some suites evolved utility Keywords re-usable with other suites. -... When the Keywords assume a SSH session is active, -... and if the Keywords do not fit into a more specific Resource, -... you can place them here. -Library SSHLibrary -Resource ${CURDIR}/Utils.robot -Resource ../variables/Variables.robot +... Some suites evolved utility Keywords re-usable with other suites. +... When the Keywords assume a SSH session is active, +... and if the Keywords do not fit into a more specific Resource, +... you can place them here. + +Library SSHLibrary +Resource ${CURDIR}/Utils.robot +Resource ../variables/Variables.robot + *** Variables *** ${SSHKeywords__current_remote_working_directory} . -${SSHKeywords__current_venv_path} /tmp/defaultvenv -${NETSTAT_COMMAND} netstat -punta +${SSHKeywords__current_venv_path} /tmp/defaultvenv +${NETSTAT_COMMAND} netstat -punta + *** Keywords *** Open_Connection_To_ODL_System - [Arguments] ${ip_address}=${ODL_SYSTEM_IP} ${timeout}=10s [Documentation] Open a connection to the ODL system at ${ip_address} and return its identifier. - ${odl_connection} = SSHLibrary.Open_Connection ${ip_address} prompt=${ODL_SYSTEM_PROMPT} timeout=${timeout} + [Arguments] ${ip_address}=${ODL_SYSTEM_IP} ${timeout}=10s + ${odl_connection} = SSHLibrary.Open_Connection + ... ${ip_address} + ... prompt=${ODL_SYSTEM_PROMPT} + ... timeout=${timeout} Flexible_Controller_Login - [Return] ${odl_connection} + RETURN ${odl_connection} Open_Connection_To_Tools_System - [Arguments] ${ip_address}=${TOOLS_SYSTEM_IP} ${timeout}=10s ${prompt}=${TOOLS_SYSTEM_PROMPT} [Documentation] Open a connection to the tools system at ${ip_address} and return its identifier. + [Arguments] ${ip_address}=${TOOLS_SYSTEM_IP} ${timeout}=10s ${prompt}=${TOOLS_SYSTEM_PROMPT} ${tools_connection} = SSHLibrary.Open_Connection ${ip_address} prompt=${prompt} timeout=${timeout} Flexible_Mininet_Login - [Return] ${tools_connection} + RETURN ${tools_connection} Restore_Current_Ssh_Connection_From_Index - [Arguments] ${connection_index} [Documentation] Restore active SSH connection in SSHLibrary to given index. ... ... Restore the currently active connection state in @@ -58,220 +63,312 @@ Restore_Current_Ssh_Connection_From_Index ... workaround is applied by opening and closing temporary connection. ... Unfortunately this will fail if run on Jython and there is no SSH server ... running on localhost, port 22 but there is nothing easy that can be done about it. - BuiltIn.Run Keyword And Return If ${connection_index} is not None SSHLibrary.Switch Connection ${connection_index} + [Arguments] ${connection_index} + BuiltIn.Run Keyword And Return If + ... ${connection_index} is not None + ... SSHLibrary.Switch Connection + ... ${connection_index} # The background connection is still current, bury it. SSHLibrary.Open Connection 127.0.0.1 SSHLibrary.Close Connection Run_Keyword_Preserve_Connection - [Arguments] ${keyword_name} @{args} &{kwargs} [Documentation] Store current connection index, run keyword returning its result, restore connection in teardown. ... Note that in order to avoid "got positional argument after named arguments", it is safer to use positional (not named) arguments on call. - ${current_connection}= SSHLibrary.Get_Connection + [Arguments] ${keyword_name} @{args} &{kwargs} + ${current_connection} = SSHLibrary.Get_Connection BuiltIn.Run_Keyword_And_Return ${keyword_name} @{args} &{kwargs} # Resource name has to be prepended, as KarafKeywords still contains a redirect. [Teardown] SSHKeywords.Restore_Current_SSH_Connection_From_Index ${current_connection.index} Run_Keyword_With_Ssh - [Arguments] ${ip_address} ${keyword_name} @{args} &{kwargs} [Documentation] Open temporary connection to given IP address, run keyword, close connection, restore previously active connection, return result. - Run_Keyword_Preserve_Connection Run_Unsafely_Keyword_Over_Temporary_Odl_Session ${ip_address} ${keyword_name} @{args} &{kwargs} + [Arguments] ${ip_address} ${keyword_name} @{args} &{kwargs} + Run_Keyword_Preserve_Connection + ... Run_Unsafely_Keyword_Over_Temporary_Odl_Session + ... ${ip_address} + ... ${keyword_name} + ... @{args} + ... &{kwargs} Run_Unsafely_Keyword_Over_Temporary_Odl_Session - [Arguments] ${ip_address} ${keyword_name} @{args} &{kwargs} [Documentation] Open connection to given IP address, run keyword, close connection, return result. ... This is unsafe in the sense that previously active session will be switched out off, but safe in the sense only the temporary connection is closed. + [Arguments] ${ip_address} ${keyword_name} @{args} &{kwargs} Open_Connection_To_ODL_System ${ip_address} # Not using Teardown, to avoid a call to close if the previous line fails. ${status} ${result} = BuiltIn.Run_Keyword_And_Ignore_Error ${keyword_name} @{args} &{kwargs} SSHLibrary.Close_Connection - BuiltIn.Return_From_Keyword_If "${status}" == "PASS" ${result} + IF "${status}" == "PASS" RETURN ${result} BuiltIn.Fail ${result} Log_Command_Results - [Arguments] ${stdout} ${stderr} ${rc} [Documentation] Log everything returned by SSHLibrary.Execute_Command + [Arguments] ${stdout} ${stderr} ${rc} BuiltIn.Log ${stdout} BuiltIn.Log ${stderr} BuiltIn.Log ${rc} Execute_Command_Passes - [Arguments] ${command} ${return_success_only}=True ${log_on_success}=False ${log_on_failure}=True ${stderr_must_be_empty}=False [Documentation] Execute command via the active SSH connection. For success, rc has to be zero and optionally stderr has to be empty. ... Log everything, depending on arguments and success. Return either success string or stdout. ... TODO: Do we want to support customizing return values the same way as SSHLibrary.Execute_Command does? - ${stdout} ${stderr} ${rc} = SSHLibrary.Execute_Command ${command} return_stderr=True return_rc=True + [Arguments] ${command} ${return_success_only}=True ${log_on_success}=False ${log_on_failure}=True ${stderr_must_be_empty}=False + ${stdout} ${stderr} ${rc} = SSHLibrary.Execute_Command + ... ${command} + ... return_stderr=True + ... return_rc=True ${emptiness_status} ${result} = BuiltIn.Run_Keyword_And_Ignore_Error BuiltIn.Should_Be_Empty ${stderr} - ${success} = BuiltIn.Set_Variable_If (${rc} == 0) and (("${emptiness_status}" == "PASS") or not ${stderr_must_be_empty}) True False - BuiltIn.Run_Keyword_If (${log_on_success} and ${success}) or (${log_on_failure} and not ${success}) Log_Command_Results ${stdout} ${stderr} ${rc} - BuiltIn.Return_From_Keyword_If ${return_success_only} ${success} - BuiltIn.Return_From_Keyword_If ${success} ${stdout} + ${success} = BuiltIn.Set_Variable_If + ... (${rc} == 0) and (("${emptiness_status}" == "PASS") or not ${stderr_must_be_empty}) + ... True + ... False + IF (${log_on_success} and ${success}) or (${log_on_failure} and not ${success}) + Log_Command_Results ${stdout} ${stderr} ${rc} + END + IF ${return_success_only} RETURN ${success} + IF ${success} RETURN ${stdout} BuiltIn.Fail Got rc: ${rc} or stderr was not empty: ${stderr} Execute_Command_Should_Pass - [Arguments] ${command} ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=False [Documentation] A wrapper for Execute_Command_Passes with return_success_only=False ... Also, log_on_success defaults to True (but is customizable, unlike return_success_only).. - BuiltIn.Run_Keyword_And_Return Execute_Command_Passes ${command} return_success_only=False log_on_success=${log_on_success} log_on_failure=${log_on_failure} stderr_must_be_empty=${stderr_must_be_empty} + [Arguments] ${command} ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=False + BuiltIn.Run_Keyword_And_Return + ... Execute_Command_Passes + ... ${command} + ... return_success_only=False + ... log_on_success=${log_on_success} + ... log_on_failure=${log_on_failure} + ... stderr_must_be_empty=${stderr_must_be_empty} Execute_Command_At_Path_Should_Pass - [Arguments] ${command} ${path}=None ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=False [Documentation] A keyword similar to Execute_Command_Should_Pass which performs "cd" to ${path} before executing the ${command}. ... This is useful when rewriting bash scripts, as series of SSHLibrary.Execute_Command do not share current working directory. ... TODO: Perhaps a Keyword which sets up environment variables would be useful as well. + [Arguments] ${command} ${path}=None ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=False ${cd_and_command} = BuiltIn.Set_Variable cd '${path}' && ${command} - BuiltIn.Run_Keyword_And_Return Execute_Command_Passes ${cd_and_command} return_success_only=False log_on_success=${log_on_success} log_on_failure=${log_on_failure} stderr_must_be_empty=${stderr_must_be_empty} + BuiltIn.Run_Keyword_And_Return + ... Execute_Command_Passes + ... ${cd_and_command} + ... return_success_only=False + ... log_on_success=${log_on_success} + ... log_on_failure=${log_on_failure} + ... stderr_must_be_empty=${stderr_must_be_empty} Set_Cwd - [Arguments] ${path} [Documentation] Set \${SSHKeywords__current_remote_working_directory} variable to ${path}. If SSH default is desired, use dot. + [Arguments] ${path} BuiltIn.Set_Suite_Variable \${SSHKeywords__current_remote_working_directory} ${path} Execute_Command_At_Cwd_Should_Pass - [Arguments] ${command} ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=True [Documentation] Run Execute_Command_At_Path_Should_Pass with previously set CWD as path. - BuiltIn.Run_Keyword_And_Return Execute_Command_At_Path_Should_Pass command=${command} path=${SSHKeywords__current_remote_working_directory} log_on_success=${log_on_success} log_on_failure=${log_on_failure} stderr_must_be_empty=${stderr_must_be_empty} + [Arguments] ${command} ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=True + BuiltIn.Run_Keyword_And_Return + ... Execute_Command_At_Path_Should_Pass + ... command=${command} + ... path=${SSHKeywords__current_remote_working_directory} + ... log_on_success=${log_on_success} + ... log_on_failure=${log_on_failure} + ... stderr_must_be_empty=${stderr_must_be_empty} Require_Python [Documentation] Verify current SSH connection leads to machine with python working. Fatal fail otherwise. ${passed} = Execute_Command_Passes python3 --help - BuiltIn.Return_From_Keyword_If ${passed} + IF ${passed} RETURN BuiltIn.Fatal_Error Python 3 is not installed! Assure_Library_Ipaddr - [Arguments] ${target_dir}=. [Documentation] Tests whether ipaddr module is present on ssh-connected machine, Puts ipaddr.py to target_dir if not. + [Arguments] ${target_dir}=. ${passed} = Execute_Command_Passes bash -c 'cd "${target_dir}" && python -c "import ipaddr"' - BuiltIn.Return_From_Keyword_If ${passed} + IF ${passed} RETURN SSHLibrary.Put_File ${CURDIR}/BGPCEP/ipaddr.py ${target_dir}/ Assure_Library_Counter - [Arguments] ${target_dir}=. [Documentation] Tests whether Counter is present in collections on ssh-connected machine, Puts Counter.py to workspace if not. - ${passed} = Execute_Command_Passes bash -c 'cd "${target_dir}" && python -c "from collections import Counter"' + [Arguments] ${target_dir}=. + ${passed} = Execute_Command_Passes + ... bash -c 'cd "${target_dir}" && python -c "from collections import Counter"' # TODO: Move the bash-cd wrapper to separate keyword? - BuiltIn.Return_From_Keyword_If ${passed} + IF ${passed} RETURN SSHLibrary.Put_File ${CURDIR}/Counter.py ${target_dir}/ Count_Port_Occurences - [Arguments] ${port} ${state} ${name} [Documentation] Run 'netstat' on the remote machine and count occurences of given port in the given state connected to process with the given name. - ${output} = SSHLibrary.Execute_Command ${NETSTAT_COMMAND} 2> /dev/null | grep -E ":${port} .+ ${state} .+${name}" | wc -l - [Return] ${output} + [Arguments] ${port} ${state} ${name} + ${output} = SSHLibrary.Execute_Command + ... ${NETSTAT_COMMAND} 2> /dev/null | grep -E ":${port} .+ ${state} .+${name}" | wc -l + RETURN ${output} Virtual_Env_Set_Path - [Arguments] ${venv_path} [Documentation] Set \${SSHKeywords__current_venv_path} variable to ${venv_path}. Path should be absolute. + [Arguments] ${venv_path} BuiltIn.Set_Global_Variable \${SSHKeywords__current_venv_path} ${venv_path} Virtual_Env_Create - [Arguments] ${upgrade_pip}=True [Documentation] Creates virtual env. If not to use the default name, use Virtual_Env_Set_Path kw. Returns stdout. + [Arguments] ${upgrade_pip}=True Execute_Command_At_Cwd_Should_Pass virtualenv ${SSHKeywords__current_venv_path} - BuiltIn.Run_Keyword_And_Return_If ${upgrade_pip} Virtual_Env_Run_Cmd_At_Cwd pip install --upgrade pip stderr_must_be_empty=False + BuiltIn.Run_Keyword_And_Return_If + ... ${upgrade_pip} + ... Virtual_Env_Run_Cmd_At_Cwd + ... pip install --upgrade pip + ... stderr_must_be_empty=False Virtual_Env_Create_Python3 - [Arguments] ${upgrade_pip}=True [Documentation] Creates virtual env. If not to use the default name, use Virtual_Env_Set_Path kw. Returns stdout. + [Arguments] ${upgrade_pip}=True Execute_Command_At_Cwd_Should_Pass python3 -m venv ${SSHKeywords__current_venv_path} - BuiltIn.Run_Keyword_And_Return_If ${upgrade_pip} Virtual_Env_Run_Cmd_At_Cwd pip install --upgrade pip stderr_must_be_empty=False + BuiltIn.Run_Keyword_And_Return_If + ... ${upgrade_pip} + ... Virtual_Env_Run_Cmd_At_Cwd + ... pip install --upgrade pip + ... stderr_must_be_empty=False Virtual_Env_Delete [Documentation] Deletes a directory with virtual env. Execute_Command_At_Cwd_Should_Pass rm -rf ${SSHKeywords__current_venv_path} Virtual_Env_Run_Cmd_At_Cwd - [Arguments] ${cmd} ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=True [Documentation] Runs given command within activated virtual env and returns stdout. - BuiltIn.Run_Keyword_And_Return Execute_Command_At_Cwd_Should_Pass source ${SSHKeywords__current_venv_path}/bin/activate; ${cmd}; deactivate log_on_success=${log_on_success} log_on_failure=${log_on_failure} stderr_must_be_empty=${stderr_must_be_empty} + [Arguments] ${cmd} ${log_on_success}=True ${log_on_failure}=True ${stderr_must_be_empty}=True + BuiltIn.Run_Keyword_And_Return + ... Execute_Command_At_Cwd_Should_Pass + ... source ${SSHKeywords__current_venv_path}/bin/activate; ${cmd}; deactivate + ... log_on_success=${log_on_success} + ... log_on_failure=${log_on_failure} + ... stderr_must_be_empty=${stderr_must_be_empty} Virtual_Env_Install_Package - [Arguments] ${package} [Documentation] Installs python package into virtual env. Use with version if needed (e.g. exabgp==3.4.16). Returns stdout. - BuiltIn.Run_Keyword_And_Return Virtual_Env_Run_Cmd_At_Cwd pip install ${package} stderr_must_be_empty=False + [Arguments] ${package} + BuiltIn.Run_Keyword_And_Return + ... Virtual_Env_Run_Cmd_At_Cwd + ... pip install ${package} + ... stderr_must_be_empty=False Virtual_Env_Uninstall_Package - [Arguments] ${package} [Documentation] Uninstalls python package from virtual env and returns stdout. - BuiltIn.Run_Keyword_And_Return Virtual_Env_Run_Cmd_At_Cwd pip uninstall -y ${package} stderr_must_be_empty=False + [Arguments] ${package} + BuiltIn.Run_Keyword_And_Return + ... Virtual_Env_Run_Cmd_At_Cwd + ... pip uninstall -y ${package} + ... stderr_must_be_empty=False Virtual_Env_Freeze [Documentation] Shows installed packages within the returned stdout. BuiltIn.Run_Keyword_And_Return Virtual_Env_Run_Cmd_At_Cwd pip freeze --all stderr_must_be_empty=False Virtual_Env_Activate_On_Current_Session - [Arguments] ${log_output}=${False} [Documentation] Activates virtual environment. To run anything in the env activated this way you should use SSHLibrary.Write and Read commands. + [Arguments] ${log_output}=${False} SSHLibrary.Write source ${SSHKeywords__current_venv_path}/bin/activate - ${output}= SSHLibrary.Read_Until_Prompt - BuiltIn.Run_Keyword_If ${log_output}==${True} BuiltIn.Log ${output} + ${output} = SSHLibrary.Read_Until_Prompt + IF ${log_output}==${True} BuiltIn.Log ${output} Virtual_Env_Deactivate_On_Current_Session - [Arguments] ${log_output}=${False} [Documentation] Deactivates virtual environment. + [Arguments] ${log_output}=${False} SSHLibrary.Write deactivate - ${output}= SSHLibrary.Read_Until_Prompt - BuiltIn.Run_Keyword_If ${log_output}==${True} BuiltIn.Log ${output} + ${output} = SSHLibrary.Read_Until_Prompt + IF ${log_output}==${True} BuiltIn.Log ${output} Unsafe_Copy_File_To_Remote_System - [Arguments] ${system} ${source} ${destination}=./ ${user}=${DEFAULT_USER} ${password}=${DEFAULT_PASSWORD} ${prompt}=${DEFAULT_LINUX_PROMPT} - ... ${prompt_timeout}=5s [Documentation] Copy the ${source} file to the ${destination} file on the remote ${system}. The keyword opens and closes a single ... ssh connection and does not rely on any existing ssh connection that may be open. + [Arguments] ${system} ${source} ${destination}=./ ${user}=${DEFAULT_USER} ${password}=${DEFAULT_PASSWORD} ${prompt}=${DEFAULT_LINUX_PROMPT} + ... ${prompt_timeout}=5s SSHLibrary.Open_Connection ${system} prompt=${prompt} timeout=${prompt_timeout} Flexible_SSH_Login ${user} ${password} SSHLibrary.Put_File ${source} ${destination} SSHLibrary.Close Connection Copy_File_To_Remote_System - [Arguments] ${system} ${source} ${destination}=./ ${user}=${DEFAULT_USER} ${password}=${DEFAULT_PASSWORD} ${prompt}=${DEFAULT_LINUX_PROMPT} - ... ${prompt_timeout}=5s [Documentation] Copy the ${source} file to the ${destination} file on the remote ${system}. Any pre-existing active ... ssh connection will be retained. - SSHKeywords.Run_Keyword_Preserve_Connection SSHKeywords.Unsafe_Copy_File_To_Remote_System ${system} ${source} ${destination} ${user} ${password} - ... ${prompt} ${prompt_timeout} + [Arguments] ${system} ${source} ${destination}=./ ${user}=${DEFAULT_USER} ${password}=${DEFAULT_PASSWORD} ${prompt}=${DEFAULT_LINUX_PROMPT} + ... ${prompt_timeout}=5s + SSHKeywords.Run_Keyword_Preserve_Connection + ... SSHKeywords.Unsafe_Copy_File_To_Remote_System + ... ${system} + ... ${source} + ... ${destination} + ... ${user} + ... ${password} + ... ${prompt} + ... ${prompt_timeout} Copy_File_To_Odl_System - [Arguments] ${system} ${source} ${destination}=./ [Documentation] Wrapper keyword to make it easier to copy a file to an ODL specific system - SSHKeywords.Copy_File_To_Remote_System ${system} ${source} ${destination} ${ODL_SYSTEM_USER} ${ODL_SYSTEM_PASSWORD} ${ODL_SYSTEM_PROMPT} + [Arguments] ${system} ${source} ${destination}=./ + SSHKeywords.Copy_File_To_Remote_System + ... ${system} + ... ${source} + ... ${destination} + ... ${ODL_SYSTEM_USER} + ... ${ODL_SYSTEM_PASSWORD} + ... ${ODL_SYSTEM_PROMPT} Copy_File_To_Tools_System - [Arguments] ${system} ${source} ${destination}=./ [Documentation] Wrapper keyword to make it easier to copy a file to an Tools specific system - SSHKeywords.Copy_File_To_Remote_System ${system} ${source} ${destination} ${TOOLS_SYSTEM_USER} ${TOOLS_SYSTEM_PASSWORD} ${TOOLS_SYSTEM_PROMPT} + [Arguments] ${system} ${source} ${destination}=./ + SSHKeywords.Copy_File_To_Remote_System + ... ${system} + ... ${source} + ... ${destination} + ... ${TOOLS_SYSTEM_USER} + ... ${TOOLS_SYSTEM_PASSWORD} + ... ${TOOLS_SYSTEM_PROMPT} Flexible_SSH_Login - [Arguments] ${user} ${password}=${EMPTY} ${delay}=0.5s [Documentation] On active SSH session: if given non-empty password, do Login, else do Login With Public Key. + [Arguments] ${user} ${password}=${EMPTY} ${delay}=0.5s ${pwd_length} = BuiltIn.Get Length ${password} # ${pwd_length} is guaranteed to be an integer, so we are safe to evaluate it as Python expression. - BuiltIn.Run Keyword And Return If ${pwd_length} > 0 SSHLibrary.Login ${user} ${password} delay=${delay} - BuiltIn.Run Keyword And Return SSHLibrary.Login With Public Key ${user} ${USER_HOME}/.ssh/${SSH_KEY} ${KEYFILE_PASS} delay=${delay} + BuiltIn.Run Keyword And Return If + ... ${pwd_length} > 0 + ... SSHLibrary.Login + ... ${user} + ... ${password} + ... delay=${delay} + BuiltIn.Run Keyword And Return + ... SSHLibrary.Login With Public Key + ... ${user} + ... ${USER_HOME}/.ssh/${SSH_KEY} + ... ${KEYFILE_PASS} + ... delay=${delay} Flexible_Mininet_Login - [Arguments] ${user}=${TOOLS_SYSTEM_USER} ${password}=${TOOLS_SYSTEM_PASSWORD} ${delay}=0.5s [Documentation] Call Flexible SSH Login, but with default values suitable for Mininet machine. + [Arguments] ${user}=${TOOLS_SYSTEM_USER} ${password}=${TOOLS_SYSTEM_PASSWORD} ${delay}=0.5s BuiltIn.Run Keyword And Return Flexible SSH Login user=${user} password=${password} delay=${delay} Flexible_Controller_Login - [Arguments] ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${delay}=0.5s [Documentation] Call Flexible SSH Login, but with default values suitable for Controller machine. + [Arguments] ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${delay}=0.5s BuiltIn.Run Keyword And Return Flexible SSH Login user=${user} password=${password} delay=${delay} Move_File_To_Remote_System - [Arguments] ${system} ${source} ${destination}=./ ${user}=${DEFAULT_USER} ${password}=${DEFAULT_PASSWORD} ${prompt}=${DEFAULT_LINUX_PROMPT} - ... ${prompt_timeout}=5s [Documentation] Moves the ${source} file to the ${destination} file on the remote ${system}. Any pre-existing active ... ssh connection will be retained. - SSHKeywords.Run_Keyword_Preserve_Connection Unsafe_Move_File_To_Remote_System ${system} ${source} ${destination} ${user} ${password} - ... ${prompt} ${prompt_timeout} - -Unsafe_Move_File_To_Remote_System [Arguments] ${system} ${source} ${destination}=./ ${user}=${DEFAULT_USER} ${password}=${DEFAULT_PASSWORD} ${prompt}=${DEFAULT_LINUX_PROMPT} ... ${prompt_timeout}=5s + SSHKeywords.Run_Keyword_Preserve_Connection + ... Unsafe_Move_File_To_Remote_System + ... ${system} + ... ${source} + ... ${destination} + ... ${user} + ... ${password} + ... ${prompt} + ... ${prompt_timeout} + +Unsafe_Move_File_To_Remote_System [Documentation] Moves the ${source} file to the ${destination} file on the remote ${system}. The keyword opens and closes a single ... ssh connection and does not rely on any existing ssh connection that may be open. + [Arguments] ${system} ${source} ${destination}=./ ${user}=${DEFAULT_USER} ${password}=${DEFAULT_PASSWORD} ${prompt}=${DEFAULT_LINUX_PROMPT} + ... ${prompt_timeout}=5s SSHLibrary.Open_Connection ${system} prompt=${prompt} timeout=${prompt_timeout} Flexible_SSH_Login ${user} ${password} SSHLibrary.Put File ${source} ${destination} diff --git a/csit/libraries/SXP/FilteringResources.robot b/csit/libraries/SXP/FilteringResources.robot index edb412f8f3..d11db4f849 100644 --- a/csit/libraries/SXP/FilteringResources.robot +++ b/csit/libraries/SXP/FilteringResources.robot @@ -1,6 +1,8 @@ *** Settings *** -Documentation Library containing Keywords used for SXP filtering test checks -Resource ../SxpLib.robot +Documentation Library containing Keywords used for SXP filtering test checks + +Resource ../SxpLib.robot + *** Keywords *** Setup Nodes @@ -119,7 +121,7 @@ Check One Group 2-5 ... permit ACL 10.10.0.0 0.0.255.0 ... permit SGT 30 ACL 10.10.10.0 0.0.0.255 ... Info regarding filtering https://wiki.opendaylight.org/view/SXP:Beryllium:Developer_Guide - @{list} Create List 127.0.0.2 127.0.0.5 + @{list} = Create List 127.0.0.2 127.0.0.5 FOR ${node} IN @{list} ${resp} = SxpLib.Get Bindings ${node} BuiltIn.Log ${resp} diff --git a/csit/libraries/ScalarClosures.robot b/csit/libraries/ScalarClosures.robot index 9d9125f17b..bad89efc73 100644 --- a/csit/libraries/ScalarClosures.robot +++ b/csit/libraries/ScalarClosures.robot @@ -1,77 +1,78 @@ *** Settings *** -Documentation Robot keyword library (Resource) for supporting functional programming via "scalar closures". +Documentation Robot keyword library (Resource) for supporting functional programming via "scalar closures". ... -... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... Python has fist-class functions. It is possible to perform partial application -... and have the resulting anonymous function passed around as an object. -... Robot Framework has second class Keywords. Keyword has to be specified by its name, -... and ordering between positional and named arguments limit their usage. +... Python has fist-class functions. It is possible to perform partial application +... and have the resulting anonymous function passed around as an object. +... Robot Framework has second class Keywords. Keyword has to be specified by its name, +... and ordering between positional and named arguments limit their usage. ... -... There are several different ways how to overcame these limitations -... to offer something resembling functional programming in Robot. -... This library does everything via "scalar closures". +... There are several different ways how to overcame these limitations +... to offer something resembling functional programming in Robot. +... This library does everything via "scalar closures". ... -... Closure is a function together with values for some seemingly free variables. -... This library encodes closure as a scalar value (that is in fact a list). -... Scalars cannot be run in Robot directly, so a method to run them as closure is provided. -... Instead of alowing arguments, methods to run with substituted values are used. -... For substitution to work, the original closure has to be defined with (placeholder) arguments. -... TODO: Look once again for a way to remove this limitation. +... Closure is a function together with values for some seemingly free variables. +... This library encodes closure as a scalar value (that is in fact a list). +... Scalars cannot be run in Robot directly, so a method to run them as closure is provided. +... Instead of alowing arguments, methods to run with substituted values are used. +... For substitution to work, the original closure has to be defined with (placeholder) arguments. +... TODO: Look once again for a way to remove this limitation. ... -... For Keywords of this library to be easily wrappable (and runable with substitution), -... their arguments are usually positional. -... TODO: Look once again if adding/substituting named arguments is doable. +... For Keywords of this library to be easily wrappable (and runable with substitution), +... their arguments are usually positional. +... TODO: Look once again if adding/substituting named arguments is doable. ... -... Current limitation: Keywords inside closures may detect there were given @{args} list, even if it is empty. +... Current limitation: Keywords inside closures may detect there were given @{args} list, even if it is empty. ... -... There are convenience closures defined, but SC_Setup has to be called to make them available. -Library Collections +... There are convenience closures defined, but SC_Setup has to be called to make them available. + +Library Collections + *** Keywords *** Closure_From_Keyword_And_Arguments - [Arguments] ${keyword} @{args} &{kwargs} [Documentation] Turn keyword with given arguments into a scalar closure. ... ... Implemented as triple of keyword name, args as scalar and kwargs as scalar. - [Return] ${keyword} ${args} ${kwargs} + [Arguments] ${keyword} @{args} &{kwargs} + RETURN ${keyword} ${args} ${kwargs} Run_Closure_As_Is - [Arguments] ${closure} [Documentation] Run the keyword from closure without affecting arguments. + [Arguments] ${closure} ${keyword} ${args} ${kwargs} = BuiltIn.Set_Variable ${closure} ${result} = BuiltIn.Run_Keyword ${keyword} @{args} &{kwargs} - [Return] ${result} + RETURN ${result} Run_Closure_After_Replacing_First_Argument - [Arguments] ${closure} ${argument} [Documentation] Run the keyword from closure with replaced first positional argument. ... ... Note, this will currently fail if the closure was created with less than 1 positional argument. + [Arguments] ${closure} ${argument} ${keyword} ${args} ${kwargs} = BuiltIn.Set_Variable ${closure} Collections.Set_List_Value ${args} 0 ${argument} # TODO: Catch failure and use Collections.Append_To_List to overcome current limitation. ${result} = BuiltIn.Run_Keyword ${keyword} @{args} &{kwargs} - [Return] ${result} + RETURN ${result} Run_Closure_After_Replacing_First_Two_Arguments - [Arguments] ${closure} ${arg1} ${arg2} [Documentation] Run the keyword from closure with replaced first two positional arguments. ... ... Note, this will currently fail if the closure was created with less than 2 positional arguments. + [Arguments] ${closure} ${arg1} ${arg2} ${keyword} ${args} ${kwargs} = BuiltIn.Set_Variable ${closure} Collections.Set_List_Value ${args} 0 ${arg1} Collections.Set_List_Value ${args} 1 ${arg2} ${result} = BuiltIn.Run_Keyword ${keyword} @{args} &{kwargs} - [Return] ${result} + RETURN ${result} Run_Keyword_And_Collect_Garbage - [Arguments] ${keyword_to_gc}=BuiltIn.Fail @{args} &{kwargs} [Documentation] Runs Keyword, but performs garbage collection before pass/fail. ... ... TODO: Move to more appropriate Resource. @@ -95,21 +96,23 @@ Run_Keyword_And_Collect_Garbage ... "sudden death syndrome" (OOM killer invocation) of the Robot process ... before Python decides to collect the multi-megabyte pieces of the ... garbage on its own. + [Arguments] ${keyword_to_gc}=BuiltIn.Fail @{args} &{kwargs} # Execute Keyword but postpone failing. - ${status} ${message}= BuiltIn.Run Keyword And Ignore Error ${keyword_to_gc} @{args} &{kwargs} + ${status} ${message} = BuiltIn.Run Keyword And Ignore Error ${keyword_to_gc} @{args} &{kwargs} # Collect garbage. BuiltIn.Evaluate gc.collect() modules=gc # Resume possible failure state Propagate_Fail status=${status} message=${message} + RETURN ${message} + # So we have passed, return value. - [Return] ${message} Propagate_Fail - [Arguments] ${status}=PASS ${message}=Message unknown. [Documentation] If ${status} is PASS do nothing. Otherwise Fail with ${message}. ... ... TODO: Move to more appropriate Resource. - BuiltIn.Return_From_Keyword_If '''${status}''' == '''PASS''' + [Arguments] ${status}=PASS ${message}=Message unknown. + IF '''${status}''' == '''PASS''' RETURN BuiltIn.Fail ${message} SC_Setup diff --git a/csit/libraries/SetupUtils.robot b/csit/libraries/SetupUtils.robot index 9fb802e8dd..466bcb0a8b 100644 --- a/csit/libraries/SetupUtils.robot +++ b/csit/libraries/SetupUtils.robot @@ -1,59 +1,68 @@ *** Settings *** -Documentation Simple resource with setup keywords which combine FailFast and Karaf logging. +Documentation Simple resource with setup keywords which combine FailFast and Karaf logging. ... -... Copyright (c) 2015-2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2015-2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... In order for most keywords to work properly, the initialization keyword -... Setup_Utils_For_Setup_And_Teardown has to be called, best in sute setup. -... This initialization also initializes dependend Resources, -... (most important KarafKeywords) whcih may initialize their dependecies as well. +... In order for most keywords to work properly, the initialization keyword +... Setup_Utils_For_Setup_And_Teardown has to be called, best in sute setup. +... This initialization also initializes dependend Resources, +... (most important KarafKeywords) whcih may initialize their dependecies as well. ... -... See FailFast.robot documentation for intricacies of that library. -Resource ${CURDIR}/FailFast.robot -Resource ${CURDIR}/KarafKeywords.robot -Resource ${CURDIR}/Utils.robot +... See FailFast.robot documentation for intricacies of that library. + +Resource ${CURDIR}/FailFast.robot +Resource ${CURDIR}/KarafKeywords.robot +Resource ${CURDIR}/Utils.robot + *** Variables *** -${SetupUtils__Known_Bug_ID} ${EMPTY} +${SetupUtils__Known_Bug_ID} ${EMPTY} + *** Keywords *** Setup_Utils_For_Setup_And_Teardown - [Arguments] ${http_timeout}=${DEFAULT_TIMEOUT_HTTP} [Documentation] Prepare both FailFast and Karaf logging, log that the caller suite has started. ... This keyword is to be used in suite setup, and without it the other keywords may not work properly. + [Arguments] ${http_timeout}=${DEFAULT_TIMEOUT_HTTP} FailFast.Do_Not_Fail_Fast_From_Now_On KarafKeywords.Setup Karaf Keywords http_timeout=${http_timeout} BuiltIn.Run Keyword And Ignore Error KarafKeywords.Log_Test_Suite_Start_To_Controller_Karaf Setup_Test_With_Logging_And_Fast_Failing - [Arguments] ${member_index_list}=${EMPTY} [Documentation] Test case setup which skips on previous failure. If not, logs test case name to Karaf log. ... Recommended to be used as the default test case setup. + [Arguments] ${member_index_list}=${EMPTY} FailFast.Fail_This_Fast_On_Previous_Error - BuiltIn.Run Keyword And Ignore Error KarafKeywords.Log_Testcase_Start_To_Controller_Karaf member_index_list=${member_index_list} + BuiltIn.Run Keyword And Ignore Error + ... KarafKeywords.Log_Testcase_Start_To_Controller_Karaf + ... member_index_list=${member_index_list} Setup_Test_With_Logging_And_Without_Fast_Failing - [Arguments] ${member_index_list}=${EMPTY} [Documentation] Test case setup which explicitly ignores previous failure and logs test case name to Karaf log. ... Needed if the recommended default is to be overriden. + [Arguments] ${member_index_list}=${EMPTY} FailFast.Run_Even_When_Failing_Fast - BuiltIn.Run Keyword And Ignore Error KarafKeywords.Log_Testcase_Start_To_Controller_Karaf member_index_list=${member_index_list} + BuiltIn.Run Keyword And Ignore Error + ... KarafKeywords.Log_Testcase_Start_To_Controller_Karaf + ... member_index_list=${member_index_list} Setup_Logging_For_Debug_Purposes_On_List_Or_All - [Arguments] ${log_level} ${loggers_list} ${member_index_list}=${EMPTY} [Documentation] Set the log level for given loggers on node nodes of the cluster + [Arguments] ${log_level} ${loggers_list} ${member_index_list}=${EMPTY} FOR ${logger} IN @{loggers_list} - ClusterManagement.Run_Karaf_Command_On_List_Or_All log:set ${log_level} ${logger} member_index_list=${member_index_list} + ClusterManagement.Run_Karaf_Command_On_List_Or_All + ... log:set ${log_level} ${logger} + ... member_index_list=${member_index_list} END Set_Known_Bug_Id - [Arguments] ${id} [Documentation] Tell the Teardown keywords that any failure from now on is due to the specified known bug. + [Arguments] ${id} Set_Suite_Variable ${SetupUtils__Known_Bug_ID} ${id} Set_Unknown_Bug_Id @@ -61,7 +70,9 @@ Set_Unknown_Bug_Id Set_Known_Bug_Id ${EMPTY} SetupUtils__Report_Bugs_Causing_Failure - BuiltIn.Run_Keyword_If '${SetupUtils__Known_Bug_ID}' != '' Utils.Report_Failure_Due_To_Bug ${SetupUtils__Known_Bug_ID} + IF '${SetupUtils__Known_Bug_ID}' != '' + Utils.Report_Failure_Due_To_Bug ${SetupUtils__Known_Bug_ID} + END BuiltIn.Run_Keyword_And_Return_If '${SetupUtils__Known_Bug_ID}' != '' Set_Known_Bug_Id ${EMPTY} Utils.Report_Failure_And_Point_To_Linked_Bugs diff --git a/csit/libraries/ShardStability.robot b/csit/libraries/ShardStability.robot index 44ab75f403..26ef6cdda4 100644 --- a/csit/libraries/ShardStability.robot +++ b/csit/libraries/ShardStability.robot @@ -1,83 +1,119 @@ *** Settings *** -Documentation Robot library to monitor shard stability. +Documentation Robot library to monitor shard stability. ... -... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... -... This is a "stateful" library to monitor shard leaders and candidates. During the initial phase -... all leaders and followeres are stored and then checked with new value on verify. -... TODO: investigate whether pure stateless library would be easier or harder to use. +... This is a "stateful" library to monitor shard leaders and candidates. During the initial phase +... all leaders and followeres are stored and then checked with new value on verify. +... TODO: investigate whether pure stateless library would be easier or harder to use. ... -... Requirements: ClusterManagement.ClusterManagement_Setup must be called before Shard_Stability_Init +... Requirements: ClusterManagement.ClusterManagement_Setup must be called before Shard_Stability_Init ... -... It is possible to use it for stateless comparison. -... Variable @{DEFAULT_SHARD_LIST} contains default module shards. -Library Collections -Library String -Resource ${CURDIR}/ClusterManagement.robot +... It is possible to use it for stateless comparison. +... Variable @{DEFAULT_SHARD_LIST} contains default module shards. + +Library Collections +Library String +Resource ${CURDIR}/ClusterManagement.robot + *** Variables *** &{stored_details} -@{DEFAULT_SHARD_LIST} default:config default:operational topology:config topology:operational inventory:config inventory:operational entity-ownership:operational +@{DEFAULT_SHARD_LIST} +... default:config +... default:operational +... topology:config +... topology:operational +... inventory:config +... inventory:operational +... entity-ownership:operational + *** Keywords *** Shards_Stability_Init_Details - [Arguments] ${shard_list} ${member_index_list}=${EMPTY} [Documentation] Initialize data for given shards. ... ${shard_list} should be initialized as @{list} shard_name1:shard_type1 shard_name2:shard.. + [Arguments] ${shard_list} ${member_index_list}=${EMPTY} ${shards_details} = Shards_Stability_Get_Details ${shard_list} member_index_list=${member_index_list} BuiltIn.Set_Suite_Variable ${stored_details} ${shards_details} Shards_Stability_Get_Details - [Arguments] ${shard_list} ${member_index_list}=${EMPTY} ${verify_restconf}=False ${http_timeout}=${EMPTY} [Documentation] Return shard details stored in dictionary. ... ${shard_list} should be initialized as @{list} shard_name1:shard_type1 shard_name2:shard.. - &{shards_details} BuiltIn.Create_Dictionary - CompareStream.Run_Keyword_If_At_Least_Phosphorus Collections.Remove_Values_From_List ${shard_list} entity-ownership:operational + [Arguments] ${shard_list} ${member_index_list}=${EMPTY} ${verify_restconf}=False ${http_timeout}=${EMPTY} + &{shards_details} = BuiltIn.Create_Dictionary + CompareStream.Run_Keyword_If_At_Least_Phosphorus + ... Collections.Remove_Values_From_List + ... ${shard_list} + ... entity-ownership:operational FOR ${shard_details} IN @{shard_list} - ${shard_name} ${shard_type} String.Split_String ${shard_details} separator=: - ${leader} ${followers} ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=${shard_name} shard_type=${shard_type} member_index_list=${member_index_list} - ... verify_restconf=${verify_restconf} http_timeout=${http_timeout} + ${shard_name} ${shard_type} = String.Split_String ${shard_details} separator=: + ${leader} ${followers} = ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=${shard_name} + ... shard_type=${shard_type} + ... member_index_list=${member_index_list} + ... verify_restconf=${verify_restconf} + ... http_timeout=${http_timeout} Collections.Sort_List ${followers} Collections.Set_To_Dictionary ${shards_details} ${shard_name}_${shard_type}_leader=${leader} Collections.Set_To_Dictionary ${shards_details} ${shard_name}_${shard_type}_followers=${followers} END - BuiltIn.Return_From_Keyword ${shards_details} + RETURN ${shards_details} Shards_Stability_Verify - [Arguments] ${shard_list} ${member_index_list}=${EMPTY} [Documentation] Verify that present details as the same as the stored one from Shards_Stability_Init_Details + [Arguments] ${shard_list} ${member_index_list}=${EMPTY} ${present_details} = Shards_Stability_Get_Details ${shard_list} member_index_list=${member_index_list} Shards_Stability_Compare_Same ${present_details} Shards_Stability_Compare_Same - [Arguments] ${details} ${stateless_details}=${EMPTY} [Documentation] Compare two distionaries created by Shards_Stability_Get_Details - ${exp_details} = BuiltIn.Set_Variable_If "${stateless_details}" == "${EMPTY}" ${stored_details} ${stateless_details} + [Arguments] ${details} ${stateless_details}=${EMPTY} + ${exp_details} = BuiltIn.Set_Variable_If + ... "${stateless_details}" == "${EMPTY}" + ... ${stored_details} + ... ${stateless_details} Collections.Log_Dictionary ${exp_details} Collections.Log_Dictionary ${details} Collections.Dictionaries_Should_Be_Equal ${exp_details} ${details} Set_Shard_Location - [Arguments] ${requested_leader_idx} [Documentation] Move default/topology config/operational shard location to local or remote node as requested ... towards the given member. + [Arguments] ${requested_leader_idx} ClusterAdmin.Make_Leader_Local ${requested_leader_idx} default config ClusterAdmin.Make_Leader_Local ${requested_leader_idx} default operational ClusterAdmin.Make_Leader_Local ${requested_leader_idx} topology config ClusterAdmin.Make_Leader_Local ${requested_leader_idx} topology operational Verify_Shard_Leader_Located_As_Expected - [Arguments] ${expected_leader_idx} ${http_timeout}=${EMPTY} [Documentation] Verify default/topology config/operational shard leader location is as expected - ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=default shard_type=config verify_restconf=False http_timeout=${http_timeout} + [Arguments] ${expected_leader_idx} ${http_timeout}=${EMPTY} + ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=default + ... shard_type=config + ... verify_restconf=False + ... http_timeout=${http_timeout} BuiltIn.Should_Be_Equal_As_Numbers ${expected_leader_idx} ${leader} - ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=default shard_type=operational verify_restconf=False http_timeout=${http_timeout} + ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=default + ... shard_type=operational + ... verify_restconf=False + ... http_timeout=${http_timeout} BuiltIn.Should_Be_Equal_As_Numbers ${expected_leader_idx} ${leader} - ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=topology shard_type=config verify_restconf=False http_timeout=${http_timeout} + ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=topology + ... shard_type=config + ... verify_restconf=False + ... http_timeout=${http_timeout} BuiltIn.Should_Be_Equal_As_Numbers ${expected_leader_idx} ${leader} - ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=topology shard_type=operational verify_restconf=False http_timeout=${http_timeout} + ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=topology + ... shard_type=operational + ... verify_restconf=False + ... http_timeout=${http_timeout} BuiltIn.Should_Be_Equal_As_Numbers ${expected_leader_idx} ${leader} diff --git a/csit/libraries/SubStrings.robot b/csit/libraries/SubStrings.robot index 9db03bce63..1fcdbee33e 100644 --- a/csit/libraries/SubStrings.robot +++ b/csit/libraries/SubStrings.robot @@ -1,17 +1,18 @@ *** Settings *** -Documentation Utility keywords for verification of substring occurrence +Documentation Utility keywords for verification of substring occurrence + *** Keywords *** Should Contain All Sub Strings - [Arguments] ${attr} @{checked} [Documentation] Passes if ${attr} includes all substrings from @{checked}, fails otherwise + [Arguments] ${attr} @{checked} FOR ${item} IN @{checked} Should Contain ${attr} ${item} END Should Not Contain Any Sub Strings - [Arguments] ${attr} @{checked} [Documentation] Fails if ${attr} includes at least one substring from @{checked}, passes otherwise + [Arguments] ${attr} @{checked} FOR ${item} IN @{checked} Should Not Contain ${attr} ${item} END diff --git a/csit/libraries/SwitchUtils.robot b/csit/libraries/SwitchUtils.robot index 34b4c46eac..be60c08380 100644 --- a/csit/libraries/SwitchUtils.robot +++ b/csit/libraries/SwitchUtils.robot @@ -1,41 +1,42 @@ *** Settings *** -Library SSHLibrary -Library Telnet +Library SSHLibrary +Library Telnet -*** Variables *** *** Keywords *** Get Switch Datapath ID - [Arguments] ${switch} [Documentation] Using the connection index for the given switch, will execute the command string ... "datapath_id_output_command" which will store the output in switch.datapath_id_output_string. ... The switch object method "update_datapath_id" is called which is assumed to place the ODL ... friendly (decimal) version of the datapath id in to switch.datapath_id and the value is also ... returned from this keyword. + [Arguments] ${switch} Configure Connection Index And Prompt Wrapper ${switch} Read Wrapper ${switch} - ${switch.datapath_id_output_string}= Execute Command Wrapper ${switch} ${switch.datapath_id_output_command} + ${switch.datapath_id_output_string}= Execute Command Wrapper + ... ${switch} + ... ${switch.datapath_id_output_command} Log ${switch.datapath_id_output_string} Call Method ${switch} update_datapath_id - [Return] ${switch.datapath_id} + RETURN ${switch.datapath_id} Verify Switch In Operational Data Store - [Arguments] ${switch} [Documentation] Verifies the existence of the switch.datapath_id in the operational datastore. - ${resp} RequestsLibrary.Get Request session ${REST_CONTEXT} + [Arguments] ${switch} + ${resp}= RequestsLibrary.Get Request session ${REST_CONTEXT} Log ${resp.text} Should Match Regexp ${resp.text} openflow:${switch.datapath_id} Verify Switch Not In Operational Data Store - [Arguments] ${switch} [Documentation] Verifies that the given switch.datapath_id is not in the operational datastore. - ${resp} RequestsLibrary.Get Request session ${REST_CONTEXT} + [Arguments] ${switch} + ${resp}= RequestsLibrary.Get Request session ${REST_CONTEXT} Log ${resp.text} Should Not Match Regexp ${resp.text} openflow:${switch.datapath_id} Iterate Switch Commands From List - [Arguments] ${switch} ${cmd_list} [Documentation] Each string in the @{cmd_list} argument is executed on the switch.connection_index. + [Arguments] ${switch} ${cmd_list} Configure Connection Index And Prompt Wrapper ${switch} FOR ${cmd} IN @{cmd_list} Log ${cmd} @@ -44,20 +45,26 @@ Iterate Switch Commands From List END Configure OpenFlow - [Arguments] ${switch} [Documentation] The commands neccessary to configure openflow on the given switch object should exist in the switch.base_openflow_config attribute. \ Also, the commands/logic to verify that openflow is working are checked in this keyword and come ... from switch.openflow_validation_cmd output where the validation strings are ... stored in switch.openflow_enable_validations + [Arguments] ${switch} Log Applying configs to configure openflow on the given switch. Configure Connection Index And Prompt Wrapper ${switch} Iterate Switch Commands From List ${switch} ${switch.base_openflow_config} Read Wrapper ${switch} - Wait Until Keyword Succeeds 10s 1s Validate Switch Output ${switch} ${switch.openflow_validation_cmd} ${switch.openflow_enable_validations} + Wait Until Keyword Succeeds + ... 10s + ... 1s + ... Validate Switch Output + ... ${switch} + ... ${switch.openflow_validation_cmd} + ... ${switch.openflow_enable_validations} Read Wrapper ${switch} Validate Switch Output - [Arguments] ${switch} ${cmd} ${validations} ${should_exist}=true [Documentation] A generic keyword that will execute one command on the switch, and check for each string in the @{validations} argument. \ There is a boolean flag ${should_exist} that can be used to check that the validations are or are NOT in the output of the command executed. + [Arguments] ${switch} ${cmd} ${validations} ${should_exist}=true Configure Connection Index And Prompt Wrapper ${switch} Read Wrapper ${switch} ${tmp}= Execute Command Wrapper ${switch} /sbin/ifconfig @@ -65,73 +72,119 @@ Validate Switch Output ${output}= Execute Command Wrapper ${switch} ${cmd} Log ${output} FOR ${str} IN @{validations} - Run Keyword If "${should_exist}" == "true" Should Match Regexp ${output} ${str} - Run Keyword If "${should_exist}" == "false" Should Not Match Regexp ${output} ${str} + IF "${should_exist}" == "true" + Should Match Regexp ${output} ${str} + END + IF "${should_exist}" == "false" + Should Not Match Regexp ${output} ${str} + END END Enable OpenFlow - [Arguments] ${switch} [Documentation] executes the switch.openflow_enable_config on the given switch and validates that openflow is operational with the switch.openflow_validation_command against all the strings in the switch.openflow_enable_validations list. + [Arguments] ${switch} Log Will toggle openflow to be ON Iterate Switch Commands From List ${switch} ${switch.openflow_enable_config} Read Wrapper ${switch} - Wait Until Keyword Succeeds 10s 1s Validate Switch Output ${switch} ${switch.openflow_validation_cmd} ${switch.openflow_enable_validations} + Wait Until Keyword Succeeds + ... 10s + ... 1s + ... Validate Switch Output + ... ${switch} + ... ${switch.openflow_validation_cmd} + ... ${switch.openflow_enable_validations} Disable OpenFlow - [Arguments] ${switch} [Documentation] executes the switch.openflow_disable_config on the given switch and validates that openflow is NOT operational with the switch.openflow_validation_command against all the strings in the switch.openflow_disable_validations list. + [Arguments] ${switch} Log Will toggle openflow to be OFF Iterate Switch Commands From List ${switch} ${switch.openflow_disable_config} Read Wrapper ${switch} - Wait Until Keyword Succeeds 10s 1s Validate Switch Output ${switch} ${switch.openflow_validation_cmd} ${switch.openflow_disable_validations} + Wait Until Keyword Succeeds + ... 10s + ... 1s + ... Validate Switch Output + ... ${switch} + ... ${switch.openflow_validation_cmd} + ... ${switch.openflow_disable_validations} Open Connection Wrapper - [Arguments] ${switch} [Documentation] Some switches require telnet access and others require ssh access. \ Based on the ... switch.mgmt_protocol, the connection open will be handled by the right robot ... library (Telnet or SSHLibrary). \ The connection_index is returned. - Run Keyword If "${switch.mgmt_protocol}" == "ssh" Call Method ${switch} set_ssh_key ${USER_HOME}/.ssh/${SSH_KEY} - Run Keyword If "${switch.mgmt_protocol}" == "ssh" Call Method ${switch} set_mgmt_user ${TOOLS_SYSTEM_USER} - ${connection_index}= Run Keyword If "${switch.mgmt_protocol}" == "ssh" SSHLibrary.Open Connection ${switch.mgmt_ip} prompt=${switch.mgmt_prompt} timeout=30s - Run Keyword If "${switch.mgmt_protocol}" == "ssh" Login With Public Key ${switch.mgmt_user} ${switch.ssh_key} any - ${connection_index}= Run Keyword If "${switch.mgmt_protocol}" == "telnet" Telnet.Open Connection ${switch.mgmt_ip} - ... ELSE Set Variable ${connection_index} - [Return] ${connection_index} + [Arguments] ${switch} + IF "${switch.mgmt_protocol}" == "ssh" + Call Method ${switch} set_ssh_key ${USER_HOME}/.ssh/${SSH_KEY} + END + IF "${switch.mgmt_protocol}" == "ssh" + Call Method ${switch} set_mgmt_user ${TOOLS_SYSTEM_USER} + END + IF "${switch.mgmt_protocol}" == "ssh" + ${connection_index}= SSHLibrary.Open Connection + ... ${switch.mgmt_ip} + ... prompt=${switch.mgmt_prompt} + ... timeout=30s + ELSE + ${connection_index}= Set Variable ${None} + END + IF "${switch.mgmt_protocol}" == "ssh" + Login With Public Key ${switch.mgmt_user} ${switch.ssh_key} any + END + IF "${switch.mgmt_protocol}" == "telnet" + ${connection_index}= Telnet.Open Connection ${switch.mgmt_ip} + ELSE + ${connection_index}= Set Variable ${connection_index} + END + RETURN ${connection_index} Configure Connection Index And Prompt Wrapper - [Arguments] ${switch} [Documentation] when using multiple switch connections (e.g. more than one switch device) this keyword will switch the current connection index and prompt so that the following ... Read or Write actions happen on the correct device. - Run Keyword If "${switch.mgmt_protocol}" == "ssh" SSHLibrary.Switch Connection ${switch.connection_index} - Run Keyword If "${switch.mgmt_protocol}" == "ssh" SSHLibrary.Set Client Configuration prompt=${switch.mgmt_prompt} timeout=5s - Run Keyword If "${switch.mgmt_protocol}" == "telnet" Telnet.Switch Connection ${switch.connection_index} - Run Keyword If "${switch.mgmt_protocol}" == "telnet" Telnet.Set Prompt ${switch.mgmt_prompt} True + [Arguments] ${switch} + IF "${switch.mgmt_protocol}" == "ssh" + SSHLibrary.Switch Connection ${switch.connection_index} + END + IF "${switch.mgmt_protocol}" == "ssh" + SSHLibrary.Set Client Configuration prompt=${switch.mgmt_prompt} timeout=5s + END + IF "${switch.mgmt_protocol}" == "telnet" + Telnet.Switch Connection ${switch.connection_index} + END + IF "${switch.mgmt_protocol}" == "telnet" + Telnet.Set Prompt ${switch.mgmt_prompt} True + END Read Wrapper - [Arguments] ${switch} [Documentation] Wraps the Read command so that depending on the switch.mgmt_protocol the right ... library (Telnet or SSHLibrary) is used. - Run Keyword If "${switch.mgmt_protocol}" == "ssh" SSHLibrary.Read - Run Keyword If "${switch.mgmt_protocol}" == "telnet" Telnet.Read + [Arguments] ${switch} + IF "${switch.mgmt_protocol}" == "ssh" SSHLibrary.Read + IF "${switch.mgmt_protocol}" == "telnet" Telnet.Read Write Bare Wrapper - [Arguments] ${switch} ${cmd} [Documentation] Wraps the Write Bare command so that depending on the switch.mgmt_protocol the right ... library (Telnet or SSHLibrary) is used. - Run Keyword If "${switch.mgmt_protocol}" == "ssh" SSHLibrary.Write Bare ${cmd} - Run Keyword If "${switch.mgmt_protocol}" == "telnet" Telnet.Write Bare ${cmd} + [Arguments] ${switch} ${cmd} + IF "${switch.mgmt_protocol}" == "ssh" SSHLibrary.Write Bare ${cmd} + IF "${switch.mgmt_protocol}" == "telnet" Telnet.Write Bare ${cmd} Execute Command Wrapper - [Arguments] ${switch} ${cmd} [Documentation] Wraps the Execute Command keyword so that depending on the switch.mgmt_protocol the right ... library (Telnet or SSHLibrary) is used. - ${output}= Run Keyword If "${switch.mgmt_protocol}" == "ssh" SSHLibrary.Execute Command ${cmd} - ${output}= Run Keyword If "${switch.mgmt_protocol}" == "telnet" Telnet.Execute Command ${cmd} - ... ELSE Set Variable ${output} - [Return] ${output} + [Arguments] ${switch} ${cmd} + IF "${switch.mgmt_protocol}" == "ssh" + ${output}= SSHLibrary.Execute Command ${cmd} + ELSE + ${output}= Set Variable ${None} + END + IF "${switch.mgmt_protocol}" == "telnet" + ${output}= Telnet.Execute Command ${cmd} + ELSE + ${output}= Set Variable ${output} + END + RETURN ${output} Connect To Switch - [Arguments] ${switch} [Documentation] Will Open a connection to the switch, which will set the switch.connection_index. ... For each switch.connection_configs string, a write bare will be executed on the ... switch connection. \ The write bare is done becuase some switch consoles require @@ -139,6 +192,7 @@ Connect To Switch ... be sufficient to put the switch console in to a usuable state so that further ... interactions with the switch can be used with the robot keyword "Execute ... Command" + [Arguments] ${switch} ${connection_index}= Open Connection Wrapper ${switch} Call Method ${switch} set_connection_index ${connection_index} Configure Connection Index And Prompt Wrapper ${switch} @@ -149,16 +203,16 @@ Connect To Switch END Cleanup Switch - [Arguments] ${switch} [Documentation] will execute and command strings stored in switch.cleanup_cmds + [Arguments] ${switch} Iterate Switch Commands From List ${switch} ${switch.cleanup_cmds} Initialize Switch - [Arguments] ${switch} [Documentation] Will connect and execute all switch.initialization_cmds on the given switch. ... In some cases, this may be a reboot. \ If so, the switch.initialization_type can ... be set to "reboot" and further logic is invoked to wait for the reboot to complete ... and a reconnect to the switch is made. + [Arguments] ${switch} Connect To Switch ${switch} Configure Connection Index And Prompt Wrapper ${switch} FOR ${cmd} IN @{switch.initialization_cmds} @@ -166,18 +220,25 @@ Initialize Switch Sleep 1 Run Keyword And Ignore Error Read Wrapper ${switch} END - Run Keyword If "${switch.initialization_type}" == "reboot" Wait For Switch Reboot ${switch} - Run Keyword If "${switch.initialization_type}" == "reboot" Connect To Switch ${switch} + IF "${switch.initialization_type}" == "reboot" + Wait For Switch Reboot ${switch} + END + IF "${switch.initialization_type}" == "reboot" + Connect To Switch ${switch} + END Wait For Switch Reboot - [Arguments] ${switch} [Documentation] If a switch has been set to reboot, it may take some time. \ This keyword will first ... make sure the switch has gone down (10 pings over 10 seconds should not see ... a 100% success, although it may respond for a short time after the reload is ... issued). \ Then a poll is done with a single ping request every 5s until a success ... is found, at which point it is assumed the switch is up and ready. + [Arguments] ${switch} ${output}= Run ping ${switch.mgmt_ip} -c 10 -W 1 - Should Not Contain ${output} 10 packets transmitted, 10 received, 0% packet loss Does not appear that switch has rebooted + Should Not Contain + ... ${output} + ... 10 packets transmitted, 10 received, 0% packet loss + ... Does not appear that switch has rebooted Wait Until Keyword Succeeds 240s 5s Ping ${switch.mgmt_ip} Ping diff --git a/csit/libraries/SxpBindingOriginsLib.robot b/csit/libraries/SxpBindingOriginsLib.robot index 8d8d837727..b41da8071d 100644 --- a/csit/libraries/SxpBindingOriginsLib.robot +++ b/csit/libraries/SxpBindingOriginsLib.robot @@ -1,47 +1,70 @@ *** Settings *** -Documentation Library containing Keywords used for SXP binding origins testing -Library ./Sxp.py -Resource ./SxpLib.robot +Documentation Library containing Keywords used for SXP binding origins testing + +Library ./Sxp.py +Resource ./SxpLib.robot + *** Variables *** -${CONFIG_REST_CONTEXT} /restconf/operations/sxp-config-controller +${CONFIG_REST_CONTEXT} /restconf/operations/sxp-config-controller + *** Keywords *** Revert To Default Binding Origins Configuration - [Arguments] ${session}=session [Documentation] Remove CLUSTER binding origin and set default priorities to default origins + [Arguments] ${session}=session BuiltIn.Run Keyword And Ignore Error SxpBindingOriginsLib.Delete Binding Origin CLUSTER session=${session} - BuiltIn.Run Keyword And Ignore Error SxpBindingOriginsLib.Update Binding Origin LOCAL 1 session=${session} - BuiltIn.Run Keyword And Ignore Error SxpBindingOriginsLib.Update Binding Origin NETWORK 2 session=${session} + BuiltIn.Run Keyword And Ignore Error + ... SxpBindingOriginsLib.Update Binding Origin + ... LOCAL + ... 1 + ... session=${session} + BuiltIn.Run Keyword And Ignore Error + ... SxpBindingOriginsLib.Update Binding Origin + ... NETWORK + ... 2 + ... session=${session} Get Binding Origins - [Arguments] ${session}=session [Documentation] Gets all binding origins via RPC from configuration + [Arguments] ${session}=session ${resp} = RequestsLibrary.Get Request ${session} /restconf/config/sxp-config:binding-origins BuiltIn.Should Be Equal As Strings ${resp.status_code} 200 - [Return] ${resp} + RETURN ${resp} Add Binding Origin - [Arguments] ${origin} ${priority} ${session}=session [Documentation] Add custom binding origin to configuration + [Arguments] ${origin} ${priority} ${session}=session ${data} = Sxp.Add Binding Origin Xml ${origin} ${priority} - SxpLib.Post To Controller ${session} path=add-binding-origin data=${data} rest_context=${CONFIG_REST_CONTEXT} + SxpLib.Post To Controller + ... ${session} + ... path=add-binding-origin + ... data=${data} + ... rest_context=${CONFIG_REST_CONTEXT} Update Binding Origin - [Arguments] ${origin} ${priority} ${session}=session [Documentation] Update binding origin in configuration + [Arguments] ${origin} ${priority} ${session}=session ${data} = Sxp.Update Binding Origin Xml ${origin} ${priority} - SxpLib.Post To Controller ${session} path=update-binding-origin data=${data} rest_context=${CONFIG_REST_CONTEXT} + SxpLib.Post To Controller + ... ${session} + ... path=update-binding-origin + ... data=${data} + ... rest_context=${CONFIG_REST_CONTEXT} Delete Binding Origin - [Arguments] ${origin} ${session}=session [Documentation] Delete custom binding origin from configuration + [Arguments] ${origin} ${session}=session ${data} = Sxp.Delete Binding Origin Xml ${origin} - SxpLib.Post To Controller ${session} path=delete-binding-origin data=${data} rest_context=${CONFIG_REST_CONTEXT} + SxpLib.Post To Controller + ... ${session} + ... path=delete-binding-origin + ... data=${data} + ... rest_context=${CONFIG_REST_CONTEXT} Should Contain Binding Origins - [Arguments] @{origins} [Documentation] Test if data contain specified binding origins + [Arguments] @{origins} ${resp} = SxpBindingOriginsLib.Get Binding Origins FOR ${origin} IN @{origins} ${out} = Sxp.Find Binding Origin ${resp.json()} ${origin} @@ -49,8 +72,8 @@ Should Contain Binding Origins END Should Not Contain Binding Origins - [Arguments] @{origins} [Documentation] Test if data DONT contain specified binding origins + [Arguments] @{origins} ${resp} = SxpBindingOriginsLib.Get Binding Origins FOR ${origin} IN @{origins} ${out} = Sxp.Find Binding Origin ${resp.json()} ${origin} @@ -58,8 +81,8 @@ Should Not Contain Binding Origins END Should Contain Binding Origin With Priority - [Arguments] ${origin} ${priority} [Documentation] Test if data contain specified binding origin with desired priority + [Arguments] ${origin} ${priority} ${resp} = SxpBindingOriginsLib.Get Binding Origins ${out} = Sxp.Find Binding Origin With Priority ${resp.json()} ${origin} ${priority} BuiltIn.Should Be True ${out} Missing origin: ${origin} with priority: ${priority} in ${resp} diff --git a/csit/libraries/SxpClusterLib.robot b/csit/libraries/SxpClusterLib.robot index edb25ef1a7..dec6a0f8b1 100644 --- a/csit/libraries/SxpClusterLib.robot +++ b/csit/libraries/SxpClusterLib.robot @@ -1,25 +1,28 @@ *** Settings *** -Documentation Library containing Keywords used for SXP cluster testing -Library Collections -Library RequestsLibrary -Resource ./ClusterManagement.robot -Resource ./CompareStream.robot -Resource ./SetupUtils.robot -Resource ./SxpLib.robot +Documentation Library containing Keywords used for SXP cluster testing + +Library Collections +Library RequestsLibrary +Resource ./ClusterManagement.robot +Resource ./CompareStream.robot +Resource ./SetupUtils.robot +Resource ./SxpLib.robot + *** Variables *** -@{SHARD_OPER_LIST} inventory topology default entity-ownership -@{SHARD_CONF_LIST} inventory topology default -@{SXP_PACKAGE} org.opendaylight.sxp -${DEVICE_SESSION} device_1 -${CONTROLLER_SESSION} ClusterManagement__session_1 -${VIRTUAL_IP} ${TOOLS_SYSTEM_2_IP} -${VIRTUAL_IP_MASK} 255.255.255.0 -${VIRTUAL_INTERFACE} dummy0 -${MAC_ADDRESS_TABLE} &{EMPTY} -${DEVICE_NODE_ID} ${TOOLS_SYSTEM_IP} -${CLUSTER_NODE_ID} ${TOOLS_SYSTEM_2_IP} -${INADDR_ANY} 0.0.0.0 +@{SHARD_OPER_LIST} inventory topology default entity-ownership +@{SHARD_CONF_LIST} inventory topology default +@{SXP_PACKAGE} org.opendaylight.sxp +${DEVICE_SESSION} device_1 +${CONTROLLER_SESSION} ClusterManagement__session_1 +${VIRTUAL_IP} ${TOOLS_SYSTEM_2_IP} +${VIRTUAL_IP_MASK} 255.255.255.0 +${VIRTUAL_INTERFACE} dummy0 +${MAC_ADDRESS_TABLE} &{EMPTY} +${DEVICE_NODE_ID} ${TOOLS_SYSTEM_IP} +${CLUSTER_NODE_ID} ${TOOLS_SYSTEM_2_IP} +${INADDR_ANY} 0.0.0.0 + *** Keywords *** Setup SXP Cluster Session @@ -30,7 +33,12 @@ Setup SXP Cluster Session Setup Device Session [Documentation] Create session on the SXP device - RequestsLibrary.Create Session ${DEVICE_SESSION} url=http://${DEVICE_NODE_ID}:${RESTCONFPORT} auth=${AUTH} timeout=${DEFAULT_TIMEOUT_HTTP} max_retries=0 + RequestsLibrary.Create Session + ... ${DEVICE_SESSION} + ... url=http://${DEVICE_NODE_ID}:${RESTCONFPORT} + ... auth=${AUTH} + ... timeout=${DEFAULT_TIMEOUT_HTTP} + ... max_retries=0 Setup SXP Cluster Session With Device [Documentation] Create sessions asociated with SXP cluster setup and one SXP device @@ -40,24 +48,41 @@ Setup SXP Cluster Session With Device Clean SXP Cluster Session [Documentation] Clean sessions asociated with SXP cluster setup ClusterManagement.Flush_Iptables_From_List_Or_All - BuiltIn.Wait Until Keyword Succeeds 60x 1s ClusterManagement.Verify_Members_Are_Ready member_index_list=${EMPTY} verify_cluster_sync=True verify_restconf=True - ... verify_system_status=False service_list=@{EMPTY} + BuiltIn.Wait Until Keyword Succeeds + ... 60x + ... 1s + ... ClusterManagement.Verify_Members_Are_Ready + ... member_index_list=${EMPTY} + ... verify_cluster_sync=True + ... verify_restconf=True + ... verify_system_status=False + ... service_list=@{EMPTY} RequestsLibrary.Delete All Sessions SetupUtils.Setup_Logging_For_Debug_Purposes_On_List_Or_All INFO ${SXP_PACKAGE} Check Shards Status [Documentation] Check Status for all shards in SXP application. ClusterManagement.Check_Cluster_Is_In_Sync - CompareStream.Run_Keyword_If_At_Least_Phosphorus Collections.Remove Values From List ${SHARD_OPER_LIST} entity-ownership + CompareStream.Run_Keyword_If_At_Least_Phosphorus + ... Collections.Remove Values From List + ... ${SHARD_OPER_LIST} + ... entity-ownership Log ${SHARD_OPER_LIST} - ClusterManagement.Verify_Leader_Exists_For_Each_Shard shard_name_list=${SHARD_OPER_LIST} shard_type=operational + ClusterManagement.Verify_Leader_Exists_For_Each_Shard + ... shard_name_list=${SHARD_OPER_LIST} + ... shard_type=operational ClusterManagement.Verify_Leader_Exists_For_Each_Shard shard_name_list=${SHARD_CONF_LIST} shard_type=config Setup SXP Cluster - [Arguments] ${peer_mode}=listener [Documentation] Setup and connect SXP cluster topology + [Arguments] ${peer_mode}=listener SxpLib.Add Node ${DEVICE_NODE_ID} session=${DEVICE_SESSION} - BuiltIn.Wait Until Keyword Succeeds 240x 1s SxpLib.Check Node Started ${DEVICE_NODE_ID} session=${DEVICE_SESSION} + BuiltIn.Wait Until Keyword Succeeds + ... 240x + ... 1s + ... SxpLib.Check Node Started + ... ${DEVICE_NODE_ID} + ... session=${DEVICE_SESSION} FOR ${i} IN RANGE ${NUM_ODL_SYSTEM} SxpLib.Add Connection version4 ${peer_mode} ${ODL_SYSTEM_${i+1}_IP} 64999 node=${DEVICE_NODE_ID} ... session=${DEVICE_SESSION} @@ -65,128 +90,206 @@ Setup SXP Cluster ${cluster_mode} = Sxp.Get Opposing Mode ${peer_mode} SxpLib.Add Node ${INADDR_ANY} session=${CONTROLLER_SESSION} BuiltIn.Wait Until Keyword Succeeds 240x 1s Check Cluster Node Started ${INADDR_ANY} ip=${EMPTY} - SxpLib.Add Connection version4 ${cluster_mode} ${DEVICE_NODE_ID} 64999 ${INADDR_ANY} session=${CONTROLLER_SESSION} - BuiltIn.Wait Until Keyword Succeeds 480x 1s Check Device is Connected ${DEVICE_NODE_ID} session=${DEVICE_SESSION} + SxpLib.Add Connection + ... version4 + ... ${cluster_mode} + ... ${DEVICE_NODE_ID} + ... 64999 + ... ${INADDR_ANY} + ... session=${CONTROLLER_SESSION} + BuiltIn.Wait Until Keyword Succeeds + ... 480x + ... 1s + ... Check Device is Connected + ... ${DEVICE_NODE_ID} + ... session=${DEVICE_SESSION} Clean SXP Cluster [Documentation] Disconnect SXP cluster topology SxpLib.Delete Node ${DEVICE_NODE_ID} session=${DEVICE_SESSION} - BuiltIn.Wait Until Keyword Succeeds 240x 1s SxpLib.Check Node Stopped ${DEVICE_NODE_ID} session=${DEVICE_SESSION} - BuiltIn.Wait Until Keyword Succeeds 60x 1s SxpLib.Delete Node ${INADDR_ANY} session=${CONTROLLER_SESSION} - BuiltIn.Wait Until Keyword Succeeds 240x 1s SxpClusterLib.Check Cluster Node Stopped ${INADDR_ANY} ip=${EMPTY} + BuiltIn.Wait Until Keyword Succeeds + ... 240x + ... 1s + ... SxpLib.Check Node Stopped + ... ${DEVICE_NODE_ID} + ... session=${DEVICE_SESSION} + BuiltIn.Wait Until Keyword Succeeds + ... 60x + ... 1s + ... SxpLib.Delete Node + ... ${INADDR_ANY} + ... session=${CONTROLLER_SESSION} + BuiltIn.Wait Until Keyword Succeeds + ... 240x + ... 1s + ... SxpClusterLib.Check Cluster Node Stopped + ... ${INADDR_ANY} + ... ip=${EMPTY} Check Cluster Node Started - [Arguments] ${node} ${port}=64999 ${ip}=${node} [Documentation] Verify that SxpNode has data written to Operational datastore and Node is running on one of cluster nodes - ${resp} = RequestsLibrary.Get Request ${CONTROLLER_SESSION} /restconf/operational/network-topology:network-topology/topology/sxp/node/${node}/ + [Arguments] ${node} ${port}=64999 ${ip}=${node} + ${resp} = RequestsLibrary.Get Request + ... ${CONTROLLER_SESSION} + ... /restconf/operational/network-topology:network-topology/topology/sxp/node/${node}/ BuiltIn.Should Be Equal As Strings ${resp.status_code} 200 ${started} = BuiltIn.Set Variable ${False} FOR ${i} IN RANGE ${NUM_ODL_SYSTEM} - ${rc} = Utils.Run Command On Remote System ${ODL_SYSTEM_${i+1}_IP} netstat -tln | grep -q ${ip}:${port} && echo 0 || echo 1 ${ODL_SYSTEM_USER} ${ODL_SYSTEM_PASSWORD} + ${rc} = Utils.Run Command On Remote System + ... ${ODL_SYSTEM_${i+1}_IP} + ... netstat -tln | grep -q ${ip}:${port} && echo 0 || echo 1 + ... ${ODL_SYSTEM_USER} + ... ${ODL_SYSTEM_PASSWORD} ... prompt=${ODL_SYSTEM_PROMPT} ${started} = BuiltIn.Set Variable If '${rc}' == '0' ${True} ${started} END BuiltIn.Should Be True ${started} Check Cluster Node Stopped - [Arguments] ${node} ${port}=64999 ${ip}=${node} [Documentation] Verify that SxpNode has data removed from Operational datastore and Node is stopped - ${resp} = RequestsLibrary.Get Request ${CONTROLLER_SESSION} /restconf/operational/network-topology:network-topology/topology/sxp/node/${node}/ + [Arguments] ${node} ${port}=64999 ${ip}=${node} + ${resp} = RequestsLibrary.Get Request + ... ${CONTROLLER_SESSION} + ... /restconf/operational/network-topology:network-topology/topology/sxp/node/${node}/ BuiltIn.Should Be Equal As Strings ${resp.status_code} 404 ${stopped} = BuiltIn.Set Variable ${False} FOR ${i} IN RANGE ${NUM_ODL_SYSTEM} - ${rc} = Utils.Run Command On Remote System ${ODL_SYSTEM_${i+1}_IP} netstat -tln | grep -q ${ip}:${port} && echo 0 || echo 1 ${ODL_SYSTEM_USER} ${ODL_SYSTEM_PASSWORD} + ${rc} = Utils.Run Command On Remote System + ... ${ODL_SYSTEM_${i+1}_IP} + ... netstat -tln | grep -q ${ip}:${port} && echo 0 || echo 1 + ... ${ODL_SYSTEM_USER} + ... ${ODL_SYSTEM_PASSWORD} ... prompt=${ODL_SYSTEM_PROMPT} ${stopped} = BuiltIn.Set Variable If '${rc}' == '1' ${True} ${stopped} END BuiltIn.Should Be True ${stopped} Check Device is Connected - [Arguments] ${node} ${version}=version4 ${port}=64999 ${session}=session [Documentation] Checks if SXP device is connected to the cluster. It means it has connection in state "on" with one of the cluster members. + [Arguments] ${node} ${version}=version4 ${port}=64999 ${session}=session ${resp} = SxpLib.Get Connections node=${node} session=${session} ${is_connected} = BuiltIn.Set Variable ${False} FOR ${i} IN RANGE ${NUM_ODL_SYSTEM} ${is_connected} = Sxp.Find Connection ${resp} ${version} any ${ODL_SYSTEM_${i+1}_IP} ... ${port} on - BuiltIn.Exit For Loop If ${is_connected} + IF ${is_connected} BREAK END BuiltIn.Should Be True ${is_connected} Check Cluster is Connected - [Arguments] ${node} ${version}=version4 ${port}=64999 ${mode}=speaker ${session}=session [Documentation] Get SXP connections of cluster ${node} and verify that they contain a connection to the device ${DEVICE_NODE_ID} in state "on" + [Arguments] ${node} ${version}=version4 ${port}=64999 ${mode}=speaker ${session}=session ${resp} = SxpLib.Get Connections node=${node} session=${session} SxpLib.Should Contain Connection ${resp} ${DEVICE_NODE_ID} ${port} ${mode} ${version} on Get Owner Controller - [Arguments] ${running_member}=1 [Documentation] Find cluster controller that is marked as cluster owner by requesting ownership data from ${running_member} node of the cluster - ${owner} ${candidates} = BuiltIn.Wait Until Keyword Succeeds 60x 1s ClusterManagement.Get_Owner_And_Successors_For_Device org.opendaylight.sxp.controller.boot.SxpControllerInstance - ... Sxp ${running_member} - [Return] ${owner} + [Arguments] ${running_member}=1 + ${owner} ${candidates} = BuiltIn.Wait Until Keyword Succeeds + ... 60x + ... 1s + ... ClusterManagement.Get_Owner_And_Successors_For_Device + ... org.opendaylight.sxp.controller.boot.SxpControllerInstance + ... Sxp + ... ${running_member} + RETURN ${owner} Get Not Owner Controller [Documentation] Find cluster controller that is not marked as owner for SXP service in cluster ${owner_controller} = Get Owner Controller - ${controller} = BuiltIn.Evaluate random.choice( filter( lambda i: i!=${owner_controller}, range(1, ${NUM_ODL_SYSTEM} + 1))) random - [Return] ${controller} + ${controller} = BuiltIn.Evaluate + ... random.choice( filter( lambda i: i!=${owner_controller}, range(1, ${NUM_ODL_SYSTEM} + 1))) + ... random + RETURN ${controller} Get Any Controller [Documentation] Get any controller from cluster range ${follower} = BuiltIn.Evaluate random.choice( range(1, ${NUM_ODL_SYSTEM} + 1)) random - [Return] ${follower} + RETURN ${follower} Map Followers To Mac Addresses [Documentation] Creates Map containing ODL_SYSTEM_IP to corresponding MAC-ADDRESS ${mac_addresses} = BuiltIn.Create dictionary FOR ${i} IN RANGE ${NUM_ODL_SYSTEM} - ${mac_address} Find Mac Address Of Ip Address ${ODL_SYSTEM_${i+1}_IP} + ${mac_address} = Find Mac Address Of Ip Address ${ODL_SYSTEM_${i+1}_IP} Collections.Set To Dictionary ${mac_addresses} ${ODL_SYSTEM_${i+1}_IP} ${mac_address} END BuiltIn.Log ${mac_addresses} - [Return] ${mac_addresses} + RETURN ${mac_addresses} Find Mac Address Of Ip Address - [Arguments] ${ip} [Documentation] Finds out MAC-ADDRESS of specified IP by pinging it from TOOLS_SYSTEM machine - ${mac_address} = Utils.Run Command On Remote System And Log ${TOOLS_SYSTEM_IP} ping -c 10 -W 10 ${ip} >/dev/null && sudo ip neighbor show ${ip} | awk '{print $5}' ${TOOLS_SYSTEM_USER} ${TOOLS_SYSTEM_PASSWORD} - [Return] ${mac_address} + [Arguments] ${ip} + ${mac_address} = Utils.Run Command On Remote System And Log + ... ${TOOLS_SYSTEM_IP} + ... ping -c 10 -W 10 ${ip} >/dev/null && sudo ip neighbor show ${ip} | awk '{print $5}' + ... ${TOOLS_SYSTEM_USER} + ... ${TOOLS_SYSTEM_PASSWORD} + RETURN ${mac_address} Ip Addres Should Not Be Routed To Follower - [Arguments] ${mac_addresses} ${ip_address} ${follower_index} [Documentation] Verify that IP-ADDRESS is not routed to follower specified by ID - ${mac_address_assigned} = Collections.Get From Dictionary ${mac_addresses} ${ODL_SYSTEM_${follower_index}_IP} + [Arguments] ${mac_addresses} ${ip_address} ${follower_index} + ${mac_address_assigned} = Collections.Get From Dictionary + ... ${mac_addresses} + ... ${ODL_SYSTEM_${follower_index}_IP} ${mac_address_resolved} = Find Mac Address Of Ip Address ${ip_address} BuiltIn.Should Not Be Equal As Strings ${mac_address_assigned} ${mac_address_resolved} Ip Addres Should Be Routed To Follower - [Arguments] ${mac_addresses} ${ip_address} ${follower_index} [Documentation] Verify that IP-ADDRESS is routed to follower specified by ID - ${mac_address_assigned} = Collections.Get From Dictionary ${mac_addresses} ${ODL_SYSTEM_${follower_index}_IP} + [Arguments] ${mac_addresses} ${ip_address} ${follower_index} + ${mac_address_assigned} = Collections.Get From Dictionary + ... ${mac_addresses} + ... ${ODL_SYSTEM_${follower_index}_IP} ${mac_address_resolved} = Find Mac Address Of Ip Address ${ip_address} BuiltIn.Should Not Be Empty ${mac_address_resolved} BuiltIn.Should Be Equal As Strings ${mac_address_assigned} ${mac_address_resolved} Shutdown Tools Node - [Arguments] ${ip_address}=${TOOLS_SYSTEM_2_IP} ${user}=${TOOLS_SYSTEM_USER} ${passwd}=${TOOLS_SYSTEM_PASSWORD} [Documentation] Shutdown Tools node to avoid conflict in resolving virtual ip that is overlaping that node. + [Arguments] ${ip_address}=${TOOLS_SYSTEM_2_IP} ${user}=${TOOLS_SYSTEM_USER} ${passwd}=${TOOLS_SYSTEM_PASSWORD} ${rc} = OperatingSystem.Run And Return Rc ping -q -c 3 ${ip_address} - ${stdout} = BuiltIn.Run Keyword And Return If ${rc} == 0 Utils.Run Command On Remote System ${ip_address} sudo shutdown -P 0 ${user} + ${stdout} = BuiltIn.Run Keyword And Return If + ... ${rc} == 0 + ... Utils.Run Command On Remote System + ... ${ip_address} + ... sudo shutdown -P 0 + ... ${user} ... ${passwd} BuiltIn.Log ${stdout} Create Virtual Interface [Documentation] Create virtual interface on all of the cluster nodes FOR ${i} IN RANGE ${NUM_ODL_SYSTEM} - Utils.Run Command On Remote System ${ODL_SYSTEM_${i+1}_IP} sudo modprobe dummy ${ODL_SYSTEM_USER} ${ODL_SYSTEM_PASSWORD} - Utils.Run Command On Remote System And Log ${ODL_SYSTEM_${i+1}_IP} sudo ip link show ${ODL_SYSTEM_USER} ${ODL_SYSTEM_PASSWORD} + Utils.Run Command On Remote System + ... ${ODL_SYSTEM_${i+1}_IP} + ... sudo modprobe dummy + ... ${ODL_SYSTEM_USER} + ... ${ODL_SYSTEM_PASSWORD} + Utils.Run Command On Remote System And Log + ... ${ODL_SYSTEM_${i+1}_IP} + ... sudo ip link show + ... ${ODL_SYSTEM_USER} + ... ${ODL_SYSTEM_PASSWORD} END Delete Virtual Interface [Documentation] Create virtual interface on all of the cluster nodes FOR ${i} IN RANGE ${NUM_ODL_SYSTEM} - Utils.Run Command On Remote System ${ODL_SYSTEM_${i+1}_IP} sudo ip link delete ${VIRTUAL_INTERFACE} type dummy ${ODL_SYSTEM_USER} ${ODL_SYSTEM_PASSWORD} - Utils.Run Command On Remote System ${ODL_SYSTEM_${i+1}_IP} sudo rmmod dummy ${ODL_SYSTEM_USER} ${ODL_SYSTEM_PASSWORD} - Utils.Run Command On Remote System And Log ${ODL_SYSTEM_${i+1}_IP} sudo ip link show ${ODL_SYSTEM_USER} ${ODL_SYSTEM_PASSWORD} + Utils.Run Command On Remote System + ... ${ODL_SYSTEM_${i+1}_IP} + ... sudo ip link delete ${VIRTUAL_INTERFACE} type dummy + ... ${ODL_SYSTEM_USER} + ... ${ODL_SYSTEM_PASSWORD} + Utils.Run Command On Remote System + ... ${ODL_SYSTEM_${i+1}_IP} + ... sudo rmmod dummy + ... ${ODL_SYSTEM_USER} + ... ${ODL_SYSTEM_PASSWORD} + Utils.Run Command On Remote System And Log + ... ${ODL_SYSTEM_${i+1}_IP} + ... sudo ip link show + ... ${ODL_SYSTEM_USER} + ... ${ODL_SYSTEM_PASSWORD} END diff --git a/csit/libraries/SxpLib.robot b/csit/libraries/SxpLib.robot index 55d7166529..e2f7c61a1c 100644 --- a/csit/libraries/SxpLib.robot +++ b/csit/libraries/SxpLib.robot @@ -1,22 +1,29 @@ *** Settings *** -Documentation Library containing Keywords used for SXP testing -Library Collections -Library RequestsLibrary -Library ./Sxp.py -Resource CompareStream.robot -Resource KarafKeywords.robot -Resource TemplatedRequests.robot -Resource Utils.robot -Resource ../variables/Variables.robot +Documentation Library containing Keywords used for SXP testing + +Library Collections +Library RequestsLibrary +Library ./Sxp.py +Resource CompareStream.robot +Resource KarafKeywords.robot +Resource TemplatedRequests.robot +Resource Utils.robot +Resource ../variables/Variables.robot + *** Variables *** -${REST_CONTEXT} /restconf/operations/sxp-controller +${REST_CONTEXT} /restconf/operations/sxp-controller + *** Keywords *** Post To Controller - [Arguments] ${session} ${path} ${data} ${rest_context}=${REST_CONTEXT} [Documentation] Post request to Controller and checks response - ${resp} = RequestsLibrary.Post Request ${session} ${rest_context}:${path} data=${data} headers=${HEADERS_XML} + [Arguments] ${session} ${path} ${data} ${rest_context}=${REST_CONTEXT} + ${resp} = RequestsLibrary.Post Request + ... ${session} + ... ${rest_context}:${path} + ... data=${data} + ... headers=${HEADERS_XML} Log ${resp.text} Log ${session} Log ${path} @@ -28,86 +35,112 @@ Post To Controller BuiltIn.Should Be True ${result} RPC result is False Add Node + [Documentation] Add node via RPC to ODL [Arguments] ${node} ${password}=${EMPTY} ${version}=version4 ${port}=64999 ${session}=session ${ip}=${node} ... ${ssl_stores}=${EMPTY} ${retry_open_timer}=1 - [Documentation] Add node via RPC to ODL ${data} = Sxp.Add Node Xml ${node} ${port} ${password} ${version} ${ip} ... keystores=${ssl_stores} retry_open_timer=${retry_open_timer} Post To Controller ${session} add-node ${data} Delete Node - [Arguments] ${node} ${session}=session [Documentation] Delete connection via RPC from node + [Arguments] ${node} ${session}=session ${data} = Sxp.Delete Node Xml ${node} Post To Controller ${session} delete-node ${data} Add Connection + [Documentation] Add connection via RPC to node [Arguments] ${version} ${mode} ${ip} ${port} ${node}=127.0.0.1 ${password}=${EMPTY} ... ${session}=session ${domain}=global ${security_mode}=${EMPTY} - [Documentation] Add connection via RPC to node ${data} = Sxp.Add Connection Xml ${version} ${mode} ${ip} ${port} ${node} ... ${password} ${domain} security_mode=${security_mode} Post To Controller ${session} add-connection ${data} Get Connections - [Arguments] ${node}=127.0.0.1 ${session}=session ${domain}=global [Documentation] Gets all connections via RPC from node + [Arguments] ${node}=127.0.0.1 ${session}=session ${domain}=global ${data} = Sxp.Get Connections From Node Xml ${node} ${domain} - ${resp} = RequestsLibrary.Post Request ${session} ${REST_CONTEXT}:get-connections data=${data} headers=${HEADERS_XML} + ${resp} = RequestsLibrary.Post Request + ... ${session} + ... ${REST_CONTEXT}:get-connections + ... data=${data} + ... headers=${HEADERS_XML} BuiltIn.Should be Equal As Strings ${resp.status_code} 200 - [Return] ${resp.text} + RETURN ${resp.text} Delete Connections - [Arguments] ${ip} ${port} ${node}=127.0.0.1 ${session}=session ${domain}=global [Documentation] Delete connection via RPC from node + [Arguments] ${ip} ${port} ${node}=127.0.0.1 ${session}=session ${domain}=global ${data} = Sxp.Delete Connections Xml ${ip} ${port} ${node} ${domain} Post To Controller ${session} delete-connection ${data} Clean Connections - [Arguments] ${node}=127.0.0.1 ${session}=session ${domain}=global [Documentation] Delete all connections via RPC from node + [Arguments] ${node}=127.0.0.1 ${session}=session ${domain}=global ${resp} = Get Connections ${node} ${session} ${domain} @{connections} = Sxp.Parse Connections ${resp} FOR ${connection} IN @{connections} - Delete Connections ${connection['peer-address']} ${connection['tcp-port']} ${node} ${session} ${domain} + Delete Connections + ... ${connection['peer-address']} + ... ${connection['tcp-port']} + ... ${node} + ... ${session} + ... ${domain} END Verify Connection + [Documentation] Verify that connection is ON [Arguments] ${version} ${mode} ${ip} ${port}=64999 ${node}=127.0.0.1 ${state}=on ... ${session}=session ${domain}=global - [Documentation] Verify that connection is ON ${resp} = Get Connections ${node} ${session} ${domain} Should Contain Connection ${resp} ${ip} ${port} ${mode} ${version} ${state} Add Bindings - [Arguments] ${sgt} ${prefixes} ${node}=127.0.0.1 ${session}=session ${domain}=global ${origin}=LOCAL [Documentation] Based on ODL version decide if bindings will be added with or without origin type (introduced in Fluorine) - CompareStream.Run_Keyword_If_At_Least_Fluorine Add Bindings Fluorine ${sgt} ${prefixes} ${node} ${session} ${domain} + [Arguments] ${sgt} ${prefixes} ${node}=127.0.0.1 ${session}=session ${domain}=global ${origin}=LOCAL + CompareStream.Run_Keyword_If_At_Least_Fluorine + ... Add Bindings Fluorine + ... ${sgt} + ... ${prefixes} + ... ${node} + ... ${session} + ... ${domain} ... ${origin} - CompareStream.Run_Keyword_If_At_Most_Oxygen Add Bindings Oxygen ${sgt} ${prefixes} ${node} ${session} ${domain} + CompareStream.Run_Keyword_If_At_Most_Oxygen + ... Add Bindings Oxygen + ... ${sgt} + ... ${prefixes} + ... ${node} + ... ${session} + ... ${domain} Add Bindings Fluorine - [Arguments] ${sgt} ${prefixes} ${node} ${session} ${domain} ${origin} [Documentation] Add/Update one or more bindings with origin type via RPC to Master DB of the node + [Arguments] ${sgt} ${prefixes} ${node} ${session} ${domain} ${origin} ${data} = Sxp.Add Bindings Xml Fluorine ${node} ${domain} ${sgt} ${prefixes} ${origin} Post To Controller ${session} add-bindings ${data} Add Bindings Oxygen - [Arguments] ${sgt} ${prefixes} ${node} ${session} ${domain} [Documentation] Add/Update one or more bindings without origin type via RPC to Master DB of the node + [Arguments] ${sgt} ${prefixes} ${node} ${session} ${domain} ${data} = Sxp.Add Bindings Xml Oxygen ${node} ${domain} ${sgt} ${prefixes} Post To Controller ${session} add-bindings ${data} Get Bindings - [Arguments] ${node}=127.0.0.1 ${session}=session ${domain}=global ${scope}=all [Documentation] Gets all binding via RPC from Master DB of node + [Arguments] ${node}=127.0.0.1 ${session}=session ${domain}=global ${scope}=all ${data} = Sxp.Get Bindings From Node Xml ${node} ${scope} ${domain} - ${resp} = TemplatedRequests.Post_To_Uri ${REST_CONTEXT}:get-node-bindings data=${data} accept=${ACCEPT_JSON} content_type=${HEADERS_XML} session=${session} - [Return] ${resp} + ${resp} = TemplatedRequests.Post_To_Uri + ... ${REST_CONTEXT}:get-node-bindings + ... data=${data} + ... accept=${ACCEPT_JSON} + ... content_type=${HEADERS_XML} + ... session=${session} + RETURN ${resp} Clean Bindings - [Arguments] ${node}=127.0.0.1 ${session}=session ${domain}=global ${scope}=local [Documentation] Delete all bindings via RPC from Master DB of node + [Arguments] ${node}=127.0.0.1 ${session}=session ${domain}=global ${scope}=local ${resp} = Get Bindings ${node} ${session} ${domain} ${scope} @{bindings} = Sxp.Parse Bindings ${resp} FOR ${binding} IN @{bindings} @@ -117,34 +150,38 @@ Clean Bindings END Delete Bindings - [Arguments] ${sgt} ${prefixes} ${node}=127.0.0.1 ${domain}=global ${session}=session [Documentation] Delete one or more bindings via RPC from Master DB of node + [Arguments] ${sgt} ${prefixes} ${node}=127.0.0.1 ${domain}=global ${session}=session ${data} = Sxp.Delete Bindings Xml ${node} ${domain} ${sgt} ${prefixes} Post To Controller ${session} delete-bindings ${data} Add PeerGroup - [Arguments] ${name} ${peers}= ${node}=127.0.0.1 ${session}=session [Documentation] Adds new PeerGroup via RPC to Node + [Arguments] ${name} ${peers}= ${node}=127.0.0.1 ${session}=session ${data} = Sxp.Add Peer Group Xml ${name} ${peers} ${node} Post To Controller ${session} add-peer-group ${data} Delete Peer Group - [Arguments] ${name} ${node}=127.0.0.1 ${session}=session [Documentation] Delete PeerGroup via RPC from Node + [Arguments] ${name} ${node}=127.0.0.1 ${session}=session ${data} = Sxp.Delete Peer Group Xml ${name} ${node} Post To Controller ${session} delete-peer-group ${data} Get Peer Groups - [Arguments] ${node}=127.0.0.1 ${session}=session [Documentation] Gets all PeerGroups via RPC from node + [Arguments] ${node}=127.0.0.1 ${session}=session ${data} = Sxp.Get Peer Groups From Node Xml ${node} - ${resp} = RequestsLibrary.Post Request ${session} ${REST_CONTEXT}:get-peer-groups data=${data} headers=${HEADERS_XML} + ${resp} = RequestsLibrary.Post Request + ... ${session} + ... ${REST_CONTEXT}:get-peer-groups + ... data=${data} + ... headers=${HEADERS_XML} BuiltIn.Should be Equal As Strings ${resp.status_code} 200 - [Return] ${resp.text} + RETURN ${resp.text} Clean Peer Groups - [Arguments] ${node}=127.0.0.1 ${session}=session [Documentation] Delete all PeerGroups via RPC from node + [Arguments] ${node}=127.0.0.1 ${session}=session ${resp} = Get Peer Groups ${node} ${session} @{prefixes} = Sxp.Parse Peer Groups ${resp} FOR ${group} IN @{prefixes} @@ -152,90 +189,101 @@ Clean Peer Groups END Add Filter - [Arguments] ${name} ${type} ${entries} ${node}=127.0.0.1 ${session}=session ${policy}=auto-update [Documentation] Add Filter via RPC from Node + [Arguments] ${name} ${type} ${entries} ${node}=127.0.0.1 ${session}=session ${policy}=auto-update ${data} = Prepare Add/Update Filter Data ${name} ${type} ${entries} ${node} ${policy} Post To Controller ${session} add-filter ${data} Update Filter - [Arguments] ${name} ${type} ${entries} ${node}=127.0.0.1 ${session}=session ${policy}=auto-update [Documentation] Update Filter via RPC + [Arguments] ${name} ${type} ${entries} ${node}=127.0.0.1 ${session}=session ${policy}=auto-update ${data} = Prepare Add/Update Filter Data ${name} ${type} ${entries} ${node} ${policy} Post To Controller ${session} update-filter ${data} Prepare Add/Update Filter Data - [Arguments] ${name} ${type} ${entries} ${node}=127.0.0.1 ${policy}=auto-update [Documentation] Prepare XML payload for add-filter and update-filter RPCs. Payloads for both RPCs are the same. - ${data} = CompareStream.Run_Keyword_If_At_Least_Else carbon Add Filter Xml ${name} ${type} ${entries} - ... ${node} ${policy} - ... ELSE Add Filter Xml ${name} ${type} ${entries} ${node} - [Return] ${data} + [Arguments] ${name} ${type} ${entries} ${node}=127.0.0.1 ${policy}=auto-update + ${data} = CompareStream.Run_Keyword_If_At_Least_Else + ... carbon + ... Add Filter Xml + ... ${name} + ... ${type} + ... ${entries} + ... ${node} + ... ${policy} + ... ELSE + ... Add Filter Xml + ... ${name} + ... ${type} + ... ${entries} + ... ${node} + RETURN ${data} Add Domain Filter - [Arguments] ${name} ${domains} ${entries} ${node}=127.0.0.1 ${filter_name}=base-domain-filter ${session}=session [Documentation] Add Domain Filter via RPC from Node + [Arguments] ${name} ${domains} ${entries} ${node}=127.0.0.1 ${filter_name}=base-domain-filter ${session}=session ${data} = Sxp.Add Domain Filter Xml ${name} ${domains} ${entries} ${node} ${filter_name} Post To Controller ${session} add-domain-filter ${data} Delete Filter - [Arguments] ${name} ${type} ${node}=127.0.0.1 ${session}=session [Documentation] Delete Filter via RPC from Node + [Arguments] ${name} ${type} ${node}=127.0.0.1 ${session}=session ${data} = Sxp.Delete Filter Xml ${name} ${type} ${node} Post To Controller ${session} delete-filter ${data} Delete Domain Filter - [Arguments] ${name} ${node}=127.0.0.1 ${filter_name}=base-domain-filter ${session}=session [Documentation] Delete Filter via RPC from Node + [Arguments] ${name} ${node}=127.0.0.1 ${filter_name}=base-domain-filter ${session}=session ${data} = Sxp.Delete Domain Filter Xml ${name} ${node} ${filter_name} Post To Controller ${session} delete-domain-filter ${data} Should Contain Binding - [Arguments] ${resp} ${sgt} ${prefix} [Documentation] Tests if data contains specified binding + [Arguments] ${resp} ${sgt} ${prefix} ${out} = Sxp.Find Binding ${resp} ${sgt} ${prefix} BuiltIn.Should Be True ${out} Doesn't have ${sgt} ${prefix} Should Not Contain Binding - [Arguments] ${resp} ${sgt} ${prefix} [Documentation] Tests if data doesn't contains specified binding + [Arguments] ${resp} ${sgt} ${prefix} ${out} = Sxp.Find Binding ${resp} ${sgt} ${prefix} BuiltIn.Should Not Be True ${out} Should't have ${sgt} ${prefix} Should Contain Connection - [Arguments] ${resp} ${ip} ${port} ${mode} ${version} ${state}=none [Documentation] Test if data contains specified connection + [Arguments] ${resp} ${ip} ${port} ${mode} ${version} ${state}=none ${out} = Sxp.Find Connection ${resp} ${version} ${mode} ${ip} ${port} ... ${state} BuiltIn.Should Be True ${out} Doesn't have ${ip}:${port} ${mode} ${version} in state ${state} Should Not Contain Connection - [Arguments] ${resp} ${ip} ${port} ${mode} ${version} ${state}=none [Documentation] Test if data doesn't contains specified connection + [Arguments] ${resp} ${ip} ${port} ${mode} ${version} ${state}=none ${out} = Sxp.Find Connection ${resp} ${version} ${mode} ${ip} ${port} ... ${state} BuiltIn.Should Not Be True ${out} Shouldn't have ${ip}:${port} ${mode} ${version} Bindings Should Contain - [Arguments] ${sgt} ${prefix} ${domain}=global ${scope}=all [Documentation] Retrieves bindings and verifies they contain given binding + [Arguments] ${sgt} ${prefix} ${domain}=global ${scope}=all ${resp} = Get Bindings domain=${domain} scope=${scope} Should Contain Binding ${resp} ${sgt} ${prefix} Bindings Should Not Contain - [Arguments] ${sgt} ${prefix} ${domain}=global ${scope}=all [Documentation] Retrieves bindings and verifies they do not contain given binding + [Arguments] ${sgt} ${prefix} ${domain}=global ${scope}=all ${resp} = Get Bindings domain=${domain} scope=${scope} Should Not Contain Binding ${resp} ${sgt} ${prefix} Connections Should Contain - [Arguments] ${ip} ${port} ${mode} ${version} ${state}=none [Documentation] Retrieves connections and verifies they contain given connection + [Arguments] ${ip} ${port} ${mode} ${version} ${state}=none ${resp} = Get Connections Should Contain Connection ${resp} ${ip} ${port} ${mode} ${version} ${state} Connections Should Not Contain - [Arguments] ${ip} ${port} ${mode} ${version} ${state}=none [Documentation] Retrieves connections and verifies they do not contain given connection + [Arguments] ${ip} ${port} ${mode} ${version} ${state}=none ${resp} = Get Connections Should Not Contain Connection ${resp} ${ip} ${port} ${mode} ${version} ${state} @@ -259,51 +307,65 @@ Setup Topology Complex Add Bindings 10 10.0.0.0/8 127.0.0.1 Verify Snapshot Was Pushed - [Arguments] ${snapshot_string}=22-sxp-controller-one-node.xml [Documentation] Will succeed if the ${snapshot_string} is found in the karaf logs - ${output} = Utils.Run Command On Controller ${ODL_SYSTEM_IP} cat ${WORKSPACE}/${BUNDLEFOLDER}/data/log/karaf.log* | grep -c 'Successfully pushed configuration snapshot.*${snapshot_string}' + [Arguments] ${snapshot_string}=22-sxp-controller-one-node.xml + ${output} = Utils.Run Command On Controller + ... ${ODL_SYSTEM_IP} + ... cat ${WORKSPACE}/${BUNDLEFOLDER}/data/log/karaf.log* | grep -c 'Successfully pushed configuration snapshot.*${snapshot_string}' BuiltIn.Should Not Be Equal As Strings ${output} 0 Add Domain - [Arguments] ${domain_name} ${sgt}=None ${prefixes}=None ${origin}=LOCAL ${node}=127.0.0.1 ${session}=session [Documentation] Based on ODL version decide if domain's bindings will be added with or without origin type (introduced in Fluorine) - CompareStream.Run_Keyword_If_At_Least_Fluorine Add Domain Fluorine ${domain_name} ${sgt} ${prefixes} ${origin} ${node} + [Arguments] ${domain_name} ${sgt}=None ${prefixes}=None ${origin}=LOCAL ${node}=127.0.0.1 ${session}=session + CompareStream.Run_Keyword_If_At_Least_Fluorine + ... Add Domain Fluorine + ... ${domain_name} + ... ${sgt} + ... ${prefixes} + ... ${origin} + ... ${node} + ... ${session} + CompareStream.Run_Keyword_If_At_Most_Oxygen + ... Add Domain Oxygen + ... ${domain_name} + ... ${sgt} + ... ${prefixes} + ... ${node} ... ${session} - CompareStream.Run_Keyword_If_At_Most_Oxygen Add Domain Oxygen ${domain_name} ${sgt} ${prefixes} ${node} ${session} Add Domain Fluorine - [Arguments] ${domain_name} ${sgt} ${prefixes} ${origin} ${node} ${session} [Documentation] Add Domain with bindings (with origin) via RPC + [Arguments] ${domain_name} ${sgt} ${prefixes} ${origin} ${node} ${session} ${data} = Sxp.Add Domain Xml Fluorine ${node} ${domain_name} ${sgt} ${prefixes} ${origin} Post To Controller ${session} add-domain ${data} Add Domain Oxygen - [Arguments] ${domain_name} ${sgt} ${prefixes} ${node} ${session} [Documentation] Add Domain with bindings (without origin) via RPC + [Arguments] ${domain_name} ${sgt} ${prefixes} ${node} ${session} ${data} = Sxp.Add Domain Xml Oxygen ${node} ${domain_name} ${sgt} ${prefixes} Post To Controller ${session} add-domain ${data} Delete Domain - [Arguments] ${domain_name} ${node}=127.0.0.1 ${session}=session [Documentation] Delete Domain via RPC + [Arguments] ${domain_name} ${node}=127.0.0.1 ${session}=session ${data} = Sxp.Delete Domain Xml ${node} ${domain_name} Post To Controller ${session} delete-domain ${data} Add Bindings Range - [Arguments] ${sgt} ${start} ${size} ${node}=127.0.0.1 [Documentation] Add Bindings to Node specified by range + [Arguments] ${sgt} ${start} ${size} ${node}=127.0.0.1 ${prefixes} = Sxp.Prefix Range ${start} ${size} Add Bindings ${sgt} ${prefixes} ${node} Delete Bindings Range - [Arguments] ${sgt} ${start} ${size} ${node}=127.0.0.1 [Documentation] Delete Bindings to Node specified by range + [Arguments] ${sgt} ${start} ${size} ${node}=127.0.0.1 ${prefixes} = Sxp.Prefix Range ${start} ${size} Delete Bindings ${sgt} ${prefixes} ${node} Check Binding Range - [Arguments] ${sgt} ${start} ${end} ${node}=127.0.0.1 [Documentation] Check if Node contains Bindings specified by range + [Arguments] ${sgt} ${start} ${end} ${node}=127.0.0.1 ${resp} = Get Bindings ${node} FOR ${num} IN RANGE ${start} ${end} ${ip} = Sxp.Get Ip From Number ${num} @@ -311,8 +373,8 @@ Check Binding Range END Check Binding Range Negative - [Arguments] ${sgt} ${start} ${end} ${node}=127.0.0.1 [Documentation] Check if Node does not contains Bindings specified by range + [Arguments] ${sgt} ${start} ${end} ${node}=127.0.0.1 ${resp} = Get Bindings ${node} FOR ${num} IN RANGE ${start} ${end} ${ip} = Sxp.Get Ip From Number ${num} @@ -320,9 +382,14 @@ Check Binding Range Negative END Setup SXP Environment - [Arguments] ${node_range}=1 [Documentation] Create session to Controller, ${node_range} parameter specifies number of localhost nodes to be created on ${ODL_SYSTEM_IP}. - RequestsLibrary.Create Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} auth=${AUTH} timeout=${DEFAULT_TIMEOUT_HTTP} max_retries=0 + [Arguments] ${node_range}=1 + RequestsLibrary.Create Session + ... session + ... http://${ODL_SYSTEM_IP}:${RESTCONFPORT} + ... auth=${AUTH} + ... timeout=${DEFAULT_TIMEOUT_HTTP} + ... max_retries=0 FOR ${num} IN RANGE 1 ${node_range}+1 ${node} = Sxp.Get Ip From Number ${num} Add Node ${node} retry_open_timer=${num} @@ -330,30 +397,39 @@ Setup SXP Environment END Check Node Started - [Arguments] ${node} ${port}=64999 ${system}=${node} ${session}=session ${ip}=${node} [Documentation] Verify that SxpNode has data writen to Operational datastore and is running - ${resp} = RequestsLibrary.Get Request ${session} /restconf/operational/network-topology:network-topology/topology/sxp/node/${node}/ + [Arguments] ${node} ${port}=64999 ${system}=${node} ${session}=session ${ip}=${node} + ${resp} = RequestsLibrary.Get Request + ... ${session} + ... /restconf/operational/network-topology:network-topology/topology/sxp/node/${node}/ BuiltIn.Should Be Equal As Strings ${resp.status_code} 200 ${rc} = Get Node Running Status ${node} ${port} ${system} ${session} ${ip} BuiltIn.Should Be Equal As Strings ${rc} 0 Check Node Stopped - [Arguments] ${node} ${port}=64999 ${system}=${node} ${session}=session ${ip}=${node} [Documentation] Verify that SxpNode has data removed from Operational datastore and is not running - ${resp} = RequestsLibrary.Get Request ${session} /restconf/operational/network-topology:network-topology/topology/sxp/node/${node}/ + [Arguments] ${node} ${port}=64999 ${system}=${node} ${session}=session ${ip}=${node} + ${resp} = RequestsLibrary.Get Request + ... ${session} + ... /restconf/operational/network-topology:network-topology/topology/sxp/node/${node}/ BuiltIn.Should Be Equal As Strings ${resp.status_code} 404 ${rc} = Get Node Running Status ${node} ${port} ${system} ${session} ${ip} BuiltIn.Should Be Equal As Strings ${rc} 1 Get Node Running Status - [Arguments] ${node} ${port} ${system} ${session} ${ip} [Documentation] Get status if node is running by checking that netty server is running - ${rc} = Utils.Run Command On Remote System ${system} netstat -tln | grep -q ${ip}:${port} && echo 0 || echo 1 ${ODL_SYSTEM_USER} ${ODL_SYSTEM_PASSWORD} prompt=${ODL_SYSTEM_PROMPT} - [Return] ${rc} + [Arguments] ${node} ${port} ${system} ${session} ${ip} + ${rc} = Utils.Run Command On Remote System + ... ${system} + ... netstat -tln | grep -q ${ip}:${port} && echo 0 || echo 1 + ... ${ODL_SYSTEM_USER} + ... ${ODL_SYSTEM_PASSWORD} + ... prompt=${ODL_SYSTEM_PROMPT} + RETURN ${rc} Clean SXP Environment - [Arguments] ${node_range}=1 [Documentation] Destroy created sessions + [Arguments] ${node_range}=1 FOR ${num} IN RANGE 1 ${node_range}+1 ${ip} = Sxp.Get Ip From Number ${num} Delete Node ${ip} @@ -362,21 +438,33 @@ Clean SXP Environment RequestsLibrary.Delete All Sessions Get Routing Configuration From Controller - [Arguments] ${session} [Documentation] Get Routing configuration from config DS - ${resp} = RequestsLibrary.Get Request ${session} /restconf/config/sxp-cluster-route:sxp-cluster-route/ headers=${ACCEPT_XML} + [Arguments] ${session} + ${resp} = RequestsLibrary.Get Request + ... ${session} + ... /restconf/config/sxp-cluster-route:sxp-cluster-route/ + ... headers=${ACCEPT_XML} ${data} = BuiltIn.Set Variable If "${resp.status_code}" == "200" ${resp.text} ${EMPTY} - [Return] ${data} + RETURN ${data} Put Routing Configuration To Controller - [Arguments] ${data} ${session} [Documentation] Put Routing configuration to Config DS - ${resp} = RequestsLibrary.Put Request ${session} /restconf/config/sxp-cluster-route:sxp-cluster-route/ data=${data} headers=${HEADERS_XML} + [Arguments] ${data} ${session} + ${resp} = RequestsLibrary.Put Request + ... ${session} + ... /restconf/config/sxp-cluster-route:sxp-cluster-route/ + ... data=${data} + ... headers=${HEADERS_XML} BuiltIn.Log ${resp} BuiltIn.Should Match "${resp.status_code}" "20?" Clean Routing Configuration To Controller - [Arguments] ${session} [Documentation] Delete Routing configuration from Config DS - ${resp} = RequestsLibrary.Get Request ${session} /restconf/config/sxp-cluster-route:sxp-cluster-route/ headers=${ACCEPT_XML} - BuiltIn.Run Keyword If "${resp.status_code}" == "200" RequestsLibrary.Delete Request ${session} /restconf/config/sxp-cluster-route:sxp-cluster-route/ + [Arguments] ${session} + ${resp} = RequestsLibrary.Get Request + ... ${session} + ... /restconf/config/sxp-cluster-route:sxp-cluster-route/ + ... headers=${ACCEPT_XML} + IF "${resp.status_code}" == "200" + RequestsLibrary.Delete Request ${session} /restconf/config/sxp-cluster-route:sxp-cluster-route/ + END diff --git a/csit/libraries/Tcpdump.robot b/csit/libraries/Tcpdump.robot index b9d8a48d6c..444a54196b 100644 --- a/csit/libraries/Tcpdump.robot +++ b/csit/libraries/Tcpdump.robot @@ -1,62 +1,65 @@ *** Settings *** -Documentation Library to catch traffic/packets using linux tcpdump command -Library SSHLibrary -Resource SSHKeywords.robot -Resource Utils.robot -Resource RemoteBash.robot -Variables ../variables/Variables.py +Documentation Library to catch traffic/packets using linux tcpdump command + +Library SSHLibrary +Resource SSHKeywords.robot +Resource Utils.robot +Resource RemoteBash.robot +Variables ../variables/Variables.py + *** Variables *** -${dumpalias} tcpdump -${dumppcap} dump.pcap -${dumppcappath} /tmp/${dumppcap} -${dumpcmd} sudo tcpdump -s 0 -w ${dumppcappath} +${dumpalias} tcpdump +${dumppcap} dump.pcap +${dumppcappath} /tmp/${dumppcap} +${dumpcmd} sudo tcpdump -s 0 -w ${dumppcappath} ${dump_default_name} tcpDump + *** Keywords *** Start Tcpdumping + [Documentation] Connects to the remote machine via ssh and starts tcpdump linux command [Arguments] ${system}=${TOOLS_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${password}=${TOOLS_SYSTEM_PASSWORD} ${prompt}=${TOOLS_SYSTEM_PROMPT} ${timeout}=5s ${eth}=eth0 ... ${more_params}=${None} - [Documentation] Connects to the remote machine via ssh and starts tcpdump linux command - ${currentcon}= SSHLibrary.Get Connection index=True + ${currentcon} = SSHLibrary.Get Connection index=True SSHLibrary.Open Connection ${system} prompt=${prompt} timeout=${timeout} alias=${dumpalias} SSHKeywords.Flexible SSH Login ${user} password=${password} delay=${timeout} SSHLibrary.Write ${dumpcmd} -i ${eth} ${more_params} - Run Keyword If ${currentcon}==${None} Return From Keyword + IF ${currentcon}==${None} RETURN SSHLibrary.Switch Connection ${currentcon} Stop Tcpdumping And Download - [Arguments] ${filename}=${dumppcap}.xz [Documentation] Stops catching packets with tcpdump and download the saved file - ${oldcon}= SSHLibrary.Switch Connection ${dumpalias} + [Arguments] ${filename}=${dumppcap}.xz + ${oldcon} = SSHLibrary.Switch Connection ${dumpalias} RemoteBash.Write_Bare_Ctrl_C SSHLibrary.Read - ${stdout}= SSHLibrary.Execute Command xz -9ekvv ${dumppcappath} + ${stdout} = SSHLibrary.Execute Command xz -9ekvv ${dumppcappath} Log ${stdout} - ${stdout}= SSHLibrary.Execute Command ls -la /tmp + ${stdout} = SSHLibrary.Execute Command ls -la /tmp Log ${stdout} SSHLibrary.Get File ${dumppcappath}.xz ${filename} SSHLibrary.Close Connection - Run Keyword If ${oldcon}==${None} Return From Keyword + IF ${oldcon}==${None} RETURN SSHLibrary.Switch Connection ${oldcon} Start Packet Capture On Node + [Documentation] Connects to the remote machine and starts tcpdump [Arguments] ${node_ip} ${file_Name}=${dump_default_name} ${network_Adapter}=eth0 ${user}=${DEFAULT_USER} ${password}=${EMPTY} ${prompt}=${DEFAULT_LINUX_PROMPT} ... ${prompt_timeout}=${DEFAULT_TIMEOUT} ${filter}=${EMPTY} - [Documentation] Connects to the remote machine and starts tcpdump - ${current_ssh_connection}= SSHLibrary.Get Connection - ${conn_id}= SSHLibrary.Open Connection ${node_ip} prompt=${prompt} timeout=${prompt_timeout} + ${current_ssh_connection} = SSHLibrary.Get Connection + ${conn_id} = SSHLibrary.Open Connection ${node_ip} prompt=${prompt} timeout=${prompt_timeout} SSHKeywords.Flexible SSH Login ${user} ${password} ${cmd} = Set Variable sudo /usr/sbin/tcpdump -vvv -ni ${networkAdapter} ${filter} -w /tmp/${file_Name}.pcap ${stdout} ${stderr} = SSHLibrary.Start Command ${cmd} Log ${stderr} Log ${stdout} + RETURN ${conn_id} [Teardown] SSHKeywords.Restore_Current_SSH_Connection_From_Index ${current_ssh_connection.index} - [Return] ${conn_id} Stop Packet Capture on Node - [Arguments] ${conn_id} [Documentation] This keyword will list the running processes looking for tcpdump and then kill the process with the name tcpdump + [Arguments] ${conn_id} SSHLibrary.Switch Connection ${conn_id} ${stdout} = SSHLibrary.Execute Command sudo ps -elf | grep tcpdump Log ${stdout} @@ -69,20 +72,20 @@ Stop Packet Capture on Node Log ${stdout} Start Packet Capture on Nodes - [Arguments] ${tag}=${EMPTY} ${filter}=${EMPTY} ${ips}=@{EMPTY} [Documentation] Start packet captures on the given list of node ips. ... The captures will be named with the tag and ip. + [Arguments] ${tag}=${EMPTY} ${filter}=${EMPTY} ${ips}=@{EMPTY} @{conn_ids} = BuiltIn.Create List @{EMPTY} FOR ${ip} IN @{ips} ${fname} = BuiltIn.Catenate SEPARATOR=__ ${tag} ${ip} ${conn_id} = Tcpdump.Start Packet Capture on Node ${ip} file_Name=${fname} filter=${filter} Collections.Append To List ${conn_ids} ${conn_id} END - [Return] @{conn_ids} + RETURN @{conn_ids} Stop Packet Capture on Nodes - [Arguments] ${conn_ids}=@{EMPTY} [Documentation] Stop the packet captures on the given list of node connection ids + [Arguments] ${conn_ids}=@{EMPTY} FOR ${conn_id} IN @{conn_ids} Stop Packet Capture on Node ${conn_id} END diff --git a/csit/libraries/Tempest.robot b/csit/libraries/Tempest.robot index 57e446d28d..4992c424ca 100644 --- a/csit/libraries/Tempest.robot +++ b/csit/libraries/Tempest.robot @@ -1,21 +1,24 @@ *** Settings *** -Documentation General Utils library. This library has broad scope, it can be used by any robot system tests. -Library SSHLibrary -Resource DevstackUtils.robot -Resource OpenStackOperations.robot -Resource SSHKeywords.robot -Resource ../variables/Variables.robot +Documentation General Utils library. This library has broad scope, it can be used by any robot system tests. + +Library SSHLibrary +Resource DevstackUtils.robot +Resource OpenStackOperations.robot +Resource SSHKeywords.robot +Resource ../variables/Variables.robot + *** Variables *** -@{stable/queens_EXCLUSION_REGEXES} ${EMPTY} -@{stable/rocky_EXCLUSION_REGEXES} ${EMPTY} -@{stable/stein_EXCLUSION_REGEXES} ${EMPTY} -@{master_EXCLUSION_REGEXES} ${EMPTY} -${BLACKLIST_FILE} /tmp/blacklist.txt -${TEMPEST_DIR} /opt/stack/tempest -${TEMPEST_CONFIG_FILE} ${TEMPEST_DIR}/etc/tempest.conf +@{stable/queens_EXCLUSION_REGEXES} ${EMPTY} +@{stable/rocky_EXCLUSION_REGEXES} ${EMPTY} +@{stable/stein_EXCLUSION_REGEXES} ${EMPTY} +@{master_EXCLUSION_REGEXES} ${EMPTY} +${BLACKLIST_FILE} /tmp/blacklist.txt +${TEMPEST_DIR} /opt/stack/tempest +${TEMPEST_CONFIG_FILE} ${TEMPEST_DIR}/etc/tempest.conf # Parameter values below are based on releng/builder - changing them requires updates in releng/builder as well -${TEMPEST_TIMEOUT} 420s +${TEMPEST_TIMEOUT} 420s + *** Keywords *** Suite Setup @@ -24,18 +27,24 @@ Suite Setup Run Tempest Tests [Arguments] ${tempest_regex} ${timeout}=${TEMPEST_TIMEOUT} ${debug}=False - BuiltIn.Run Keyword If "${debug}" == "False" Tempest.Run Tempest Tests Without Debug ${tempest_regex} timeout=${timeout} - BuiltIn.Run Keyword If "${debug}" == "True" Tempest.Run Tempest Tests With Debug ${tempest_regex} timeout=${timeout} - BuiltIn.Run Keyword If "${debug}" != "True" and "${debug}" != "False" Fail debug argument must be True or False + IF "${debug}" == "False" + Tempest.Run Tempest Tests Without Debug ${tempest_regex} timeout=${timeout} + END + IF "${debug}" == "True" + Tempest.Run Tempest Tests With Debug ${tempest_regex} timeout=${timeout} + END + IF "${debug}" != "True" and "${debug}" != "False" + Fail debug argument must be True or False + END Run Tempest Tests Without Debug - [Arguments] ${tempest_regex} ${TEMPEST_DIRectory}=${TEMPEST_DIR} ${timeout}=${TEMPEST_TIMEOUT} [Documentation] Using ostestr will allow us to (by default) run tests in paralllel. ... Because of the parallel fashion, we must ensure there is no pause on teardown so that flag in tempest.conf is ... explicitly set to False. - BuiltIn.Return From Keyword If "skip_if_${OPENSTACK_BRANCH}" in @{TEST_TAGS} - BuiltIn.Return From Keyword If "skip_if_${SECURITY_GROUP_MODE}" in @{TEST_TAGS} - BuiltIn.Return From Keyword If "skip_if_${ODL_SNAT_MODE}" in @{TEST_TAGS} + [Arguments] ${tempest_regex} ${TEMPEST_DIRectory}=${TEMPEST_DIR} ${timeout}=${TEMPEST_TIMEOUT} + IF "skip_if_${OPENSTACK_BRANCH}" in @{TEST_TAGS} RETURN + IF "skip_if_${SECURITY_GROUP_MODE}" in @{TEST_TAGS} RETURN + IF "skip_if_${ODL_SNAT_MODE}" in @{TEST_TAGS} RETURN ${tempest_conn_id} = SSHLibrary.Open Connection ${OS_CNTL_IP} prompt=${DEFAULT_LINUX_PROMPT_STRICT} SSHKeywords.Flexible SSH Login ${OS_USER} ${DEVSTACK_SYSTEM_PASSWORD} DevstackUtils.Write Commands Until Prompt source ${DEVSTACK_DEPLOY_PATH}/openrc admin admin @@ -46,19 +55,21 @@ Run Tempest Tests Without Debug # There are tons of deprecation error messages when we use ostestr in our CSIT environment (openstack via devstack) # The robot log files are very large and one culprit is all these deprecation warnings. If we redirect stderr to # /dev/null we should be able to ignore them. We will miss any other errors, however. - ${output} = DevstackUtils.Write Commands Until Prompt And Log ostestr --regex ${tempest_regex} timeout=${timeout} + ${output} = DevstackUtils.Write Commands Until Prompt And Log + ... ostestr --regex ${tempest_regex} + ... timeout=${timeout} SSHLibrary.Close Connection BuiltIn.Should Contain ${output} Failed: 0 Run Tempest Tests With Debug - [Arguments] ${tempest_regex} ${TEMPEST_DIRectory}=${TEMPEST_DIR} ${timeout}=${TEMPEST_TIMEOUT} [Documentation] After setting pause_teardown=True in tempest.conf, use the python -m testtools.run module to execute ... a single tempest test case. We need to run only one tempest test case at a time as there will ... be potentional for an unkown number of debug pdb() prompts to catch and continue if we are running multiple ... test cases with a single command. Essentially, this keyword only handles one breakpoint at a single teardown. - BuiltIn.Return From Keyword If "skip_if_${OPENSTACK_BRANCH}" in @{TEST_TAGS} - BuiltIn.Return From Keyword If "skip_if_${SECURITY_GROUP_MODE}" in @{TEST_TAGS} - BuiltIn.Return From Keyword If "skip_if_${ODL_SNAT_MODE}" in @{TEST_TAGS} + [Arguments] ${tempest_regex} ${TEMPEST_DIRectory}=${TEMPEST_DIR} ${timeout}=${TEMPEST_TIMEOUT} + IF "skip_if_${OPENSTACK_BRANCH}" in @{TEST_TAGS} RETURN + IF "skip_if_${SECURITY_GROUP_MODE}" in @{TEST_TAGS} RETURN + IF "skip_if_${ODL_SNAT_MODE}" in @{TEST_TAGS} RETURN ${tempest_conn_id} = SSHLibrary.Open Connection ${OS_CNTL_IP} prompt=${DEFAULT_LINUX_PROMPT_STRICT} SSHKeywords.Flexible SSH Login ${OS_USER} ${DEVSTACK_SYSTEM_PASSWORD} DevstackUtils.Write Commands Until Prompt source ${DEVSTACK_DEPLOY_PATH}/openrc admin admin @@ -88,8 +99,14 @@ Log In To Tempest Executor And Setup Test Environment ... and pushed to the tempest executor. Tempest.Create Blacklist File # Tempest tests need an existing external network in order to create routers. - OpenStackOperations.Create Network ${EXTERNAL_NET_NAME} --external --default --provider-network-type flat --provider-physical-network ${PUBLIC_PHYSICAL_NETWORK} - OpenStackOperations.Create Subnet ${EXTERNAL_NET_NAME} ${EXTERNAL_SUBNET_NAME} ${EXTERNAL_SUBNET} --gateway ${EXTERNAL_GATEWAY} --allocation-pool ${EXTERNAL_SUBNET_ALLOCATION_POOL} + OpenStackOperations.Create Network + ... ${EXTERNAL_NET_NAME} + ... --external --default --provider-network-type flat --provider-physical-network ${PUBLIC_PHYSICAL_NETWORK} + OpenStackOperations.Create Subnet + ... ${EXTERNAL_NET_NAME} + ... ${EXTERNAL_SUBNET_NAME} + ... ${EXTERNAL_SUBNET} + ... --gateway ${EXTERNAL_GATEWAY} --allocation-pool ${EXTERNAL_SUBNET_ALLOCATION_POOL} OpenStackOperations.List Networks ${control_node_conn_id} = SSHLibrary.Open Connection ${OS_CNTL_IP} prompt=${DEFAULT_LINUX_PROMPT_STRICT} SSHKeywords.Flexible SSH Login ${OS_USER} @@ -103,28 +120,54 @@ Log In To Tempest Executor And Setup Test Environment Tempest.Tempest Conf Add External Network And Floating Network Name ${net_id} Tempest Conf Add External Network And Floating Network Name - [Arguments] ${external_network_id} [Documentation] Tempest will be run with a config file - this function will add the ... given external network ID to the configuration file. - Tempest.Modify Config In File On Existing SSH Connection ${TEMPEST_CONFIG_FILE} set network public_network_id ${external_network_id} - Tempest.Modify Config In File On Existing SSH Connection ${TEMPEST_CONFIG_FILE} set DEFAULT debug False - Tempest.Modify Config In File On Existing SSH Connection ${TEMPEST_CONFIG_FILE} set DEFAULT log_level INFO - Tempest.Modify Config In File On Existing SSH Connection ${TEMPEST_CONFIG_FILE} set network floating_network_name ${EXTERNAL_NET_NAME} + [Arguments] ${external_network_id} + Tempest.Modify Config In File On Existing SSH Connection + ... ${TEMPEST_CONFIG_FILE} + ... set + ... network + ... public_network_id + ... ${external_network_id} + Tempest.Modify Config In File On Existing SSH Connection + ... ${TEMPEST_CONFIG_FILE} + ... set + ... DEFAULT + ... debug + ... False + Tempest.Modify Config In File On Existing SSH Connection + ... ${TEMPEST_CONFIG_FILE} + ... set + ... DEFAULT + ... log_level + ... INFO + Tempest.Modify Config In File On Existing SSH Connection + ... ${TEMPEST_CONFIG_FILE} + ... set + ... network + ... floating_network_name + ... ${EXTERNAL_NET_NAME} DevstackUtils.Write Commands Until Prompt sudo cat ${TEMPEST_CONFIG_FILE} DevstackUtils.Write Commands Until Prompt sudo chmod 777 ${TEMPEST_CONFIG_FILE} Tempest Conf Modify Pause On Test Teardown - [Arguments] ${pause_flag} [Documentation] Sets the DEFAULT section flag for pausing the test teardown. If True the tempest test case ... being executed will break to a pdb() debug shell when it hits it's teardown() function. - Tempest.Modify Config In File On Existing SSH Connection ${TEMPEST_CONFIG_FILE} set DEFAULT pause_teardown ${pause_flag} + [Arguments] ${pause_flag} + Tempest.Modify Config In File On Existing SSH Connection + ... ${TEMPEST_CONFIG_FILE} + ... set + ... DEFAULT + ... pause_teardown + ... ${pause_flag} Modify Config In File On Existing SSH Connection - [Arguments] ${config_file} ${modifier} ${config_section} ${config_key} ${config_value}=${EMPTY} [Documentation] uses crudini to populate oslo cofg file. + [Arguments] ${config_file} ${modifier} ${config_section} ${config_key} ${config_value}=${EMPTY} # this keyword is only one line so seems like extra overhead, but this may be a good candidate to move # to a library at some point, when/if other suites need to use it, so wanted to make it generic. - DevstackUtils.Write Commands Until Prompt sudo -E crudini --${modifier} ${config_file} ${config_section} ${config_key} ${config_value} + DevstackUtils.Write Commands Until Prompt + ... sudo -E crudini --${modifier} ${config_file} ${config_section} ${config_key} ${config_value} Create Blacklist File [Documentation] For each exclusion regex in the required @{${OPENSTACK_BRANCH}_EXCLUSION_REGEXES} list a new diff --git a/csit/libraries/TemplatedRequests.robot b/csit/libraries/TemplatedRequests.robot index 158b57f66c..67cb62ae3a 100644 --- a/csit/libraries/TemplatedRequests.robot +++ b/csit/libraries/TemplatedRequests.robot @@ -1,210 +1,309 @@ *** Settings *** -Documentation Resource for supporting http Requests based on data stored in files. +Documentation Resource for supporting http Requests based on data stored in files. ... -... Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... The main strength of this library are *_As_*_Templated keywords -... User gives a path to directory where files with templates for URI -... and XML (or JSON) data are present, and a mapping with substitution to make; -... the keywords will take it from there. -... Mapping can be given as a dict object, or as its json text representation. -... Simple example (tidy insists on single space where 4 spaces should be): -... TemplatedRequests.Put_As_Json_Templated folder=${VAR_BASE}/person mapping={"NAME":"joe"} -... TemplatedRequests.Get_As_Json_Templated folder=${VAR_BASE}/person mapping={"NAME":"joe"} verify=True +... The main strength of this library are *_As_*_Templated keywords +... User gives a path to directory where files with templates for URI +... and XML (or JSON) data are present, and a mapping with substitution to make; +... the keywords will take it from there. +... Mapping can be given as a dict object, or as its json text representation. +... Simple example (tidy insists on single space where 4 spaces should be): +... TemplatedRequests.Put_As_Json_Templated folder=${VAR_BASE}/person mapping={"NAME":"joe"} +... TemplatedRequests.Get_As_Json_Templated folder=${VAR_BASE}/person mapping={"NAME":"joe"} verify=True ... -... In that example, we are PUTting "person" data with specified value for "NAME" placeholder. -... We are not verifying PUT response (probably empty string which is not a valid JSON), -... but we are issuing GET (same URI) and verifying the repsonse matches the same data. -... Both lines are returning text response, but in the example we are not saving it into variable. +... In that example, we are PUTting "person" data with specified value for "NAME" placeholder. +... We are not verifying PUT response (probably empty string which is not a valid JSON), +... but we are issuing GET (same URI) and verifying the repsonse matches the same data. +... Both lines are returning text response, but in the example we are not saving it into variable. ... -... Optionally, *_As_*_Templated keywords call verification of response. -... There are separate Verify_* keywords, for users who use intermediate processing. -... For JSON responses, there is a support for normalizing. -... *_Templated keywords without As allow more customization at cost of more arguments. -... *_Uri keywords do not use templates, but may be useful in general, -... perhaps for users who call Resolve_Text_* keywords. -... *_As_*_Uri are the less flexible but less argument-heavy versions of *_Uri keywords. +... Optionally, *_As_*_Templated keywords call verification of response. +... There are separate Verify_* keywords, for users who use intermediate processing. +... For JSON responses, there is a support for normalizing. +... *_Templated keywords without As allow more customization at cost of more arguments. +... *_Uri keywords do not use templates, but may be useful in general, +... perhaps for users who call Resolve_Text_* keywords. +... *_As_*_Uri are the less flexible but less argument-heavy versions of *_Uri keywords. ... -... This resource supports generating data with simple lists. -... ${iterations} argument control number of items, "$i" will be substituted -... automatically (not by the provided mapping) with integers starting with ${iter_start} (default 1). -... For example "iterations=2 iter_start=3" will create items with i=3 and i=4. +... This resource supports generating data with simple lists. +... ${iterations} argument control number of items, "$i" will be substituted +... automatically (not by the provided mapping) with integers starting with ${iter_start} (default 1). +... For example "iterations=2 iter_start=3" will create items with i=3 and i=4. ... -... This implementation relies on file names to distinguish data. -... Each file is expected to end in newline, compiled data has final newline removed. -... Here is a table so that users can create their own templates: -... location.uri: Template with URI. -... data.xml: Template with XML data to send, or GET data to expect. -... data.json: Template with JSON data to send, or GET data to expect. -... post_data.xml: Template with XML data to POST, (different from GET response). -... post_data.json: Template with JSON data to POST, (different from GET response). -... response.xml: Template with PUT or POST XML response to expect. -... response.json: Template with PUT or POST JSON response to expect. -... *.prolog.*: Temlate with data before iterated items. -... *.item.*: Template with data piece corresponding to one item. -... *.epilog.*: Temlate with data after iterated items. +... This implementation relies on file names to distinguish data. +... Each file is expected to end in newline, compiled data has final newline removed. +... Here is a table so that users can create their own templates: +... location.uri: Template with URI. +... data.xml: Template with XML data to send, or GET data to expect. +... data.json: Template with JSON data to send, or GET data to expect. +... post_data.xml: Template with XML data to POST, (different from GET response). +... post_data.json: Template with JSON data to POST, (different from GET response). +... response.xml: Template with PUT or POST XML response to expect. +... response.json: Template with PUT or POST JSON response to expect. +... *.prolog.*: Temlate with data before iterated items. +... *.item.*: Template with data piece corresponding to one item. +... *.epilog.*: Temlate with data after iterated items. ... -... One typical use of this Resource is to make runtime changes to ODL configuration. -... Different ODL parts have varying ways of configuration, -... this library affects only the Config Subsystem way. -... Config Subsystem has (except for Java APIs mostly available only from inside of ODL) -... a NETCONF server as its publicly available entry point. -... Netconf-connector feature makes this netconf server available for RESTCONF calls. -... Be careful to use appropriate feature, odl-netconf-connector* does not work in cluster. +... One typical use of this Resource is to make runtime changes to ODL configuration. +... Different ODL parts have varying ways of configuration, +... this library affects only the Config Subsystem way. +... Config Subsystem has (except for Java APIs mostly available only from inside of ODL) +... a NETCONF server as its publicly available entry point. +... Netconf-connector feature makes this netconf server available for RESTCONF calls. +... Be careful to use appropriate feature, odl-netconf-connector* does not work in cluster. ... -... This Resource currently calls RequestsLibrary directly, -... so it does not work with AuthStandalone or similar. -... This Resource does not maintain any internal Sessions. -... If caller does not provide any, session with alias "default" is used. -... There is a helper Keyword to create the "default" session. -... The session used is assumed to have most things pre-configured appropriately, -... which includes auth, host, port and (lack of) base URI. -... It is recommended to have everything past port (for example /restconf) be defined -... not in the session, but in URI data of individual templates. -... Headers are set in Keywords appropriately. Http session's timout is configurable -... both on session level (where it becomes a default value for requests) and on request -... level (when present, it overrides the session value). To override the default -... value keywords' http_timeout parameter may be used. +... This Resource currently calls RequestsLibrary directly, +... so it does not work with AuthStandalone or similar. +... This Resource does not maintain any internal Sessions. +... If caller does not provide any, session with alias "default" is used. +... There is a helper Keyword to create the "default" session. +... The session used is assumed to have most things pre-configured appropriately, +... which includes auth, host, port and (lack of) base URI. +... It is recommended to have everything past port (for example /restconf) be defined +... not in the session, but in URI data of individual templates. +... Headers are set in Keywords appropriately. Http session's timout is configurable +... both on session level (where it becomes a default value for requests) and on request +... level (when present, it overrides the session value). To override the default +... value keywords' http_timeout parameter may be used. ... -... These Keywords contain frequent BuiltIn.Log invocations, -... so they are not suited for scale or performance suites. -... And as usual, performance tests should use specialized utilities, -... as Robot in general and this Resource specifically will be too slow. +... These Keywords contain frequent BuiltIn.Log invocations, +... so they are not suited for scale or performance suites. +... And as usual, performance tests should use specialized utilities, +... as Robot in general and this Resource specifically will be too slow. ... -... As this Resource makes assumptions about intended headers, -... it is not flexible enough for suites specifically testing Restconf corner cases. -... Also, list of allowed http status codes is quite rigid and broad. +... As this Resource makes assumptions about intended headers, +... it is not flexible enough for suites specifically testing Restconf corner cases. +... Also, list of allowed http status codes is quite rigid and broad. ... -... Rules for ordering Keywords within this Resource: -... 1. User friendlier Keywords first. -... 2. Get, Put, Post, Delete, Verify. -... 3. Within class of equally usable, use order in which a suite would call them. -... 4. Higher-level Keywords first. -... 5. Json before Xml. -... Motivation: Users read from the start, so it is important -... to offer them the better-to-use Keywords first. -... https://wiki.opendaylight.org/view/Integration/Test/Test_Code_Guidelines#Keyword_ordering -... In this case, templates are nicer that raw data, -... *_As_* keywords are better than messing wth explicit header dicts, -... Json is less prone to element ordering issues. -... PUT does not fail on existing element, also it does not allow -... shortened URIs (container instead keyed list element) as Post does. +... Rules for ordering Keywords within this Resource: +... 1. User friendlier Keywords first. +... 2. Get, Put, Post, Delete, Verify. +... 3. Within class of equally usable, use order in which a suite would call them. +... 4. Higher-level Keywords first. +... 5. Json before Xml. +... Motivation: Users read from the start, so it is important +... to offer them the better-to-use Keywords first. +... https://wiki.opendaylight.org/view/Integration/Test/Test_Code_Guidelines#Keyword_ordering +... In this case, templates are nicer that raw data, +... *_As_* keywords are better than messing wth explicit header dicts, +... Json is less prone to element ordering issues. +... PUT does not fail on existing element, also it does not allow +... shortened URIs (container instead keyed list element) as Post does. ... -... TODO: Add ability to override allowed status codes, -... so that negative tests do not need to parse the failure message. +... TODO: Add ability to override allowed status codes, +... so that negative tests do not need to parse the failure message. ... -... TODO: Migrate suites to this Resource and remove *ViaRestconf Resources. +... TODO: Migrate suites to this Resource and remove *ViaRestconf Resources. ... -... TODO: Currently the verification step is only in *_As_*_Templated keywords. -... It could be moved to "non-as" *_Templated ones, -... but that would take even more horizontal space. Is it worth doing? +... TODO: Currently the verification step is only in *_As_*_Templated keywords. +... It could be moved to "non-as" *_Templated ones, +... but that would take even more horizontal space. Is it worth doing? ... -... TODO: Should iterations=0 be supported for JSON (remove [])? +... TODO: Should iterations=0 be supported for JSON (remove [])? ... -... TODO: Currently, ${ACCEPT_EMPTY} is used for JSON-expecting requests. -... perhaps explicit ${ACCEPT_JSON} will be better, even if it sends few bytes more? -Library Collections -Library OperatingSystem -Library String -Library RequestsLibrary -Library ${CURDIR}/norm_json.py -Resource ${CURDIR}/../variables/Variables.robot +... TODO: Currently, ${ACCEPT_EMPTY} is used for JSON-expecting requests. +... perhaps explicit ${ACCEPT_JSON} will be better, even if it sends few bytes more? + +Library Collections +Library OperatingSystem +Library String +Library RequestsLibrary +Library ${CURDIR}/norm_json.py +Resource ${CURDIR}/../variables/Variables.robot + *** Variables *** # TODO: Make the following list more narrow when streams without Bug 2594 fix (up to beryllium) are no longer used. -@{ALLOWED_DELETE_STATUS_CODES} ${200} ${201} ${204} ${404} # List of integers, not strings. Used by DELETE if the resource may be not present. -@{ALLOWED_STATUS_CODES} ${200} ${201} ${204} # List of integers, not strings. Used by both PUT and DELETE (if the resource should have been present). -@{DATA_VALIDATION_ERROR} ${400} # For testing mildly negative scenarios where ODL reports user error. -@{DELETED_STATUS_CODES} ${404} ${409} # List of integers, not strings. Used by DELETE if the resource may be not present. +# List of integers, not strings. Used by DELETE if the resource may be not present. +@{ALLOWED_DELETE_STATUS_CODES} +... ${200} +... ${201} +... ${204} +... ${404} +# List of integers, not strings. Used by both PUT and DELETE (if the resource should have been present). +@{ALLOWED_STATUS_CODES} +... ${200} +... ${201} +... ${204} +@{DATA_VALIDATION_ERROR} ${400} # For testing mildly negative scenarios where ODL reports user error. +# List of integers, not strings. Used by DELETE if the resource may be not present. +@{DELETED_STATUS_CODES} +... ${404} +... ${409} # TODO: Add option for delete to require 404. -@{INTERNAL_SERVER_ERROR} ${500} # Only for testing severely negative scenarios where ODL cannot recover. -@{KEYS_WITH_BITS} op # the default list with keys to be sorted when norm_json libray is used +@{INTERNAL_SERVER_ERROR} ${500} # Only for testing severely negative scenarios where ODL cannot recover. +@{KEYS_WITH_BITS} op # the default list with keys to be sorted when norm_json libray is used @{NO_STATUS_CODES} -@{UNAUTHORIZED_STATUS_CODES} ${401} # List of integers, not strings. Used in Keystone Authentication when the user is not authorized to use the requested resource. +# List of integers, not strings. Used in Keystone Authentication when the user is not authorized to use the requested resource. +@{UNAUTHORIZED_STATUS_CODES} +... ${401} + *** Keywords *** Create_Default_Session - [Arguments] ${url}=http://${ODL_SYSTEM_IP}:${RESTCONFPORT} ${auth}=${AUTH} ${timeout}=${DEFAULT_TIMEOUT_HTTP} ${max_retries}=0 [Documentation] Create "default" session to ${url} with authentication and connection parameters. ... This Keyword is in this Resource only so that user do not need to call RequestsLibrary directly. - RequestsLibrary.Create_Session alias=default url=${url} auth=${auth} timeout=${timeout} max_retries=${max_retries} + [Arguments] ${url}=http://${ODL_SYSTEM_IP}:${RESTCONFPORT} ${auth}=${AUTH} ${timeout}=${DEFAULT_TIMEOUT_HTTP} ${max_retries}=0 + RequestsLibrary.Create_Session + ... alias=default + ... url=${url} + ... auth=${auth} + ... timeout=${timeout} + ... max_retries=${max_retries} Get_As_Json_Templated - [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${verify}=False ${iterations}=${EMPTY} ${iter_start}=1 - ... ${http_timeout}=${EMPTY} ${log_response}=True ${iter_j_offset}=0 [Documentation] Add arguments sensible for JSON data, return Get_Templated response text. ... Optionally, verification against JSON data (may be iterated) is called. ... Only subset of JSON data is verified and returned if JMES path is specified in ... file ${folder}${/}jmespath.expr. - ${response_text} = Get_Templated folder=${folder} mapping=${mapping} accept=${ACCEPT_EMPTY} session=${session} normalize_json=True - ... http_timeout=${http_timeout} log_response=${log_response} - BuiltIn.Run_Keyword_If ${verify} Verify_Response_As_Json_Templated response=${response_text} folder=${folder} base_name=data mapping=${mapping} - ... iterations=${iterations} iter_start=${iter_start} iter_j_offset=${iter_j_offset} - [Return] ${response_text} + [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${verify}=False ${iterations}=${EMPTY} ${iter_start}=1 + ... ${http_timeout}=${EMPTY} ${log_response}=True ${iter_j_offset}=0 + ${response_text} = Get_Templated + ... folder=${folder} + ... mapping=${mapping} + ... accept=${ACCEPT_EMPTY} + ... session=${session} + ... normalize_json=True + ... http_timeout=${http_timeout} + ... log_response=${log_response} + IF ${verify} + Verify_Response_As_Json_Templated + ... response=${response_text} + ... folder=${folder} + ... base_name=data + ... mapping=${mapping} + ... iterations=${iterations} + ... iter_start=${iter_start} + ... iter_j_offset=${iter_j_offset} + END + RETURN ${response_text} Get_As_Xml_Templated - [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${verify}=False ${iterations}=${EMPTY} ${iter_start}=1 - ... ${http_timeout}=${EMPTY} ${iter_j_offset}=0 [Documentation] Add arguments sensible for XML data, return Get_Templated response text. ... Optionally, verification against XML data (may be iterated) is called. - ${response_text} = Get_Templated folder=${folder} mapping=${mapping} accept=${ACCEPT_XML} session=${session} normalize_json=False + [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${verify}=False ${iterations}=${EMPTY} ${iter_start}=1 + ... ${http_timeout}=${EMPTY} ${iter_j_offset}=0 + ${response_text} = Get_Templated + ... folder=${folder} + ... mapping=${mapping} + ... accept=${ACCEPT_XML} + ... session=${session} + ... normalize_json=False ... http_timeout=${http_timeout} - BuiltIn.Run_Keyword_If ${verify} Verify_Response_As_Xml_Templated response=${response_text} folder=${folder} base_name=data mapping=${mapping} - ... iterations=${iterations} iter_start=${iter_start} iter_j_offset=${iter_j_offset} - [Return] ${response_text} + IF ${verify} + Verify_Response_As_Xml_Templated + ... response=${response_text} + ... folder=${folder} + ... base_name=data + ... mapping=${mapping} + ... iterations=${iterations} + ... iter_start=${iter_start} + ... iter_j_offset=${iter_j_offset} + END + RETURN ${response_text} Put_As_Json_Templated - [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${verify}=False ${iterations}=${EMPTY} ${iter_start}=1 - ... ${http_timeout}=${EMPTY} ${iter_j_offset}=0 [Documentation] Add arguments sensible for JSON data, return Put_Templated response text. ... Optionally, verification against response.json (no iteration) is called. ... Only subset of JSON data is verified and returned if JMES path is specified in ... file ${folder}${/}jmespath.expr. - ${response_text} = Put_Templated folder=${folder} base_name=data extension=json accept=${ACCEPT_EMPTY} content_type=${HEADERS_YANG_JSON} - ... mapping=${mapping} session=${session} normalize_json=True endline=${\n} iterations=${iterations} iter_start=${iter_start} - ... http_timeout=${http_timeout} iter_j_offset=${iter_j_offset} - BuiltIn.Run_Keyword_If ${verify} Verify_Response_As_Json_Templated response=${response_text} folder=${folder} - ... base_name=response mapping=${mapping} iter_j_offset=${iter_j_offset} - [Return] ${response_text} - -Put_As_Xml_Templated [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${verify}=False ${iterations}=${EMPTY} ${iter_start}=1 ... ${http_timeout}=${EMPTY} ${iter_j_offset}=0 + ${response_text} = Put_Templated + ... folder=${folder} + ... base_name=data + ... extension=json + ... accept=${ACCEPT_EMPTY} + ... content_type=${HEADERS_YANG_JSON} + ... mapping=${mapping} + ... session=${session} + ... normalize_json=True + ... endline=${\n} + ... iterations=${iterations} + ... iter_start=${iter_start} + ... http_timeout=${http_timeout} + ... iter_j_offset=${iter_j_offset} + IF ${verify} + Verify_Response_As_Json_Templated + ... response=${response_text} + ... folder=${folder} + ... base_name=response + ... mapping=${mapping} + ... iter_j_offset=${iter_j_offset} + END + RETURN ${response_text} + +Put_As_Xml_Templated [Documentation] Add arguments sensible for XML data, return Put_Templated response text. ... Optionally, verification against response.xml (no iteration) is called. + [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${verify}=False ${iterations}=${EMPTY} ${iter_start}=1 + ... ${http_timeout}=${EMPTY} ${iter_j_offset}=0 # In case of iterations, we use endlines in data to send, as it should not matter and it is more readable. - ${response_text} = Put_Templated folder=${folder} base_name=data extension=xml accept=${ACCEPT_XML} content_type=${HEADERS_XML} - ... mapping=${mapping} session=${session} normalize_json=False endline=${\n} iterations=${iterations} iter_start=${iter_start} - ... http_timeout=${http_timeout} iter_j_offset=${iter_j_offset} - BuiltIn.Run_Keyword_If ${verify} Verify_Response_As_Xml_Templated response=${response_text} folder=${folder} - ... base_name=response mapping=${mapping} iter_j_offset=${iter_j_offset} - [Return] ${response_text} + ${response_text} = Put_Templated + ... folder=${folder} + ... base_name=data + ... extension=xml + ... accept=${ACCEPT_XML} + ... content_type=${HEADERS_XML} + ... mapping=${mapping} + ... session=${session} + ... normalize_json=False + ... endline=${\n} + ... iterations=${iterations} + ... iter_start=${iter_start} + ... http_timeout=${http_timeout} + ... iter_j_offset=${iter_j_offset} + IF ${verify} + Verify_Response_As_Xml_Templated + ... response=${response_text} + ... folder=${folder} + ... base_name=response + ... mapping=${mapping} + ... iter_j_offset=${iter_j_offset} + END + RETURN ${response_text} Post_As_Json_Templated - [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${verify}=False ${iterations}=${EMPTY} ${iter_start}=1 - ... ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${explicit_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} ${iter_j_offset}=0 [Documentation] Add arguments sensible for JSON data, return Post_Templated response text. ... Optionally, verification against response.json (no iteration) is called. ... Only subset of JSON data is verified and returned if JMES path is specified in ... file ${folder}${/}jmespath.expr. ... Response status code must be one of values from ${explicit_status_codes} if specified or one of set ... created from all positive HTTP status codes together with ${additional_allowed_status_codes}. - ${response_text} = Post_Templated folder=${folder} base_name=data extension=json accept=${ACCEPT_EMPTY} content_type=${HEADERS_YANG_JSON} - ... mapping=${mapping} session=${session} normalize_json=True endline=${\n} iterations=${iterations} iter_start=${iter_start} - ... additional_allowed_status_codes=${additional_allowed_status_codes} explicit_status_codes=${explicit_status_codes} http_timeout=${http_timeout} + [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${verify}=False ${iterations}=${EMPTY} ${iter_start}=1 + ... ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${explicit_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} ${iter_j_offset}=0 + ${response_text} = Post_Templated + ... folder=${folder} + ... base_name=data + ... extension=json + ... accept=${ACCEPT_EMPTY} + ... content_type=${HEADERS_YANG_JSON} + ... mapping=${mapping} + ... session=${session} + ... normalize_json=True + ... endline=${\n} + ... iterations=${iterations} + ... iter_start=${iter_start} + ... additional_allowed_status_codes=${additional_allowed_status_codes} + ... explicit_status_codes=${explicit_status_codes} + ... http_timeout=${http_timeout} ... iter_j_offset=${iter_j_offset} - BuiltIn.Run_Keyword_If ${verify} Verify_Response_As_Json_Templated response=${response_text} folder=${folder} - ... base_name=response mapping=${mapping} iter_j_offset=${iter_j_offset} - [Return] ${response_text} + IF ${verify} + Verify_Response_As_Json_Templated + ... response=${response_text} + ... folder=${folder} + ... base_name=response + ... mapping=${mapping} + ... iter_j_offset=${iter_j_offset} + END + RETURN ${response_text} Post_As_Json_Rfc8040_Templated - [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${verify}=False ${iterations}=${EMPTY} ${iter_start}=1 - ... ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${explicit_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} ${iter_j_offset}=0 [Documentation] Add arguments sensible for JSON data, return Post_Templated response text. ... Optionally, verification against response.json (no iteration) is called. ... Only subset of JSON data is verified and returned if JMES path is specified in @@ -213,255 +312,477 @@ Post_As_Json_Rfc8040_Templated ... created from all positive HTTP status codes together with ${additional_allowed_status_codes}. ... RFC8040 defines RESTCONF protocol, for configuring data defined in YANG version 1 ... or YANG version 1.1, using the datastore concepts defined in NETCONF. - ${response_text} = Post_Templated folder=${folder} base_name=data extension=json accept=${ACCEPT_EMPTY} content_type=${HEADERS_YANG_RFC8040_JSON} - ... mapping=${mapping} session=${session} normalize_json=True endline=${\n} iterations=${iterations} iter_start=${iter_start} - ... additional_allowed_status_codes=${additional_allowed_status_codes} explicit_status_codes=${explicit_status_codes} http_timeout=${http_timeout} - ... iter_j_offset=${iter_j_offset} - BuiltIn.Run_Keyword_If ${verify} Verify_Response_As_Json_Templated response=${response_text} folder=${folder} base_name=response mapping=${mapping} + [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${verify}=False ${iterations}=${EMPTY} ${iter_start}=1 + ... ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${explicit_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} ${iter_j_offset}=0 + ${response_text} = Post_Templated + ... folder=${folder} + ... base_name=data + ... extension=json + ... accept=${ACCEPT_EMPTY} + ... content_type=${HEADERS_YANG_RFC8040_JSON} + ... mapping=${mapping} + ... session=${session} + ... normalize_json=True + ... endline=${\n} + ... iterations=${iterations} + ... iter_start=${iter_start} + ... additional_allowed_status_codes=${additional_allowed_status_codes} + ... explicit_status_codes=${explicit_status_codes} + ... http_timeout=${http_timeout} ... iter_j_offset=${iter_j_offset} - [Return] ${response_text} + IF ${verify} + Verify_Response_As_Json_Templated + ... response=${response_text} + ... folder=${folder} + ... base_name=response + ... mapping=${mapping} + ... iter_j_offset=${iter_j_offset} + END + RETURN ${response_text} Post_As_Xml_Templated - [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${verify}=False ${iterations}=${EMPTY} ${iter_start}=1 - ... ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${explicit_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} ${iter_j_offset}=0 [Documentation] Add arguments sensible for XML data, return Post_Templated response text. ... Optionally, verification against response.xml (no iteration) is called. + [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${verify}=False ${iterations}=${EMPTY} ${iter_start}=1 + ... ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${explicit_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} ${iter_j_offset}=0 # In case of iterations, we use endlines in data to send, as it should not matter and it is more readable. - ${response_text} = Post_Templated folder=${folder} base_name=data extension=xml accept=${ACCEPT_XML} content_type=${HEADERS_XML} - ... mapping=${mapping} session=${session} normalize_json=False endline=${\n} iterations=${iterations} iter_start=${iter_start} - ... additional_allowed_status_codes=${additional_allowed_status_codes} explicit_status_codes=${explicit_status_codes} http_timeout=${http_timeout} - ... iter_j_offset=${iter_j_offset} - BuiltIn.Run_Keyword_If ${verify} Verify_Response_As_Xml_Templated response=${response_text} folder=${folder} base_name=response mapping=${mapping} + ${response_text} = Post_Templated + ... folder=${folder} + ... base_name=data + ... extension=xml + ... accept=${ACCEPT_XML} + ... content_type=${HEADERS_XML} + ... mapping=${mapping} + ... session=${session} + ... normalize_json=False + ... endline=${\n} + ... iterations=${iterations} + ... iter_start=${iter_start} + ... additional_allowed_status_codes=${additional_allowed_status_codes} + ... explicit_status_codes=${explicit_status_codes} + ... http_timeout=${http_timeout} ... iter_j_offset=${iter_j_offset} - [Return] ${response_text} + IF ${verify} + Verify_Response_As_Xml_Templated + ... response=${response_text} + ... folder=${folder} + ... base_name=response + ... mapping=${mapping} + ... iter_j_offset=${iter_j_offset} + END + RETURN ${response_text} Delete_Templated - [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} ${location}=location [Documentation] Resolve URI from folder, issue DELETE request. - ${uri} = Resolve_Text_From_Template_Folder folder=${folder} base_name=${location} extension=uri mapping=${mapping} percent_encode=True - ${response_text} = Delete_From_Uri uri=${uri} session=${session} additional_allowed_status_codes=${additional_allowed_status_codes} http_timeout=${http_timeout} - [Return] ${response_text} + [Arguments] ${folder} ${mapping}=&{EMPTY} ${session}=default ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} ${location}=location + ${uri} = Resolve_Text_From_Template_Folder + ... folder=${folder} + ... base_name=${location} + ... extension=uri + ... mapping=${mapping} + ... percent_encode=True + ${response_text} = Delete_From_Uri + ... uri=${uri} + ... session=${session} + ... additional_allowed_status_codes=${additional_allowed_status_codes} + ... http_timeout=${http_timeout} + RETURN ${response_text} Verify_Response_As_Json_Templated - [Arguments] ${response} ${folder} ${base_name}=response ${mapping}=&{EMPTY} ${iterations}=${EMPTY} ${iter_start}=1 ${iter_j_offset}=0 [Documentation] Resolve expected JSON data, should be equal to provided \${response}. ... JSON normalization is used, endlines enabled for readability. - Verify_Response_Templated response=${response} folder=${folder} base_name=${base_name} extension=json mapping=${mapping} normalize_json=True - ... endline=${\n} iterations=${iterations} iter_start=${iter_start} iter_j_offset=${iter_j_offset} + [Arguments] ${response} ${folder} ${base_name}=response ${mapping}=&{EMPTY} ${iterations}=${EMPTY} ${iter_start}=1 ${iter_j_offset}=0 + Verify_Response_Templated + ... response=${response} + ... folder=${folder} + ... base_name=${base_name} + ... extension=json + ... mapping=${mapping} + ... normalize_json=True + ... endline=${\n} + ... iterations=${iterations} + ... iter_start=${iter_start} + ... iter_j_offset=${iter_j_offset} Verify_Response_As_Xml_Templated - [Arguments] ${response} ${folder} ${base_name}=response ${mapping}=&{EMPTY} ${iterations}=${EMPTY} ${iter_start}=1 ${iter_j_offset}=0 [Documentation] Resolve expected XML data, should be equal to provided \${response}. ... Endline set to empty, as this Resource does not support indented XML comparison. - Verify_Response_Templated response=${response} folder=${folder} base_name=${base_name} extension=xml mapping=${mapping} normalize_json=False - ... endline=${EMPTY} iterations=${iterations} iter_start=${iter_start} iter_j_offset=${iter_j_offset} + [Arguments] ${response} ${folder} ${base_name}=response ${mapping}=&{EMPTY} ${iterations}=${EMPTY} ${iter_start}=1 ${iter_j_offset}=0 + Verify_Response_Templated + ... response=${response} + ... folder=${folder} + ... base_name=${base_name} + ... extension=xml + ... mapping=${mapping} + ... normalize_json=False + ... endline=${EMPTY} + ... iterations=${iterations} + ... iter_start=${iter_start} + ... iter_j_offset=${iter_j_offset} Get_As_Json_From_Uri - [Arguments] ${uri} ${session}=default ${http_timeout}=${EMPTY} ${log_response}=True [Documentation] Specify JSON headers and return Get_From_Uri normalized response text. - ${response_text} = Get_From_Uri uri=${uri} accept=${ACCEPT_EMPTY} session=${session} normalize_json=True http_timeout=${http_timeout} log_response=${log_response} - [Return] ${response_text} + [Arguments] ${uri} ${session}=default ${http_timeout}=${EMPTY} ${log_response}=True + ${response_text} = Get_From_Uri + ... uri=${uri} + ... accept=${ACCEPT_EMPTY} + ... session=${session} + ... normalize_json=True + ... http_timeout=${http_timeout} + ... log_response=${log_response} + RETURN ${response_text} Get_As_Xml_From_Uri - [Arguments] ${uri} ${session}=default ${http_timeout}=${EMPTY} ${log_response}=True [Documentation] Specify XML headers and return Get_From_Uri response text. - ${response_text} = Get_From_Uri uri=${uri} accept=${ACCEPT_XML} session=${session} normalize_json=False http_timeout=${http_timeout} log_response=${log_response} - [Return] ${response_text} + [Arguments] ${uri} ${session}=default ${http_timeout}=${EMPTY} ${log_response}=True + ${response_text} = Get_From_Uri + ... uri=${uri} + ... accept=${ACCEPT_XML} + ... session=${session} + ... normalize_json=False + ... http_timeout=${http_timeout} + ... log_response=${log_response} + RETURN ${response_text} Put_As_Json_To_Uri - [Arguments] ${uri} ${data} ${session}=default ${http_timeout}=${EMPTY} [Documentation] Specify JSON headers and return Put_To_Uri normalized response text. ... Yang json content type is used as a workaround to RequestsLibrary json conversion eagerness. - ${response_text} = Put_To_Uri uri=${uri} data=${data} accept=${ACCEPT_EMPTY} content_type=${HEADERS_YANG_JSON} session=${session} - ... normalize_json=True http_timeout=${http_timeout} - [Return] ${response_text} + [Arguments] ${uri} ${data} ${session}=default ${http_timeout}=${EMPTY} + ${response_text} = Put_To_Uri + ... uri=${uri} + ... data=${data} + ... accept=${ACCEPT_EMPTY} + ... content_type=${HEADERS_YANG_JSON} + ... session=${session} + ... normalize_json=True + ... http_timeout=${http_timeout} + RETURN ${response_text} Put_As_Xml_To_Uri - [Arguments] ${uri} ${data} ${session}=default ${http_timeout}=${EMPTY} [Documentation] Specify XML headers and return Put_To_Uri response text. - ${response_text} = Put_To_Uri uri=${uri} data=${data} accept=${ACCEPT_XML} content_type=${HEADERS_XML} session=${session} - ... normalize_json=False http_timeout=${http_timeout} - [Return] ${response_text} + [Arguments] ${uri} ${data} ${session}=default ${http_timeout}=${EMPTY} + ${response_text} = Put_To_Uri + ... uri=${uri} + ... data=${data} + ... accept=${ACCEPT_XML} + ... content_type=${HEADERS_XML} + ... session=${session} + ... normalize_json=False + ... http_timeout=${http_timeout} + RETURN ${response_text} Post_As_Json_To_Uri - [Arguments] ${uri} ${data} ${session}=default ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${explicit_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} [Documentation] Specify JSON headers and return Post_To_Uri normalized response text. ... Yang json content type is used as a workaround to RequestsLibrary json conversion eagerness. ... Response status code must be one of values from ${explicit_status_codes} if specified or one of set ... created from all positive HTTP status codes together with ${additional_allowed_status_codes}. - ${response_text} = Post_To_Uri uri=${uri} data=${data} accept=${ACCEPT_EMPTY} content_type=${HEADERS_YANG_JSON} session=${session} - ... normalize_json=True additional_allowed_status_codes=${additional_allowed_status_codes} explicit_status_codes=${explicit_status_codes} http_timeout=${http_timeout} - [Return] ${response_text} + [Arguments] ${uri} ${data} ${session}=default ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${explicit_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} + ${response_text} = Post_To_Uri + ... uri=${uri} + ... data=${data} + ... accept=${ACCEPT_EMPTY} + ... content_type=${HEADERS_YANG_JSON} + ... session=${session} + ... normalize_json=True + ... additional_allowed_status_codes=${additional_allowed_status_codes} + ... explicit_status_codes=${explicit_status_codes} + ... http_timeout=${http_timeout} + RETURN ${response_text} Post_As_Xml_To_Uri - [Arguments] ${uri} ${data} ${session}=default ${http_timeout}=${EMPTY} [Documentation] Specify XML headers and return Post_To_Uri response text. - ${response_text} = Post_To_Uri uri=${uri} data=${data} accept=${ACCEPT_XML} content_type=${HEADERS_XML} session=${session} - ... normalize_json=False http_timeout=${http_timeout} - [Return] ${response_text} + [Arguments] ${uri} ${data} ${session}=default ${http_timeout}=${EMPTY} + ${response_text} = Post_To_Uri + ... uri=${uri} + ... data=${data} + ... accept=${ACCEPT_XML} + ... content_type=${HEADERS_XML} + ... session=${session} + ... normalize_json=False + ... http_timeout=${http_timeout} + RETURN ${response_text} Delete_From_Uri - [Arguments] ${uri} ${session}=default ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} [Documentation] DELETE resource at URI, check status_code and return response text.. + [Arguments] ${uri} ${session}=default ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} BuiltIn.Log ${uri} - ${response} = BuiltIn.Run_Keyword_If """${http_timeout}""" == """${EMPTY}""" RequestsLibrary.Delete_Request alias=${session} uri=${uri} - ... ELSE RequestsLibrary.Delete_Request alias=${session} uri=${uri} timeout=${http_timeout} + IF """${http_timeout}""" == """${EMPTY}""" + ${response} = RequestsLibrary.Delete_Request alias=${session} uri=${uri} + ELSE + ${response} = RequestsLibrary.Delete_Request alias=${session} uri=${uri} timeout=${http_timeout} + END Check_Status_Code ${response} additional_allowed_status_codes=${additional_allowed_status_codes} - [Return] ${response.text} + RETURN ${response.text} Resolve_Jmes_Path - [Arguments] ${folder} [Documentation] Reads JMES path from file ${folder}${/}jmespath.expr if the file exists and ... returns the JMES path. Empty string is returned otherwise. - ${read_jmes_file} = BuiltIn.Run Keyword And Return Status OperatingSystem.File Should Exist ${folder}${/}jmespath.expr - ${jmes_expression} = Run Keyword If ${read_jmes_file} == ${true} OperatingSystem.Get_File ${folder}${/}jmespath.expr + [Arguments] ${folder} + ${read_jmes_file} = BuiltIn.Run Keyword And Return Status + ... OperatingSystem.File Should Exist + ... ${folder}${/}jmespath.expr + IF ${read_jmes_file} == ${true} + ${jmes_expression} = OperatingSystem.Get_File ${folder}${/}jmespath.expr + ELSE + ${jmes_expression} = Set Variable ${None} + END ${expression} = BuiltIn.Set Variable If ${read_jmes_file} == ${true} ${jmes_expression} ${EMPTY} - [Return] ${expression} + RETURN ${expression} Resolve_Volatiles_Path - [Arguments] ${folder} [Documentation] Reads Volatiles List from file ${folder}${/}volatiles.list if the file exists and ... returns the Volatiles List. Empty string is returned otherwise. - ${read_volatiles_file} = BuiltIn.Run Keyword And Return Status OperatingSystem.File Should Exist ${folder}${/}volatiles.list - Return From Keyword If ${read_volatiles_file} == ${false} ${EMPTY} - ${volatiles}= OperatingSystem.Get_File ${folder}${/}volatiles.list - ${volatiles_list}= String.Split_String ${volatiles} ${\n} - [Return] ${volatiles_list} + [Arguments] ${folder} + ${read_volatiles_file} = BuiltIn.Run Keyword And Return Status + ... OperatingSystem.File Should Exist + ... ${folder}${/}volatiles.list + IF ${read_volatiles_file} == ${false} RETURN ${EMPTY} + ${volatiles} = OperatingSystem.Get_File ${folder}${/}volatiles.list + ${volatiles_list} = String.Split_String ${volatiles} ${\n} + RETURN ${volatiles_list} Get_Templated - [Arguments] ${folder} ${accept} ${mapping}=&{EMPTY} ${session}=default ${normalize_json}=False ${http_timeout}=${EMPTY} ${log_response}=True [Documentation] Resolve URI from folder, call Get_From_Uri, return response text. - ${uri} = Resolve_Text_From_Template_Folder folder=${folder} base_name=location extension=uri mapping=${mapping} percent_encode=True + [Arguments] ${folder} ${accept} ${mapping}=&{EMPTY} ${session}=default ${normalize_json}=False ${http_timeout}=${EMPTY} ${log_response}=True + ${uri} = Resolve_Text_From_Template_Folder + ... folder=${folder} + ... base_name=location + ... extension=uri + ... mapping=${mapping} + ... percent_encode=True ${jmes_expression} = Resolve_Jmes_Path ${folder} - ${volatiles_list}= Resolve_Volatiles_Path ${folder} - ${response_text} = Get_From_Uri uri=${uri} accept=${accept} session=${session} normalize_json=${normalize_json} jmes_path=${jmes_expression} - ... http_timeout=${http_timeout} keys_with_volatiles=${volatiles_list} log_response=${log_response} - [Return] ${response_text} + ${volatiles_list} = Resolve_Volatiles_Path ${folder} + ${response_text} = Get_From_Uri + ... uri=${uri} + ... accept=${accept} + ... session=${session} + ... normalize_json=${normalize_json} + ... jmes_path=${jmes_expression} + ... http_timeout=${http_timeout} + ... keys_with_volatiles=${volatiles_list} + ... log_response=${log_response} + RETURN ${response_text} Put_Templated + [Documentation] Resolve URI and data from folder, call Put_To_Uri, return response text. [Arguments] ${folder} ${base_name} ${extension} ${content_type} ${accept} ${mapping}=&{EMPTY} ... ${session}=default ${normalize_json}=False ${endline}=${\n} ${iterations}=${EMPTY} ${iter_start}=1 ${http_timeout}=${EMPTY} ${iter_j_offset}=0 - [Documentation] Resolve URI and data from folder, call Put_To_Uri, return response text. - ${uri} = Resolve_Text_From_Template_Folder folder=${folder} base_name=location extension=uri mapping=${mapping} percent_encode=True - ${data} = Resolve_Text_From_Template_Folder folder=${folder} base_name=${base_name} extension=${extension} mapping=${mapping} endline=${endline} - ... iterations=${iterations} iter_start=${iter_start} iter_j_offset=${iter_j_offset} + ${uri} = Resolve_Text_From_Template_Folder + ... folder=${folder} + ... base_name=location + ... extension=uri + ... mapping=${mapping} + ... percent_encode=True + ${data} = Resolve_Text_From_Template_Folder + ... folder=${folder} + ... base_name=${base_name} + ... extension=${extension} + ... mapping=${mapping} + ... endline=${endline} + ... iterations=${iterations} + ... iter_start=${iter_start} + ... iter_j_offset=${iter_j_offset} ${jmes_expression} = Resolve_Jmes_Path ${folder} - ${response_text} = Put_To_Uri uri=${uri} data=${data} content_type=${content_type} accept=${accept} session=${session} - ... http_timeout=${http_timeout} normalize_json=${normalize_json} jmes_path=${jmes_expression} - [Return] ${response_text} + ${response_text} = Put_To_Uri + ... uri=${uri} + ... data=${data} + ... content_type=${content_type} + ... accept=${accept} + ... session=${session} + ... http_timeout=${http_timeout} + ... normalize_json=${normalize_json} + ... jmes_path=${jmes_expression} + RETURN ${response_text} Post_Templated + [Documentation] Resolve URI and data from folder, call Post_To_Uri, return response text. [Arguments] ${folder} ${base_name} ${extension} ${content_type} ${accept} ${mapping}=&{EMPTY} ... ${session}=default ${normalize_json}=False ${endline}=${\n} ${iterations}=${EMPTY} ${iter_start}=1 ${additional_allowed_status_codes}=${NO_STATUS_CODES} ... ${explicit_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} ${iter_j_offset}=0 - [Documentation] Resolve URI and data from folder, call Post_To_Uri, return response text. - ${uri} = Resolve_Text_From_Template_Folder folder=${folder} base_name=location extension=uri mapping=${mapping} percent_encode=True - ${data} = Resolve_Text_From_Template_Folder folder=${folder} name_prefix=post_ base_name=${base_name} extension=${extension} mapping=${mapping} - ... endline=${endline} iterations=${iterations} iter_start=${iter_start} iter_j_offset=${iter_j_offset} + ${uri} = Resolve_Text_From_Template_Folder + ... folder=${folder} + ... base_name=location + ... extension=uri + ... mapping=${mapping} + ... percent_encode=True + ${data} = Resolve_Text_From_Template_Folder + ... folder=${folder} + ... name_prefix=post_ + ... base_name=${base_name} + ... extension=${extension} + ... mapping=${mapping} + ... endline=${endline} + ... iterations=${iterations} + ... iter_start=${iter_start} + ... iter_j_offset=${iter_j_offset} ${jmes_expression} = Resolve_Jmes_Path ${folder} - ${response_text} = Post_To_Uri uri=${uri} data=${data} content_type=${content_type} accept=${accept} session=${session} - ... jmes_path=${jmes_expression} normalize_json=${normalize_json} additional_allowed_status_codes=${additional_allowed_status_codes} explicit_status_codes=${explicit_status_codes} http_timeout=${http_timeout} - [Return] ${response_text} + ${response_text} = Post_To_Uri + ... uri=${uri} + ... data=${data} + ... content_type=${content_type} + ... accept=${accept} + ... session=${session} + ... jmes_path=${jmes_expression} + ... normalize_json=${normalize_json} + ... additional_allowed_status_codes=${additional_allowed_status_codes} + ... explicit_status_codes=${explicit_status_codes} + ... http_timeout=${http_timeout} + RETURN ${response_text} Verify_Response_Templated - [Arguments] ${response} ${folder} ${base_name} ${extension} ${mapping}=&{EMPTY} ${normalize_json}=False - ... ${endline}=${\n} ${iterations}=${EMPTY} ${iter_start}=1 ${iter_j_offset}=0 [Documentation] Resolve expected text from template, provided response shuld be equal. ... If \${normalize_json}, perform normalization before comparison. + [Arguments] ${response} ${folder} ${base_name} ${extension} ${mapping}=&{EMPTY} ${normalize_json}=False + ... ${endline}=${\n} ${iterations}=${EMPTY} ${iter_start}=1 ${iter_j_offset}=0 # TODO: Support for XML-aware comparison could be added, but there are issues with namespaces and similar. - ${expected_text} = Resolve_Text_From_Template_Folder folder=${folder} base_name=${base_name} extension=${extension} mapping=${mapping} endline=${endline} - ... iterations=${iterations} iter_start=${iter_start} iter_j_offset=${iter_j_offset} - BuiltIn.Run_Keyword_And_Return_If """${expected_text}""" == """${EMPTY}""" BuiltIn.Should_Be_Equal ${EMPTY} ${response} - BuiltIn.Run_Keyword_If ${normalize_json} Normalize_Jsons_And_Compare expected_raw=${expected_text} actual_raw=${response} - ... ELSE BuiltIn.Should_Be_Equal ${expected_text} ${response} + ${expected_text} = Resolve_Text_From_Template_Folder + ... folder=${folder} + ... base_name=${base_name} + ... extension=${extension} + ... mapping=${mapping} + ... endline=${endline} + ... iterations=${iterations} + ... iter_start=${iter_start} + ... iter_j_offset=${iter_j_offset} + BuiltIn.Run_Keyword_And_Return_If + ... """${expected_text}""" == """${EMPTY}""" + ... BuiltIn.Should_Be_Equal + ... ${EMPTY} + ... ${response} + IF ${normalize_json} + Normalize_Jsons_And_Compare expected_raw=${expected_text} actual_raw=${response} + ELSE + BuiltIn.Should_Be_Equal ${expected_text} ${response} + END Get_From_Uri - [Arguments] ${uri} ${accept}=${ACCEPT_EMPTY} ${session}=default ${normalize_json}=False ${jmes_path}=${EMPTY} ${http_timeout}=${EMPTY} - ... ${keys_with_volatiles}=${EMPTY} ${log_response}=True [Documentation] GET data from given URI, check status code and return response text. ... \${accept} is a Python object with headers to use. ... If \${normalize_json}, normalize as JSON text before returning. + [Arguments] ${uri} ${accept}=${ACCEPT_EMPTY} ${session}=default ${normalize_json}=False ${jmes_path}=${EMPTY} ${http_timeout}=${EMPTY} + ... ${keys_with_volatiles}=${EMPTY} ${log_response}=True BuiltIn.Log ${uri} BuiltIn.Log ${accept} - ${response} = BuiltIn.Run_Keyword_If """${http_timeout}""" == """${EMPTY}""" RequestsLibrary.Get_Request alias=${session} uri=${uri} headers=${accept} - ... ELSE RequestsLibrary.Get_Request alias=${session} uri=${uri} headers=${accept} timeout=${http_timeout} + IF """${http_timeout}""" == """${EMPTY}""" + ${response} = RequestsLibrary.Get_Request alias=${session} uri=${uri} headers=${accept} + ELSE + ${response} = RequestsLibrary.Get_Request + ... alias=${session} + ... uri=${uri} + ... headers=${accept} + ... timeout=${http_timeout} + END Check_Status_Code ${response} log_response=${log_response} - BuiltIn.Run_Keyword_If not ${normalize_json} BuiltIn.Return_From_Keyword ${response.text} - ${text_normalized} = norm_json.normalize_json_text ${response.text} jmes_path=${jmes_path} keys_with_volatiles=${keys_with_volatiles} - [Return] ${text_normalized} + IF not ${normalize_json} RETURN ${response.text} + ${text_normalized} = norm_json.normalize_json_text + ... ${response.text} + ... jmes_path=${jmes_path} + ... keys_with_volatiles=${keys_with_volatiles} + RETURN ${text_normalized} Put_To_Uri - [Arguments] ${uri} ${data} ${content_type} ${accept} ${session}=default ${normalize_json}=False - ... ${jmes_path}=${EMPTY} ${http_timeout}=${EMPTY} [Documentation] PUT data to given URI, check status code and return response text. ... \${content_type} and \${accept} are mandatory Python objects with headers to use. ... If \${normalize_json}, normalize text before returning. + [Arguments] ${uri} ${data} ${content_type} ${accept} ${session}=default ${normalize_json}=False + ... ${jmes_path}=${EMPTY} ${http_timeout}=${EMPTY} BuiltIn.Log ${uri} BuiltIn.Log ${data} BuiltIn.Log ${content_type} BuiltIn.Log ${accept} ${headers} = Join_Two_Headers first=${content_type} second=${accept} - ${response} = BuiltIn.Run_Keyword_If """${http_timeout}""" == """${EMPTY}""" RequestsLibrary.Put_Request alias=${session} uri=${uri} data=${data} - ... headers=${headers} - ... ELSE RequestsLibrary.Put_Request alias=${session} uri=${uri} data=${data} headers=${headers} - ... timeout=${http_timeout} + IF """${http_timeout}""" == """${EMPTY}""" + ${response} = RequestsLibrary.Put_Request + ... alias=${session} + ... uri=${uri} + ... data=${data} + ... headers=${headers} + ELSE + ${response} = RequestsLibrary.Put_Request + ... alias=${session} + ... uri=${uri} + ... data=${data} + ... headers=${headers} + ... timeout=${http_timeout} + END Check_Status_Code ${response} - BuiltIn.Run_Keyword_If not ${normalize_json} BuiltIn.Return_From_Keyword ${response.text} + IF not ${normalize_json} RETURN ${response.text} ${text_normalized} = norm_json.normalize_json_text ${response.text} jmes_path=${jmes_path} - [Return] ${text_normalized} + RETURN ${text_normalized} Post_To_Uri - [Arguments] ${uri} ${data} ${content_type} ${accept} ${session}=default ${normalize_json}=False - ... ${jmes_path}=${EMPTY} ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${explicit_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} [Documentation] POST data to given URI, check status code and return response text. ... \${content_type} and \${accept} are mandatory Python objects with headers to use. ... If \${normalize_json}, normalize text before returning. + [Arguments] ${uri} ${data} ${content_type} ${accept} ${session}=default ${normalize_json}=False + ... ${jmes_path}=${EMPTY} ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${explicit_status_codes}=${NO_STATUS_CODES} ${http_timeout}=${EMPTY} BuiltIn.Log ${uri} BuiltIn.Log ${data} BuiltIn.Log ${content_type} BuiltIn.Log ${accept} ${headers} = Join_Two_Headers first=${content_type} second=${accept} - ${response} = BuiltIn.Run_Keyword_If """${http_timeout}""" == """${EMPTY}""" RequestsLibrary.Post_Request alias=${session} uri=${uri} data=${data} - ... headers=${headers} - ... ELSE RequestsLibrary.Post_Request alias=${session} uri=${uri} data=${data} headers=${headers} - ... timeout=${http_timeout} - Check_Status_Code ${response} additional_allowed_status_codes=${additional_allowed_status_codes} explicit_status_codes=${explicit_status_codes} - BuiltIn.Run_Keyword_If not ${normalize_json} BuiltIn.Return_From_Keyword ${response.text} + IF """${http_timeout}""" == """${EMPTY}""" + ${response} = RequestsLibrary.Post_Request + ... alias=${session} + ... uri=${uri} + ... data=${data} + ... headers=${headers} + ELSE + ${response} = RequestsLibrary.Post_Request + ... alias=${session} + ... uri=${uri} + ... data=${data} + ... headers=${headers} + ... timeout=${http_timeout} + END + Check_Status_Code + ... ${response} + ... additional_allowed_status_codes=${additional_allowed_status_codes} + ... explicit_status_codes=${explicit_status_codes} + IF not ${normalize_json} RETURN ${response.text} ${text_normalized} = norm_json.normalize_json_text ${response.text} jmes_path=${jmes_path} - [Return] ${text_normalized} + RETURN ${text_normalized} Check_Status_Code - [Arguments] ${response} ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${explicit_status_codes}=${NO_STATUS_CODES} ${log_response}=True [Documentation] Log response text, check status_code is one of allowed ones. In cases where this keyword is ... called in a WUKS it could end up logging tons of data and it may be desired to skip the logging by passing ... log_response=False, but by default it remains True. + [Arguments] ${response} ${additional_allowed_status_codes}=${NO_STATUS_CODES} ${explicit_status_codes}=${NO_STATUS_CODES} ${log_response}=True # TODO: Remove overlap with keywords from Utils.robot - Run Keyword If "${log_response}" == "True" BuiltIn.Log ${response.text} - Run Keyword If "${log_response}" == "True" BuiltIn.Log ${response.status_code} + IF "${log_response}" == "True" BuiltIn.Log ${response.text} + IF "${log_response}" == "True" BuiltIn.Log ${response.status_code} # In order to allow other existing keywords to consume this keyword by passing a single non-list status code, we need to # check the type of the argument passed and convert those single non-list codes in to a one item list ${status_codes_type} = Evaluate type($additional_allowed_status_codes).__name__ - ${allowed_status_codes_list} = Run Keyword If "${status_codes_type}"!="list" Create List ${additional_allowed_status_codes} - ... ELSE Set Variable ${additional_allowed_status_codes} + IF "${status_codes_type}"!="list" + ${allowed_status_codes_list} = Create List ${additional_allowed_status_codes} + ELSE + ${allowed_status_codes_list} = Set Variable ${additional_allowed_status_codes} + END ${status_codes_type} = Evaluate type($explicit_status_codes).__name__ - ${explicit_status_codes_list} = Run Keyword If "${status_codes_type}"!="list" Create List ${explicit_status_codes} - ... ELSE Set Variable ${explicit_status_codes} - BuiltIn.Run_Keyword_And_Return_If """${explicit_status_codes_list}""" != """${NO_STATUS_CODES}""" Collections.List_Should_Contain_Value ${explicit_status_codes_list} ${response.status_code} + IF "${status_codes_type}"!="list" + ${explicit_status_codes_list} = Create List ${explicit_status_codes} + ELSE + ${explicit_status_codes_list} = Set Variable ${explicit_status_codes} + END + BuiltIn.Run_Keyword_And_Return_If + ... """${explicit_status_codes_list}""" != """${NO_STATUS_CODES}""" + ... Collections.List_Should_Contain_Value + ... ${explicit_status_codes_list} + ... ${response.status_code} ${final_allowd_list} = Collections.Combine_Lists ${ALLOWED_STATUS_CODES} ${allowed_status_codes_list} Collections.List_Should_Contain_Value ${final_allowd_list} ${response.status_code} Join_Two_Headers - [Arguments] ${first} ${second} [Documentation] Take two dicts, join them, return result. Second argument values take precedence. + [Arguments] ${first} ${second} ${accumulator} = Collections.Copy_Dictionary ${first} ${items_to_add} = Collections.Get_Dictionary_Items ${second} Collections.Set_To_Dictionary ${accumulator} @{items_to_add} BuiltIn.Log ${accumulator} - [Return] ${accumulator} + RETURN ${accumulator} Resolve_Text_From_Template_Folder - [Arguments] ${folder} ${name_prefix}=${EMPTY} ${base_name}=data ${extension}=json ${mapping}=${EMPTY} ${iterations}=${EMPTY} - ... ${iter_start}=1 ${iter_j_offset}=0 ${endline}=${\n} ${percent_encode}=False [Documentation] Read a template from folder, strip endline, make changes according to mapping, return the result. ... If \${iterations} value is present, put text together from "prolog", "item" and "epilog" parts, ... where additional template variable ${i} goes from ${iter_start}, by one ${iterations} times. @@ -469,43 +790,77 @@ Resolve_Text_From_Template_Folder ... used to create non uniform data in order to be able to validate UPDATE operations. ... POST (as opposed to PUT) needs slightly different data, \${name_prefix} may be used to distinguish. ... (Actually, it is GET who formats data differently when URI is a top-level container.) - BuiltIn.Run_Keyword_And_Return_If not "${iterations}" Resolve_Text_From_Template_File folder=${folder} file_name=${name_prefix}${base_name}.${extension} mapping=${mapping} percent_encode=${percent_encode} - ${prolog} = Resolve_Text_From_Template_File folder=${folder} file_name=${name_prefix}${base_name}.prolog.${extension} mapping=${mapping} percent_encode=${percent_encode} - ${epilog} = Resolve_Text_From_Template_File folder=${folder} file_name=${name_prefix}${base_name}.epilog.${extension} mapping=${mapping} percent_encode=${percent_encode} + [Arguments] ${folder} ${name_prefix}=${EMPTY} ${base_name}=data ${extension}=json ${mapping}=${EMPTY} ${iterations}=${EMPTY} + ... ${iter_start}=1 ${iter_j_offset}=0 ${endline}=${\n} ${percent_encode}=False + BuiltIn.Run_Keyword_And_Return_If + ... not "${iterations}" + ... Resolve_Text_From_Template_File + ... folder=${folder} + ... file_name=${name_prefix}${base_name}.${extension} + ... mapping=${mapping} + ... percent_encode=${percent_encode} + ${prolog} = Resolve_Text_From_Template_File + ... folder=${folder} + ... file_name=${name_prefix}${base_name}.prolog.${extension} + ... mapping=${mapping} + ... percent_encode=${percent_encode} + ${epilog} = Resolve_Text_From_Template_File + ... folder=${folder} + ... file_name=${name_prefix}${base_name}.epilog.${extension} + ... mapping=${mapping} + ... percent_encode=${percent_encode} # Even POST uses the same item template (except indentation), so name prefix is ignored. - ${item_template} = Resolve_Text_From_Template_File folder=${folder} file_name=${base_name}.item.${extension} mapping=${mapping} + ${item_template} = Resolve_Text_From_Template_File + ... folder=${folder} + ... file_name=${base_name}.item.${extension} + ... mapping=${mapping} ${items} = BuiltIn.Create_List ${separator} = BuiltIn.Set_Variable_If '${extension}' != 'json' ${endline} ,${endline} FOR ${iteration} IN RANGE ${iter_start} ${iterations}+${iter_start} - BuiltIn.Run_Keyword_If ${iteration} > ${iter_start} Collections.Append_To_List ${items} ${separator} + IF ${iteration} > ${iter_start} + Collections.Append_To_List ${items} ${separator} + END ${j} = BuiltIn.Evaluate ${iteration}+${iter_j_offset} - ${item} = BuiltIn.Evaluate string.Template('''${item_template}''').substitute({"i":"${iteration}", "j":${j}}) modules=string + ${item} = BuiltIn.Evaluate + ... string.Template('''${item_template}''').substitute({"i":"${iteration}", "j":${j}}) + ... modules=string Collections.Append_To_List ${items} ${item} # TODO: The following makes ugly result for iterations=0. Should we fix that? END ${final_text} = BuiltIn.Catenate SEPARATOR= ${prolog} ${endline} @{items} ${endline} ... ${epilog} - [Return] ${final_text} + RETURN ${final_text} Resolve_Text_From_Template_File - [Arguments] ${folder} ${file_name} ${mapping}=&{EMPTY} ${percent_encode}=False [Documentation] Check if ${folder}.${ODL_STREAM}/${file_name} exists. If yes read and Log contents of file ${folder}.${ODL_STREAM}/${file_name}, ... remove endline, perform safe substitution, return result. ... If no do it with the default ${folder}/${file_name}. - ${file_path_stream}= BuiltIn.Set Variable ${folder}.${ODL_STREAM}${/}${file_name} - ${file_stream_exists}= BuiltIn.Run Keyword And Return Status OperatingSystem.File Should Exist ${file_path_stream} - ${file_path}= BuiltIn.Set Variable If ${file_stream_exists} ${file_path_stream} ${folder}${/}${file_name} + [Arguments] ${folder} ${file_name} ${mapping}=&{EMPTY} ${percent_encode}=False + ${file_path_stream} = BuiltIn.Set Variable ${folder}.${ODL_STREAM}${/}${file_name} + ${file_stream_exists} = BuiltIn.Run Keyword And Return Status + ... OperatingSystem.File Should Exist + ... ${file_path_stream} + ${file_path} = BuiltIn.Set Variable If + ... ${file_stream_exists} + ... ${file_path_stream} + ... ${folder}${/}${file_name} ${template} = OperatingSystem.Get_File ${file_path} BuiltIn.Log ${template} - ${mapping_to_use} = BuiltIn.Run_Keyword_If ${percent_encode} == True Encode_Mapping ${mapping} - ... ELSE BuiltIn.Set_Variable ${mapping} - ${final_text} = BuiltIn.Evaluate string.Template('''${template}'''.rstrip()).safe_substitute(${mapping_to_use}) modules=string + IF ${percent_encode} == True + ${mapping_to_use} = Encode_Mapping ${mapping} + ELSE + ${mapping_to_use} = BuiltIn.Set_Variable ${mapping} + END + ${final_text} = BuiltIn.Evaluate + ... string.Template('''${template}'''.rstrip()).safe_substitute(${mapping_to_use}) + ... modules=string + RETURN ${final_text} + # Final text is logged where used. - [Return] ${final_text} Normalize_Jsons_And_Compare - [Arguments] ${expected_raw} ${actual_raw} [Documentation] Use norm_json to normalize both JSON arguments, call Should_Be_Equal. + [Arguments] ${expected_raw} ${actual_raw} ${expected_normalized} = norm_json.normalize_json_text ${expected_raw} ${actual_normalized} = norm_json.normalize_json_text ${actual_raw} # Should_Be_Equal shall print nice diff-style line comparison. @@ -513,8 +868,8 @@ Normalize_Jsons_And_Compare # TODO: Add garbage collection? Check whether the temporary data accumulates. Normalize_Jsons_With_Bits_And_Compare - [Arguments] ${expected_raw} ${actual_raw} ${keys_with_bits}=${KEYS_WITH_BITS} [Documentation] Use norm_json to normalize both JSON arguments, call Should_Be_Equal. + [Arguments] ${expected_raw} ${actual_raw} ${keys_with_bits}=${KEYS_WITH_BITS} ${expected_normalized} = norm_json.normalize_json_text ${expected_raw} keys_with_bits=${keys_with_bits} ${actual_normalized} = norm_json.normalize_json_text ${actual_raw} keys_with_bits=${keys_with_bits} BuiltIn.Should_Be_Equal ${expected_normalized} ${actual_normalized} @@ -527,10 +882,10 @@ Encode_Mapping ${encoded_value} = Percent_Encode_String ${value} Collections.Set_To_Dictionary ${encoded_mapping} ${key} ${encoded_value} END - [Return] ${encoded_mapping} + RETURN ${encoded_mapping} Percent_Encode_String - [Arguments] ${value} [Documentation] Percent encodes reserved characters in the given string so it can be used as part of url. + [Arguments] ${value} ${encoded} = String.Replace_String_Using_Regexp ${value} : %3A - [Return] ${encoded} + RETURN ${encoded} diff --git a/csit/libraries/ToolsSystem.robot b/csit/libraries/ToolsSystem.robot index f7c5f0fa7f..475b051745 100644 --- a/csit/libraries/ToolsSystem.robot +++ b/csit/libraries/ToolsSystem.robot @@ -1,14 +1,17 @@ *** Settings *** -Documentation Library for the tools system nodes. -Library Collections -Library SSHLibrary -Resource Utils.robot -Resource ../variables/Variables.robot +Documentation Library for the tools system nodes. + +Library Collections +Library SSHLibrary +Resource Utils.robot +Resource ../variables/Variables.robot + *** Variables *** -@{TOOLS_SYSTEM_ALL_IPS} @{EMPTY} +@{TOOLS_SYSTEM_ALL_IPS} @{EMPTY} @{TOOLS_SYSTEM_ALL_CONN_IDS} @{EMPTY} + *** Keywords *** Get Tools System Nodes Data FOR ${i} IN RANGE 1 ${NUM_TOOLS_SYSTEM} + 1 @@ -19,8 +22,8 @@ Get Tools System Nodes Data END Run Command On All Tools Systems - [Arguments] ${cmd} [Documentation] Run command on all tools systems + [Arguments] ${cmd} FOR ${ip} IN @{TOOLS_SYSTEM_ALL_IPS} Utils.Run Command On Remote System ${ip} ${cmd} END diff --git a/csit/libraries/TopoprocessingKeywords.robot b/csit/libraries/TopoprocessingKeywords.robot index d4a47cf320..6f60263945 100644 --- a/csit/libraries/TopoprocessingKeywords.robot +++ b/csit/libraries/TopoprocessingKeywords.robot @@ -1,29 +1,31 @@ *** Settings *** -Variables ../variables/Variables.py -Variables ../variables/topoprocessing/Topologies.py -Variables ../variables/topoprocessing/TopologyRequests.py -Library RequestsLibrary -Library SSHLibrary -Library XML -Resource CompareStream.robot -Resource KarafKeywords.robot -Resource SetupUtils.robot -Resource Utils.robot +Variables ../variables/Variables.py +Variables ../variables/topoprocessing/Topologies.py +Variables ../variables/topoprocessing/TopologyRequests.py +Library RequestsLibrary +Library SSHLibrary +Library XML +Resource CompareStream.robot +Resource KarafKeywords.robot +Resource SetupUtils.robot +Resource Utils.robot + *** Variables *** ${CONFIGURATION_XML} ${CURDIR}/../suites/topoprocessing/configuration.xml -${OPERATIONAL_XML} ${CURDIR}/../suites/topoprocessing/operational.xml +${OPERATIONAL_XML} ${CURDIR}/../suites/topoprocessing/operational.xml ${CONFIGURATION_CFG} ${CURDIR}/../suites/topoprocessing/configuration.cfg -${OPERATIONAL_CFG} ${CURDIR}/../suites/topoprocessing/operational.cfg -${REMOTE_XML_FILE} ${WORKSPACE}/${BUNDLEFOLDER}/etc/opendaylight/karaf/80-topoprocessing-config.xml -${REMOTE_CFG_FILE} ${WORKSPACE}/${BUNDLEFOLDER}/etc/org.opendaylight.topoprocessing.cfg -${OUTPUT_TOPO_NAME} topo:1 -${OVERLAY_TOPO_URL} ${TOPOLOGY_URL}/${OUTPUT_TOPO_NAME} +${OPERATIONAL_CFG} ${CURDIR}/../suites/topoprocessing/operational.cfg +${REMOTE_XML_FILE} ${WORKSPACE}/${BUNDLEFOLDER}/etc/opendaylight/karaf/80-topoprocessing-config.xml +${REMOTE_CFG_FILE} ${WORKSPACE}/${BUNDLEFOLDER}/etc/org.opendaylight.topoprocessing.cfg +${OUTPUT_TOPO_NAME} topo:1 +${OVERLAY_TOPO_URL} ${TOPOLOGY_URL}/${OUTPUT_TOPO_NAME} + *** Keywords *** Basic Request Put - [Arguments] ${request} ${overlay_topology_url} [Documentation] Send a simple HTTP PUT request to Configurational datastore + [Arguments] ${request} ${overlay_topology_url} ${resp} Put Request session ${CONFIG_API}/${overlay_topology_url} data=${request} Log ${CONFIG_API}/${overlay_topology_url} Should Match "${resp.status_code}" "20?" @@ -31,36 +33,36 @@ Basic Request Put Wait For Karaf Log Transaction successfully written Basic Request Get - [Arguments] ${overlay_topology_url} [Documentation] Send a simple HTTP GET request to a given URL + [Arguments] ${overlay_topology_url} ${resp} Get Request session ${OPERATIONAL_API}/${overlay_topology_url} Should Be Equal As Strings ${resp.status_code} 200 - [Return] ${resp} + RETURN ${resp} Send Basic Delete Request - [Arguments] ${url} [Documentation] Sends a HTTP/DELETE request to a given URL + [Arguments] ${url} ${resp} Delete Request session ${CONFIG_API}/${url} Log Deleting ${CONFIG_API}/${url} - [Return] ${resp} + RETURN ${resp} Delete Underlay Node - [Arguments] ${topology-id} ${node-id} [Documentation] Deletes a node from an underlay topology + [Arguments] ${topology-id} ${node-id} ${resp} Send Basic Delete Request ${TOPOLOGY_URL}/${topology-id}/node/${node-id} - [Return] ${resp} + RETURN ${resp} Delete Underlay Termination Point - [Arguments] ${topology-id} ${node-id} ${tp-id} [Documentation] Deletes a termination point from an underlay topology + [Arguments] ${topology-id} ${node-id} ${tp-id} ${resp} Send Basic Delete Request ${TOPOLOGY_URL}/${topology-id}/node/${node-id}/termination-point/${tp-id} - [Return] ${resp} + RETURN ${resp} Delete Underlay Link - [Arguments] ${topology-id} ${link-id} [Documentation] Deletes a link from an underlay topology + [Arguments] ${topology-id} ${link-id} ${resp} Send Basic Delete Request ${TOPOLOGY_URL}/${topology-id}/link/${link-id} - [Return] ${resp} + RETURN ${resp} Setup Environment [Documentation] Setup karaf enviroment for following tests @@ -70,32 +72,44 @@ Setup Environment Flexible Controller Login Put File ${CONFIGURATION_CFG} ${REMOTE_CFG_FILE} Close Connection - Wait Until Keyword Succeeds 2x 2s Issue Command On Karaf Console log:set DEBUG org.opendaylight.topoprocessing - Create Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} auth=${AUTH} headers=${SEND_ACCEPT_XML_HEADERS} + Wait Until Keyword Succeeds + ... 2x + ... 2s + ... Issue Command On Karaf Console + ... log:set DEBUG org.opendaylight.topoprocessing + Create Session + ... session + ... http://${ODL_SYSTEM_IP}:${RESTCONFPORT} + ... auth=${AUTH} + ... headers=${SEND_ACCEPT_XML_HEADERS} Prepare New Feature Installation Insert Underlay topologies Install Features - [Arguments] ${features} ${timeout}=180 [Documentation] Install features according to tested distribution + [Arguments] ${features} ${timeout}=180 Install Features for Other Distributions ${features} ${timeout} Install Features for Beryllium Distribution - [Arguments] ${features} ${timeout} [Documentation] Will wait for features to install only once per run + [Arguments] ${features} ${timeout} Install a Feature ${features} timeout=${timeout} Set Global Variable If It Does Not Exist \${WAIT_FOR_FEATURES_TO_INSTALL} ${TRUE} - Run Keyword If ${WAIT_FOR_FEATURES_TO_INSTALL} Run Keywords Wait For Karaf Log Registering Topology Request Listener ${timeout} - ... AND Set Global Variable \${WAIT_FOR_FEATURES_TO_INSTALL} ${FALSE} + IF ${WAIT_FOR_FEATURES_TO_INSTALL} + Wait For Karaf Log Registering Topology Request Listener ${timeout} + Set Global Variable \${WAIT_FOR_FEATURES_TO_INSTALL} ${FALSE} + END Install Features for Other Distributions - [Arguments] ${features} ${timeout} [Documentation] Will wait for features to install only if no topoprocessing feature was installed + [Arguments] ${features} ${timeout} ${installed_features} Issue Command On Karaf Console feature:list -i ${lines} Get Lines Containing String ${installed_features} odl-topoprocessing-framework ${length} Get Length ${lines} Install a Feature ${features} timeout=${timeout} - Run Keyword If ${length} == 0 Wait For Karaf Log Registering Topology Request Listener ${timeout} + IF ${length} == 0 + Wait For Karaf Log Registering Topology Request Listener ${timeout} + END Clean Environment [Documentation] Revert startup changes @@ -137,7 +151,10 @@ Insert Underlay Topologies Log Inserting underlay topologies # Network underlay topologies FOR ${index} IN RANGE 1 7 - ${resp} Put Request session ${CONFIG_API}/${TOPOLOGY_URL}/network-topo:${index} data=${NETWORK_UNDERLAY_TOPOLOGY_${index}} + ${resp} Put Request + ... session + ... ${CONFIG_API}/${TOPOLOGY_URL}/network-topo:${index} + ... data=${NETWORK_UNDERLAY_TOPOLOGY_${index}} Log ${resp.text} Should Match "${resp.status_code}" "20?" # Openflow underlay nodes @@ -147,7 +164,10 @@ Insert Underlay Topologies Should Match "${resp.status_code}" "20?" # Openflow underlay topologies FOR ${index} IN RANGE 1 7 - ${resp} Put Request session ${CONFIG_API}/${TOPOLOGY_URL}/openflow-topo:${index} data=${OPENFLOW_UNDERLAY_TOPOLOGY_${index}} + ${resp} Put Request + ... session + ... ${CONFIG_API}/${TOPOLOGY_URL}/openflow-topo:${index} + ... data=${OPENFLOW_UNDERLAY_TOPOLOGY_${index}} Log ${resp.text} Should Match "${resp.status_code}" "20?" END @@ -155,210 +175,365 @@ Insert Underlay Topologies Log ${resp.text} Prepare Unification Inside Topology Request - [Arguments] ${request_template} ${model} ${correlation_item} ${underlay_topo1} [Documentation] Prepare topology request for unification inside from template + [Arguments] ${request_template} ${model} ${correlation_item} ${underlay_topo1} ${request_template} Set Element Text ${request_template} ${model} xpath=.//correlations/output-model - ${request_template} Set Element Text ${request_template} aggregation-only xpath=.//correlations/correlation/type - ${request_template} Set Element Text ${request_template} ${correlation_item} xpath=.//correlation/correlation-item - ${request_template} Set Element Text ${request_template} unification xpath=.//correlation/aggregation/aggregation-type - ${request_template} Set Element Text ${request_template} ${model} xpath=.//correlation/aggregation/mapping[1]/input-model - ${request_template} Set Element Text ${request_template} ${underlay_topo1} xpath=.//correlation/aggregation/mapping[1]/underlay-topology + ${request_template} Set Element Text + ... ${request_template} + ... aggregation-only + ... xpath=.//correlations/correlation/type + ${request_template} Set Element Text + ... ${request_template} + ... ${correlation_item} + ... xpath=.//correlation/correlation-item + ${request_template} Set Element Text + ... ${request_template} + ... unification + ... xpath=.//correlation/aggregation/aggregation-type + ${request_template} Set Element Text + ... ${request_template} + ... ${model} + ... xpath=.//correlation/aggregation/mapping[1]/input-model + ${request_template} Set Element Text + ... ${request_template} + ... ${underlay_topo1} + ... xpath=.//correlation/aggregation/mapping[1]/underlay-topology ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Prepare Unification Topology Request - [Arguments] ${request_template} ${model} ${correlation_item} ${underlay_topo1} ${underlay_topo2} [Documentation] Prepare topology request for unification on two topologies from template - ${request_template} Prepare Unification Inside Topology Request ${request_template} ${model} ${correlation_item} ${underlay_topo1} - ${request_template} Set Element Text ${request_template} ${underlay_topo2} xpath=.//correlation/aggregation/mapping[2]/underlay-topology - ${request_template} Set Element Text ${request_template} ${model} xpath=.//correlation/aggregation/mapping[2]/input-model + [Arguments] ${request_template} ${model} ${correlation_item} ${underlay_topo1} ${underlay_topo2} + ${request_template} Prepare Unification Inside Topology Request + ... ${request_template} + ... ${model} + ... ${correlation_item} + ... ${underlay_topo1} + ${request_template} Set Element Text + ... ${request_template} + ... ${underlay_topo2} + ... xpath=.//correlation/aggregation/mapping[2]/underlay-topology + ${request_template} Set Element Text + ... ${request_template} + ... ${model} + ... xpath=.//correlation/aggregation/mapping[2]/input-model ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Prepare Unification Filtration Topology Request + [Documentation] Prepare topology request for unification on two topologies from template [Arguments] ${request_template} ${model} ${correlation_item} ${target_field1} ${underlay_topo1} ${target_field2} ... ${underlay_topo2} - [Documentation] Prepare topology request for unification on two topologies from template - ${request_template} Prepare Unification Filtration Inside Topology Request ${request_template} ${model} ${correlation_item} ${target_field1} ${underlay_topo1} - ${request_template} Set Element Text ${request_template} ${underlay_topo2} xpath=.//correlation/aggregation/mapping[2]/underlay-topology + ${request_template} Prepare Unification Filtration Inside Topology Request + ... ${request_template} + ... ${model} + ... ${correlation_item} + ... ${target_field1} + ... ${underlay_topo1} + ${request_template} Set Element Text + ... ${request_template} + ... ${underlay_topo2} + ... xpath=.//correlation/aggregation/mapping[2]/underlay-topology Insert Target Field ${request_template} 2 ${target_field2} 1 - ${request_template} Set Element Text ${request_template} ${model} xpath=.//correlation/aggregation/mapping[2]/input-model + ${request_template} Set Element Text + ... ${request_template} + ... ${model} + ... xpath=.//correlation/aggregation/mapping[2]/input-model ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Prepare Unification Filtration Inside Topology Request - [Arguments] ${request_template} ${model} ${correlation_item} ${target-field} ${underlay_topo} [Documentation] Prepare topology request for unification filtration inside from template + [Arguments] ${request_template} ${model} ${correlation_item} ${target-field} ${underlay_topo} ${request_template} Set Element Text ${request_template} ${model} xpath=.//correlations/output-model - ${request_template} Set Element Text ${request_template} filtration-aggregation xpath=.//correlations/correlation/type - ${request_template} Set Element Text ${request_template} ${correlation_item} xpath=.//correlation/correlation-item - ${request_template} Set Element Text ${request_template} unification xpath=.//correlation/aggregation/aggregation-type - ${request_template} Set Element Text ${request_template} ${model} xpath=.//correlation/aggregation/mapping[1]/input-model - ${request_template} Set Element Text ${request_template} ${underlay_topo} xpath=.//correlation/aggregation/mapping[1]/underlay-topology + ${request_template} Set Element Text + ... ${request_template} + ... filtration-aggregation + ... xpath=.//correlations/correlation/type + ${request_template} Set Element Text + ... ${request_template} + ... ${correlation_item} + ... xpath=.//correlation/correlation-item + ${request_template} Set Element Text + ... ${request_template} + ... unification + ... xpath=.//correlation/aggregation/aggregation-type + ${request_template} Set Element Text + ... ${request_template} + ... ${model} + ... xpath=.//correlation/aggregation/mapping[1]/input-model + ${request_template} Set Element Text + ... ${request_template} + ... ${underlay_topo} + ... xpath=.//correlation/aggregation/mapping[1]/underlay-topology Insert Target Field ${request_template} 1 ${target-field} 1 - ${request_template} Set Element Text ${request_template} ${underlay_topo} xpath=.//correlation/filtration/underlay-topology + ${request_template} Set Element Text + ... ${request_template} + ... ${underlay_topo} + ... xpath=.//correlation/filtration/underlay-topology ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Insert Apply Filters [Arguments] ${request_template} ${mapping} ${filter_id} - ${request_template} Add Element ${request_template} ${APPLY_FILTERS} xpath=.//correlation/aggregation/mapping[${mapping}] - ${request_template} Set Element Text ${request_template} ${filter_id} xpath=.//correlation/aggregation/mapping[${mapping}]/apply-filters - [Return] ${request_template} + ${request_template} Add Element + ... ${request_template} + ... ${APPLY_FILTERS} + ... xpath=.//correlation/aggregation/mapping[${mapping}] + ${request_template} Set Element Text + ... ${request_template} + ... ${filter_id} + ... xpath=.//correlation/aggregation/mapping[${mapping}]/apply-filters + RETURN ${request_template} Prepare Filtration Topology Request - [Arguments] ${request_template} ${model} ${correlation_item} ${underlay_topo} [Documentation] Prepare topology request for filtration from template + [Arguments] ${request_template} ${model} ${correlation_item} ${underlay_topo} ${request_template} Set Element Text ${request_template} ${model} xpath=.//correlations/output-model - ${request_template} Set Element Text ${request_template} ${correlation_item} xpath=.//correlation/correlation-item - ${request_template} Set Element Text ${request_template} ${underlay_topo} xpath=.//correlation/filtration/underlay-topology - [Return] ${request_template} + ${request_template} Set Element Text + ... ${request_template} + ... ${correlation_item} + ... xpath=.//correlation/correlation-item + ${request_template} Set Element Text + ... ${request_template} + ... ${underlay_topo} + ... xpath=.//correlation/filtration/underlay-topology + RETURN ${request_template} Insert Target Field - [Arguments] ${request_template} ${mapping_index} ${target_field_path} ${matching_key} [Documentation] Add target field to request - ${target_field_template} Set Element Text ${TARGET_FIELD} ${target_field_path} xpath=.//target-field-path - ${target_field_template} Set Element Text ${target_field_template} ${matching_key} xpath=.//matching-key - ${request_template} Add Element ${request_template} ${target_field_template} xpath=.//correlation/aggregation/mapping[${mapping_index}] + [Arguments] ${request_template} ${mapping_index} ${target_field_path} ${matching_key} + ${target_field_template} Set Element Text + ... ${TARGET_FIELD} + ... ${target_field_path} + ... xpath=.//target-field-path + ${target_field_template} Set Element Text + ... ${target_field_template} + ... ${matching_key} + ... xpath=.//matching-key + ${request_template} Add Element + ... ${request_template} + ... ${target_field_template} + ... xpath=.//correlation/aggregation/mapping[${mapping_index}] ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Insert Filter - [Arguments] ${request_template} ${filter_template} ${target_field} [Documentation] Add filter to filtration + [Arguments] ${request_template} ${filter_template} ${target_field} ${request_template} Add Element ${request_template} ${filter_template} xpath=.//correlation/filtration ${model} Get Element Text ${request_template} xpath=.//correlations/output-model - ${request_template} Set Element Text ${request_template} ${model} xpath=.//correlation/filtration/filter/input-model - ${request_template} Set Element Text ${request_template} ${target_field} xpath=.//correlation/filtration/filter/target-field - [Return] ${request_template} + ${request_template} Set Element Text + ... ${request_template} + ... ${model} + ... xpath=.//correlation/filtration/filter/input-model + ${request_template} Set Element Text + ... ${request_template} + ... ${target_field} + ... xpath=.//correlation/filtration/filter/target-field + RETURN ${request_template} Insert Filter With ID - [Arguments] ${request_template} ${filter_template} ${target_field} ${filter_id} [Documentation] Add filter to filtration with specified id + [Arguments] ${request_template} ${filter_template} ${target_field} ${filter_id} ${request_template} Insert Filter ${request_template} ${filter_template} ${target_field} - ${request_template} Set Element Text ${request_template} ${filter_id} xpath=.//correlation/filtration/filter/filter-id - [Return] ${request_template} + ${request_template} Set Element Text + ... ${request_template} + ... ${filter_id} + ... xpath=.//correlation/filtration/filter/filter-id + RETURN ${request_template} Set IPV4 Filter - [Arguments] ${request_template} ${ip_address} [Documentation] Set filter ipv4 address - ${request_template} Set Element Text ${request_template} ${ip_address} xpath=.//correlation/filtration/filter/ipv4-address-filter/ipv4-address + [Arguments] ${request_template} ${ip_address} + ${request_template} Set Element Text + ... ${request_template} + ... ${ip_address} + ... xpath=.//correlation/filtration/filter/ipv4-address-filter/ipv4-address ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Set Range Number Filter - [Arguments] ${request_template} ${min_number} ${max_number} [Documentation] Set filter minimum and maximum number values - ${request_template} Set Element Text ${request_template} ${min_number} xpath=.//correlation/filtration/filter/range-number-filter/min-number-value - ${request_template} Set Element Text ${request_template} ${max_number} xpath=.//correlation/filtration/filter/range-number-filter/max-number-value + [Arguments] ${request_template} ${min_number} ${max_number} + ${request_template} Set Element Text + ... ${request_template} + ... ${min_number} + ... xpath=.//correlation/filtration/filter/range-number-filter/min-number-value + ${request_template} Set Element Text + ... ${request_template} + ... ${max_number} + ... xpath=.//correlation/filtration/filter/range-number-filter/max-number-value ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Set Range String Filter - [Arguments] ${request_template} ${min_value} ${max_value} [Documentation] Set filter minimum and maximum string values - ${request_template} Set Element Text ${request_template} ${min_value} xpath=.//correlation/filtration/filter/range-string-filter/min-string-value - ${request_template} Set Element Text ${request_template} ${max_value} xpath=.//correlation/filtration/filter/range-string-filter/max-string-value + [Arguments] ${request_template} ${min_value} ${max_value} + ${request_template} Set Element Text + ... ${request_template} + ... ${min_value} + ... xpath=.//correlation/filtration/filter/range-string-filter/min-string-value + ${request_template} Set Element Text + ... ${request_template} + ... ${max_value} + ... xpath=.//correlation/filtration/filter/range-string-filter/max-string-value ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Set Specific Number Filter - [Arguments] ${request_template} ${number} [Documentation] Set filter number value - ${request_template} Set Element Text ${request_template} ${number} xpath=.//correlation/filtration/filter/specific-number-filter/specific-number + [Arguments] ${request_template} ${number} + ${request_template} Set Element Text + ... ${request_template} + ... ${number} + ... xpath=.//correlation/filtration/filter/specific-number-filter/specific-number ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Set Specific String Filter - [Arguments] ${request_template} ${string_value} [Documentation] Set filter string value - ${request_template} Set Element Text ${request_template} ${string_value} xpath=.//correlation/filtration/filter/specific-string-filter/specific-string + [Arguments] ${request_template} ${string_value} + ${request_template} Set Element Text + ... ${request_template} + ... ${string_value} + ... xpath=.//correlation/filtration/filter/specific-string-filter/specific-string ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Set IPV6 Filter - [Arguments] ${request_template} ${ip_address} [Documentation] Set filter ipv6 address - ${request_template} Set Element Text ${request_template} ${ip_address} xpath=.//correlation/filtration/filter/ipv6-address-filter/ipv6-address + [Arguments] ${request_template} ${ip_address} + ${request_template} Set Element Text + ... ${request_template} + ... ${ip_address} + ... xpath=.//correlation/filtration/filter/ipv6-address-filter/ipv6-address ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Set Script Filter - [Arguments] ${request_template} ${script_language} ${script} [Documentation] Set filter script - ${request_template} Set Element Text ${request_template} ${script_language} xpath=.//correlation/filtration/filter/script-filter/scripting/language - ${request_template} Set Element Text ${request_template} ${script} xpath=.//correlation/filtration/filter/script-filter/scripting/script + [Arguments] ${request_template} ${script_language} ${script} + ${request_template} Set Element Text + ... ${request_template} + ... ${script_language} + ... xpath=.//correlation/filtration/filter/script-filter/scripting/language + ${request_template} Set Element Text + ... ${request_template} + ... ${script} + ... xpath=.//correlation/filtration/filter/script-filter/scripting/script ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Insert Link Computation Inside - [Arguments] ${request_template} ${link_computation_template} ${input_model} ${underlay_topology} [Documentation] Add link computation to request + [Arguments] ${request_template} ${link_computation_template} ${input_model} ${underlay_topology} ${request_template} Add Element ${request_template} ${link_computation_template} xpath=. - ${request_template} Set Element Text ${request_template} ${input_model} xpath=.//link-computation/node-info/input-model - ${request_template} Set Element Text ${request_template} ${input_model} xpath=.//link-computation/link-info/input-model - ${request_template} Set Element Text ${request_template} ${input_model} xpath=.//link-computation/output-model - ${request_template} Set Element Text ${request_template} ${underlay_topology} xpath=.//link-computation/link-info/link-topology - ${request_template} Set Element Attribute ${request_template} xmlns:n urn:opendaylight:topology:correlation xpath=./link-computation + ${request_template} Set Element Text + ... ${request_template} + ... ${input_model} + ... xpath=.//link-computation/node-info/input-model + ${request_template} Set Element Text + ... ${request_template} + ... ${input_model} + ... xpath=.//link-computation/link-info/input-model + ${request_template} Set Element Text + ... ${request_template} + ... ${input_model} + ... xpath=.//link-computation/output-model + ${request_template} Set Element Text + ... ${request_template} + ... ${underlay_topology} + ... xpath=.//link-computation/link-info/link-topology + ${request_template} Set Element Attribute + ... ${request_template} + ... xmlns:n + ... urn:opendaylight:topology:correlation + ... xpath=./link-computation ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Insert Link Computation - [Arguments] ${request_template} ${link_computation_template} ${input_model} ${underlay_topology_1} ${underlay_topology_2} [Documentation] Add link computation to request + [Arguments] ${request_template} ${link_computation_template} ${input_model} ${underlay_topology_1} ${underlay_topology_2} ${request_template} Add Element ${request_template} ${link_computation_template} xpath=. - ${request_template} Set Element Text ${request_template} ${input_model} xpath=.//link-computation/node-info/input-model - ${request_template} Set Element Text ${request_template} ${input_model} xpath=.//link-computation/link-info[1]/input-model - ${request_template} Set Element Text ${request_template} ${input_model} xpath=.//link-computation/link-info[2]/input-model - ${request_template} Set Element Text ${request_template} ${input_model} xpath=.//link-computation/output-model - ${request_template} Set Element Text ${request_template} ${underlay_topology_1} xpath=.//link-computation/link-info[1]/link-topology - ${request_template} Set Element Text ${request_template} ${underlay_topology_2} xpath=.//link-computation/link-info[2]/link-topology - ${request_template} Set Element Attribute ${request_template} xmlns:n urn:opendaylight:topology:correlation xpath=./link-computation + ${request_template} Set Element Text + ... ${request_template} + ... ${input_model} + ... xpath=.//link-computation/node-info/input-model + ${request_template} Set Element Text + ... ${request_template} + ... ${input_model} + ... xpath=.//link-computation/link-info[1]/input-model + ${request_template} Set Element Text + ... ${request_template} + ... ${input_model} + ... xpath=.//link-computation/link-info[2]/input-model + ${request_template} Set Element Text + ... ${request_template} + ... ${input_model} + ... xpath=.//link-computation/output-model + ${request_template} Set Element Text + ... ${request_template} + ... ${underlay_topology_1} + ... xpath=.//link-computation/link-info[1]/link-topology + ${request_template} Set Element Text + ... ${request_template} + ... ${underlay_topology_2} + ... xpath=.//link-computation/link-info[2]/link-topology + ${request_template} Set Element Attribute + ... ${request_template} + ... xmlns:n + ... urn:opendaylight:topology:correlation + ... xpath=./link-computation ${request_template} Element to String ${request_template} - [Return] ${request_template} + RETURN ${request_template} Insert Scripting into Request - [Arguments] ${request} ${language} ${script} [Documentation] Insert Scripting into Request under aggregation node + [Arguments] ${request} ${language} ${script} ${request} Add Element ${request} ${SCRIPTING} xpath=.//correlation/aggregation ${request} Set Element Text ${request} ${script} xpath=.//correlation/aggregation/scripting/script ${request} Set Element Text ${request} ${language} xpath=.//correlation/aggregation/scripting/language ${request} Element to String ${request} - [Return] ${request} + RETURN ${request} Create Isis Node - [Arguments] ${node-id} ${ovs-version}=23 ${router-id-ipv4}=10.0.0.1 [Documentation] Create an isis node element with id and ip + [Arguments] ${node-id} ${ovs-version}=23 ${router-id-ipv4}=10.0.0.1 ${request} Set Element Text ${NODE_ISIS} ${node-id} xpath=.//node-id ${request} Set Element Text ${request} ${ovs-version} xpath=.//ovs-version - ${request} Set Element Text ${request} ${router-id-ipv4} xpath=.//igp-node-attributes/isis-node-attributes/ted/te-router-id-ipv4 + ${request} Set Element Text + ... ${request} + ... ${router-id-ipv4} + ... xpath=.//igp-node-attributes/isis-node-attributes/ted/te-router-id-ipv4 ${request} Element to String ${request} - [Return] ${request} + RETURN ${request} Create Openflow Node - [Arguments] ${node-id} ${ip-address}=10.0.0.1 ${serial-number}=27 [Documentation] Create an Openflow node element with id and ip + [Arguments] ${node-id} ${ip-address}=10.0.0.1 ${serial-number}=27 ${request} Set Element Text ${NODE_OPENFLOW} ${node-id} xpath=.//id ${request} Set Element Text ${request} ${ip-address} xpath=.//ip-address ${request} Set Element Text ${request} ${serial-number} xpath=.//serial-number ${request} Element to String ${request} - [Return] ${request} + RETURN ${request} Create OVSDB Termination Point - [Arguments] ${tp-id} ${ofport} [Documentation] Create an OVSDB termination point element with id and port + [Arguments] ${tp-id} ${ofport} ${request} Set Element Text ${TERMINATION_POINT_OVSDB} ${tp-id} xpath=.//tp-id ${request} Set Element Text ${request} ${ofport} xpath=.//ofport ${request} Element to String ${request} - [Return] ${request} + RETURN ${request} Create Openflow Node Connector - [Arguments] ${nc-id} ${port-number} [Documentation] Create an Openflow node connector element with id and port number + [Arguments] ${nc-id} ${port-number} ${request} Set Element Text ${NODE_CONNECTOR_OPENFLOW} ${nc-id} xpath=.//id ${request} Set Element Text ${request} ${port-number} xpath=.//port-number ${request} Element to String ${request} - [Return] ${request} + RETURN ${request} Create Link [Arguments] ${link-id} ${source-node} ${dest-node} ${name} ${metric} @@ -368,42 +543,50 @@ Create Link ${request} Set Element Text ${request} ${name} xpath=.//igp-link-attributes/name ${request} Set Element Text ${request} ${metric} xpath=.//igp-link-attributes/metric ${request} Element to String ${request} - [Return] ${request} + RETURN ${request} Extract Node from Topology - [Arguments] ${topology} ${supp_node_id} [Documentation] Returns node that contains supporting node with ID specified in argument supp_node_id + [Arguments] ${topology} ${supp_node_id} ${xpath} Set Variable .//node/supporting-node[node-ref='${supp_node_id}']/.. ${node} Get Element ${topology} xpath=${xpath} ${node} Element to String ${node} - [Return] ${node} + RETURN ${node} Extract Termination Point from Topology - [Arguments] ${model} ${topology} ${topo_id} ${node_id} ${tp_id} [Documentation] Returns termination point that contains supporting termination point from specified topology, node and with specified id + [Arguments] ${model} ${topology} ${topo_id} ${node_id} ${tp_id} Check Supported Model ${model} - ${xpath} Set Variable If '${model}' == 'network-topology-model' or '${model}' == 'opendaylight-inventory-model' .//termination-point[tp-ref='/network-topology:network-topology/topology/${topo_id}/node/${node_id}/termination-point/${tp_id}'] .//termination-point/supporting-termination-point[tp-ref='${tp_id}']/.. + ${xpath} Set Variable If + ... '${model}' == 'network-topology-model' or '${model}' == 'opendaylight-inventory-model' + ... .//termination-point[tp-ref='/network-topology:network-topology/topology/${topo_id}/node/${node_id}/termination-point/${tp_id}'] + ... .//termination-point/supporting-termination-point[tp-ref='${tp_id}']/.. ${tp} Get Element ${topology} xpath=${xpath} ${tp} Element to String ${tp} - [Return] ${tp} + RETURN ${tp} Extract Link from Topology - [Arguments] ${model} ${topology} ${topo_id} ${link_id} [Documentation] Returns link that contains supporting link + [Arguments] ${model} ${topology} ${topo_id} ${link_id} Check Supported Model ${model} - ${xpath} Set Variable If '${model}' == 'network-topology-model' or '${model}' == 'opendaylight-inventory-model' .//link/supporting-link[link-ref='/network-topology/topology/${topo_id}/link/${link_id}']/.. .//link/supporting-link[tp-ref='${tp_id}']/.. + ${xpath} Set Variable If + ... '${model}' == 'network-topology-model' or '${model}' == 'opendaylight-inventory-model' + ... .//link/supporting-link[link-ref='/network-topology/topology/${topo_id}/link/${link_id}']/.. + ... .//link/supporting-link[tp-ref='${tp_id}']/.. ${link} Get Element ${topology} xpath=${xpath} ${link} Element to String ${link} - [Return] ${link} + RETURN ${link} Check Supported Model - [Arguments] ${model} [Documentation] Checks if model is supported. - Run Keyword If '${model}' != 'network-topology-model' and '${model}' != 'i2rs-model' and '${model}' != 'opendaylight-inventory-model' Fail Not supported model + [Arguments] ${model} + IF '${model}' != 'network-topology-model' and '${model}' != 'i2rs-model' and '${model}' != 'opendaylight-inventory-model' + Fail Not supported model + END Check Aggregated Node in Topology - [Arguments] ${model} ${topology} ${tp_count} @{supp_node_ids} [Documentation] Checks number of termination points and concrete supporting nodes in aggregated node and returns overlay node id. Model should be 'network-topology-model', 'opendaylight-inventory-model' or 'i2rs-model'. + [Arguments] ${model} ${topology} ${tp_count} @{supp_node_ids} Check Supported Model ${model} ${node_id} Get From List ${supp_node_ids} 0 ${aggregated_node} Extract Node from Topology ${topology} ${node_id} @@ -412,16 +595,24 @@ Check Aggregated Node in Topology Should Contain X Times ${aggregated_node} ${tp_count} Should Contain X Times ${aggregated_node} ${tp_count} FOR ${supp_node_id} IN @{supp_node_ids} - Element Text Should Be ${aggregated_node} ${supp_node_id} xpath=.//supporting-node[node-ref='${supp_node_id}']/node-ref + Element Text Should Be + ... ${aggregated_node} + ... ${supp_node_id} + ... xpath=.//supporting-node[node-ref='${supp_node_id}']/node-ref END ${overlay_node_id} Get Element Text ${aggregated_node} xpath=./node-id - [Return] ${overlay_node_id} + RETURN ${overlay_node_id} Check Aggregated Termination Point in Node - [Arguments] ${model} ${topology} ${topology_id} ${node_id} ${tp_id} @{supp_tp_ids} [Documentation] Checks supporting termination points in aggregated termination point. Model should be 'network-topology-model', 'opendaylight-inventory-model' or 'i2rs-model'. + [Arguments] ${model} ${topology} ${topology_id} ${node_id} ${tp_id} @{supp_tp_ids} Check Supported Model ${model} - ${tp} Extract Termination Point from Topology ${model} ${topology} ${topology_id} ${node_id} ${tp_id} + ${tp} Extract Termination Point from Topology + ... ${model} + ... ${topology} + ... ${topology_id} + ... ${node_id} + ... ${tp_id} ${supp_tp_count} Get Length ${supp_tp_ids} Should Contain X Times ${tp} ${supp_tp_count} FOR ${supp_tp_id} IN @{supp_tp_ids} @@ -429,15 +620,18 @@ Check Aggregated Termination Point in Node END Check Filtered Nodes in Topology - [Arguments] ${topology} ${tp_count} @{node_ids} [Documentation] Checks nodes in filtered topology + [Arguments] ${topology} ${tp_count} @{node_ids} FOR ${node_id} IN @{node_ids} - Element Text Should Be ${topology} ${node_id} xpath=.//node/supporting-node[node-ref='${node_id}']/node-ref + Element Text Should Be + ... ${topology} + ... ${node_id} + ... xpath=.//node/supporting-node[node-ref='${node_id}']/node-ref END Check Filtered Termination Points in Node - [Arguments] ${topology} ${supp_node_id} @{supp_tp_ids} [Documentation] Checks termination points in filtered topology + [Arguments] ${topology} ${supp_node_id} @{supp_tp_ids} ${node} Extract Node from Topology ${topology} ${supp_node_id} ${supp_tp_count} Get Length ${supp_tp_ids} Should Contain X Times ${node} 1 @@ -448,15 +642,15 @@ Check Filtered Termination Points in Node END Check Filtered Links In Topology - [Arguments] ${topology} @{supp_link_ids} [Documentation] Checks links in filtered topology + [Arguments] ${topology} @{supp_link_ids} FOR ${supp_link_id} IN @{supp_link_ids} Should Contain X Times ${topology} ${supp_link_id} 1 END Check Overlay Link Source And Destination - [Arguments] ${model} ${topology} ${topo_id} ${link_id} ${expected_source} ${expected_destination} [Documentation] Checks if the overlay link's source and destination specified by a supporting link ref matches given source and destination + [Arguments] ${model} ${topology} ${topo_id} ${link_id} ${expected_source} ${expected_destination} ${link} Extract Link from Topology ${model} ${topology} ${topo_id} ${link_id} ${link_source} Get Element Text ${link} xpath=.//source-node ${link_destination} Get Element Text ${link} xpath=.//dest-node @@ -464,23 +658,37 @@ Check Overlay Link Source And Destination Should Be Equal As Strings ${link_destination} ${expected_destination} Output Topo Should Be Complete + [Documentation] Verifies that the output topology contains the expected amount of essential elements [Arguments] ${node_count}=-1 ${supporting-node_count}=-1 ${node-ref_count}=-1 ${tp_count}=-1 ${tp-ref_count}=-1 ${link_count}=-1 ... ${link-ref_count}=-1 - [Documentation] Verifies that the output topology contains the expected amount of essential elements ${resp} Wait Until Keyword Succeeds 5x 250ms Basic Request Get ${OVERLAY_TOPO_URL} Should Contain ${resp.text} ${OUTPUT_TOPO_NAME} - Run Keyword If ${node_count}>-1 Should Contain X Times ${resp.text} ${node_count} - Run Keyword If ${supporting-node_count}>-1 Should Contain X Times ${resp.text} ${supporting-node_count} - Run Keyword If ${node-ref_count}>-1 Should Contain X Times ${resp.text} ${node-ref_count} - Run Keyword If ${link_count}>-1 Should Contain X Times ${resp.text} ${link_count} - Run Keyword If ${link-ref_count}>-1 Should Contain X Times ${resp.text} ${link-ref_count} - Run Keyword If ${tp_count}>-1 Should Contain X Times ${resp.text} ${tp_count} - Run Keyword If ${tp-ref_count}>-1 Should Contain X Times ${resp.text} ${tp-ref_count} + IF ${node_count}>-1 + Should Contain X Times ${resp.text} ${node_count} + END + IF ${supporting-node_count}>-1 + Should Contain X Times ${resp.text} ${supporting-node_count} + END + IF ${node-ref_count}>-1 + Should Contain X Times ${resp.text} ${node-ref_count} + END + IF ${link_count}>-1 + Should Contain X Times ${resp.text} ${link_count} + END + IF ${link-ref_count}>-1 + Should Contain X Times ${resp.text} ${link-ref_count} + END + IF ${tp_count}>-1 + Should Contain X Times ${resp.text} ${tp_count} + END + IF ${tp-ref_count}>-1 + Should Contain X Times ${resp.text} ${tp-ref_count} + END Log ---- Output Topo ---- Log ${resp.text} - [Return] ${resp} + RETURN ${resp} Set Global Variable If It Does Not Exist [Arguments] ${name} ${value} - ${status} ${message} = Run Keyword And Ignore Error Variable Should Exist ${name} - Run Keyword If "${status}" == "FAIL" Set Global Variable ${name} ${value} + ${status} ${message} Run Keyword And Ignore Error Variable Should Exist ${name} + IF "${status}" == "FAIL" Set Global Variable ${name} ${value} diff --git a/csit/libraries/TsdrUtils.robot b/csit/libraries/TsdrUtils.robot index 9c3604e853..94e05937d3 100644 --- a/csit/libraries/TsdrUtils.robot +++ b/csit/libraries/TsdrUtils.robot @@ -1,88 +1,95 @@ *** Settings *** -Library RequestsLibrary -Library XML -Library OperatingSystem -Library String -Library Collections -Library DateTime -Resource Utils.robot -Variables ../variables/Variables.py -Library json -Library Process +Library RequestsLibrary +Library XML +Library OperatingSystem +Library String +Library Collections +Library DateTime +Resource Utils.robot +Variables ../variables/Variables.py +Library json +Library Process + *** Variables *** -${HBASE_CLIENT} /tmp/Hbase/hbase-0.94.27/bin -${CASSANDRA_CLIENT} /tmp/cassandra/apache-cassandra-2.1.16/bin -${final} ${EMPTY} -${prompt_timeout} ${EMPTY} +${HBASE_CLIENT} /tmp/Hbase/hbase-0.94.27/bin +${CASSANDRA_CLIENT} /tmp/cassandra/apache-cassandra-2.1.16/bin +${final} ${EMPTY} +${prompt_timeout} ${EMPTY} ${CASSANDRA_DB_PATH} /tmp/cassandra/apache-cassandra-2.1.16/ -${metric_path} metricpath -${metric_val} metricval -${metric_log} metriclog -${temp_metric_val} temp_metric_val -${NETFLOW_PORT} 2055 -${KARAF_PATH} ${WORKSPACE}/${BUNDLEFOLDER} -${TSDR_PATH} ${KARAF_PATH}/tsdr -${PURGE_PATH} ${KARAF_PATH}/etc/tsdr.data.purge.cfg -${SNMP_PATH} ${KARAF_PATH}/etc/tsdr.snmp.cfg -${SNMP_COMMUNITY} mib2dev\/if-mib -&{HEADERS_QUERY} Content-Type=application/json Content-Type=application/json -&{OPER_STATUS} up=1 down=2 testing=3 unknown=4 dormant=5 notPresent=6 lowerLayerDown=7 -&{syslog_facility} kern=0 -${MESSAGE} Oct 29 18:10:31: ODL: %STKUNIT0-M:CP %IFMGR-5-ASTATE_UP: Changed interface Admin state to up: Te 0/0 -${MESSAGE_PATTERN} Changed interface +${metric_path} metricpath +${metric_val} metricval +${metric_log} metriclog +${temp_metric_val} temp_metric_val +${NETFLOW_PORT} 2055 +${KARAF_PATH} ${WORKSPACE}/${BUNDLEFOLDER} +${TSDR_PATH} ${KARAF_PATH}/tsdr +${PURGE_PATH} ${KARAF_PATH}/etc/tsdr.data.purge.cfg +${SNMP_PATH} ${KARAF_PATH}/etc/tsdr.snmp.cfg +${SNMP_COMMUNITY} mib2dev\/if-mib +&{HEADERS_QUERY} Content-Type=application/json Content-Type=application/json +&{OPER_STATUS} up=1 down=2 testing=3 unknown=4 dormant=5 notPresent=6 lowerLayerDown=7 +&{syslog_facility} kern=0 +${MESSAGE} +... Oct 29 18:10:31: ODL: %STKUNIT0-M:CP %IFMGR-5-ASTATE_UP: Changed interface Admin state to up: Te 0/0 +${MESSAGE_PATTERN} Changed interface + *** Keywords *** Start Tsdr Suite - [Arguments] ${switch}=ovsk ${switch_count}=3 [Documentation] TSDR specific setup/cleanup work that can be done safely before any system. ... is run. + [Arguments] ${switch}=ovsk ${switch_count}=3 Clean Mininet System ${mininet_conn_id1}= Open Connection ${TOOLS_SYSTEM_IP} prompt=${DEFAULT_LINUX_PROMPT} timeout=120s Set Suite Variable ${mininet_conn_id1} Login With Public Key ${TOOLS_SYSTEM_USER} ${USER_HOME}/.ssh/${SSH_KEY} any Execute Command sudo ovs-vsctl set-manager ptcp:6644 - ${start}= Set Variable sudo mn --controller=remote,ip=${ODL_SYSTEM_IP} --topo=linear,${switch_count} --switch ${switch},protocols=OpenFlow13 + ${start}= Set Variable + ... sudo mn --controller=remote,ip=${ODL_SYSTEM_IP} --topo=linear,${switch_count} --switch ${switch},protocols=OpenFlow13 Log ${start} Write ${start} Read Until mininet> Configure Netflow - [Arguments] ${user}=${TOOLS_SYSTEM_USER} [Documentation] Configure Netflow - ${output}= Run Command On Controller ${TOOLS_SYSTEM_IP} sudo ovs-vsctl -- set Bridge s1 netflow=@nf -- --id=@nf create NetFlow target=\\"${ODL_SYSTEM_IP}:${NETFLOW_PORT}\\" active-timeout=10 ${user} + [Arguments] ${user}=${TOOLS_SYSTEM_USER} + ${output}= Run Command On Controller + ... ${TOOLS_SYSTEM_IP} + ... sudo ovs-vsctl -- set Bridge s1 netflow=@nf -- --id=@nf create NetFlow target=\\"${ODL_SYSTEM_IP}:${NETFLOW_PORT}\\" active-timeout=10 + ... ${user} Ping All Hosts - [Arguments] ${switch}=ovsk [Documentation] Ping between all hosts in mininet topology. + [Arguments] ${switch}=ovsk Switch Connection ${mininet_conn_id1} Write pingall Read Until mininet> Ping Pair Hosts - [Arguments] ${host1} ${host2} [Documentation] Ping between ${host1} and ${host2} + [Arguments] ${host1} ${host2} Switch Connection ${mininet_conn_id1} Write pingpair ${host1} ${host2} Read Until mininet> Ping Pair Hosts Hbase - [Arguments] ${pattern} [Documentation] Ping between h1 and h2 and check Hbase + [Arguments] ${pattern} Ping Pair Hosts h1 h2 ${query_output}= Query the Data from HBaseClient count 'NETFLOW' Should Match Regexp ${query_output} ${pattern} Ping Pair Hosts Cassandra - [Arguments] ${pattern} [Documentation] Ping between h1 and h2 and check Cassandra + [Arguments] ${pattern} Ping Pair Hosts h1 h2 ${query_output}= Count Cassandra rows select count(*) from tsdr.metriclog; Should Match Regexp ${query_output} ${pattern} Ping Pair Hosts HSQLDB - [Arguments] ${pattern} [Documentation] Iperf between h1 and h2 and check Cassandra + [Arguments] ${pattern} Ping Pair Hosts h1 h2 ${query_output}= Issue Command On Karaf Console tsdr:list NETFLOW | wc -l Should Match Regexp ${query_output} ${pattern} @@ -97,8 +104,8 @@ Stop Tsdr Suite Close Connection Purge Data - [Arguments] ${HOST}=127.0.0.1 ${purge_enabled}=true ${purge_time}=00:00:00 ${purge_interval}=1400 ${retention}=0 [Documentation] Write Purge file and copy it to directory.127.0.0.1 refers local controller + [Arguments] ${HOST}=127.0.0.1 ${purge_enabled}=true ${purge_time}=00:00:00 ${purge_interval}=1400 ${retention}=0 Create File purge.cfg \#TSDR Project Configuration file Append To File purge.cfg \n Append To File purge.cfg host=${HOST} @@ -115,26 +122,36 @@ Purge Data Initialize the HBase for TSDR [Documentation] Install and initialize the tsdr tables on HBase Server - ${hbase_server}= Run Command On Remote System ${ODL_SYSTEM_IP} export JAVA_HOME=/usr && ${HBASE_CLIENT}/start-hbase.sh ${TOOLS_SYSTEM_USER} ${prompt_timeout}=120 + ${hbase_server}= Run Command On Remote System + ... ${ODL_SYSTEM_IP} + ... export JAVA_HOME=/usr && ${HBASE_CLIENT}/start-hbase.sh + ... ${TOOLS_SYSTEM_USER} + ... ${prompt_timeout}=120 Log ${hbase_server} ${hbase_process}= Run Command On Remote System ${ODL_SYSTEM_IP} ps -ef | grep HMaster Log ${hbase_process} Stop the HBase Server [Documentation] Stop the HBase server - ${hbase_server}= Run Command On Remote System ${ODL_SYSTEM_IP} export JAVA_HOME=/usr && ${HBASE_CLIENT}/stop-hbase.sh ${TOOLS_SYSTEM_USER} ${prompt_timeout}=90 + ${hbase_server}= Run Command On Remote System + ... ${ODL_SYSTEM_IP} + ... export JAVA_HOME=/usr && ${HBASE_CLIENT}/stop-hbase.sh + ... ${TOOLS_SYSTEM_USER} + ... ${prompt_timeout}=90 Log ${hbase_server} Configure the Queue on Switch - [Arguments] ${queue_interface} ${user}=${TOOLS_SYSTEM_USER} [Documentation] Configure the 2 queues on specified openvswitch interface + [Arguments] ${queue_interface} ${user}=${TOOLS_SYSTEM_USER} Log Configure the queue on ${queue_interface} - ${output}= Run Command On Remote System ${TOOLS_SYSTEM_IP} sudo ovs-vsctl set port ${queue_interface} qos=@newqos -- --id=@newqos create qos type=linux-htb other-config:max-rate=200000000 queues=0=@q0,1=@q1,2=@q2 -- --id=@q0 create queue other-config:min-rate=100000 other-config:max-rate=200000 -- --id=@q1 create queue other-config:min-rate=10001 other-config:max-rate=300000 -- --id=@q2 create queue other-config:min-rate=300001 other-config:max-rate=200000000 + ${output}= Run Command On Remote System + ... ${TOOLS_SYSTEM_IP} + ... sudo ovs-vsctl set port ${queue_interface} qos=@newqos -- --id=@newqos create qos type=linux-htb other-config:max-rate=200000000 queues=0=@q0,1=@q1,2=@q2 -- --id=@q0 create queue other-config:min-rate=100000 other-config:max-rate=200000 -- --id=@q1 create queue other-config:min-rate=10001 other-config:max-rate=300000 -- --id=@q2 create queue other-config:min-rate=300001 other-config:max-rate=200000000 Log ${output} Query the Data from HBaseClient - [Arguments] ${query} ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s [Documentation] Execute the HBase Query and return the result + [Arguments] ${query} ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s Log Attempting to execute ${query} on ${remote} via HbaseClient ${conn_id}= Open Connection ${remote} prompt=${DEFAULT_LINUX_PROMPT} timeout=${prompt_timeout} Login With Public Key ${user} ${USER_HOME}/.ssh/${SSH_KEY} any @@ -147,28 +164,37 @@ Query the Data from HBaseClient LOG ${output} Comment ${output}= Read Until ${DEFAULT_LINUX_PROMPT} Close Connection - [Return] ${output} + RETURN ${output} Verify the Metric is Collected? - [Arguments] ${tsdr_cmd} ${metric} ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s [Documentation] Verify the ${tsdr_cmd} output contains ${metric} - ${output}= Issue Command On Karaf Console ${tsdr_cmd} ${remote} ${KARAF_SHELL_PORT} ${prompt_timeout} + [Arguments] ${tsdr_cmd} ${metric} ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s + ${output}= Issue Command On Karaf Console + ... ${tsdr_cmd} + ... ${remote} + ... ${KARAF_SHELL_PORT} + ... ${prompt_timeout} Should Contain ${output} ${metric} Prepare HBase Filter - [Arguments] ${left_str} ${right_str} ${connector} [Documentation] Prepare the Hbase Filter from Tsdr List output + [Arguments] ${left_str} ${right_str} ${connector} ${left_str}= Remove Space on String ${left_str} ${right_str}= Remove Space on String ${right_str} 1 - ${x}= Run Keyword If '${left_str}' == 'MetricID' Catenate ${SPACE} _ - ... ELSE IF '${left_str}' == 'ObjectKeys' Catenate ${right_str} _ - ... ELSE IF '${left_str}' == 'TimeStamp' Get Epoch Time ${right_str} - ... ELSE Catenate ${SPACE} - [Return] ${x} + IF '${left_str}' == 'MetricID' + ${x}= Catenate ${SPACE} _ + ELSE IF '${left_str}' == 'ObjectKeys' + ${x}= Catenate ${right_str} _ + ELSE IF '${left_str}' == 'TimeStamp' + ${x}= Get Epoch Time ${right_str} + ELSE + ${x}= Catenate ${SPACE} + END + RETURN ${x} Create the Hbase table row - [Arguments] ${tsdr_line} ${metrics} [Documentation] Create the Hbase table row from tsdr:list + [Arguments] ${tsdr_line} ${metrics} @{words}= Split String ${tsdr_line} | FOR ${li} IN @{words} ${key}= Fetch From Left ${li} = @@ -178,11 +204,11 @@ Create the Hbase table row END ${query}= Concatenate the String ${metrics} ${final} ${query}= Remove Space on String ${query} - [Return] ${query} + RETURN ${query} Initialize Cassandra Tables - [Arguments] ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s ${key_table}=metricpath ${val_table}=metricval [Documentation] Truncate Existing tables in Cassandra to Start it fresh. + [Arguments] ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s ${key_table}=metricpath ${val_table}=metricval Log Attempting to truncate tables in Cassandra Run Command On Remote System ${ODL_SYSTEM_IP} sudo rm -rf ${CASSANDRA_DB_PATH}${key_table} Run Command On Remote System ${ODL_SYSTEM_IP} sudo rm -rf ${CASSANDRA_DB_PATH}${val_table} @@ -199,8 +225,8 @@ Initialize Cassandra Tables Close Connection Initialize Cassandra Tables Metricval - [Arguments] ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s ${key_table}=metricpath ${val_table}=metricval [Documentation] Truncate Existing tables in Cassandra to Start it fresh + [Arguments] ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s ${key_table}=metricpath ${val_table}=metricval Log Attempting to truncate tables in Cassandra Run Command On Remote System ${ODL_SYSTEM_IP} sudo rm -rf ${CASSANDRA_DB_PATH}${key_table} Run Command On Remote System ${ODL_SYSTEM_IP} sudo rm -rf ${CASSANDRA_DB_PATH}${val_table} @@ -215,49 +241,56 @@ Initialize Cassandra Tables Metricval Close Connection Query Metrics on H2 Datastore - [Arguments] ${category} ${attribute} ${nodeid}=openflow:1 [Documentation] Generate the JDBC query for H2 Datastore - ${h2_query}= Concatenate the String jdbc:query metric "select * from Metric where MetricCategory= '${category}' and - ${h2_query}= Concatenate the String ${h2_query} MetricName = '${attribute}' and NODEID = '${nodeid}' order by ID desc limit 5" + [Arguments] ${category} ${attribute} ${nodeid}=openflow:1 + ${h2_query}= Concatenate the String + ... jdbc:query metric "select * from Metric where MetricCategory= + ... '${category}' and + ${h2_query}= Concatenate the String + ... ${h2_query} + ... MetricName = '${attribute}' and NODEID = '${nodeid}' order by ID desc limit 5" ${output}= Issue Command On Karaf Console ${h2_query} ${ODL_SYSTEM_IP} ${KARAF_SHELL_PORT} 30 - [Return] ${output} + RETURN ${output} Generate HBase Query - [Arguments] ${table} ${filter} ${metric} [Documentation] Scan the Hbase Table with Filter + [Arguments] ${table} ${filter} ${metric} ${hbase_query}= Concatenate the String scan '${table}' ${hbase_query}= Concatenate the String ${hbase_query} ,{ FILTER =>\"(RowFilter(=, ${hbase_query}= Concatenate the String ${hbase_query} 'regexstring:${filter}*\')) AND (RowFilter(=, ${hbase_query}= Concatenate the String ${hbase_query} 'regexstring:${metric}*\'))\",LIMIT=>10} - [Return] ${hbase_query} + RETURN ${hbase_query} Get Metrics Value - [Arguments] ${tsdr_line} [Documentation] Get Metric Value from tsdr:list + [Arguments] ${tsdr_line} ${value}= Fetch From Right ${tsdr_line} | ${value}= Replace String ${value} MetricValue value ${value}= Replace String ${value} [m ${EMPTY} ${value}= Replace String ${value} = \= ${value}= Remove Space on String ${value} ${value}= Convert to String ${value} - [Return] ${value} + RETURN ${value} Verify the Metrics Attributes on Hbase Client - [Arguments] ${attribute} ${rowfilter} ${table}=PortStats [Documentation] Verification on Metrics attributes on Hbase Client + [Arguments] ${attribute} ${rowfilter} ${table}=PortStats ${query}= Generate HBase Query ${table} ${rowfilter} ${attribute} ${out}= Query the Data from HBaseClient ${query} Should Match Regexp ${out} (?mui)value Verify the Metrics Attributes on Cassandra Client - [Arguments] ${pattern} [Documentation] Verification on Metrics attributes on Cassandra Client + [Arguments] ${pattern} @{metric_row}= Find Metricval Keys ${pattern} metricpath ${keya}= Get From List ${metric_row} 1 ${keyb}= Get From List ${metric_row} 2 ${keya_bool}= Evaluate ${keya} < 0 - ${keya}= Run Keyword If '${keya_bool}' == 'True' Catenate SEPARATOR= \\ ${keya} - ... ELSE Catenate ${keya} + IF '${keya_bool}' == 'True' + ${keya}= Catenate SEPARATOR= \\ ${keya} + ELSE + ${keya}= Catenate ${keya} + END ${metricval}= Create Temporary Key Info ${keya} ${keyb} @{lines}= Split to lines ${metricval} ${mv_len}= Get Length ${lines} @@ -265,11 +298,11 @@ Verify the Metrics Attributes on Cassandra Client ${found_line}= Get From List ${lines} ${mv_len} @{split_line}= Split String ${found_line} ${SPACE} ${metric_count}= Get From List ${split_line} 3 - [Return] ${metric_count} + RETURN ${metric_count} Form Portstats Query Pattern - [Arguments] ${metric} ${node} ${port} ${attribute} [Documentation] Used for geneating openflow metrics Queries for Cassandra. + [Arguments] ${metric} ${node} ${port} ${attribute} ${pattern}= Concatenate the String ${attribute} . ${pattern}= Concatenate the String ${pattern} ${metric} ${pattern}= Concatenate the String ${pattern} . @@ -279,13 +312,15 @@ Form Portstats Query Pattern ${pattern}= Concatenate the String ${pattern} . ${pattern}= Concatenate the String ${pattern} NodeConnector_${node}:${port} ${pattern}= Remove Space on String ${pattern} - [Return] ${pattern} + RETURN ${pattern} Create Temporary Key Info - [Arguments] ${pattern} ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s ${val_table}=metricval [Documentation] Return rows matching keya and keyb - ${output}= Run Command On Remote System ${ODL_SYSTEM_IP} cat ${CASSANDRA_DB_PATH}${val_table}|grep "${pattern}" - [Return] ${output} + [Arguments] ${pattern} ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s ${val_table}=metricval + ${output}= Run Command On Remote System + ... ${ODL_SYSTEM_IP} + ... cat ${CASSANDRA_DB_PATH}${val_table}|grep "${pattern}" + RETURN ${output} Verify Metric Val File [Documentation] Returns Value for metric matching particular keya,keyb @@ -295,31 +330,31 @@ Verify Metric Val File ${found_line}= Get From List ${metricval} ${mv_len} @{split_line}= Split String ${found_line} ${SPACE} ${metric_count}= Get From List ${split_line} 3 - [Return] ${metric_count} + RETURN ${metric_count} Verify Metric log File - [Arguments] ${metric_log} ${pattern} [Documentation] Returns Value for lines in Metriclog matching the pattern + [Arguments] ${metric_log} ${pattern} ${contents}= Grep From File ${CASSANDRA_DB_PATH}${temp_metric_val} ${pattern} - [Return] ${contents} + RETURN ${contents} Grep From File - [Arguments] ${file} ${pattern} [Documentation] Use cat to grep from the file and return the output + [Arguments] ${file} ${pattern} ${output}= Run Command On Remote System ${ODL_SYSTEM_IP} cat ${file} | ${pattern} - [Return] ${output} + RETURN ${output} Find Metricval Keys - [Arguments] ${pattern} ${file} [Documentation] Return list element which has the particular pattern. + [Arguments] ${pattern} ${file} ${metric_grep}= Grep From File ${TSDR_PATH}/tsdrKeyCache.txt ${pattern} @{split_line}= Split String ${metric_grep} | ${keypath}= Get From List ${split_line} 0 - [Return] @{split_line} + RETURN @{split_line} Copy TSDR tables - [Arguments] ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s ${key_table}=metricpath ${val_table}=metricval [Documentation] Copy TSDR files to external File system for text processing. + [Arguments] ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s ${key_table}=metricpath ${val_table}=metricval Log Attempting to truncate tables in Cassandra ${conn_id}= Open Connection ${remote} prompt=${DEFAULT_LINUX_PROMPT} timeout=${prompt_timeout} Login With Public Key ${user} ${USER_HOME}/.ssh/${SSH_KEY} any @@ -334,8 +369,8 @@ Copy TSDR tables Close Connection Issue Cassandra Query - [Arguments] ${query} ${output} ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s [Documentation] Issue query in cqlsh and match it with output which is passed as a argument + [Arguments] ${query} ${output} ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s ${conn_id}= Open Connection ${remote} prompt=${DEFAULT_LINUX_PROMPT} timeout=${prompt_timeout} Login With Public Key ${user} ${USER_HOME}/.ssh/${SSH_KEY} any Write export JAVA_HOME=/usr @@ -349,8 +384,8 @@ Issue Cassandra Query Close Connection Count Cassandra rows - [Arguments] ${query} ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s [Documentation] Issue query in cqlsh and match it with output which is passed as a argument + [Arguments] ${query} ${remote}=${ODL_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${prompt_timeout}=120s ${conn_id}= Open Connection ${remote} prompt=${DEFAULT_LINUX_PROMPT} timeout=${prompt_timeout} Login With Public Key ${user} ${USER_HOME}/.ssh/${SSH_KEY} any Write export JAVA_HOME=/usr @@ -360,66 +395,80 @@ Count Cassandra rows ${query_output}= Read Until cqlsh> Write exit Close Connection - [Return] ${query_output} + RETURN ${query_output} Read File and Return Split Lines - [Arguments] ${filename} [Documentation] Reads the file and returns each line as list + [Arguments] ${filename} ${contents}= Run Command On Remote System ${ODL_SYSTEM_IP} cat ${filename} @{lines}= Split to lines ${contents} - [Return] @{lines} + RETURN @{lines} Get Stats XML - [Arguments] ${query} ${xpath} [Documentation] Parse the xml output and returns it. - ${sid}= RequestsLibrary.Create_Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} headers=${SEND_ACCEPT_XML_HEADERS} auth=${AUTH} + [Arguments] ${query} ${xpath} + ${sid}= RequestsLibrary.Create_Session + ... session + ... http://${ODL_SYSTEM_IP}:${RESTCONFPORT} + ... headers=${SEND_ACCEPT_XML_HEADERS} + ... auth=${AUTH} ${resp}= RequestsLibrary.Get Request session ${query} headers=${SEND_ACCEPT_XML_HEADERS} ${resp_xml}= Parse XML ${resp.text} ${id1}= Get Element Text ${resp_xml} ${xpath} Delete All Sessions - [Return] ${id1} + RETURN ${id1} Return all XML matches - [Arguments] ${query} ${xpath} [Documentation] Returns all the values from xpath - ${sid}= RequestsLibrary.Create_Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} headers=${SEND_ACCEPT_XML_HEADERS} auth=${AUTH} + [Arguments] ${query} ${xpath} + ${sid}= RequestsLibrary.Create_Session + ... session + ... http://${ODL_SYSTEM_IP}:${RESTCONFPORT} + ... headers=${SEND_ACCEPT_XML_HEADERS} + ... auth=${AUTH} ${resp}= RequestsLibrary.Get Request session ${query} headers=${SEND_ACCEPT_XML_HEADERS} ${resp_xml}= Parse XML ${resp.text} @{id1}= Get Elements Texts ${resp_xml} ${xpath} Delete All Sessions - [Return] @{id1} + RETURN @{id1} Compare Tsdr XML Metrics - [Arguments] ${xml} ${tsdr} ${deviation}=10 [Documentation] Compares xml metrics from openflow plugin with TSDR metric values + [Arguments] ${xml} ${tsdr} ${deviation}=10 ${val_max}= Evaluate ${xml}*${deviation}/100 ${val_diff}= Evaluate ${tsdr} - ${xml} ${find_negative}= Evaluate ${val_diff} < 0 - ${val_diff}= Run Keyword If '${find_negative}' == 'True' Evaluate ${val_diff}*-1 - ... ELSE Evaluate ${val_diff}*1 + IF '${find_negative}' == 'True' + ${val_diff}= Evaluate ${val_diff}*-1 + ELSE + ${val_diff}= Evaluate ${val_diff}*1 + END Should Be True ${val_diff} <= ${val_max} Generate Syslog - [Arguments] ${facility} [Documentation] Uses netcat to generate logs and send it to port ${ODL_SYSTEM_IP}:1514 + [Arguments] ${facility} Run echo "<${facility}>${MESSAGE}" | nc -w 4 -u ${ODL_SYSTEM_IP} 1514 Verify Metric Val File For Syslog [Documentation] Returns Value for metric matching particular keya,keyb @{metricval}= Read File and Return Split Lines ${CASSANDRA_DB_PATH}${temp_metric_val} - [Return] ${metricval} + RETURN ${metricval} Verify the Metrics Syslog on Cassandra Client - [Arguments] ${pattern} [Documentation] Getting the keya and keyb for a particular syslog agent and create a temporary file from metriclog + [Arguments] ${pattern} @{metric_row}= Find Metricval Keys ${pattern} metricpath ${keya}= Get From List ${metric_row} 1 ${keyb}= Get From List ${metric_row} 2 ${keya_bool}= Evaluate ${keya} < 0 - ${keya}= Run Keyword If '${keya_bool}' == 'True' Catenate SEPARATOR= \\ ${keya} - ... ELSE Catenate ${keya} + IF '${keya_bool}' == 'True' + ${keya}= Catenate SEPARATOR= \\ ${keya} + ELSE + ${keya}= Catenate ${keya} + END ${metric_log}= Create Temporary Key Info ${keya} ${keyb} val_table=metriclog - [Return] ${metric_log} + RETURN ${metric_log} Iterating over metricpath [Documentation] Used to traverse over metricpath file and traverse over metricpath file and get the keys @@ -432,70 +481,76 @@ Iterating over metricpath END Iterating over metricval - [Arguments] ${keya} ${keyb} [Documentation] Used to traverse over metricval file and check if keya and keyb are present. + [Arguments] ${keya} ${keyb} ${mv_contents}= OperatingSystem.Get File ${CASSANDRA_DB_PATH}${metric_val} Should Contain ${mv_contents} ${keya} ${keyb} Check Metric path - [Arguments] ${pattern} [Documentation] Count the number of rows in metricpath and compare with the pattern. + [Arguments] ${pattern} ${query_output}= Count Cassandra rows select count(*) from tsdr.metricpath; Should Match Regexp ${query_output} ${pattern} Check HSQLDB - [Arguments] ${pattern} ${TYPE} [Documentation] Count the number of rows in HSQLDB with Metric ${TYPE} + [Arguments] ${pattern} ${TYPE} ${output}= Issue Command On Karaf Console tsdr:list ${TYPE} Should Match Regexp ${output} ${pattern} Check Metric Val - [Arguments] ${pattern} [Documentation] Count the number of rows in metricval table and compare with the pattern. + [Arguments] ${pattern} ${query_output}= Count Cassandra rows select count(*) from tsdr.metricval; Should Match Regexp ${query_output} ${pattern} Check Metric Log - [Arguments] ${pattern} [Documentation] Count the number of rows in metriclog and compare with the pattern. + [Arguments] ${pattern} ${query_output}= Count Cassandra rows select count(*) from tsdr.metriclog; Should Match Regexp ${query_output} ${pattern} Generate TSDR Query - [Arguments] ${DC}= ${MN}= ${NID}= ${RK}= ${from}=0 ${until}=now [Documentation] Issues TSDR Query and returns the list + [Arguments] ${DC}= ${MN}= ${NID}= ${RK}= ${from}=0 ${until}=now Create Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} auth=${AUTH} headers=${HEADERS_QUERY} - ${resp}= RequestsLibrary.Get Request session /tsdr/metrics/query?tsdrkey="[NID=${NID}][DC=${DC}][MN=${MN}][RK=${RK}]"&from=${from}&until=${until} headers=${HEADERS_QUERY} + ${resp}= RequestsLibrary.Get Request + ... session + ... /tsdr/metrics/query?tsdrkey="[NID=${NID}][DC=${DC}][MN=${MN}][RK=${RK}]"&from=${from}&until=${until} + ... headers=${HEADERS_QUERY} @{convert}= Parse Json ${resp.text} Delete All Sessions - [Return] @{convert} + RETURN @{convert} Generate TSDR NBI + [Documentation] Issues TSDR Query and returns the list [Arguments] ${DC}= ${MN}= ${NID}= ${RK}= ${from}=0 ${until}=now ... ${datapts}=1000000 - [Documentation] Issues TSDR Query and returns the list Create Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} auth=${AUTH} headers=${HEADERS_QUERY} - ${resp}= RequestsLibrary.Get Request session /tsdr/nbi/render?target="[NID=${NID}][DC=${DC}][MN=${MN}][RK=${RK}]"&from=${from}&until=${until}&maxDataPoints=${datapts} headers=${HEADERS_QUERY} + ${resp}= RequestsLibrary.Get Request + ... session + ... /tsdr/nbi/render?target="[NID=${NID}][DC=${DC}][MN=${MN}][RK=${RK}]"&from=${from}&until=${until}&maxDataPoints=${datapts} + ... headers=${HEADERS_QUERY} @{convert}= Parse Json ${resp.text} ${dict_convert}= Convert To Dictionary @{convert} @{dict}= Get Dictionary Values ${dict_convert} ${datapoints_list}= Convert to List ${dict}[0] Delete All Sessions - [Return] @{datapoints_list} + RETURN @{datapoints_list} Extract PORTSTATS RecordKeys - [Arguments] ${Record_keys} [Documentation] Dissect Record keys for Portstats + [Arguments] ${Record_keys} ${node_dict}= Get From List ${Record_keys} 0 ${nc_dict}= Get From List ${Record_keys} 1 ${NODE}= Get From Dictionary ${node_dict} keyValue ${NC}= Get From Dictionary ${nc_dict} keyValue ${rk_val}= Set Variable Node:${NODE},NodeConnector:${NC} - [Return] ${rk_val} + RETURN ${rk_val} Extract QUEUESTATS RecordKeys - [Arguments] ${Record_keys} [Documentation] Dissect Record keys for Queuestats + [Arguments] ${Record_keys} ${node_dict}= Get From List ${Record_keys} 0 ${connect_dict}= Get From List ${Record_keys} 1 ${queue_dict}= Get From List ${Record_keys} 2 @@ -503,11 +558,11 @@ Extract QUEUESTATS RecordKeys ${CONNECT}= Get From Dictionary ${connect_dict} keyValue ${QUEUE}= Get From Dictionary ${queue_dict} keyValue ${rk_val}= Set Variable Node:${NODE},NodeConnector:${CONNECT},Queue:${QUEUE} - [Return] ${rk_val} + RETURN ${rk_val} Extract FLOWSTATS RecordKeys - [Arguments] ${Record_keys} [Documentation] Dissect Record keys for Flowstats + [Arguments] ${Record_keys} ${node_dict}= Get From List ${Record_keys} 0 ${table_dict}= Get From List ${Record_keys} 1 ${flow_dict}= Get From List ${Record_keys} 2 @@ -515,21 +570,21 @@ Extract FLOWSTATS RecordKeys ${TABLE}= Get From Dictionary ${table_dict} keyValue ${FLOW}= Get From Dictionary ${flow_dict} keyValue ${rk_val}= Set Variable Node:${NODE},Table:${TABLE},Flow:${FLOW} - [Return] ${rk_val} + RETURN ${rk_val} Extract FLOWTABLESTATS RecordKeys - [Arguments] ${Record_keys} [Documentation] Dissect Record keys for Flowtablestats + [Arguments] ${Record_keys} ${node_dict}= Get From List ${Record_keys} 0 ${table_dict}= Get From List ${Record_keys} 1 ${NODE}= Get From Dictionary ${node_dict} keyValue ${TABLE}= Get From Dictionary ${table_dict} keyValue ${rk_val}= Set Variable Node:${NODE},Table:${TABLE} - [Return] ${rk_val} + RETURN ${rk_val} Extract Row Values from TSDR Query - [Arguments] ${row_dict} ${tsdr_row} ${nbi_row} ${DATA_CATEGORY} [Documentation] Extract the row values from query and generate it in DB format + [Arguments] ${row_dict} ${tsdr_row} ${nbi_row} ${DATA_CATEGORY} ${nbi_value}= Get From List ${nbi_row} 0 ${nbi_time}= Get From List ${nbi_row} 1 ${MN}= Get From Dictionary ${row_dict} metricName @@ -538,10 +593,17 @@ Extract Row Values from TSDR Query ${RK}= Get From Dictionary ${row_dict} recordKeys ${time}= Get From Dictionary ${row_dict} timeStamp ${DC}= Get From Dictionary ${row_dict} tsdrDataCategory - ${RK_VAL}= Run Keyword If '${DATA_CATEGORY}'=='PORTSTATS' Extract PORTSTATS RecordKeys ${RK} - ... ELSE IF '${DATA_CATEGORY}'=='FLOWSTATS' Extract FLOWSTATS RecordKeys ${RK} - ... ELSE IF '${DATA_CATEGORY}'=='FLOWTABLESTATS' Extract FLOWTABLESTATS RecordKeys ${RK} - ... ELSE IF '${DATA_CATEGORY}'=='QUEUESTATS' Extract QUEUESTATS RecordKeys ${RK} + IF '${DATA_CATEGORY}'=='PORTSTATS' + ${RK_VAL}= Extract PORTSTATS RecordKeys ${RK} + ELSE IF '${DATA_CATEGORY}'=='FLOWSTATS' + ${RK_VAL}= Extract FLOWSTATS RecordKeys ${RK} + ELSE IF '${DATA_CATEGORY}'=='FLOWTABLESTATS' + ${RK_VAL}= Extract FLOWTABLESTATS RecordKeys ${RK} + ELSE IF '${DATA_CATEGORY}'=='QUEUESTATS' + ${RK_VAL}= Extract QUEUESTATS RecordKeys ${RK} + ELSE + ${RK_VAL}= Set Variable ${None} + END ${epoch_time}= Convert Date ${time} epoch date_format=%a %b %d %H:%M:%S %Z %Y ${epoch_time_int}= Convert To Integer ${epoch_time} Should Match ${tsdr_row} *${NID}* @@ -554,8 +616,8 @@ Extract Row Values from TSDR Query Should Be Equal As Numbers ${nbi_value} ${MV} Evaluate Datasets Length - [Arguments] ${tsdr_lines} ${query_output} ${nbi_output} [Documentation] Compare the outputs returned from all Data Stores + [Arguments] ${tsdr_lines} ${query_output} ${nbi_output} ${query_count}= Get Length ${query_output} ${tsdr_count}= Get Length ${tsdr_lines} ${nbi_count}= Get Length ${nbi_output} @@ -563,8 +625,8 @@ Evaluate Datasets Length Should Be Equal As Numbers ${nbi_count} ${tsdr_count} Evaluate Datasets Value - [Arguments] ${tsdr_lines} ${query_output} ${nbi_output} ${TYPE} [Documentation] Compare the outputs returned from all Data Stores + [Arguments] ${tsdr_lines} ${query_output} ${nbi_output} ${TYPE} FOR ${q_item} ${t_item} ${n_item} IN ZIP ${query_output} ${tsdr_lines} ... ${nbi_output} ${query_row}= Extract Row Values from TSDR Query ${q_item} ${t_item} ${n_item} ${TYPE} @@ -575,11 +637,11 @@ Evaluate Datasets Value ${if_desc}= Decode Bytes To String ${hex_name} HEX Append To List ${ifdesc_list} ${if_desc} END - [Return] @{ifdesc_list} + RETURN @{ifdesc_list} Write SNMP config - [Arguments] ${HOST}=127.0.0.1 ${community}=${SNMP_COMMUNITY} [Documentation] Write SNMP Config File + [Arguments] ${HOST}=127.0.0.1 ${community}=${SNMP_COMMUNITY} Create File snmp.cfg credentials=[${HOST},${community}] Append To File snmp.cfg \n Move File snmp.cfg ${SNMP_PATH} @@ -593,13 +655,16 @@ Bringup Netflow Configure Netflow Collect Data from SNMP Agent - [Arguments] ${SNMP_IP}=127.0.0.1 ${SNMP_AGENT_COMM}=${SNMP_COMMUNITY} [Documentation] Poll for SNMP Agent OID - ${snmpagentinfo} Create Dictionary ip-address=${SNMP_IP} community=${SNMP_AGENT_COMM} - ${snmpagentcreate} Create Dictionary input=${snmpagentinfo} + [Arguments] ${SNMP_IP}=127.0.0.1 ${SNMP_AGENT_COMM}=${SNMP_COMMUNITY} + ${snmpagentinfo}= Create Dictionary ip-address=${SNMP_IP} community=${SNMP_AGENT_COMM} + ${snmpagentcreate}= Create Dictionary input=${snmpagentinfo} ${snmpagentcreate_json}= json.dumps ${snmpagentcreate} Create Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} auth=${AUTH} headers=${HEADERS_QUERY} - ${resp}= RequestsLibrary.Post Request session /restconf/operations/snmp:get-interfaces data=${snmpagentcreate_json} + ${resp}= RequestsLibrary.Post Request + ... session + ... /restconf/operations/snmp:get-interfaces + ... data=${snmpagentcreate_json} ${convert}= To Json ${resp.text} @{dict1}= Get Dictionary Keys ${convert} ${dict1_0}= Get From List ${dict1} 0 @@ -629,40 +694,68 @@ Collect Data from SNMP Agent ${ifMtu}= Get From Dictionary ${int} ifMtu ${ifOperStatus1}= Get From Dictionary ${int} ifOperStatus ${ifOperStatus}= Get From Dictionary ${OPER_STATUS} ${ifOperStatus1} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOutDiscards | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOutDiscards + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOutDiscards | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOutDiscards Append To List ${SNMP_VALUES} ${ifOutDiscards} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfInDiscards | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfInDiscards + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfInDiscards | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfInDiscards Append To List ${SNMP_VALUES} ${ifInDiscards} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfInOctets | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfInOctets + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfInOctets | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfInOctets Append To List ${SNMP_VALUES} ${ifInOctets} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOutQLen | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOutQLen + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOutQLen | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOutQLen Append To List ${SNMP_VALUES} ${ifOutQLen} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOutErrors | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOutErrors + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOutErrors | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOutErrors Append To List ${SNMP_VALUES} ${ifOutErrors} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfInUcastPkts | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfInUcastPkts + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfInUcastPkts | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfInUcastPkts Append To List ${SNMP_VALUES} ${ifInUcastPkts} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOutNUcastPkts | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOutNUcastPkts + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOutNUcastPkts | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOutNUcastPkts Append To List ${SNMP_VALUES} ${ifOutNUcastPkts} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfInErrors | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfInErrors + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfInErrors | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfInErrors Append To List ${SNMP_VALUES} ${ifInErrors} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOutOctets | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOutOctets + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOutOctets | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOutOctets Append To List ${SNMP_VALUES} ${ifOutOctets} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfAdminStatus | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfAdminStatus + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfAdminStatus | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfAdminStatus Append To List ${SNMP_VALUES} ${ifAdminStatus} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfInUnknownProtos | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfInUnknownProtos + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfInUnknownProtos | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfInUnknownProtos Append To List ${SNMP_VALUES} ${ifInUnknownProtos} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOutUcastPkts | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOutUcastPkts + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOutUcastPkts | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOutUcastPkts Append To List ${SNMP_VALUES} ${ifOutUcastPkts} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfInNUcastPkts | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfInNUcastPkts + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfInNUcastPkts | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfInNUcastPkts Append To List ${SNMP_VALUES} ${ifInNUcastPkts} - Append To List ${SNMP_ENTRY} grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOperStatus | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOperStatus + Append To List + ... ${SNMP_ENTRY} + ... grep NID=${SNMP_IP} | grep DC=SNMPINTERFACES | grep MN=IfOperStatus | grep RK=ifIndex:${ifindex},ifName:Iso88023Csmacd,SnmpMetric:IfOperStatus Append To List ${SNMP_VALUES} ${ifOperStatus} END - [Return] ${SNMP_ENTRY} ${SNMP_VALUES} + RETURN ${SNMP_ENTRY} ${SNMP_VALUES} Retrieve Value From Elasticsearch - [Arguments] ${data_category} ${metric_name} ${node_id} ${rk_node_id} [Documentation] Retrieve the last record of Elastic Search from index TSDR. Query is done by data category, metricname and node ID + [Arguments] ${data_category} ${metric_name} ${node_id} ${rk_node_id} Create Session session http://${ODL_SYSTEM_IP}:${ELASTICPORT} auth=${AUTH} headers=${HEADERS_QUERY} ${els_query}= create_query_string_search ${data_category} ${metric_name} ${node_id} ${rk_node_id} ${els_JSON_request}= build_elastic_search_JSON_request ${els_query} @@ -671,12 +764,12 @@ Retrieve Value From Elasticsearch @{convert}= Parse Json ${resp.text} ${json}= RequestsLibrary.To Json ${resp.text} ${result}= extract_metric_value_search ${json} + RETURN ${result} [Teardown] Delete All Sessions - [Return] ${result} Check Available values from Elasticsearch - [Arguments] ${data_category} ${number_items} [Documentation] Check whether data were sent to Elastic Search. We retrieve all data by data category and then compare its count + [Arguments] ${data_category} ${number_items} Create Session session http://${ODL_SYSTEM_IP}:${ELASTICPORT} auth=${AUTH} headers=${HEADERS_QUERY} ${els_query}= create_query_string_count ${data_category} ${els_JSON_request}= build_elastic_search_JSON_request ${els_query} @@ -694,5 +787,5 @@ Clear Elasticsearch Datastore Create Session session http://${ODL_SYSTEM_IP}:${ELASTICPORT} auth=${AUTH} headers=${HEADERS_QUERY} ${resp}= RequestsLibrary.Delete_Request session tsdr Should Be Equal As Strings ${resp.status_code} 200 + RETURN ${resp.status_code} [Teardown] Delete All Sessions - [Return] ${resp.status_code} diff --git a/csit/libraries/UnimgrKeywords.robot b/csit/libraries/UnimgrKeywords.robot index bb469e8987..f753fcf437 100644 --- a/csit/libraries/UnimgrKeywords.robot +++ b/csit/libraries/UnimgrKeywords.robot @@ -1,15 +1,18 @@ *** Settings *** -Documentation Unimgr keywords defination that will be used in Unimgr suite. -Library OperatingSystem -Library SSHLibrary -Library String -Resource ./OVSDB.robot -Resource ./Utils.robot -Variables ../variables/Variables.py +Documentation Unimgr keywords defination that will be used in Unimgr suite. + +Library OperatingSystem +Library SSHLibrary +Library String +Resource ./OVSDB.robot +Resource ./Utils.robot +Variables ../variables/Variables.py + *** Variables *** -${Bridge_Name} ovsbr0 -${UniMgr_Variables_DIR} ../variables/unimgr +${Bridge_Name} ovsbr0 +${UniMgr_Variables_DIR} ../variables/unimgr + *** Keywords *** Setup Unimgr Test Environment @@ -19,26 +22,26 @@ Setup Unimgr Test Environment Prepair Unimgr Test Environment ${TOOLS_SYSTEM_2_IP} Prepair Unimgr Test Environment - [Arguments] ${Mininet_IP} [Documentation] delete the ovs bridge and manager then set the manager to a passive mode ptcp:6640. + [Arguments] ${Mininet_IP} Run Command On Remote System ${Mininet_IP} sudo ovs-vsctl del-manager Run Command On Remote System ${Mininet_IP} sudo ovs-vsctl del-br ${Bridge_Name} Run Command On Remote System ${Mininet_IP} sudo ovs-vsctl set-manager ptcp:${OVSDBPORT} - ${stdout}= Run Command On Remote System ${Mininet_IP} sudo ovs-vsctl show + ${stdout} Run Command On Remote System ${Mininet_IP} sudo ovs-vsctl show Should Contain ${stdout} "ptcp:${OVSDBPORT}" Get Add Uni Json - [Arguments] ${IP-Address} ${MAC-Address} [Documentation] read the add_uni.json file and replace the IPaddress and MACaddress with the give arguments. + [Arguments] ${IP-Address} ${MAC-Address} ${json} OperatingSystem.Get File ${UniMgr_Variables_DIR}/add_uni.json ${temp} Replace String ${json} {mac-address} ${MAC-Address} ${uniJson} Replace String ${temp} {uni-ip} ${IP-Address} - [Return] ${uniJson} + RETURN ${uniJson} Get Add Evc Json - [Arguments] ${UNI1-IP} ${UNI2-IP} [Documentation] read the add_evc.json file and replace the IP-address with the give arguments. + [Arguments] ${UNI1-IP} ${UNI2-IP} ${Json} OperatingSystem.Get File ${UniMgr_Variables_DIR}/add_evc.json ${temp} Replace String ${Json} {uni1-ip} ${UNI1-IP} ${evcJson} Replace String ${temp} {uni2-ip} ${UNI2-IP} - [Return] ${evcJson} + RETURN ${evcJson} diff --git a/csit/libraries/UscUtils.robot b/csit/libraries/UscUtils.robot index 05161a5f5c..27fc85b5ef 100644 --- a/csit/libraries/UscUtils.robot +++ b/csit/libraries/UscUtils.robot @@ -1,28 +1,31 @@ *** Settings *** -Library Collections -Library SSHLibrary -Library UtilLibrary.py -Resource RemoteBash.robot -Resource SSHKeywords.robot +Library Collections +Library SSHLibrary +Library UtilLibrary.py +Resource RemoteBash.robot +Resource SSHKeywords.robot + *** Variables *** -${REST_VIEW_CHANNEL} /restconf/operations/usc-channel:view-channel -${REST_ADD_CHANNEL} /restconf/operations/usc-channel:add-channel -${REST_REMOVE_CHANNEL} /restconf/operations/usc-channel:remove-channel -${REST_REMOVE_SESSION} /restconf/operations/usc-channel:remove-session -${REST_SEND_MESSAGE} /restconf/operations/usc-channel:send-message -${NAV_USC_TOOLS} cd ~/usc-tools -${CLONE_USC_TOOLS} [ -f ~/usc-tools/UscAgent.jar ] && echo "The usc-tools does exist, done." || git clone https://github.com/victorxu99/usc-tools.git ~/usc-tools -${ECHO_SERVER_PORT} 2007 +${REST_VIEW_CHANNEL} /restconf/operations/usc-channel:view-channel +${REST_ADD_CHANNEL} /restconf/operations/usc-channel:add-channel +${REST_REMOVE_CHANNEL} /restconf/operations/usc-channel:remove-channel +${REST_REMOVE_SESSION} /restconf/operations/usc-channel:remove-session +${REST_SEND_MESSAGE} /restconf/operations/usc-channel:send-message +${NAV_USC_TOOLS} cd ~/usc-tools +${CLONE_USC_TOOLS} +... [ -f ~/usc-tools/UscAgent.jar ] && echo "The usc-tools does exist, done." || git clone https://github.com/victorxu99/usc-tools.git ~/usc-tools +${ECHO_SERVER_PORT} 2007 @{LIST_ECHO_SERVER_PORT} 2007 2008 2009 -${TEST_MESSAGE} This is a test message. -${NUM_OF_MESSAGES} 100 -${AgentTcp} java -jar UscAgent.jar -t true -${AgentUdp} java -jar UscAgent.jar -t false -${AgentTcpCallhome} java -jar UscAgent.jar -t true -c true -h -${AgentUdpCallhome} java -jar UscAgent.jar -t false -c true -h -${EchoServerTcp} java -jar EchoServer.jar -t true -p 2007 -${EchoServerUdp} java -jar EchoServer.jar -t false -p 2007 +${TEST_MESSAGE} This is a test message. +${NUM_OF_MESSAGES} 100 +${AgentTcp} java -jar UscAgent.jar -t true +${AgentUdp} java -jar UscAgent.jar -t false +${AgentTcpCallhome} java -jar UscAgent.jar -t true -c true -h +${AgentUdpCallhome} java -jar UscAgent.jar -t false -c true -h +${EchoServerTcp} java -jar EchoServer.jar -t true -p 2007 +${EchoServerUdp} java -jar EchoServer.jar -t false -p 2007 + *** Keywords *** Download Tools @@ -134,7 +137,7 @@ Start Multiple_Sessions_TCP Write ${NAV_USC_TOOLS} Write ${AgentTcp} Read - ${L1} Create List + ${L1}= Create List FOR ${port_index} IN @{LIST_ECHO_SERVER_PORT} Log ${port_index} ${echo_conn_id}= Open Connection ${TOOLS_SYSTEM_IP} timeout=30s @@ -156,7 +159,7 @@ Start Multiple_Sessions_UDP Write ${NAV_USC_TOOLS} Write ${AgentUdp} Read - ${L1} Create List + ${L1}= Create List FOR ${port_index} IN @{LIST_ECHO_SERVER_PORT} Log ${port_index} ${echo_conn_id}= Open Connection ${TOOLS_SYSTEM_IP} timeout=30s diff --git a/csit/libraries/Utils.robot b/csit/libraries/Utils.robot index 1a5016b7a4..f9b8139bde 100644 --- a/csit/libraries/Utils.robot +++ b/csit/libraries/Utils.robot @@ -1,27 +1,30 @@ *** Settings *** -Documentation General Utils library. This library has broad scope, it can be used by any robot system tests. -Library SSHLibrary -Library String -Library DateTime -Library Process -Library Collections -Library RequestsLibrary -Library OperatingSystem -Library ${CURDIR}/UtilLibrary.py -Resource ${CURDIR}/SSHKeywords.robot -Resource ${CURDIR}/TemplatedRequests.robot -Resource ${CURDIR}/../variables/Variables.robot -Resource ${CURDIR}/../variables/openflowplugin/Variables.robot +Documentation General Utils library. This library has broad scope, it can be used by any robot system tests. + +Library SSHLibrary +Library String +Library DateTime +Library Process +Library Collections +Library RequestsLibrary +Library OperatingSystem +Library ${CURDIR}/UtilLibrary.py +Resource ${CURDIR}/SSHKeywords.robot +Resource ${CURDIR}/TemplatedRequests.robot +Resource ${CURDIR}/../variables/Variables.robot +Resource ${CURDIR}/../variables/openflowplugin/Variables.robot + *** Variables *** # TODO: Introduce ${tree_size} and use instead of 1 in the next line. -${start} sudo mn --controller=remote,ip=${ODL_SYSTEM_IP} --topo tree,1 --switch ovsk,protocols=OpenFlow13 +${start} sudo mn --controller=remote,ip=${ODL_SYSTEM_IP} --topo tree,1 --switch ovsk,protocols=OpenFlow13 + *** Keywords *** Start Mininet - [Arguments] ${system}=${TOOLS_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${password}=${TOOLS_SYSTEM_PASSWORD} ${prompt}=${TOOLS_SYSTEM_PROMPT} ${timeout}=30s [Documentation] Basic setup/cleanup work that can be done safely before any system ... is run. + [Arguments] ${system}=${TOOLS_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${password}=${TOOLS_SYSTEM_PASSWORD} ${prompt}=${TOOLS_SYSTEM_PROMPT} ${timeout}=30s Log Start the test on the base edition Clean Mininet System ${mininet_conn_id}= Open Connection ${system} prompt=${prompt} timeout=${timeout} @@ -32,9 +35,9 @@ Start Mininet Read Until mininet> Stop Mininet - [Arguments] ${prompt}=${TOOLS_SYSTEM_PROMPT} [Documentation] Cleanup/Shutdown work that should be done at the completion of all ... tests + [Arguments] ${prompt}=${TOOLS_SYSTEM_PROMPT} Log Stop the test on the base edition Switch Connection ${mininet_conn_id} Read @@ -43,7 +46,6 @@ Stop Mininet Close Connection Report Failure Due To Bug - [Arguments] ${number} ${include_bug_in_tags}=True [Documentation] Report that a test failed due to a known Bugzilla bug whose ... number is provided as an argument. ... Not FAILED (incl. SKIPPED) test are not reported. @@ -51,16 +53,20 @@ Report Failure Due To Bug ... or as the first line of the test if FastFail module is not being ... used. It reports the URL of the bug on console and also puts it ... into the Robot log file. + [Arguments] ${number} ${include_bug_in_tags}=True ${test_skipped}= BuiltIn.Evaluate len(re.findall('SKIPPED', """${TEST_MESSAGE}""")) > 0 modules=re - BuiltIn.Return From Keyword If ('${TEST_STATUS}' != 'FAIL') or ${test_skipped} + IF ('${TEST_STATUS}' != 'FAIL') or ${test_skipped} RETURN Comment Jira tickets are {PROJECT}-{NUMBER} while Bugzilla tickets are {NUMBER} - ${match} BuiltIn.Run Keyword And Return Status Should Contain ${number} - - ${bug_url}= BuiltIn.Set Variable If ${match} https://jira.opendaylight.org/browse/${number} https://bugs.opendaylight.org/show_bug.cgi?id=${number} + ${match}= BuiltIn.Run Keyword And Return Status Should Contain ${number} - + ${bug_url}= BuiltIn.Set Variable If + ... ${match} + ... https://jira.opendaylight.org/browse/${number} + ... https://bugs.opendaylight.org/show_bug.cgi?id=${number} ${msg}= BuiltIn.Set_Variable This test fails due to ${bug_url} ${newline}= BuiltIn.Evaluate chr(10) BuiltIn.Set Test Message ${msg}${newline}${newline}${TEST_MESSAGE} BuiltIn.Log ${msg} - BuiltIn.Run Keyword If "${include_bug_in_tags}"=="True" Set Tags ${bug_url} + IF "${include_bug_in_tags}"=="True" Set Tags ${bug_url} Report_Failure_And_Point_To_Linked_Bugs [Documentation] Report that a test failed and point to linked Bugzilla bug(s). @@ -73,62 +79,77 @@ Report_Failure_And_Point_To_Linked_Bugs ... used. It reports the URL of the bug on console and also puts it ... into the Robot log file. ${test_skipped}= BuiltIn.Evaluate len(re.findall('SKIPPED', """${TEST_MESSAGE}""")) > 0 modules=re - BuiltIn.Return From Keyword If ('${TEST_STATUS}' != 'FAIL') or ${test_skipped} + IF ('${TEST_STATUS}' != 'FAIL') or ${test_skipped} RETURN ${newline}= BuiltIn.Evaluate chr(10) ${reference}= String.Replace_String_Using_Regexp ${SUITE_NAME}_${TEST_NAME} [ /\.-] _ ${reference}= String.Convert_To_Lowercase ${reference} - ${msg}= BuiltIn.Set_Variable ... click for list of related bugs or create a new one if needed (with the${newline}"${reference}"${newline}reference somewhere inside) - ${bugs}= BuiltIn.Set_Variable "https://bugs.opendaylight.org/buglist.cgi?f1=cf_external_ref&o1=substring&v1=${reference}&order=bug_status" + ${msg}= BuiltIn.Set_Variable + ... ... click for list of related bugs or create a new one if needed (with the${newline}"${reference}"${newline}reference somewhere inside) + ${bugs}= BuiltIn.Set_Variable + ... "https://bugs.opendaylight.org/buglist.cgi?f1=cf_external_ref&o1=substring&v1=${reference}&order=bug_status" BuiltIn.Set Test Message ${msg}${newline}${bugs}${newline}${newline}${TEST_MESSAGE} BuiltIn.Log ${msg}${newline}${bugs} Check Nodes Stats - [Arguments] ${node} ${session}=session [Documentation] A GET on the /node/${node} API is made and specific flow stat ... strings are checked for existence. - ${resp} RequestsLibrary.Get Request ${session} ${RFC8040_NODES_API}/node=${node}?${RFC8040_OPERATIONAL_CONTENT} + [Arguments] ${node} ${session}=session + ${resp}= RequestsLibrary.Get Request + ... ${session} + ... ${RFC8040_NODES_API}/node=${node}?${RFC8040_OPERATIONAL_CONTENT} Should Be Equal As Strings ${resp.status_code} 200 Should Contain ${resp.text} flow-capable-node-connector-statistics Should Contain ${resp.text} flow-table-statistics Check For Specific Number Of Elements At URI - [Arguments] ${uri} ${element} ${expected_count} ${session}=session [Documentation] A GET is made to the specified ${URI} and the specific count of a ... given element is done (as supplied by ${element} and ${expected_count}) - ${resp} RequestsLibrary.Get Request ${session} ${uri} + [Arguments] ${uri} ${element} ${expected_count} ${session}=session + ${resp}= RequestsLibrary.Get Request ${session} ${uri} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 Should Contain X Times ${resp.text} ${element} ${expected_count} Log Content [Arguments] ${resp_content} - ${resp_json} = BuiltIn.Run Keyword If '''${resp_content}''' != '${EMPTY}' RequestsLibrary.To Json ${resp_content} pretty_print=True - ... ELSE BuiltIn.Set Variable ${EMPTY} + IF '''${resp_content}''' != '${EMPTY}' + ${resp_json}= RequestsLibrary.To Json ${resp_content} pretty_print=True + ELSE + ${resp_json}= BuiltIn.Set Variable ${EMPTY} + END BuiltIn.Log ${resp_json} - [Return] ${resp_json} + RETURN ${resp_json} Check For Elements At URI - [Arguments] ${uri} ${elements} ${session}=session ${pretty_print_json}=False [Documentation] A GET is made at the supplied ${URI} and every item in the list of ... ${elements} is verified to exist in the response - ${resp} RequestsLibrary.Get Request ${session} ${uri} - BuiltIn.Run Keyword If "${pretty_print_json}" == "True" Log Content ${resp.text} - ... ELSE BuiltIn.Log ${resp.text} + [Arguments] ${uri} ${elements} ${session}=session ${pretty_print_json}=False + ${resp}= RequestsLibrary.Get Request ${session} ${uri} + IF "${pretty_print_json}" == "True" + Log Content ${resp.text} + ELSE + BuiltIn.Log ${resp.text} + END Should Be Equal As Strings ${resp.status_code} 200 FOR ${i} IN @{elements} Should Contain ${resp.text} ${i} END Check For Elements Not At URI - [Arguments] ${uri} ${elements} ${session}=session ${pretty_print_json}=False ${check_for_null}=False [Documentation] A GET is made at the supplied ${uri} and every item in the list of ... ${elements} is verified to NOT exist in the response. If ${check_for_null} is True ... return of 404 is treated as empty list. From Neon onwards, an empty list is always ... returned as null, giving 404 on rest call. - ${resp} RequestsLibrary.Get Request ${session} ${uri} - BuiltIn.Run Keyword If "${pretty_print_json}" == "True" Log Content ${resp.text} - ... ELSE BuiltIn.Log ${resp.text} - BuiltIn.Run Keyword If "${check_for_null}" == "True" Builtin.Return From Keyword If ${resp.status_code} == 404 or ${resp.status_code} == 409 + [Arguments] ${uri} ${elements} ${session}=session ${pretty_print_json}=False ${check_for_null}=False + ${resp}= RequestsLibrary.Get Request ${session} ${uri} + IF "${pretty_print_json}" == "True" + Log Content ${resp.text} + ELSE + BuiltIn.Log ${resp.text} + END + IF "${check_for_null}" == "True" + IF ${resp.status_code} == 404 or ${resp.status_code} == 409 RETURN + END Should Be Equal As Strings ${resp.status_code} 200 FOR ${i} IN @{elements} Should Not Contain ${resp.text} ${i} @@ -137,11 +158,13 @@ Check For Elements Not At URI Clean Mininet System [Arguments] ${system}=${TOOLS_SYSTEM_IP} Run Command On Mininet ${system} sudo mn -c - Run Command On Mininet ${system} sudo ps -elf | egrep 'usr/local/bin/mn' | egrep python | awk '{print "sudo kill -9",$4}' | sh + Run Command On Mininet + ... ${system} + ... sudo ps -elf | egrep 'usr/local/bin/mn' | egrep python | awk '{print "sudo kill -9",$4}' | sh Clean Up Ovs - [Arguments] ${system}=${TOOLS_SYSTEM_IP} [Documentation] Cleans up the OVS instance and remove any existing common known bridges. + [Arguments] ${system}=${TOOLS_SYSTEM_IP} ${output}= Run Command On Mininet ${system} sudo ovs-vsctl list-br Log ${output} FOR ${i} IN ${output} @@ -150,309 +173,345 @@ Clean Up Ovs Run Command On Mininet ${system} sudo ovs-vsctl del-manager Extract Value From Content - [Arguments] ${content} ${index} [Documentation] Will take the given response content and return the value at the given index as a string - ${JSON} = Evaluate json.loads('''${content}''') json - ${value} = Set Variable ${JSON${index}} - [Return] ${value} + [Arguments] ${content} ${index} + ${JSON}= Evaluate json.loads('''${content}''') json + ${value}= Set Variable ${JSON${index}} + RETURN ${value} Get Process ID Based On Regex On Remote System - [Arguments] ${system} ${regex_string_to_match_on} ${user}=${TOOLS_SYSTEM_USER} ${password}=${EMPTY} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=30s [Documentation] Uses ps to find a process that matches the supplied regex. Returns the PID of that process ... The ${regex_string_to_match_on} should produce a unique process otherwise the PID returned may not be ... the expected PID + [Arguments] ${system} ${regex_string_to_match_on} ${user}=${TOOLS_SYSTEM_USER} ${password}=${EMPTY} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=30s # doing the extra -v grep in this command to exclude the grep process itself from the output ${cmd}= Set Variable ps -elf | grep -v grep | grep ${regex_string_to_match_on} | awk '{print $4}' - ${output}= Run Command On Remote System ${system} ${cmd} user=${user} password=${password} prompt=${prompt} + ${output}= Run Command On Remote System + ... ${system} + ... ${cmd} + ... user=${user} + ... password=${password} + ... prompt=${prompt} ... prompt_timeout=${prompt_timeout} # ${output} contains the system prompt and all we want is the value of the number ${pid}= Fetch From Left ${output} \r - # TODO: Get Process * keywords have perhaps non-standard default credentials. + RETURN ${pid} + # ... Should there be * On Mininet and * On Controller specializations? - [Return] ${pid} + # TODO: Get Process * keywords have perhaps non-standard default credentials. Get Process Thread Count On Remote System - [Arguments] ${system} ${pid} ${user}=${TOOLS_SYSTEM_USER} ${password}=${EMPTY} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=30s [Documentation] Executes the ps command to retrieve the lightweight process (aka thread) count. + [Arguments] ${system} ${pid} ${user}=${TOOLS_SYSTEM_USER} ${password}=${EMPTY} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=30s ${cmd}= Set Variable ps --no-headers -o nlwp ${pid} - ${output}= Run Command On Remote System ${system} ${cmd} user=${user} password=${password} prompt=${prompt} + ${output}= Run Command On Remote System + ... ${system} + ... ${cmd} + ... user=${user} + ... password=${password} + ... prompt=${prompt} ... prompt_timeout=${prompt_timeout} # ${output} contains the system prompt and all we want is the value of the number ${thread_count}= Fetch From Left ${output} \r - [Return] ${thread_count} + RETURN ${thread_count} Strip Quotes - [Arguments] ${string_to_strip} [Documentation] Will strip ALL quotes from given string and return the new string + [Arguments] ${string_to_strip} ${string_to_return}= Replace String ${string_to_strip} " \ count=-1 - [Return] ${string_to_return} + RETURN ${string_to_return} Run Command On Remote System - [Arguments] ${system} ${cmd} ${user}=${DEFAULT_USER} ${password}=${EMPTY} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=${DEFAULT_TIMEOUT} - ... ${return_stdout}=True ${return_stderr}=False [Documentation] Reduces the common work of running a command on a remote system to a single higher level ... robot keyword, taking care to log in with a public key and. The command given is written and the return value ... depends on the passed argument values of return_stdout (default: True) and return_stderr (default: False). ... At least one should be True, or the keyword will exit and FAIL. If both are True, the resulting return value ... will be a two element list containing both. Otherwise the resulting return value is a string. ... No test conditions are checked. - Run Keyword If "${return_stdout}"!="True" and "${return_stderr}"!="True" Fail At least one of {return_stdout} or {return_stderr} args should be set to True + [Arguments] ${system} ${cmd} ${user}=${DEFAULT_USER} ${password}=${EMPTY} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=${DEFAULT_TIMEOUT} + ... ${return_stdout}=True ${return_stderr}=False + IF "${return_stdout}"!="True" and "${return_stderr}"!="True" + Fail At least one of {return_stdout} or {return_stderr} args should be set to True + END ${current_ssh_connection}= SSHLibrary.Get Connection - BuiltIn.Log Attempting to execute command "${cmd}" on remote system "${system}" by user "${user}" with keyfile pass "${keyfile_pass}" and prompt "${prompt}" and password "${password}" + BuiltIn.Log + ... Attempting to execute command "${cmd}" on remote system "${system}" by user "${user}" with keyfile pass "${keyfile_pass}" and prompt "${prompt}" and password "${password}" ${conn_id}= SSHLibrary.Open Connection ${system} prompt=${prompt} timeout=${prompt_timeout} SSHKeywords.Flexible SSH Login ${user} ${password} - ${stdout} ${stderr} SSHLibrary.Execute Command ${cmd} return_stderr=True + ${stdout} ${stderr}= SSHLibrary.Execute Command ${cmd} return_stderr=True SSHLibrary.Close Connection Log ${stderr} - Run Keyword If "${return_stdout}"!="True" Return From Keyword ${stderr} - Run Keyword If "${return_stderr}"!="True" Return From Keyword ${stdout} + IF "${return_stdout}"!="True" RETURN ${stderr} + IF "${return_stderr}"!="True" RETURN ${stdout} + RETURN ${stdout} ${stderr} [Teardown] SSHKeywords.Restore_Current_SSH_Connection_From_Index ${current_ssh_connection.index} - [Return] ${stdout} ${stderr} Run Command On Remote System And Log - [Arguments] ${system} ${cmd} ${user}=${DEFAULT_USER} ${password}=${EMPTY} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=${DEFAULT_TIMEOUT} [Documentation] Reduces the common work of running a command on a remote system to a single higher level ... robot keyword, taking care to log in with a public key and. The command given is written ... and the output returned. No test conditions are checked. - ${output} = Run Command On Remote System ${system} ${cmd} ${user} ${password} ${prompt} + [Arguments] ${system} ${cmd} ${user}=${DEFAULT_USER} ${password}=${EMPTY} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=${DEFAULT_TIMEOUT} + ${output}= Run Command On Remote System ${system} ${cmd} ${user} ${password} ${prompt} ... ${prompt_timeout} Log ${output} - [Return] ${output} + RETURN ${output} Run Command On Mininet - [Arguments] ${system}=${TOOLS_SYSTEM_IP} ${cmd}=echo ${user}=${TOOLS_SYSTEM_USER} ${password}=${TOOLS_SYSTEM_PASSWORD} ${prompt}=${TOOLS_SYSTEM_PROMPT} [Documentation] Call Run Comand On Remote System, but with default values suitable for Mininet machine. - BuiltIn.Run Keyword And Return Run Command On Remote System ${system} ${cmd} ${user} ${password} prompt=${prompt} + [Arguments] ${system}=${TOOLS_SYSTEM_IP} ${cmd}=echo ${user}=${TOOLS_SYSTEM_USER} ${password}=${TOOLS_SYSTEM_PASSWORD} ${prompt}=${TOOLS_SYSTEM_PROMPT} + BuiltIn.Run Keyword And Return + ... Run Command On Remote System + ... ${system} + ... ${cmd} + ... ${user} + ... ${password} + ... prompt=${prompt} Run Command On Controller - [Arguments] ${system}=${ODL_SYSTEM_IP} ${cmd}=echo ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} [Documentation] Call Run Comand On Remote System, but with default values suitable for Controller machine. - BuiltIn.Run Keyword And Return Run Command On Remote System ${system} ${cmd} ${user} ${password} prompt=${prompt} + [Arguments] ${system}=${ODL_SYSTEM_IP} ${cmd}=echo ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} + BuiltIn.Run Keyword And Return + ... Run Command On Remote System + ... ${system} + ... ${cmd} + ... ${user} + ... ${password} + ... prompt=${prompt} Run Command On Existing Connection - [Arguments] ${conn_id}=${EMPTY} ${cmd}=echo ${return_stdout}=True ${return_stderr}=False [Documentation] Switch to and run command on an already existing SSH connection and switch back - Run Keyword If "${return_stdout}"!="True" and "${return_stderr}"!="True" Fail At least one of {return_stdout} or {return_stderr} args should be set to True + [Arguments] ${conn_id}=${EMPTY} ${cmd}=echo ${return_stdout}=True ${return_stderr}=False + IF "${return_stdout}"!="True" and "${return_stderr}"!="True" + Fail At least one of {return_stdout} or {return_stderr} args should be set to True + END ${current_ssh_connection}= SSHLibrary.Get Connection BuiltIn.Log Attempting to execute command "${cmd}" on existing connection "${conn_id} SSHLibrary.Switch Connection ${conn_id} - ${stdout} ${stderr} SSHLibrary.Execute Command ${cmd} return_stderr=True + ${stdout} ${stderr}= SSHLibrary.Execute Command ${cmd} return_stderr=True Log ${stderr} - Run Keyword If "${return_stdout}"!="True" Return From Keyword ${stderr} - Run Keyword If "${return_stderr}"!="True" Return From Keyword ${stdout} + IF "${return_stdout}"!="True" RETURN ${stderr} + IF "${return_stderr}"!="True" RETURN ${stdout} + RETURN ${stdout} ${stderr} [Teardown] SSHKeywords.Restore_Current_SSH_Connection_From_Index ${current_ssh_connection.index} - [Return] ${stdout} ${stderr} Verify File Exists On Remote System - [Arguments] ${system} ${file} ${user}=${TOOLS_SYSTEM_USER} ${password}=${TOOLS_SYSTEM_PASSWORD} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=5s [Documentation] Will create connection with public key and will PASS if the given ${file} exists, ... otherwise will FAIL + [Arguments] ${system} ${file} ${user}=${TOOLS_SYSTEM_USER} ${password}=${TOOLS_SYSTEM_PASSWORD} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=5s ${conn_id}= Open Connection ${system} prompt=${prompt} timeout=${prompt_timeout} SSHKeywords.Flexible SSH Login ${user} ${password} SSHLibrary.File Should Exist ${file} Close Connection Check Karaf Log File Does Not Have Messages - [Arguments] ${ip} ${message} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} ${log_file}=${WORKSPACE}/${BUNDLEFOLDER}/data/log/karaf.log [Documentation] Fails if the provided ${message} is found in the karaf.log file. Uses grep to search. The ... karaf.log file can be overridden with ${log_file} to be any file on the given system @ ${ip} - ${output}= Run Command On Controller ${ip} grep -c '${message}' ${log_file} user=${user} password=${password} prompt=${prompt} + [Arguments] ${ip} ${message} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} ${log_file}=${WORKSPACE}/${BUNDLEFOLDER}/data/log/karaf.log + ${output}= Run Command On Controller + ... ${ip} + ... grep -c '${message}' ${log_file} + ... user=${user} + ... password=${password} + ... prompt=${prompt} Should Be Equal As Strings ${output} 0 Verify Controller Is Not Dead - [Arguments] ${controller_ip}=${ODL_SYSTEM_IP} [Documentation] Will execute any tests to verify the controller is not dead. Some checks are ... Out Of Memory Execptions. + [Arguments] ${controller_ip}=${ODL_SYSTEM_IP} Check Karaf Log File Does Not Have Messages ${controller_ip} java.lang.OutOfMemoryError # TODO: Should Verify Controller * keywords also accept user, password, prompt and karaf_log arguments? Verify Controller Has No Null Pointer Exceptions - [Arguments] ${controller_ip}=${ODL_SYSTEM_IP} [Documentation] Will execute any tests to verify the controller is not having any null pointer eceptions. + [Arguments] ${controller_ip}=${ODL_SYSTEM_IP} Check Karaf Log File Does Not Have Messages ${controller_ip} java.lang.NullPointerException Verify Controller Has No Runtime Exceptions - [Arguments] ${controller_ip}=${ODL_SYSTEM_IP} [Documentation] Will execute any tests to verify the controller is not having any runtime eceptions. + [Arguments] ${controller_ip}=${ODL_SYSTEM_IP} Check Karaf Log File Does Not Have Messages ${controller_ip} java.lang.RuntimeException Get Epoch Time - [Arguments] ${time} [Documentation] Get the Epoc time from MM/DD/YYYY HH:MM:SS + [Arguments] ${time} ${epoch_time}= Convert Date ${time} epoch exclude_milles=True date_format=%m/%d/%Y %H:%M:%S ${epoch_time}= Convert To Integer ${epoch_time} - [Return] ${epoch_time} + RETURN ${epoch_time} Remove Space on String - [Arguments] ${str} ${count}=-1 [Documentation] Remove the empty space from given string.count is optional,if its given ... that many occurence of space will be removed from left + [Arguments] ${str} ${count}=-1 ${x}= Convert To String ${str} ${x}= Replace String ${str} ${SPACE} ${EMPTY} count=${count} - [Return] ${x} + RETURN ${x} Split Value from String - [Arguments] ${str} ${splitter} [Documentation] Split the String based on given splitter and return as list + [Arguments] ${str} ${splitter} @{x}= Split String ${str} ${splitter} - [Return] @{x} + RETURN @{x} Concatenate the String - [Arguments] ${str1} ${str2} [Documentation] Catenate the two non-string objects and return as String + [Arguments] ${str1} ${str2} ${str1}= Convert to String ${str1} ${str2}= Convert to String ${str2} ${output}= Catenate ${str1} ${str2} - [Return] ${output} + RETURN ${output} Post Elements To URI - [Arguments] ${rest_uri} ${data} ${headers}=${headers} ${session}=session [Documentation] Perform a POST rest operation, using the URL and data provided - ${resp} = RequestsLibrary.Post Request ${session} ${rest_uri} data=${data} headers=${headers} + [Arguments] ${rest_uri} ${data} ${headers}=${headers} ${session}=session + ${resp}= RequestsLibrary.Post Request ${session} ${rest_uri} data=${data} headers=${headers} Log ${resp.text} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Remove All Elements At URI [Arguments] ${uri} ${session}=session - ${resp} RequestsLibrary.Delete Request ${session} ${uri} + ${resp}= RequestsLibrary.Delete Request ${session} ${uri} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Remove All Elements At URI And Verify [Arguments] ${uri} ${session}=session - ${resp} RequestsLibrary.Delete Request ${session} ${uri} + ${resp}= RequestsLibrary.Delete Request ${session} ${uri} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} - ${resp} RequestsLibrary.Get Request ${session} ${uri} + ${resp}= RequestsLibrary.Get Request ${session} ${uri} Should Contain ${DELETED_STATUS_CODES} ${resp.status_code} Remove All Elements If Exist - [Arguments] ${uri} ${session}=session [Documentation] Delete all elements from an URI if the configuration was not empty - ${resp} RequestsLibrary.Get Request ${session} ${uri} - Run Keyword If '${resp.status_code}'!='404' and '${resp.status_code}'!='409' Remove All Elements At URI ${uri} ${session} + [Arguments] ${uri} ${session}=session + ${resp}= RequestsLibrary.Get Request ${session} ${uri} + IF '${resp.status_code}'!='404' and '${resp.status_code}'!='409' + Remove All Elements At URI ${uri} ${session} + END Add Elements To URI From File - [Arguments] ${dest_uri} ${data_file} ${headers}=${headers} ${session}=session [Documentation] Put data from a file to a URI - ${body} OperatingSystem.Get File ${data_file} - ${resp} RequestsLibrary.Put Request ${session} ${dest_uri} data=${body} headers=${headers} + [Arguments] ${dest_uri} ${data_file} ${headers}=${headers} ${session}=session + ${body}= OperatingSystem.Get File ${data_file} + ${resp}= RequestsLibrary.Put Request ${session} ${dest_uri} data=${body} headers=${headers} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Add Elements To URI From File And Verify - [Arguments] ${dest_uri} ${data_file} ${headers}=${headers} ${session}=session [Documentation] Put data from a file to a URI and verify the HTTP response - ${body} OperatingSystem.Get File ${data_file} + [Arguments] ${dest_uri} ${data_file} ${headers}=${headers} ${session}=session + ${body}= OperatingSystem.Get File ${data_file} Add Elements to URI And Verify ${dest_uri} ${body} ${headers} ${session} Add Elements To URI And Verify - [Arguments] ${dest_uri} ${data} ${headers}=${headers} ${session}=session [Documentation] Put data to a URI and verify the HTTP response - ${resp} RequestsLibrary.Put Request ${session} ${dest_uri} ${data} headers=${headers} + [Arguments] ${dest_uri} ${data} ${headers}=${headers} ${session}=session + ${resp}= RequestsLibrary.Put Request ${session} ${dest_uri} ${data} headers=${headers} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} - ${resp} RequestsLibrary.Get Request ${session} ${dest_uri} + ${resp}= RequestsLibrary.Get Request ${session} ${dest_uri} Should Not Contain ${DELETED_STATUS_CODES} ${resp.status_code} Add Elements To URI From File And Check Validation Error - [Arguments] ${dest_uri} ${data_file} ${headers}=${headers} ${session}=session [Documentation] Shorthand for PUTting data from file and expecting status code 400. + [Arguments] ${dest_uri} ${data_file} ${headers}=${headers} ${session}=session BuiltIn.Comment TODO: Does this have any benefits, considering TemplatedRequests can also do this in one line? - ${body} OperatingSystem.Get File ${data_file} - ${resp} RequestsLibrary.Put Request ${session} ${dest_uri} data=${body} headers=${headers} + ${body}= OperatingSystem.Get File ${data_file} + ${resp}= RequestsLibrary.Put Request ${session} ${dest_uri} data=${body} headers=${headers} Should Contain ${DATA_VALIDATION_ERROR} ${resp.status_code} Add Elements To URI From File And Check Server Error - [Arguments] ${dest_uri} ${data_file} ${headers}=${headers} ${session}=session [Documentation] Shorthand for PUTting data from file and expecting status code 500. ... Consider opening a Bug against ODL, as in most test cases, 400 is the http code to expect. + [Arguments] ${dest_uri} ${data_file} ${headers}=${headers} ${session}=session BuiltIn.Comment TODO: Does this have any benefits, considering TemplatedRequests can also do this in one line? - ${body} OperatingSystem.Get File ${data_file} - ${resp} RequestsLibrary.Put Request ${session} ${dest_uri} data=${body} headers=${headers} + ${body}= OperatingSystem.Get File ${data_file} + ${resp}= RequestsLibrary.Put Request ${session} ${dest_uri} data=${body} headers=${headers} Should Contain ${INTERNAL_SERVER_ERROR} ${resp.status_code} Post Elements To URI From File [Arguments] ${dest_uri} ${data_file} ${headers}=${headers} ${session}=session - ${body} OperatingSystem.Get File ${data_file} - ${resp} RequestsLibrary.Post Request ${session} ${dest_uri} data=${body} headers=${headers} + ${body}= OperatingSystem.Get File ${data_file} + ${resp}= RequestsLibrary.Post Request ${session} ${dest_uri} data=${body} headers=${headers} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Run Process With Logging And Status Check - [Arguments] @{proc_args} [Documentation] Execute an OS command, log STDOUT and STDERR output and check exit code to be 0 + [Arguments] @{proc_args} ${result}= Run Process @{proc_args} Log ${result.stdout} Log ${result.stderr} Should Be Equal As Integers ${result.rc} 0 - [Return] ${result} + RETURN ${result} Get Data From URI - [Arguments] ${session} ${uri} ${headers}=${NONE} [Documentation] Issue a GET request and return the data obtained or on error log the error and fail. ... Issues a GET request for ${uri} in ${session} using headers from ... ${headers}. If the request returns a HTTP error, fails. Otherwise ... returns the data obtained by the request. + [Arguments] ${session} ${uri} ${headers}=${NONE} ${resp}= RequestsLibrary.Get Request ${session} ${uri} ${headers} - Builtin.Return_From_Keyword_If ${resp.status_code} == 200 ${resp.text} + IF ${resp.status_code} == 200 RETURN ${resp.text} Builtin.Log ${resp.text} Builtin.Fail The request failed with code ${resp.status_code} Get URI And Verify - [Arguments] ${uri} ${session}=session ${headers}=${NONE} [Documentation] Issue a GET request and verify a successfull HTTP return. ... Issues a GET request for ${uri} in ${session} using headers from ${headers}. - ${resp} = RequestsLibrary.Get Request ${session} ${uri} ${headers} + [Arguments] ${uri} ${session}=session ${headers}=${NONE} + ${resp}= RequestsLibrary.Get Request ${session} ${uri} ${headers} Builtin.Log ${resp.status_code} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} No Content From URI - [Arguments] ${session} ${uri} ${headers}=${NONE} [Documentation] Issue a GET request and return on error 404 (No content) or will fail and log the content. ... Issues a GET request for ${uri} in ${session} using headers from ... ${headers}. If the request returns a HTTP error, fails. Otherwise ... returns the data obtained by the request. + [Arguments] ${session} ${uri} ${headers}=${NONE} ${resp}= RequestsLibrary.Get Request ${session} ${uri} ${headers} - Builtin.Return_From_Keyword_If ${resp.status_code} == 404 or ${resp.status_code} == 409 + IF ${resp.status_code} == 404 or ${resp.status_code} == 409 RETURN Builtin.Log ${resp.text} Builtin.Fail The request failed with code ${resp.status_code} Get Index From List Of Dictionaries - [Arguments] ${dictionary_list} ${key} ${value} [Documentation] Extract index for the dictionary in a list that contains a key-value pair. Returns -1 if key-value is not found. + [Arguments] ${dictionary_list} ${key} ${value} ${length}= Get Length ${dictionary_list} ${index}= Set Variable -1 FOR ${i} IN RANGE ${length} ${dictionary}= Get From List ${dictionary_list} ${i} - Run Keyword If """${dictionary}[${key}]""" == """${value}""" Set Test Variable ${index} ${i} + IF """${dictionary}[${key}]""" == """${value}""" + Set Test Variable ${index} ${i} + END END - [Return] ${index} + RETURN ${index} Check Item Occurrence - [Arguments] ${string} ${dictionary_item_occurrence} [Documentation] Check string for occurrences of items expressed in a list of dictionaries {item=occurrences}. 0 occurences means item is not present. + [Arguments] ${string} ${dictionary_item_occurrence} FOR ${item} IN @{dictionary_item_occurrence} Should Contain X Times ${string} ${item} ${dictionary_item_occurrence}[${item}] END Post Log Check - [Arguments] ${uri} ${body} ${session}=session ${status_codes}=200 [Documentation] Post body to ${uri}, log response content, and check status + [Arguments] ${uri} ${body} ${session}=session ${status_codes}=200 ${resp}= RequestsLibrary.Post Request ${session} ${uri} ${body} Log ${resp.text} TemplatedRequests.Check Status Code ${resp} ${status_codes} - [Return] ${resp} + RETURN ${resp} Get Log File Name - [Arguments] ${testtool} ${testcase}=${EMPTY} [Documentation] Get the name of the suite sanitized to be usable as a part of filename. ... These names are used to constructs names of the log files produced ... by the testing tools so two suites using a tool wont overwrite the ... log files if they happen to run in one job. + [Arguments] ${testtool} ${testcase}=${EMPTY} ${name}= BuiltIn.Evaluate """${SUITE_NAME}""".replace(" ","-").replace("/","-").replace(".","-") ${suffix}= BuiltIn.Set_Variable_If '${testcase}' != '' --${testcase} ${EMPTY} - ${date} = DateTime.Get Current Date - ${timestamp} = DateTime.Convert Date ${date} epoch - [Return] ${testtool}--${name}${suffix}.${timestamp}.log + ${date}= DateTime.Get Current Date + ${timestamp}= DateTime.Convert Date ${date} epoch + RETURN ${testtool}--${name}${suffix}.${timestamp}.log Set_User_Configurable_Variable_Default - [Arguments] ${name} ${value} [Documentation] Set a default value for an user configurable variable. ... This keyword is needed if your default value is calculated using ... a complex expression which needs BuiltIn.Evaluate or even more @@ -465,6 +524,7 @@ Set_User_Configurable_Variable_Default ... set by another keyword will silently turn the call into a NOP and ... thus is a bug in the suite or resource trying to call this ... keyword. + [Arguments] ${name} ${value} # TODO: Figure out how to make the ${value} evaluation "lazy" (meaning # evaluating it only when the user did not set anything and thus the # default is needed). This might be needed to avoid potentially costly @@ -499,40 +559,40 @@ Set_User_Configurable_Variable_Default BuiltIn.Set_Suite_Variable \${${name}} ${value} Convert_To_Minutes - [Arguments] ${time} [Documentation] Convert a Robot time string to an integer expressing the time in minutes, rounded up ... This is a wrapper around DateTime.Convert_Time which does not ... provide this functionality directly nor is even able to produce ... an integer directly. It is needed for RestPerfClient which ... cannot accept floats for its --timeout parameter and interprets ... the value supplied in this parameter in minutes. + [Arguments] ${time} ${seconds}= DateTime.Convert_Time ${time} result_format=number ${minutes}= BuiltIn.Evaluate int(math.ceil(${seconds}/60.0)) modules=math - [Return] ${minutes} + RETURN ${minutes} Write Commands Until Expected Prompt - [Arguments] ${cmd} ${prompt} ${timeout}=${DEFAULT_TIMEOUT} [Documentation] quick wrapper for Write and Read Until Prompt Keywords to make test cases more readable + [Arguments] ${cmd} ${prompt} ${timeout}=${DEFAULT_TIMEOUT} BuiltIn.Log cmd: ${cmd} SSHLibrary.Set Client Configuration timeout=${timeout} SSHLibrary.Read SSHLibrary.Write ${cmd} ${output}= SSHLibrary.Read Until ${prompt} - [Return] ${output} + RETURN ${output} Write Commands Until Expected Regexp - [Arguments] ${cmd} ${regexp} ${timeout}=${DEFAULT_TIMEOUT} [Documentation] quick wrapper for Write and Read Until Prompt Keywords to make test cases more readable + [Arguments] ${cmd} ${regexp} ${timeout}=${DEFAULT_TIMEOUT} BuiltIn.Log cmd: ${cmd} SSHLibrary.Set Client Configuration timeout=${timeout} SSHLibrary.Read SSHLibrary.Write ${cmd} ${output}= SSHLibrary.Read Until Regexp ${regexp} - [Return] ${output} + RETURN ${output} Install Package On Ubuntu System - [Arguments] ${package_name} ${system}=${TOOLS_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${password}=${TOOLS_SYSTEM_PASSWORD} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=30s [Documentation] Keyword to install packages for testing to Ubuntu Mininet VM + [Arguments] ${package_name} ${system}=${TOOLS_SYSTEM_IP} ${user}=${TOOLS_SYSTEM_USER} ${password}=${TOOLS_SYSTEM_PASSWORD} ${prompt}=${DEFAULT_LINUX_PROMPT} ${prompt_timeout}=30s Log Keyword to install package to Mininet Ubuntu VM Open Connection ${system} prompt=${prompt} timeout=${prompt_timeout} SSHKeywords.Flexible Mininet Login user=${user} password=${password} @@ -540,55 +600,74 @@ Install Package On Ubuntu System Read Until ${prompt} Json Parse From String - [Arguments] ${plain_string_with_json} [Documentation] Parse given plain string into json (dictionary) - ${json_data} Evaluate json.loads('''${plain_string_with_json}''') json - [Return] ${json_data} + [Arguments] ${plain_string_with_json} + ${json_data}= Evaluate json.loads('''${plain_string_with_json}''') json + RETURN ${json_data} Json Parse From File - [Arguments] ${json_file} [Documentation] Parse given file content into json (dictionary) - ${json_plain_string} OperatingSystem.Get file ${json_file} - ${json_data} Json Parse From String ${json_plain_string} - [Return] ${json_data} + [Arguments] ${json_file} + ${json_plain_string}= OperatingSystem.Get file ${json_file} + ${json_data}= Json Parse From String ${json_plain_string} + RETURN ${json_data} Modify Iptables On Remote System - [Arguments] ${remote_system_ip} ${iptables_rule} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} [Documentation] Wrapper keyword to run iptables with any given ${iptables_rule} string on the remote system given ... by ${remote_system_ip}. The iptables listing will be output before and after the command is run - ${list_iptables_command} = BuiltIn.Set Variable sudo /sbin/iptables -L -n - ${output} = Utils.Run Command On Remote System ${remote_system_ip} ${list_iptables_command} ${user} ${password} prompt=${prompt} + [Arguments] ${remote_system_ip} ${iptables_rule} ${user}=${ODL_SYSTEM_USER} ${password}=${ODL_SYSTEM_PASSWORD} ${prompt}=${ODL_SYSTEM_PROMPT} + ${list_iptables_command}= BuiltIn.Set Variable sudo /sbin/iptables -L -n + ${output}= Utils.Run Command On Remote System + ... ${remote_system_ip} + ... ${list_iptables_command} + ... ${user} + ... ${password} + ... prompt=${prompt} BuiltIn.Log ${output} - Utils.Run Command On Remote System ${remote_system_ip} sudo /sbin/iptables ${iptables_rule} ${user} ${password} prompt=${prompt} - ${output} = Utils.Run Command On Remote System ${remote_system_ip} ${list_iptables_command} ${user} ${password} prompt=${prompt} + Utils.Run Command On Remote System + ... ${remote_system_ip} + ... sudo /sbin/iptables ${iptables_rule} + ... ${user} + ... ${password} + ... prompt=${prompt} + ${output}= Utils.Run Command On Remote System + ... ${remote_system_ip} + ... ${list_iptables_command} + ... ${user} + ... ${password} + ... prompt=${prompt} BuiltIn.Log ${output} Get_Sysstat_Statistics - [Arguments] ${ip_address}=${ODL_SYSTEM_IP} [Documentation] Store current connection index, open new connection to ip_address. Run command to get sysstat results from script, ... which is running on all children nodes. Returns cpu, network, memory usage statistics from the node for each 10 minutes ... that node was running. Used for debug purposes. Returns whole output of sysstat. + [Arguments] ${ip_address}=${ODL_SYSTEM_IP} ${current_connection}= SSHLibrary.Get_Connection SSHKeywords.Open_Connection_To_ODL_System ${ip_address} SSHLibrary.Write sar -A -f /var/log/sa/sa* - ${output} SSHLibrary.Read_Until_Prompt + ${output}= SSHLibrary.Read_Until_Prompt BuiltIn.Log ${output} SSHLibrary.Close_Connection + RETURN ${output} [Teardown] SSHKeywords.Restore_Current_SSH_Connection_From_Index ${current_connection.index} - [Return] ${output} Check Diagstatus - [Arguments] ${ip_address}=${ODL_SYSTEM_IP} ${check_status}=True ${expected_status}=${200} [Documentation] GET http://${ip_address}:${RESTCONFPORT}/diagstatus and return the response. ${check_status} ... and ${expected_status_code} can be used to ignore the status code, or validate any status code value. ... By default, this keyword will pass if the status code returned is 200, and fail otherwise. + [Arguments] ${ip_address}=${ODL_SYSTEM_IP} ${check_status}=True ${expected_status}=${200} RequestsLibrary.Create Session diagstatus_session http://${ip_address}:${RESTCONFPORT} - ${resp} RequestsLibrary.Get Request diagstatus_session /diagstatus - Run Keyword If "${check_status}" == "True" BuiltIn.Should Be Equal As Strings ${resp.status_code} ${expected_status} - [Return] ${resp} + ${resp}= RequestsLibrary.Get Request diagstatus_session /diagstatus + IF "${check_status}" == "True" + BuiltIn.Should Be Equal As Strings ${resp.status_code} ${expected_status} + END + RETURN ${resp} Download File On Openstack Node - [Arguments] ${conn_id} ${save_file_name} ${url} [Documentation] Download a file from web to the node. the input will be a session ID with established SSH connection. + [Arguments] ${conn_id} ${save_file_name} ${url} SSHLibrary.Switch Connection ${conn_id} - Utils.Write Commands Until Expected Prompt wget -O /tmp/${save_file_name} ${url} ${DEFAULT_LINUX_PROMPT_STRICT} + Utils.Write Commands Until Expected Prompt + ... wget -O /tmp/${save_file_name} ${url} + ... ${DEFAULT_LINUX_PROMPT_STRICT} diff --git a/csit/libraries/VpnOperations.robot b/csit/libraries/VpnOperations.robot index 57f207adef..af962f111c 100644 --- a/csit/libraries/VpnOperations.robot +++ b/csit/libraries/VpnOperations.robot @@ -1,28 +1,46 @@ *** Settings *** -Documentation Openstack library. This library is useful for tests to create network, subnet, router and vm instances -Library SSHLibrary -Resource CompareStream.robot -Resource Utils.robot -Resource TemplatedRequests.robot -Resource KarafKeywords.robot -Resource ../variables/Variables.robot -Resource ../variables/netvirt/Variables.robot -Library Collections -Library String -Library OperatingSystem +Documentation Openstack library. This library is useful for tests to create network, subnet, router and vm instances + +Library SSHLibrary +Resource CompareStream.robot +Resource Utils.robot +Resource TemplatedRequests.robot +Resource KarafKeywords.robot +Resource ../variables/Variables.robot +Resource ../variables/netvirt/Variables.robot +Library Collections +Library String +Library OperatingSystem + *** Variables *** -&{ITM_CREATE_DEFAULT} tunneltype=vxlan vlanid=0 prefix=1.1.1.1/24 gateway=0.0.0.0 dpnid1=1 portname1=BR1-eth1 ipaddress1=2.2.2.2 -... dpnid2=2 portname2= BR2-eth1 ipaddress2=3.3.3.3 -&{L3VPN_CREATE_DEFAULT} vpnid=4ae8cd92-48ca-49b5-94e1-b2921a261111 name=vpn1 rd=["2200:1"] exportrt=["2200:1","8800:1"] importrt=["2200:1","8800:1"] tenantid=6c53df3a-3456-11e5-a151-feff819cdc9f -${VAR_BASE} ${CURDIR}/../variables/vpnservice/ -${ODL_FLOWTABLE_L3VPN} 21 -${STATE_UP} UP -${STATE_DOWN} DOWN -${STATE_UNKNOWN} UNKNOWN -${STATE_ENABLE} ENABLED -${STATE_DISABLE} DISABLE -${SESSION_TIMEOUT} 10 +&{ITM_CREATE_DEFAULT} +... tunneltype=vxlan +... vlanid=0 +... prefix=1.1.1.1/24 +... gateway=0.0.0.0 +... dpnid1=1 +... portname1=BR1-eth1 +... ipaddress1=2.2.2.2 +... dpnid2=2 +... portname2= BR2-eth1 +... ipaddress2=3.3.3.3 +&{L3VPN_CREATE_DEFAULT} +... vpnid=4ae8cd92-48ca-49b5-94e1-b2921a261111 +... name=vpn1 +... rd=["2200:1"] +... exportrt=["2200:1","8800:1"] +... importrt=["2200:1","8800:1"] +... tenantid=6c53df3a-3456-11e5-a151-feff819cdc9f +${VAR_BASE} ${CURDIR}/../variables/vpnservice/ +${ODL_FLOWTABLE_L3VPN} 21 +${STATE_UP} UP +${STATE_DOWN} DOWN +${STATE_UNKNOWN} UNKNOWN +${STATE_ENABLE} ENABLED +${STATE_DISABLE} DISABLE +${SESSION_TIMEOUT} 10 + *** Keywords *** Basic Suite Setup @@ -37,47 +55,65 @@ Basic Vpnservice Suite Cleanup OpenStackOperations.Neutron Cleanup ${vms} ${networks} ${subnets} ${ports} ${sgs} VPN Create L3VPN - [Arguments] &{Kwargs} [Documentation] Create an L3VPN using the Json using the list of optional arguments received. - Run keyword if "routerid" in ${Kwargs} Collections.Set_To_Dictionary ${Kwargs} router=, "router-id":"${Kwargs['routerid']}" - ... ELSE Collections.Set_To_Dictionary ${Kwargs} router=${empty} + [Arguments] &{Kwargs} + IF "routerid" in ${Kwargs} + Collections.Set_To_Dictionary ${Kwargs} router=, "router-id":"${Kwargs['routerid']}" + ELSE + Collections.Set_To_Dictionary ${Kwargs} router=${empty} + END &{L3vpn_create_actual_val} = Collections.Copy_Dictionary ${L3VPN_CREATE_DEFAULT} Collections.Set_To_Dictionary ${L3vpn_create_actual_val} &{Kwargs} - TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE}/l3vpn_create mapping=${L3vpn_create_actual_val} session=default http_timeout=${SESSION_TIMEOUT} + TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE}/l3vpn_create + ... mapping=${L3vpn_create_actual_val} + ... session=default + ... http_timeout=${SESSION_TIMEOUT} VPN Get L3VPN - [Arguments] &{Kwargs} [Documentation] Will return detailed list of the L3VPN_ID received - ${resp} = TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE}/get_l3vpn mapping=${Kwargs} session=default http_timeout=${SESSION_TIMEOUT} + [Arguments] &{Kwargs} + ${resp} = TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE}/get_l3vpn + ... mapping=${Kwargs} + ... session=default + ... http_timeout=${SESSION_TIMEOUT} Log ${resp} - [Return] ${resp} + RETURN ${resp} VPN Get L3VPN ID - [Arguments] ${vrf_id} [Documentation] Check that sub interface ip has been learnt after ARP request + [Arguments] ${vrf_id} ${resp} = RequestsLibrary.Get Request session ${VPN_REST} BuiltIn.Log ${resp.text} - @{list_any_matches} = String.Get_Regexp_Matches ${resp.text} \"vpn-instance-name\":\"${VPN_INSTANCE_ID}\",.*"vrf-id":"${vrf_id}",\"vpn-id\":(\\d+) 1 + @{list_any_matches} = String.Get_Regexp_Matches + ... ${resp.text} + ... \"vpn-instance-name\":\"${VPN_INSTANCE_ID}\",.*"vrf-id":"${vrf_id}",\"vpn-id\":(\\d+) + ... 1 ${result} = Evaluate ${list_any_matches[0]} * 2 ${vpn_id_hex} = BuiltIn.Convert To Hex ${result} - [Return] ${vpn_id_hex.lower()} + RETURN ${vpn_id_hex.lower()} Verify L3VPN On ODL - [Arguments] @{vpns} [Documentation] To verify L3VPN on ODL for given vpn ids + [Arguments] @{vpns} FOR ${vpn} IN @{vpns} ${resp} = VpnOperations.VPN Get L3VPN vpnid=${vpn} BuiltIn.Should Contain ${resp} ${vpn} END Associate L3VPN To Network - [Arguments] &{Kwargs} [Documentation] Associate the created L3VPN to a network-id received as dictionary argument - TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE}/assoc_l3vpn mapping=${Kwargs} session=default http_timeout=${SESSION_TIMEOUT} + [Arguments] &{Kwargs} + TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE}/assoc_l3vpn + ... mapping=${Kwargs} + ... session=default + ... http_timeout=${SESSION_TIMEOUT} Associate L3VPNs To Networks - [Arguments] ${vpnid_list} ${network_list} [Documentation] Associates multiple networks to L3VPN and verify the same + [Arguments] ${vpnid_list} ${network_list} FOR ${network} ${vpnid} IN ZIP ${network_list} ${vpnid_list} ${network_id} = OpenStackOperations.Get Net Id ${network} VpnOperations.Associate L3VPN To Network networkid=${network_id} vpnid=${vpnid} @@ -86,70 +122,111 @@ Associate L3VPNs To Networks END Dissociate L3VPN From Networks - [Arguments] &{Kwargs} [Documentation] Disssociate the already associated networks from L3VPN - TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE}/dissoc_l3vpn mapping=${Kwargs} session=default http_timeout=${SESSION_TIMEOUT} + [Arguments] &{Kwargs} + TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE}/dissoc_l3vpn + ... mapping=${Kwargs} + ... session=default + ... http_timeout=${SESSION_TIMEOUT} Associate VPN to Router - [Arguments] &{Kwargs} [Documentation] Associate the created L3VPN to a router-id received as argument - CompareStream.Run_Keyword_If_At_Least_Fluorine TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE}/assoc_two_router_l3vpn mapping=${Kwargs} session=default http_timeout=${SESSION_TIMEOUT} - CompareStream.Run_Keyword_If_At_Most_Oxygen TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE}/assoc_router_l3vpn mapping=${Kwargs} session=default http_timeout=${SESSION_TIMEOUT} + [Arguments] &{Kwargs} + CompareStream.Run_Keyword_If_At_Least_Fluorine + ... TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE}/assoc_two_router_l3vpn + ... mapping=${Kwargs} + ... session=default + ... http_timeout=${SESSION_TIMEOUT} + CompareStream.Run_Keyword_If_At_Most_Oxygen + ... TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE}/assoc_router_l3vpn + ... mapping=${Kwargs} + ... session=default + ... http_timeout=${SESSION_TIMEOUT} Dissociate VPN to Router - [Arguments] &{Kwargs} [Documentation] Dissociate the already associated routers from L3VPN - CompareStream.Run_Keyword_If_At_Least_Fluorine TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE}/dissoc_two_router_l3vpn mapping=${Kwargs} session=default http_timeout=${SESSION_TIMEOUT} - CompareStream.Run_Keyword_If_At_Most_Oxygen TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE}/dissoc_router_l3vpn mapping=${Kwargs} session=default http_timeout=${SESSION_TIMEOUT} + [Arguments] &{Kwargs} + CompareStream.Run_Keyword_If_At_Least_Fluorine + ... TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE}/dissoc_two_router_l3vpn + ... mapping=${Kwargs} + ... session=default + ... http_timeout=${SESSION_TIMEOUT} + CompareStream.Run_Keyword_If_At_Most_Oxygen + ... TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE}/dissoc_router_l3vpn + ... mapping=${Kwargs} + ... session=default + ... http_timeout=${SESSION_TIMEOUT} VPN Delete L3VPN - [Arguments] &{Kwargs} [Documentation] Delete the created L3VPN - TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE}/l3vpn_delete mapping=${Kwargs} session=default http_timeout=${SESSION_TIMEOUT} + [Arguments] &{Kwargs} + TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE}/l3vpn_delete + ... mapping=${Kwargs} + ... session=default + ... http_timeout=${SESSION_TIMEOUT} ITM Create Tunnel - [Arguments] &{Kwargs} [Documentation] Creates Tunnel between the two DPNs received in the dictionary argument + [Arguments] &{Kwargs} &{Itm_actual_val} = Collections.Copy_Dictionary ${ITM_CREATE_DEFAULT} Collections.Set_To_Dictionary ${Itm_actual_val} &{Kwargs} - TemplatedRequests.Post_As_Json_Templated folder=${VAR_BASE}/itm_create mapping=${Itm_actual_val} session=default http_timeout=${SESSION_TIMEOUT} + TemplatedRequests.Post_As_Json_Templated + ... folder=${VAR_BASE}/itm_create + ... mapping=${Itm_actual_val} + ... session=default + ... http_timeout=${SESSION_TIMEOUT} ITM Get Tunnels [Documentation] Get all Tunnels and return the contents ${resp} = RequestsLibrary.Get Request session ${CONFIG_API}/itm:transport-zones/ Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 - [Return] ${resp.text} + RETURN ${resp.text} ITM Delete Tunnel - [Arguments] ${zone-name} [Documentation] Delete Tunnels created under the transport-zone - ${resp} = RequestsLibrary.Delete Request session ${CONFIG_API}/itm:transport-zones/transport-zone/${zone-name}/ + [Arguments] ${zone-name} + ${resp} = RequestsLibrary.Delete Request + ... session + ... ${CONFIG_API}/itm:transport-zones/transport-zone/${zone-name}/ Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 - [Return] ${resp.text} + RETURN ${resp.text} Verify Flows Are Present For L3VPN - [Arguments] ${ip} ${vm_ips} [Documentation] Verify Flows Are Present For L3VPN - ${flow_output}= Run Command On Remote System And Log ${ip} sudo ovs-ofctl -O OpenFlow13 dump-flows ${INTEGRATION_BRIDGE} + [Arguments] ${ip} ${vm_ips} + ${flow_output} = Run Command On Remote System And Log + ... ${ip} + ... sudo ovs-ofctl -O OpenFlow13 dump-flows ${INTEGRATION_BRIDGE} Should Contain ${flow_output} table=${ODL_FLOWTABLE_L3VPN} ${l3vpn_table} = Get Lines Containing String ${flow_output} table=${ODL_FLOWTABLE_L3VPN}, Log ${l3vpn_table} FOR ${i} IN @{vm_ips} - ${resp}= Should Contain ${l3vpn_table} ${i} + ${resp} = Should Contain ${l3vpn_table} ${i} END Verify Flows Are Present For L3VPN On All Compute Nodes - [Arguments] ${vm_ips} [Documentation] Verify Flows Are Present For L3VPN On All Compute Nodes + [Arguments] ${vm_ips} FOR ${ip} IN @{OS_CMP_IPS} - BuiltIn.Wait Until Keyword Succeeds 30s 10s VpnOperations.Verify Flows Are Present For L3VPN ${ip} ${vm_ips} + BuiltIn.Wait Until Keyword Succeeds + ... 30s + ... 10s + ... VpnOperations.Verify Flows Are Present For L3VPN + ... ${ip} + ... ${vm_ips} END Verify GWMAC Entry On ODL - [Arguments] ${GWMAC_ADDRS} [Documentation] get ODL GWMAC table entry + [Arguments] ${GWMAC_ADDRS} ${resp} = RequestsLibrary.Get Request session ${VPN_PORT_DATA_URL} Log ${resp.text} Should Be Equal As Strings ${resp.status_code} 200 @@ -158,9 +235,11 @@ Verify GWMAC Entry On ODL END Verify GWMAC Flow Entry Removed From Flow Table - [Arguments] ${cnIp} [Documentation] Verify the GWMAC Table, ARP Response table and Dispatcher table. - ${flow_output}= Run Command On Remote System And Log ${cnIp} sudo ovs-ofctl -O OpenFlow13 dump-flows ${INTEGRATION_BRIDGE} + [Arguments] ${cnIp} + ${flow_output} = Run Command On Remote System And Log + ... ${cnIp} + ... sudo ovs-ofctl -O OpenFlow13 dump-flows ${INTEGRATION_BRIDGE} Should Contain ${flow_output} table=${GWMAC_TABLE} ${gwmac_table} = Get Lines Containing String ${flow_output} table=${GWMAC_TABLE} Log ${gwmac_table} @@ -176,18 +255,24 @@ Verify GWMAC Flow Entry Removed From Flow Table On All Compute Nodes END Verify ARP REQUEST in groupTable - [Arguments] ${group_output} ${Group-ID} [Documentation] get flow dump for group ID + [Arguments] ${group_output} ${Group-ID} Should Contain ${group_output} group_id=${Group-ID} ${arp_group} = Get Lines Containing String ${group_output} group_id=${Group-ID} Log ${arp_group} - CompareStream.Run_Keyword_If_At_Most_Oxygen BuiltIn.Should Match Regexp ${arp_group} ${ARP_REQUEST_GROUP_REGEX} - CompareStream.Run_Keyword_If_At_Least_Fluorine BuiltIn.Should Match Regexp ${arp_group} ${ARP_REQUEST_GROUP_REGEX_FLUORINE} + CompareStream.Run_Keyword_If_At_Most_Oxygen + ... BuiltIn.Should Match Regexp + ... ${arp_group} + ... ${ARP_REQUEST_GROUP_REGEX} + CompareStream.Run_Keyword_If_At_Least_Fluorine + ... BuiltIn.Should Match Regexp + ... ${arp_group} + ... ${ARP_REQUEST_GROUP_REGEX_FLUORINE} Verify Tunnel Status as UP [Documentation] Verify that the tunnels are UP - BuiltIn.Return From Keyword If ${OS_NODE_CNT} == ${1} ${True} - ${output}= Issue Command On Karaf Console ${TEP_SHOW_STATE} + IF ${OS_NODE_CNT} == ${1} RETURN ${True} + ${output} = Issue Command On Karaf Console ${TEP_SHOW_STATE} Log ${output} Should Contain ${output} ${STATE_UP} Should Not Contain ${output} ${STATE_DOWN} @@ -195,7 +280,7 @@ Verify Tunnel Status as UP Verify Tunnel Status as DOWN [Documentation] Verify that the tunnels are DOWN - ${output}= Issue Command On Karaf Console ${TEP_SHOW_STATE} + ${output} = Issue Command On Karaf Console ${TEP_SHOW_STATE} Log ${output} Should Contain ${output} ${STATE_DOWN} Should Not Contain ${output} ${STATE_UP} @@ -203,7 +288,7 @@ Verify Tunnel Status as DOWN Verify Tunnel Status as UNKNOWN [Documentation] Verify that the tunnels are in Unknown state - ${output}= Issue Command On Karaf Console ${TEP_SHOW_STATE} + ${output} = Issue Command On Karaf Console ${TEP_SHOW_STATE} Log ${output} Should Not Contain ${output} ${STATE_UP} Should Not Contain ${output} ${STATE_DOWN} @@ -211,26 +296,26 @@ Verify Tunnel Status as UNKNOWN Verify VXLAN interface [Documentation] Verify that the VXLAN interfaces are Enabled - ${output}= Issue Command On Karaf Console ${VXLAN_SHOW} + ${output} = Issue Command On Karaf Console ${VXLAN_SHOW} Log ${output} Should Contain ${output} ${STATE_UP} Should Contain ${output} ${STATE_ENABLE} Should Not Contain ${output} ${STATE_DISABLE} Get Fib Entries - [Arguments] ${session} [Documentation] Get Fib table entries from ODL session - ${resp} RequestsLibrary.Get Request ${session} ${FIB_ENTRIES_URL} + [Arguments] ${session} + ${resp} = RequestsLibrary.Get Request ${session} ${FIB_ENTRIES_URL} Log ${resp.text} - [Return] ${resp.text} + RETURN ${resp.text} Get Gateway MAC And IP Address - [Arguments] ${router_Name} ${ip_regex}=${IP_REGEX} [Documentation] Get Gateway mac and IP Address + [Arguments] ${router_Name} ${ip_regex}=${IP_REGEX} ${output} = OpenStack CLI openstack port list --router ${router_Name} @{MacAddr-list} = Get Regexp Matches ${output} ${MAC_REGEX} @{IpAddr-list} = Get Regexp Matches ${output} ${ip_regex} - [Return] ${MacAddr-list} ${IpAddr-list} + RETURN ${MacAddr-list} ${IpAddr-list} Test Teardown With Tcpdump Stop [Arguments] ${conn_ids}=@{EMPTY} @@ -245,7 +330,8 @@ Verify IPv4 GWMAC Flow Entry On Flow Table ${arpResponder_table} = Get Lines Containing String ${flow_output} table=${ARP_RESPONSE_TABLE} Should Contain ${arpResponder_table} priority=0 actions=drop FOR ${macAdd} ${ipAdd} IN ZIP ${GWMAC_ADDRS} ${GWIP_ADDRS} - ${ARP_RESPONSE_IP_MAC_REGEX} = Set Variable arp_tpa=${ipAdd},arp_op=1 actions=.*,set_field:${macAdd}->eth_src + ${ARP_RESPONSE_IP_MAC_REGEX} = Set Variable + ... arp_tpa=${ipAdd},arp_op=1 actions=.*,set_field:${macAdd}->eth_src Should Match Regexp ${arpResponder_table} ${ARP_RESPONSE_IP_MAC_REGEX} END @@ -259,10 +345,14 @@ Verify IPv6 GWMAC Flow Entry On Flow Table END Verify GWMAC Flow Entry On Flow Table - [Arguments] ${cnIp} ${ipv}=ipv4 [Documentation] Verify the GWMAC Table, ARP Response table and Dispatcher table. - ${flow_output}= Run Command On Remote System ${cnIp} sudo ovs-ofctl -O OpenFlow13 dump-flows ${INTEGRATION_BRIDGE} - ${group_output}= Run Command On Remote System ${cnIp} sudo ovs-ofctl -O OpenFlow13 dump-groups ${INTEGRATION_BRIDGE} + [Arguments] ${cnIp} ${ipv}=ipv4 + ${flow_output} = Run Command On Remote System + ... ${cnIp} + ... sudo ovs-ofctl -O OpenFlow13 dump-flows ${INTEGRATION_BRIDGE} + ${group_output} = Run Command On Remote System + ... ${cnIp} + ... sudo ovs-ofctl -O OpenFlow13 dump-groups ${INTEGRATION_BRIDGE} Should Contain ${flow_output} table=${DISPATCHER_TABLE} ${dispatcher_table} = Get Lines Containing String ${flow_output} table=${DISPATCHER_TABLE} Should Contain ${dispatcher_table} goto_table:${GWMAC_TABLE} @@ -278,33 +368,50 @@ Verify GWMAC Flow Entry On Flow Table #Verify ARP_CHECK_TABLE - 43 #arp request and response ${arpchk_table} = Get Lines Containing String ${flow_output} table=${ARP_CHECK_TABLE} - CompareStream.Run_Keyword_If_At_Most_Oxygen BuiltIn.Should Match Regexp ${arpchk_table} ${ARP_RESPONSE_REGEX} - CompareStream.Run_Keyword_If_At_Least_Fluorine BuiltIn.Should Match Regexp ${arpchk_table} ${ARP_RESPONSE_REGEX_FLUORINE} + CompareStream.Run_Keyword_If_At_Most_Oxygen + ... BuiltIn.Should Match Regexp + ... ${arpchk_table} + ... ${ARP_RESPONSE_REGEX} + CompareStream.Run_Keyword_If_At_Least_Fluorine + ... BuiltIn.Should Match Regexp + ... ${arpchk_table} + ... ${ARP_RESPONSE_REGEX_FLUORINE} ${arppunt_table} = String.Get Lines Containing String ${flow_output} table=${ARP_PUNT_TABLE} - CompareStream.Run_Keyword_If_At_Least_Fluorine BuiltIn.Should Match Regexp ${arppunt_table} ${ARP_PUNT_RESPONSE_REGEX} + CompareStream.Run_Keyword_If_At_Least_Fluorine + ... BuiltIn.Should Match Regexp + ... ${arppunt_table} + ... ${ARP_PUNT_RESPONSE_REGEX} ${match} = Should Match Regexp ${arpchk_table} ${ARP_REQUEST_REGEX} ${groupID} = Split String ${match} separator=: - BuiltIn.Run Keyword If '${ipv}' == 'ipv4' Verify IPv4 GWMAC Flow Entry On Flow Table ${group_output} ${group_id} ${flow_output} - ... ELSE Verify IPv6 GWMAC Flow Entry On Flow Table ${flow_output} + IF '${ipv}' == 'ipv4' + Verify IPv4 GWMAC Flow Entry On Flow Table ${group_output} ${group_id} ${flow_output} + ELSE + Verify IPv6 GWMAC Flow Entry On Flow Table ${flow_output} + END Verify GWMAC Flow Entry On Flow Table On All Compute Nodes - [Arguments] ${ipv}=ipv4 [Documentation] Verify the GWMAC Table, ARP Response table and Dispatcher table. + [Arguments] ${ipv}=ipv4 FOR ${ip} IN @{OS_CMP_IPS} - BuiltIn.Wait Until Keyword Succeeds 30s 10s VpnOperations.Verify GWMAC Flow Entry On Flow Table ${ip} ${ipv} + BuiltIn.Wait Until Keyword Succeeds + ... 30s + ... 10s + ... VpnOperations.Verify GWMAC Flow Entry On Flow Table + ... ${ip} + ... ${ipv} END Delete Multiple L3VPNs - [Arguments] @{vpns} [Documentation] Delete three L3VPNs created using Multiple L3VPN Test + [Arguments] @{vpns} FOR ${vpn} IN @{vpns} VPN Delete L3VPN vpnid=${vpn} END VNI Test Setup - BuiltIn.Return From Keyword If "${OPENSTACK_TOPO}" == "1cmb-0ctl-0cmp" + IF "${OPENSTACK_TOPO}" == "1cmb-0ctl-0cmp" RETURN SetupUtils.Setup_Test_With_Logging_And_Without_Fast_Failing VNI Test Teardown - BuiltIn.Return From Keyword If "${OPENSTACK_TOPO}" == "1cmb-0ctl-0cmp" + IF "${OPENSTACK_TOPO}" == "1cmb-0ctl-0cmp" RETURN OpenStackOperations.Get Test Teardown Debugs diff --git a/csit/libraries/VtnMaKeywords.robot b/csit/libraries/VtnMaKeywords.robot index 7869a1ba30..03b5020d40 100644 --- a/csit/libraries/VtnMaKeywords.robot +++ b/csit/libraries/VtnMaKeywords.robot @@ -1,60 +1,70 @@ *** Settings *** -Library SSHLibrary -Library String -Library DateTime -Library Collections -Library json -Library RequestsLibrary -Variables ../variables/Variables.py -Variables ../variables/vtn/Modules.py -Resource ./Utils.robot -Resource ./KarafKeywords.robot -Resource ./MininetKeywords.robot -Resource ./TemplatedRequests.robot -Resource DataModels.robot +Library SSHLibrary +Library String +Library DateTime +Library Collections +Library json +Library RequestsLibrary +Variables ../variables/Variables.py +Variables ../variables/vtn/Modules.py +Resource ./Utils.robot +Resource ./KarafKeywords.robot +Resource ./MininetKeywords.robot +Resource ./TemplatedRequests.robot +Resource DataModels.robot + *** Variables *** -${vlan_topo} --custom vlan_vtn_test.py --topo vlantopo -${VERSION_VTN} controller/nb/v2/vtn/version -${VTN_INVENTORY} restconf/operational/vtn-inventory:vtn-nodes -${ENTITY_OWNERS} restconf/operational/entity-owners:entity-owners -${DUMPFLOWS_OF10} dpctl dump-flows -OOpenFlow10 -${DUMPFLOWS_OF13} dpctl dump-flows -OOpenFlow13 -${FF_DUMPFLOWS_OF10} sh ovs-ofctl dump-flows -OOpenFlow10 s3 -${FF_DUMPFLOWS_OF13} sh ovs-ofctl dump-flows -OOpenFlow13 s3 -${DROP_DUMPFLOWS_OF10} sh ovs-ofctl dump-flows -OOpenFlow10 s2 -${DROP_DUMPFLOWS_OF13} sh ovs-ofctl dump-flows -OOpenFlow13 s2 -${DROP_OUT_DUMPFLOWS_OF10} sh ovs-ofctl dump-flows -OOpenFlow10 s3 -${DROP_OUT_DUMPFLOWS_OF13} sh ovs-ofctl dump-flows -OOpenFlow13 s3 -${FF_OUT_DUMPFLOWS_OF10} sh ovs-ofctl dump-flows -OOpenFlow10 s2 -${FF_OUT_DUMPFLOWS_OF13} sh ovs-ofctl dump-flows -OOpenFlow13 s2 -${index} 7 -@{inet_actions} mod_nw_src:192.0.0.1 mod_nw_dst:192.0.0.2 -@{BRIDGE1_DATAFLOW} "reason":"PORTMAPPED" "tenant-name":"Tenant1" "bridge-name":"vBridge1" "interface-name":"if2" -@{BRIDGE2_DATAFLOW} "reason":"PORTMAPPED" "tenant-name":"Tenant1" "bridge-name":"vBridge2" "interface-name":"if3" -${vlanmap_bridge1} 200 -${vlanmap_bridge2} 300 -@{VLANMAP_BRIDGE1_DATAFLOW} "reason":"VLANMAPPED" "tenant-name":"Tenant1" "bridge-name":"vBridge1_vlan" -@{VLANMAP_BRIDGE2_DATAFLOW} "reason":"VLANMAPPED" "tenant-name":"Tenant1" "bridge-name":"vBridge2_vlan" -${out_before_pathpolicy} output:2 -${out_after_pathpolicy} output:3 -${pathpolicy_topo} --custom topo-3sw-2host_multipath.py --topo pathpolicytopo -@{PATHMAP_ATTR} "index":"1" "condition":"flowcond_path" "policy":"1" -${policy_id} 1 -${in_port} 1 -${filter_index} 1 -@{inet_action} set_field:192.0.0.1->ip_src set_field:192.0.0.2->ip_dst -${dscp_action} set_field:32->ip_dscp -${dscp_be_action} set_field:32->nw_tos_shifted -${dscp_flow} mod_nw_tos:128 -@{icmp_action} mod_tp_dst:1 mod_tp_src:3 -${drop_action} actions=drop -${vlanpcp_action} mod_vlan_pcp:6 -${vlanpcp_actions} set_field:6->vlan_pcp -${dlsrc_action} mod_dl_src:00:00:00:00:00:11 -${dlsrc_actions} set_field:00:00:00:00:00:11->eth_src -@{PATHPOLICY_ATTR} "id":1 "port-desc":"openflow:4,2,s4-eth2" -${custom} ${CURDIR}/${CREATE_PATHPOLICY_TOPOLOGY_FILE_PATH} +${vlan_topo} --custom vlan_vtn_test.py --topo vlantopo +${VERSION_VTN} controller/nb/v2/vtn/version +${VTN_INVENTORY} restconf/operational/vtn-inventory:vtn-nodes +${ENTITY_OWNERS} restconf/operational/entity-owners:entity-owners +${DUMPFLOWS_OF10} dpctl dump-flows -OOpenFlow10 +${DUMPFLOWS_OF13} dpctl dump-flows -OOpenFlow13 +${FF_DUMPFLOWS_OF10} sh ovs-ofctl dump-flows -OOpenFlow10 s3 +${FF_DUMPFLOWS_OF13} sh ovs-ofctl dump-flows -OOpenFlow13 s3 +${DROP_DUMPFLOWS_OF10} sh ovs-ofctl dump-flows -OOpenFlow10 s2 +${DROP_DUMPFLOWS_OF13} sh ovs-ofctl dump-flows -OOpenFlow13 s2 +${DROP_OUT_DUMPFLOWS_OF10} sh ovs-ofctl dump-flows -OOpenFlow10 s3 +${DROP_OUT_DUMPFLOWS_OF13} sh ovs-ofctl dump-flows -OOpenFlow13 s3 +${FF_OUT_DUMPFLOWS_OF10} sh ovs-ofctl dump-flows -OOpenFlow10 s2 +${FF_OUT_DUMPFLOWS_OF13} sh ovs-ofctl dump-flows -OOpenFlow13 s2 +${index} 7 +@{inet_actions} mod_nw_src:192.0.0.1 mod_nw_dst:192.0.0.2 +@{BRIDGE1_DATAFLOW} +... "reason":"PORTMAPPED" +... "tenant-name":"Tenant1" +... "bridge-name":"vBridge1" +... "interface-name":"if2" +@{BRIDGE2_DATAFLOW} +... "reason":"PORTMAPPED" +... "tenant-name":"Tenant1" +... "bridge-name":"vBridge2" +... "interface-name":"if3" +${vlanmap_bridge1} 200 +${vlanmap_bridge2} 300 +@{VLANMAP_BRIDGE1_DATAFLOW} "reason":"VLANMAPPED" "tenant-name":"Tenant1" "bridge-name":"vBridge1_vlan" +@{VLANMAP_BRIDGE2_DATAFLOW} "reason":"VLANMAPPED" "tenant-name":"Tenant1" "bridge-name":"vBridge2_vlan" +${out_before_pathpolicy} output:2 +${out_after_pathpolicy} output:3 +${pathpolicy_topo} --custom topo-3sw-2host_multipath.py --topo pathpolicytopo +@{PATHMAP_ATTR} "index":"1" "condition":"flowcond_path" "policy":"1" +${policy_id} 1 +${in_port} 1 +${filter_index} 1 +@{inet_action} set_field:192.0.0.1->ip_src set_field:192.0.0.2->ip_dst +${dscp_action} set_field:32->ip_dscp +${dscp_be_action} set_field:32->nw_tos_shifted +${dscp_flow} mod_nw_tos:128 +@{icmp_action} mod_tp_dst:1 mod_tp_src:3 +${drop_action} actions=drop +${vlanpcp_action} mod_vlan_pcp:6 +${vlanpcp_actions} set_field:6->vlan_pcp +${dlsrc_action} mod_dl_src:00:00:00:00:00:11 +${dlsrc_actions} set_field:00:00:00:00:00:11->eth_src +@{PATHPOLICY_ATTR} "id":1 "port-desc":"openflow:4,2,s4-eth2" +${custom} ${CURDIR}/${CREATE_PATHPOLICY_TOPOLOGY_FILE_PATH} + *** Keywords *** Start SuiteVtnMa @@ -63,14 +73,23 @@ Start SuiteVtnMa ${vtn_mgr_id}= SSHLibrary.Open Connection ${ODL_SYSTEM_IP} prompt=${DEFAULT_LINUX_PROMPT} timeout=30s Set Suite Variable ${vtn_mgr_id} SSHLibrary.Login_With_Public_Key ${ODL_SYSTEM_USER} ${USER_HOME}/.ssh/${SSH_KEY} any - SSHLibrary.Execute Command sudo sed -i "$ i log4j.logger.org.opendaylight.vtn = TRACE" ${WORKSPACE}/${BUNDLEFOLDER}/etc/org.ops4j.pax.logging.cfg - Create Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} auth=${AUTH} headers=${HEADERS_YANG_JSON} + SSHLibrary.Execute Command + ... sudo sed -i "$ i log4j.logger.org.opendaylight.vtn = TRACE" ${WORKSPACE}/${BUNDLEFOLDER}/etc/org.ops4j.pax.logging.cfg + Create Session + ... session + ... http://${ODL_SYSTEM_IP}:${RESTCONFPORT} + ... auth=${AUTH} + ... headers=${HEADERS_YANG_JSON} BuiltIn.Wait_Until_Keyword_Succeeds 30 3 Fetch vtn list Start Mininet Start SuiteVtnMaTest [Documentation] Start VTN Manager Test Suite - Create Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} auth=${AUTH} headers=${HEADERS_YANG_JSON} + Create Session + ... session + ... http://${ODL_SYSTEM_IP}:${RESTCONFPORT} + ... auth=${AUTH} + ... headers=${HEADERS_YANG_JSON} Stop SuiteVtnMa [Documentation] Stop VTN Manager Test Suite @@ -86,79 +105,120 @@ Fetch vtn list Should Be Equal As Strings ${resp.status_code} 200 Fetch vtn switch inventory - [Arguments] ${sw_name} [Documentation] Check if Switch is detected. - ${resp}= RequestsLibrary.Get Request session restconf/operational/vtn-inventory:vtn-nodes/vtn-node/${sw_name} + [Arguments] ${sw_name} + ${resp}= RequestsLibrary.Get Request + ... session + ... restconf/operational/vtn-inventory:vtn-nodes/vtn-node/${sw_name} Should Be Equal As Strings ${resp.status_code} 200 Collect Debug Info [Documentation] Check if Switch is detected. write ${DUMPFLOWS_OF10} - ${result} Read Until mininet> + ${result}= Read Until mininet> write ${DUMPFLOWS_OF13} - ${result} Read Until mininet> + ${result}= Read Until mininet> Get Model Dump ${ODL_SYSTEM_IP} ${vtn_data_models} Add a Topology wait - [Arguments] ${topo_wait} [Documentation] Add a topology wait to complete all Inter-switch link connection of switches - ${resp}= RequestsLibrary.Put Request session restconf/config/vtn-config:vtn-config data={"vtn-config": {"topology-wait":${topo_wait}, "host-tracking": "true"}} + [Arguments] ${topo_wait} + ${resp}= RequestsLibrary.Put Request + ... session + ... restconf/config/vtn-config:vtn-config + ... data={"vtn-config": {"topology-wait":${topo_wait}, "host-tracking": "true"}} Should Contain ${ALLOWED_STATUS_CODES} ${resp.status_code} Add a Vtn - [Arguments] ${vtn_name} [Documentation] Create a vtn with specified parameters. - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn:update-vtn data={"input": {"tenant-name":${vtn_name}, "update-mode": "CREATE","operation": "SET", "description": "creating vtn", "idle-timeout":300, "hard-timeout":0}} + [Arguments] ${vtn_name} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn:update-vtn + ... data={"input": {"tenant-name":${vtn_name}, "update-mode": "CREATE","operation": "SET", "description": "creating vtn", "idle-timeout":300, "hard-timeout":0}} Should Be Equal As Strings ${resp.status_code} 200 Add a vBridge - [Arguments] ${vtn_name} ${vbr_name} [Documentation] Create a vBridge in a VTN - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-vbridge:update-vbridge data={"input": {"update-mode": "CREATE","operation":"SET", "tenant-name":${vtn_name}, "bridge-name":${vbr_name}, "description": "vbrdige created"}} + [Arguments] ${vtn_name} ${vbr_name} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-vbridge:update-vbridge + ... data={"input": {"update-mode": "CREATE","operation":"SET", "tenant-name":${vtn_name}, "bridge-name":${vbr_name}, "description": "vbrdige created"}} Should Be Equal As Strings ${resp.status_code} 200 Add a interface - [Arguments] ${vtn_name} ${vbr_name} ${interface_name} [Documentation] Create a interface into a vBridge of a VTN - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-vinterface:update-vinterface data={"input": {"update-mode":"CREATE","operation":"SET", "tenant-name":${vtn_name}, "bridge-name":${vbr_name}, "description": "vbrdige interfacecreated", "enabled":"true", "interface-name": ${interface_name}}} + [Arguments] ${vtn_name} ${vbr_name} ${interface_name} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-vinterface:update-vinterface + ... data={"input": {"update-mode":"CREATE","operation":"SET", "tenant-name":${vtn_name}, "bridge-name":${vbr_name}, "description": "vbrdige interfacecreated", "enabled":"true", "interface-name": ${interface_name}}} Should Be Equal As Strings ${resp.status_code} 200 Add a portmap - [Arguments] ${vtn_name} ${vbr_name} ${interface_name} ${node_id} ${port_id} [Documentation] Create a portmap for a interface of a vbridge - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-port-map:set-port-map data={"input": { "tenant-name":${vtn_name}, "bridge-name":${vbr_name}, "interface-name": ${interface_name}, "node":"${node_id}", "port-name":"${port_id}"}} + [Arguments] ${vtn_name} ${vbr_name} ${interface_name} ${node_id} ${port_id} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-port-map:set-port-map + ... data={"input": { "tenant-name":${vtn_name}, "bridge-name":${vbr_name}, "interface-name": ${interface_name}, "node":"${node_id}", "port-name":"${port_id}"}} Should Be Equal As Strings ${resp.status_code} 200 Delete a Vtn - [Arguments] ${vtn_name} [Documentation] Delete a vtn with specified parameters. - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn:remove-vtn data={"input": {"tenant-name":${vtn_name}}} + [Arguments] ${vtn_name} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn:remove-vtn + ... data={"input": {"tenant-name":${vtn_name}}} Should Be Equal As Strings ${resp.status_code} 200 Add a vlanmap - [Arguments] ${vtn_name} ${vbr_name} ${vlan_id} [Documentation] Create a vlanmap - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-vlan-map:add-vlan-map data={"input": {"tenant-name":${vtn_name},"bridge-name":${vbr_name},"vlan-id":${vlan_id}}} + [Arguments] ${vtn_name} ${vbr_name} ${vlan_id} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-vlan-map:add-vlan-map + ... data={"input": {"tenant-name":${vtn_name},"bridge-name":${vbr_name},"vlan-id":${vlan_id}}} Should Be Equal As Strings ${resp.status_code} 200 Verify Data Flows - [Arguments] ${vtn_name} ${vBridge_name} [Documentation] Verify the reason and physical data flows for the specified vtn and vbridge - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-flow:get-data-flow data={"input":{"tenant-name":"${vtn_name}","mode":"UPDATESTATS"}} - Run Keyword If '${vBridge_name}' == 'vBridge1' DataFlowsForBridge ${resp} @{BRIDGE1_DATAFLOW} - ... ELSE IF '${vBridge_name}' == 'vBridge2' DataFlowsForBridge ${resp} @{BRIDGE2_DATAFLOW} - ... ELSE IF '${vBridge_name}' == 'vBridge1_vlan' DataFlowsForBridge ${resp} @{VLANMAP_BRIDGE1_DATAFLOW} - ... ELSE DataFlowsForBridge ${resp} @{VLANMAP_BRIDGE2_DATAFLOW} + [Arguments] ${vtn_name} ${vBridge_name} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-flow:get-data-flow + ... data={"input":{"tenant-name":"${vtn_name}","mode":"UPDATESTATS"}} + IF '${vBridge_name}' == 'vBridge1' + DataFlowsForBridge ${resp} @{BRIDGE1_DATAFLOW} + ELSE IF '${vBridge_name}' == 'vBridge2' + DataFlowsForBridge ${resp} @{BRIDGE2_DATAFLOW} + ELSE IF '${vBridge_name}' == 'vBridge1_vlan' + DataFlowsForBridge ${resp} @{VLANMAP_BRIDGE1_DATAFLOW} + ELSE + DataFlowsForBridge ${resp} @{VLANMAP_BRIDGE2_DATAFLOW} + END Start PathSuiteVtnMaTest [Documentation] Start VTN Manager Test Suite and Mininet Start SuiteVtnMaTest - MininetKeywords.Start Mininet Single Controller ${TOOLS_SYSTEM_IP} ${ODL_SYSTEM_IP} ${pathpolicy_topo} ${custom} ofversion=13 + MininetKeywords.Start Mininet Single Controller + ... ${TOOLS_SYSTEM_IP} + ... ${ODL_SYSTEM_IP} + ... ${pathpolicy_topo} + ... ${custom} + ... ofversion=13 Start PathSuiteVtnMaTestOF10 [Documentation] Start VTN Manager Test Suite and Mininet in Open Flow 10 Specification Start SuiteVtnMaTest - MininetKeywords.Start Mininet Single Controller ${TOOLS_SYSTEM_IP} ${ODL_SYSTEM_IP} ${pathpolicy_topo} ${custom} ofversion=10 + MininetKeywords.Start Mininet Single Controller + ... ${TOOLS_SYSTEM_IP} + ... ${ODL_SYSTEM_IP} + ... ${pathpolicy_topo} + ... ${custom} + ... ofversion=10 Stop PathSuiteVtnMaTest [Documentation] Cleanup/Shutdown work at the completion of all tests. @@ -166,16 +226,19 @@ Stop PathSuiteVtnMaTest MininetKeywords.Stop Mininet And Exit DataFlowsForBridge - [Arguments] ${resp} @{BRIDGE_DATAFLOW} [Documentation] Verify whether the required attributes exists. + [Arguments] ${resp} @{BRIDGE_DATAFLOW} FOR ${dataflowElement} IN @{BRIDGE_DATAFLOW} should Contain ${resp.text} ${dataflowElement} END Add a pathmap - [Arguments] ${pathmap_data} [Documentation] Create a pathmap for a vtn - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-path-map:set-path-map data=${pathmap_data} + [Arguments] ${pathmap_data} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-path-map:set-path-map + ... data=${pathmap_data} Should Be Equal As Strings ${resp.status_code} 200 Get a pathmap @@ -186,206 +249,272 @@ Get a pathmap END Add a pathpolicy - [Arguments] ${pathpolicy_data} [Documentation] Create a pathpolicy for a vtn - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-path-policy:set-path-policy data=${pathpolicy_data} + [Arguments] ${pathpolicy_data} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-path-policy:set-path-policy + ... data=${pathpolicy_data} Should Be Equal As Strings ${resp.status_code} 200 Get a pathpolicy - [Arguments] ${pathpolicy_id} [Documentation] Get a pathpolicy for a vtn. - ${resp}= RequestsLibrary.Get Request session restconf/operational/vtn-path-policy:vtn-path-policies/vtn-path-policy/${pathpolicy_id} + [Arguments] ${pathpolicy_id} + ${resp}= RequestsLibrary.Get Request + ... session + ... restconf/operational/vtn-path-policy:vtn-path-policies/vtn-path-policy/${pathpolicy_id} FOR ${pathpolicyElement} IN @{PATHPOLICY_ATTR} should Contain ${resp.text} ${pathpolicyElement} END Delete a pathmap - [Arguments] ${tenant_path} [Documentation] Remove a pathmap for a vtn - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-path-map:remove-path-map data={"input":{"tenant-name":"${tenant_path}","map-index":["${policy_id}"]}} + [Arguments] ${tenant_path} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-path-map:remove-path-map + ... data={"input":{"tenant-name":"${tenant_path}","map-index":["${policy_id}"]}} Should Be Equal As Strings ${resp.status_code} 200 Delete a pathpolicy - [Arguments] ${policy_id} [Documentation] Delete a pathpolicy for a vtn - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-path-policy:remove-path-policy data={"input":{"id":"${policy_id}"}} + [Arguments] ${policy_id} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-path-policy:remove-path-policy + ... data={"input":{"id":"${policy_id}"}} Should Be Equal As Strings ${resp.status_code} 200 Verify flowEntryPathPolicy - [Arguments] ${of_version} ${port} ${output} [Documentation] Checking Flows on switch S1 and switch S3 after applying path policy + [Arguments] ${of_version} ${port} ${output} ${DUMPFLOWS}= Set Variable If "${of_version}"=="OF10" ${DUMPFLOWS_OF10} ${DUMPFLOWS_OF13} write ${DUMPFLOWS} - ${result} Read Until mininet> + ${result}= Read Until mininet> Should Contain ${result} in_port=${port} actions=${output} Add a macmap - [Arguments] ${vtn_name} ${vBridge_name} ${src_add} ${dst_add} [Documentation] Create a macmap for a vbridge - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-mac-map:set-mac-map data={"input":{"operation":"SET","allowed-hosts":["${dst_add}@0","${src_add}@0"],"tenant-name":"${vtn_name}","bridge-name":"${vBridge_name}"}} + [Arguments] ${vtn_name} ${vBridge_name} ${src_add} ${dst_add} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-mac-map:set-mac-map + ... data={"input":{"operation":"SET","allowed-hosts":["${dst_add}@0","${src_add}@0"],"tenant-name":"${vtn_name}","bridge-name":"${vBridge_name}"}} Should Be Equal As Strings ${resp.status_code} 200 Get DynamicMacAddress - [Arguments] ${h} [Documentation] Get Dynamic mac address of Host + [Arguments] ${h} write ${h} ifconfig -a | grep HWaddr - ${source} Read Until mininet> + ${source}= Read Until mininet> ${HWaddress}= Split String ${source} ${SPACE} ${sourceHWaddr}= Get from List ${HWaddress} ${index} ${sourceHWaddress}= Convert To Lowercase ${sourceHWaddr} - Return From Keyword ${sourceHWaddress} # Also [Return] would work here. + RETURN ${sourceHWaddress} # Also [Return] would work here. Mininet Ping Should Succeed - [Arguments] ${host1} ${host2} [Documentation] Ping hosts to check connectivity + [Arguments] ${host1} ${host2} Write ${host1} ping -c 1 ${host2} - ${result} Read Until mininet> + ${result}= Read Until mininet> Should Contain ${result} 64 bytes Mininet Ping Should Not Succeed - [Arguments] ${host1} ${host2} [Documentation] Ping hosts when there is no connectivity and check hosts is unreachable + [Arguments] ${host1} ${host2} Write ${host1} ping -c 3 ${host2} - ${result} Read Until mininet> + ${result}= Read Until mininet> Should Not Contain ${result} 64 bytes Start vlan_topo - [Arguments] ${OF} [Documentation] Create custom topology for vlan functionality + [Arguments] ${OF} Install Package On Ubuntu System vlan - Run Keyword If '${OF}' == 'OF13' MininetKeywords.Start Mininet Single Controller ${TOOLS_SYSTEM_IP} ${ODL_SYSTEM_IP} ${vlan_topo} ${CURDIR}/${CREATE_VLAN_TOPOLOGY_FILE_PATH} - ... ofversion=13 - ... ELSE IF '${OF}' == 'OF10' MininetKeywords.Start Mininet Single Controller ${TOOLS_SYSTEM_IP} ${ODL_SYSTEM_IP} ${vlan_topo} - ... ${CURDIR}/${CREATE_VLAN_TOPOLOGY_FILE_PATH} ofversion=10 + IF '${OF}' == 'OF13' + MininetKeywords.Start Mininet Single Controller + ... ${TOOLS_SYSTEM_IP} + ... ${ODL_SYSTEM_IP} + ... ${vlan_topo} + ... ${CURDIR}/${CREATE_VLAN_TOPOLOGY_FILE_PATH} + ... ofversion=13 + ELSE IF '${OF}' == 'OF10' + MininetKeywords.Start Mininet Single Controller + ... ${TOOLS_SYSTEM_IP} + ... ${ODL_SYSTEM_IP} + ... ${vlan_topo} + ... ${CURDIR}/${CREATE_VLAN_TOPOLOGY_FILE_PATH} + ... ofversion=10 + END Get flow - [Arguments] ${vtn_name} [Documentation] Get data flow. - ${resp}= RequestsLibrary.Get Request session restconf/operational/vtn-flow-impl:vtn-flows/vtn-flow-table/${vtn_name} + [Arguments] ${vtn_name} + ${resp}= RequestsLibrary.Get Request + ... session + ... restconf/operational/vtn-flow-impl:vtn-flows/vtn-flow-table/${vtn_name} Should Be Equal As Strings ${resp.status_code} 200 Remove a portmap - [Arguments] ${vtn_name} ${vBridge_name} ${interface_name} [Documentation] Remove a portmap for a interface of a vbridge - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-port-map:remove-port-map data={"input": {"tenant-name":${vtn_name},"bridge-name":${vBridge_name},"interface-name":${interface_name}}} + [Arguments] ${vtn_name} ${vBridge_name} ${interface_name} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-port-map:remove-port-map + ... data={"input": {"tenant-name":${vtn_name},"bridge-name":${vBridge_name},"interface-name":${interface_name}}} Should Be Equal As Strings ${resp.status_code} 200 Verify FlowMacAddress - [Arguments] ${host1} ${host2} ${OF_VERSION} [Documentation] Verify the source and destination mac address. - Run Keyword If '${OF_VERSION}' == 'OF10' Verify Flows On OpenFlow ${host1} ${host2} ${FF_DUMPFLOWS_OF10} - ... ELSE VerifyFlowsOnOpenFlow ${host1} ${host2} ${FF_DUMPFLOWS_OF13} + [Arguments] ${host1} ${host2} ${OF_VERSION} + IF '${OF_VERSION}' == 'OF10' + Verify Flows On OpenFlow ${host1} ${host2} ${FF_DUMPFLOWS_OF10} + ELSE + VerifyFlowsOnOpenFlow ${host1} ${host2} ${FF_DUMPFLOWS_OF13} + END Verify Flows On OpenFlow - [Arguments] ${host1} ${host2} ${DUMPFLOWS} [Documentation] Verify the mac addresses on the specified open flow. + [Arguments] ${host1} ${host2} ${DUMPFLOWS} ${booleanValue}= Run Keyword And Return Status Verify macaddress ${host1} ${host2} ${DUMPFLOWS} Should Be Equal As Strings ${booleanValue} True Verify RemovedFlowMacAddress - [Arguments] ${host1} ${host2} ${OF_VERSION} [Documentation] Verify the removed source and destination mac address. - Run Keyword If '${OF_VERSION}' == 'OF10' Verify Removed Flows On OpenFlow ${host1} ${host2} ${FF_DUMPFLOWS_OF10} - ... ELSE Verify Removed Flows On OpenFlow ${host1} ${host2} ${FF_DUMPFLOWS_OF13} + [Arguments] ${host1} ${host2} ${OF_VERSION} + IF '${OF_VERSION}' == 'OF10' + Verify Removed Flows On OpenFlow ${host1} ${host2} ${FF_DUMPFLOWS_OF10} + ELSE + Verify Removed Flows On OpenFlow ${host1} ${host2} ${FF_DUMPFLOWS_OF13} + END Verify Removed Flows On OpenFlow - [Arguments] ${host1} ${host2} ${DUMPFLOWS} [Documentation] Verify the removed mac addresses on the specified open flow. + [Arguments] ${host1} ${host2} ${DUMPFLOWS} ${booleanValue}= Run Keyword And Return Status Verify macaddress ${host1} ${host2} ${DUMPFLOWS} Should Not Be Equal As Strings ${booleanValue} True Verify macaddress - [Arguments] ${host1} ${host2} ${DUMPFLOWS} [Documentation] Verify the source and destination mac address after ping in the dumpflows + [Arguments] ${host1} ${host2} ${DUMPFLOWS} write ${host1} ifconfig -a | grep HWaddr - ${sourcemacaddr} Read Until mininet> + ${sourcemacaddr}= Read Until mininet> ${macaddress}= Split String ${sourcemacaddr} ${SPACE} ${sourcemacaddr}= Get from List ${macaddress} ${index} ${sourcemacaddress}= Convert To Lowercase ${sourcemacaddr} write ${host2} ifconfig -a | grep HWaddr - ${destmacaddr} Read Until mininet> + ${destmacaddr}= Read Until mininet> ${macaddress}= Split String ${destmacaddr} ${SPACE} ${destmacaddr}= Get from List ${macaddress} ${index} ${destmacaddress}= Convert To Lowercase ${destmacaddr} write ${DUMPFLOWS} - ${result} Read Until mininet> + ${result}= Read Until mininet> Should Contain ${result} ${sourcemacaddress} Should Contain ${result} ${destmacaddress} Verify flowactions - [Arguments] ${actions} ${DUMPFLOWS} [Documentation] Verify the flowfilter actions after ping in the dumpflows + [Arguments] ${actions} ${DUMPFLOWS} write ${DUMPFLOWS} - ${result} Read Until mininet> + ${result}= Read Until mininet> Should Contain ${result} ${actions} Add a vtn flowfilter - [Arguments] ${vtn_name} ${vtnflowfilter_data} [Documentation] Create a flowfilter for a vtn - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-flow-filter:set-flow-filter data={"input": {"tenant-name": "${vtn_name}",${vtnflowfilter_data}}} + [Arguments] ${vtn_name} ${vtnflowfilter_data} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-flow-filter:set-flow-filter + ... data={"input": {"tenant-name": "${vtn_name}",${vtnflowfilter_data}}} Should Be Equal As Strings ${resp.status_code} 200 Remove a vtn flowfilter - [Arguments] ${vtn_name} ${filter_index} [Documentation] Delete a vtn flowfilter - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-flow-filter:remove-flow-filter data={"input": {"indices": ["${filter_index}"], "tenant-name": "${vtn_name}"}} + [Arguments] ${vtn_name} ${filter_index} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-flow-filter:remove-flow-filter + ... data={"input": {"indices": ["${filter_index}"], "tenant-name": "${vtn_name}"}} Should Be Equal As Strings ${resp.status_code} 200 Add a vbr flowfilter - [Arguments] ${vtn_name} ${vBridge_name} ${vbrflowfilter_data} [Documentation] Create a flowfilter for a vbr - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-flow-filter:set-flow-filter data={"input": {"tenant-name": "${vtn_name}", "bridge-name": "${vBridge_name}", ${vbrflowfilter_data}}} + [Arguments] ${vtn_name} ${vBridge_name} ${vbrflowfilter_data} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-flow-filter:set-flow-filter + ... data={"input": {"tenant-name": "${vtn_name}", "bridge-name": "${vBridge_name}", ${vbrflowfilter_data}}} Should Be Equal As Strings ${resp.status_code} 200 Remove a vbr flowfilter - [Arguments] ${vtn_name} ${vBridge_name} ${filter_index} [Documentation] Delete a vbr flowfilter - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-flow-filter:remove-flow-filter data={"input": {"indices": ["${filter_index}"], "tenant-name": "${vtn_name}","bridge-name": "${vBridge_name}"}} + [Arguments] ${vtn_name} ${vBridge_name} ${filter_index} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-flow-filter:remove-flow-filter + ... data={"input": {"indices": ["${filter_index}"], "tenant-name": "${vtn_name}","bridge-name": "${vBridge_name}"}} Should Be Equal As Strings ${resp.status_code} 200 Add a vbrif flowfilter - [Arguments] ${vtn_name} ${vBridge_name} ${interface_name} ${vbrif_flowfilter_data} [Documentation] Create a flowfilter for a vbrif - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-flow-filter:set-flow-filter data={"input": {"tenant-name": ${vtn_name}, "bridge-name": "${vBridge_name}","interface-name":"${interface_name}",${vbrif_flowfilter_data}}} + [Arguments] ${vtn_name} ${vBridge_name} ${interface_name} ${vbrif_flowfilter_data} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-flow-filter:set-flow-filter + ... data={"input": {"tenant-name": ${vtn_name}, "bridge-name": "${vBridge_name}","interface-name":"${interface_name}",${vbrif_flowfilter_data}}} Should Be Equal As Strings ${resp.status_code} 200 Remove a vbrif flowfilter - [Arguments] ${vtn_name} ${vBridge_name} ${interface_name} ${filter_index} [Documentation] Delete a vbrif flowfilter - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-flow-filter:remove-flow-filter data={"input": {"indices": ["${filter_index}"], "tenant-name": "${vtn_name}","bridge-name": "${vBridge_name}","interface-name": "${interface_name}"}} + [Arguments] ${vtn_name} ${vBridge_name} ${interface_name} ${filter_index} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-flow-filter:remove-flow-filter + ... data={"input": {"indices": ["${filter_index}"], "tenant-name": "${vtn_name}","bridge-name": "${vBridge_name}","interface-name": "${interface_name}"}} Should Be Equal As Strings ${resp.status_code} 200 Add a vlan portmap - [Arguments] ${vtn_name} ${vbr_name} ${interface_name} ${id} ${node_id} ${port_id} [Documentation] Create a portmap for a interface of a vbridge - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-port-map:set-port-map data={"input": { "tenant-name":${vtn_name}, "bridge-name":${vbr_name}, "interface-name": ${interface_name}, "vlan-id": ${id}, "node":"${node_id}", "port-name":"${port_id}"}} + [Arguments] ${vtn_name} ${vbr_name} ${interface_name} ${id} ${node_id} ${port_id} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-port-map:set-port-map + ... data={"input": { "tenant-name":${vtn_name}, "bridge-name":${vbr_name}, "interface-name": ${interface_name}, "vlan-id": ${id}, "node":"${node_id}", "port-name":"${port_id}"}} Should Be Equal As Strings ${resp.status_code} 200 Verify Flow Entries for Flowfilter - [Arguments] ${dumpflows} @{flowfilter_actions} [Documentation] Verify switch flow entry using flowfilter for a vtn - ${booleanValue}= Run Keyword And Return Status Verify Actions on Flow Entry ${dumpflows} @{flowfilter_actions} + [Arguments] ${dumpflows} @{flowfilter_actions} + ${booleanValue}= Run Keyword And Return Status + ... Verify Actions on Flow Entry + ... ${dumpflows} + ... @{flowfilter_actions} Should Be Equal As Strings ${booleanValue} True Verify Removed Flow Entry for Inet Drop Flowfilter - [Arguments] ${dumpflows} @{flowfilter_actions} [Documentation] Verify removed switch flow entry using flowfilter drop for a vtn - ${booleanValue}= Run Keyword And Return Status Verify Actions on Flow Entry ${dumpflows} @{flowfilter_actions} + [Arguments] ${dumpflows} @{flowfilter_actions} + ${booleanValue}= Run Keyword And Return Status + ... Verify Actions on Flow Entry + ... ${dumpflows} + ... @{flowfilter_actions} Should Be Equal As Strings ${booleanValue} True Verify Actions on Flow Entry - [Arguments] ${dumpflows} @{flowfilter_actions} [Documentation] check flow action elements by giving dumpflows in mininet + [Arguments] ${dumpflows} @{flowfilter_actions} write ${dumpflows} - ${result} Read Until mininet> + ${result}= Read Until mininet> FOR ${flowElement} IN @{flowfilter_actions} should Contain ${result} ${flowElement} END Add a flowcondition - [Arguments] ${flowcond_name} ${flowconditiondata} [Documentation] Create a flowcondition using Restconfig Api - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-flow-condition:set-flow-condition data={"input":{"operation":"SET","present":"false","name":"${flowcond_name}",${flowconditiondata}}} + [Arguments] ${flowcond_name} ${flowconditiondata} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-flow-condition:set-flow-condition + ... data={"input":{"operation":"SET","present":"false","name":"${flowcond_name}",${flowconditiondata}}} Should Be Equal As Strings ${resp.status_code} 200 Get flowconditions @@ -394,15 +523,23 @@ Get flowconditions Should Be Equal As Strings ${resp.status_code} 200 Get flowcondition - [Arguments] ${flowcond_name} ${retrieve} [Documentation] Retrieve the flowcondition by name and to check the removed flowcondition we added "retrieve" argument to differentiate the status code, ... since after removing flowcondition name the status will be different compare to status code when the flowcondition name is present. - ${resp}= RequestsLibrary.Get Request session restconf/operational/vtn-flow-condition:vtn-flow-conditions/vtn-flow-condition/${flowcond_name} - Run Keyword If '${retrieve}' == 'retrieve' Should Be Equal As Strings ${resp.status_code} 200 - ... ELSE Should Not Be Equal As Strings ${resp.status_code} 200 + [Arguments] ${flowcond_name} ${retrieve} + ${resp}= RequestsLibrary.Get Request + ... session + ... restconf/operational/vtn-flow-condition:vtn-flow-conditions/vtn-flow-condition/${flowcond_name} + IF '${retrieve}' == 'retrieve' + Should Be Equal As Strings ${resp.status_code} 200 + ELSE + Should Not Be Equal As Strings ${resp.status_code} 200 + END Remove flowcondition - [Arguments] ${flowcond_name} [Documentation] Remove the flowcondition by name - ${resp}= RequestsLibrary.Post Request session restconf/operations/vtn-flow-condition:remove-flow-condition data={"input":{"name":"${flowcond_name}"}} + [Arguments] ${flowcond_name} + ${resp}= RequestsLibrary.Post Request + ... session + ... restconf/operations/vtn-flow-condition:remove-flow-condition + ... data={"input":{"name":"${flowcond_name}"}} Should Be Equal As Strings ${resp.status_code} 200 diff --git a/csit/libraries/WaitForFailure.robot b/csit/libraries/WaitForFailure.robot index 3a0e16b01f..b743ced928 100644 --- a/csit/libraries/WaitForFailure.robot +++ b/csit/libraries/WaitForFailure.robot @@ -1,65 +1,82 @@ *** Settings *** -Documentation Robot keyword Resource for catching a later failure in temporarily passing repeated check. +Documentation Robot keyword Resource for catching a later failure in temporarily passing repeated check. ... -... Copyright (c) 2015-2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2015-2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... Terminology: -... "cell_sequence" is a sequence of Robot cells, usually executable. -... "keyword_name" is a first cell in that sequence, entry point of execution, -... the item defined in Keywords table (or in a Library or Resource) -... which may take arguments (the rest of cell sequence). -... Note that this may not work correctly with named arguments, due to ordering, -... so positional cells are strongly suggested to be positional arguments. -... "Keyword" or "keyword" may refer to keyword_name or executable cell sequence, -... or both, depending on context. +... Terminology: +... "cell_sequence" is a sequence of Robot cells, usually executable. +... "keyword_name" is a first cell in that sequence, entry point of execution, +... the item defined in Keywords table (or in a Library or Resource) +... which may take arguments (the rest of cell sequence). +... Note that this may not work correctly with named arguments, due to ordering, +... so positional cells are strongly suggested to be positional arguments. +... "Keyword" or "keyword" may refer to keyword_name or executable cell sequence, +... or both, depending on context. + *** Keywords *** Log_Failable_Keyword - [Arguments] @{cell_sequence} [Documentation] Execute failable Keyword. Log the resulting value when it does not fail. ... Deprecated, was used in previous implementation of higher-level keywords. + [Arguments] @{cell_sequence} ${result} = BuiltIn.Run_Keyword @{cell_sequence} BuiltIn.Log ${result} - [Return] ${result} + RETURN ${result} Keyword_Should_Fail_In_Any_Way - [Arguments] @{cell_sequence} [Documentation] Try to run the Keyword and Log the result. Pass and return the error on any failure, Fail otherwise. ... Deprecated, was used in previous implementation of higher-level keywords. + [Arguments] @{cell_sequence} ${error} = BuiltIn.Run_Keyword_And_Expect_Error * Log_Failable_Keyword @{cell_sequence} + RETURN ${error} + # '*' means we really catch all types of errors. - [Return] ${error} Invert_Failure - [Arguments] @{cell_sequence} [Documentation] The response of Keyword execution is either a return value or a failure message. ... This keyword calls the argument keyword and returns its failure message string, ... or fails with its return value converted to string. + [Arguments] @{cell_sequence} ${status} ${output} = BuiltIn.Run_Keyword_And_Ignore_Error @{cell_sequence} - BuiltIn.Run_Keyword_If "${status}" != "PASS" BuiltIn.Return_From_Keyword ${output} + IF "${status}" != "PASS" RETURN ${output} ${output} = BuiltIn.Convert_To_String ${output} BuiltIn.Fail ${output} Confirm_Keyword_Fails_Within_Timeout - [Arguments] ${timeout} ${refresh} @{cell_list} [Documentation] Some Keywords need several tries to finally fail, this keyword passes if and only if the failure ultimately happens. + [Arguments] ${timeout} ${refresh} @{cell_list} # Arguments with default values interact badly with varargs, so using WUKS argument style. - BuiltIn.Run_Keyword_And_Return BuiltIn.Wait_Until_Keyword_Succeeds ${timeout} ${refresh} Invert_Failure @{cell_list} + BuiltIn.Run_Keyword_And_Return + ... BuiltIn.Wait_Until_Keyword_Succeeds + ... ${timeout} + ... ${refresh} + ... Invert_Failure + ... @{cell_list} Verify_Keyword_Never_Passes_Within_Timeout - [Arguments] ${timeout} ${refresh} @{cell_list} [Documentation] Some negative checks report false failure for a short time. This keyword verifies no pass does happen within timeout period. - BuiltIn.Run_Keyword_And_Return Invert_Failure BuiltIn.Wait_Until_Keyword_Succeeds ${timeout} ${refresh} @{cell_list} + [Arguments] ${timeout} ${refresh} @{cell_list} + BuiltIn.Run_Keyword_And_Return + ... Invert_Failure + ... BuiltIn.Wait_Until_Keyword_Succeeds + ... ${timeout} + ... ${refresh} + ... @{cell_list} Verify_Keyword_Does_Not_Fail_Within_Timeout - [Arguments] ${timeout} ${refresh} @{cell_list} [Documentation] Some positive checks report false success for a short time. This keyword verifies no failure does happen within timeout period. ... This implementation needs more complicated logic than, Verify_Keyword_Never_Passes_Within_Timeout, ... so use that keyword in case you have a negative check handy. - BuiltIn.Run_Keyword_And_Return Invert_Failure Confirm_Keyword_Fails_Within_Timeout ${timeout} ${refresh} @{cell_list} + [Arguments] ${timeout} ${refresh} @{cell_list} + BuiltIn.Run_Keyword_And_Return + ... Invert_Failure + ... Confirm_Keyword_Fails_Within_Timeout + ... ${timeout} + ... ${refresh} + ... @{cell_list} # TODO: Remove the added comment text of time running out to restore last Keyword return value. diff --git a/csit/libraries/WaitUtils.robot b/csit/libraries/WaitUtils.robot index 7968ead021..3fb5c7b01e 100644 --- a/csit/libraries/WaitUtils.robot +++ b/csit/libraries/WaitUtils.robot @@ -1,38 +1,40 @@ *** Settings *** -Documentation Robot keyword library (Resource) with several Keywords for monitoring and waiting. +Documentation Robot keyword library (Resource) with several Keywords for monitoring and waiting. ... -... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... BuiltIn.Wait_Until_Keyword_Succeeds has two possible results: Fast pass or fail on timeout. -... Generally, keywords in this Resource also allow for some kind of fast failure condition. -... This usually requires more than a single keyword to run inside the iteration loop. -... This library uses ScalarClosures for plugging in specific (multiple) Keywords. +... BuiltIn.Wait_Until_Keyword_Succeeds has two possible results: Fast pass or fail on timeout. +... Generally, keywords in this Resource also allow for some kind of fast failure condition. +... This usually requires more than a single keyword to run inside the iteration loop. +... This library uses ScalarClosures for plugging in specific (multiple) Keywords. ... -... Storing private state in suite variables is easy, but it can lead to hard-to-debug issues, -... so this library tries to support explicit state passing. -... Unfortunately, failing limits type of message to return, -... so implementation of some Keywords looks quite convoluted. +... Storing private state in suite variables is easy, but it can lead to hard-to-debug issues, +... so this library tries to support explicit state passing. +... Unfortunately, failing limits type of message to return, +... so implementation of some Keywords looks quite convoluted. ... -... Particular closures are to be given by caller: -... Stateless Assertor: Take no arguments. Return comment or Fail with message. -... Stateful Assertor: Take single ${state} argument. Return new state and comment, or Fail with message. -... (Stateless) Getter: Take no argument. Return single scalar data, or Fail with message. -... Stateless Validator: Take single ${data} argument. Return comment, or Fail with message. -... (Unsafe) Stateful Validator: Take ${state} and ${data} arguments. Return new state and comment, or Fail with message. -... Safe Stateful Validator: Take ${state} and ${data} arguments. Return new state, validation status and comment/message. -... TODO: Create a dummy closure for each type to be used as default value? +... Particular closures are to be given by caller: +... Stateless Assertor: Take no arguments. Return comment or Fail with message. +... Stateful Assertor: Take single ${state} argument. Return new state and comment, or Fail with message. +... (Stateless) Getter: Take no argument. Return single scalar data, or Fail with message. +... Stateless Validator: Take single ${data} argument. Return comment, or Fail with message. +... (Unsafe) Stateful Validator: Take ${state} and ${data} arguments. Return new state and comment, or Fail with message. +... Safe Stateful Validator: Take ${state} and ${data} arguments. Return new state, validation status and comment/message. +... TODO: Create a dummy closure for each type to be used as default value? ... -... TODO: Figure out a way to merge this with WaitForFailure.robot -... TODO: Add Keywords that are Safe (return state, success and message) -... so that callers do not need to refresh state explicitly. -Library DateTime -Library String -Resource ${CURDIR}/ScalarClosures.robot +... TODO: Figure out a way to merge this with WaitForFailure.robot +... TODO: Add Keywords that are Safe (return state, success and message) +... so that callers do not need to refresh state explicitly. + +Library DateTime +Library String +Resource ${CURDIR}/ScalarClosures.robot + *** Keywords *** WU_Setup @@ -40,190 +42,309 @@ WU_Setup ScalarClosures.SC_Setup Limiting_Stability_Safe_Stateful_Validator_As_Keyword - [Arguments] ${old_state} ${data} ${valid_minimum}=-1 [Documentation] Report failure if minimum not reached or data value changed from last time. Useful to become validator. + [Arguments] ${old_state} ${data} ${valid_minimum}=-1 ${new_state} = BuiltIn.Set_Variable ${data} - BuiltIn.Return_From_Keyword_If ${data} < ${valid_minimum} ${new_state} FAIL Minimum not reached. - BuiltIn.Return_From_Keyword_If ${data} != ${old_state} ${new_state} FAIL Data value has changed. - [Return] ${new_state} PASS Validated stable: ${data} + IF ${data} < ${valid_minimum} + RETURN ${new_state} FAIL Minimum not reached. + END + IF ${data} != ${old_state} + RETURN ${new_state} FAIL Data value has changed. + END + RETURN ${new_state} PASS Validated stable: ${data} Create_Limiting_Stability_Safe_Stateful_Validator_From_Value_To_Overcome - [Arguments] ${maximum_invalid}=-1 [Documentation] Helper function to use if maximum invalid value (instead of minimum valid) is known. + [Arguments] ${maximum_invalid}=-1 ${valid_minimum} = BuiltIn.Evaluate str(int(${maximum_invalid}) + 1) - ${validator} = ScalarClosures.Closure_From_Keyword_And_Arguments WaitUtils.Limiting_Stability_Safe_Stateful_Validator_As_Keyword state_holder data_holder valid_minimum=${valid_minimum} - [Return] ${validator} + ${validator} = ScalarClosures.Closure_From_Keyword_And_Arguments + ... WaitUtils.Limiting_Stability_Safe_Stateful_Validator_As_Keyword + ... state_holder + ... data_holder + ... valid_minimum=${valid_minimum} + RETURN ${validator} Excluding_Stability_Safe_Stateful_Validator_As_Keyword - [Arguments] ${old_state} ${data} ${excluded_value}=-1 [Documentation] Report failure if got the excluded value or if data value changed from last time. Useful to become validator. + [Arguments] ${old_state} ${data} ${excluded_value}=-1 ${new_state} = BuiltIn.Set_Variable ${data} - BuiltIn.Return_From_Keyword_If ${data} == ${excluded_value} ${new_state} FAIL Got the excluded value. - BuiltIn.Return_From_Keyword_If ${data} != ${old_state} ${new_state} FAIL Data value has changed. - [Return] ${new_state} PASS Validated stable: ${data} + IF ${data} == ${excluded_value} + RETURN ${new_state} FAIL Got the excluded value. + END + IF ${data} != ${old_state} + RETURN ${new_state} FAIL Data value has changed. + END + RETURN ${new_state} PASS Validated stable: ${data} WaitUtils__Check_Sanity_And_Compute_Derived_Times - [Arguments] ${timeout}=60s ${period}=1s ${count}=1 [Documentation] Common checks for argument values. Return times in seconds and deadline date implied by timeout time. + [Arguments] ${timeout}=60s ${period}=1s ${count}=1 # Sanity check ${count}. - BuiltIn.Run_Keyword_If int(${count}) < 1 BuiltIn.Fail \${count} is ${count} and not at least 1. + IF int(${count}) < 1 + BuiltIn.Fail \${count} is ${count} and not at least 1. + END # Sanity check ${period}. ${period_in_seconds} = DateTime.Convert_Time ${period} result_format=number - BuiltIn.Run_Keyword_If ${period_in_seconds} <= 0.0 BuiltIn.Fail \${period} ${period} has to be positive. + IF ${period_in_seconds} <= 0.0 + BuiltIn.Fail \${period} ${period} has to be positive. + END # Figure out deadline. ${date_now} = DateTime.Get_Current_Date ${timeout_in_seconds} = DateTime.Convert_Time ${timeout} result_format=number # In the following line, arguments have to be in order which is opposite to what name suggests. ${date_deadline} = DateTime.Add_Time_To_Date ${date_now} ${timeout_in_seconds} - [Return] ${timeout_in_seconds} ${period_in_seconds} ${date_deadline} + RETURN ${timeout_in_seconds} ${period_in_seconds} ${date_deadline} WaitUtils__Is_Deadline_Reachable - [Arguments] ${date_deadline}=0 ${period_in_seconds}=1 ${sleeps_left}=1 ${message}=No attempt made. [Documentation] Compute time to be wasted in sleeps, compare to deadline. Fail with message when needed. + [Arguments] ${date_deadline}=0 ${period_in_seconds}=1 ${sleeps_left}=1 ${message}=No attempt made. # FIXME: Sensible default for deadline? ${date_now} = DateTime.Get_Current_Date ${time_deadline} = DateTime.Subtract_Date_From_Date ${date_deadline} ${date_now} result_format=number ${time_minimal} = BuiltIn.Evaluate int(${sleeps_left}) * ${period_in_seconds} - BuiltIn.Run_Keyword_If ${time_minimal} >= ${time_deadline} BuiltIn.Fail Not possible to succeed within the deadline. ${message} + IF ${time_minimal} >= ${time_deadline} + BuiltIn.Fail Not possible to succeed within the deadline. ${message} + END Wait_For_Getter_Failure_Or_Stateless_Validator_Pass - [Arguments] ${timeout}=60s ${period}=1s ${getter}=${ScalarClosures__fail} ${stateless_validator}=${ScalarClosures__identity} [Documentation] Repeatedly run getter and plug its output to validator. If both pass, return validator message. ... If getter fails, fail. If validator fails, repeat in WUKS fashion (fail when timeout is exceeded). ... FIXME: Cover this keyword in WaitUtilTest.robot - ${timeout_in_seconds} ${period_in_seconds} ${date_deadline} = WaitUtils__Check_Sanity_And_Compute_Derived_Times timeout=${timeout} period=${period} + [Arguments] ${timeout}=60s ${period}=1s ${getter}=${ScalarClosures__fail} ${stateless_validator}=${ScalarClosures__identity} + ${timeout_in_seconds} + ... ${period_in_seconds} + ... ${date_deadline} = + ... WaitUtils__Check_Sanity_And_Compute_Derived_Times + ... timeout=${timeout} + ... period=${period} ${iterations} = BuiltIn.Evaluate ${timeout_in_seconds} / ${period_in_seconds} FOR ${i} IN RANGE ${iterations} ${data} = ScalarClosures.Run_Keyword_And_Collect_Garbage ScalarClosures.Run_Closure_As_Is ${getter} - ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error ScalarClosures.Run_Keyword_And_Collect_Garbage ScalarClosures.Run_Closure_After_Replacing_First_Argument ${stateless_validator} + ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error + ... ScalarClosures.Run_Keyword_And_Collect_Garbage + ... ScalarClosures.Run_Closure_After_Replacing_First_Argument + ... ${stateless_validator} ... ${data} - BuiltIn.Return_From_Keyword_If "${status}" == "PASS" ${message} - WaitUtils__Is_Deadline_Reachable date_deadline=${date_deadline} period_in_seconds=${period_in_seconds} message=Last validator message: ${message} + IF "${status}" == "PASS" RETURN ${message} + WaitUtils__Is_Deadline_Reachable + ... date_deadline=${date_deadline} + ... period_in_seconds=${period_in_seconds} + ... message=Last validator message: ${message} BuiltIn.Sleep ${period_in_seconds} s END BuiltIn.Fail Logic error, we should have returned before. Stateless_Assert_Closure_Has_To_Succeed_Consecutively_By_Deadline - [Arguments] ${date_deadline}=0 ${period_in_seconds}=1 ${count}=1 ${assertor}=${ScalarClosures__fail} [Documentation] Pass only if \${assertor} passes ${count} times in a row with ${period_in_seconds} between attempts; less standard arguments. + [Arguments] ${date_deadline}=0 ${period_in_seconds}=1 ${count}=1 ${assertor}=${ScalarClosures__fail} ${result} = BuiltIn.Set_Variable No result yet. # Do we have enough time to succeed? ${sleeps} = BuiltIn.Evaluate ${count} - 1 - WaitUtils__Is_Deadline_Reachable date_deadline=${date_deadline} period_in_seconds=${period_in_seconds} sleeps_left=${sleeps} message=Last result: ${result} + WaitUtils__Is_Deadline_Reachable + ... date_deadline=${date_deadline} + ... period_in_seconds=${period_in_seconds} + ... sleeps_left=${sleeps} + ... message=Last result: ${result} # Entering the main loop. FOR ${sleeps_left} IN RANGE ${count}-1 -1 -1 # If count is 3, for will go through 2, 1, and 0. # Run the assertor and collect the garbage. - ${result} = ScalarClosures.Run_Keyword_And_Collect_Garbage ScalarClosures.Run_Closure_As_Is ${assertor} + ${result} = ScalarClosures.Run_Keyword_And_Collect_Garbage + ... ScalarClosures.Run_Closure_As_Is + ... ${assertor} # We have not failed yet. Was this the final try? - BuiltIn.Return_From_Keyword_If ${sleeps_left} <= 0 ${result} + IF ${sleeps_left} <= 0 RETURN ${result} # Is there enough time left? - WaitUtils__Is_Deadline_Reachable date_deadline=${date_deadline} period_in_seconds=${period_in_seconds} sleeps_left=${sleeps_left} message=Last result: ${result} + WaitUtils__Is_Deadline_Reachable + ... date_deadline=${date_deadline} + ... period_in_seconds=${period_in_seconds} + ... sleeps_left=${sleeps_left} + ... message=Last result: ${result} # We will do next try, byt we have to sleep before. BuiltIn.Sleep ${period_in_seconds} s END BuiltIn.Fail Logic error, we should have returned before. Stateless_Assert_Closure_Has_To_Succeed_Consecutively - [Arguments] ${timeout}=60s ${period}=1s ${count}=1 ${assertor}=${ScalarClosures__fail} [Documentation] Pass only if \${assertor} passes ${count} times in a row with ${period} between attempts; standard arguments. + [Arguments] ${timeout}=60s ${period}=1s ${count}=1 ${assertor}=${ScalarClosures__fail} # TODO: Put default values into variables for users to override at pybot invocation? - ${timeout_in_seconds} ${period_in_seconds} ${date_deadline} = WaitUtils__Check_Sanity_And_Compute_Derived_Times timeout=${timeout} period=${period} count=${count} - ${result} = Stateless_Assert_Closure_Has_To_Succeed_Consecutively_By_Deadline date_deadline=${date_deadline} period_in_seconds=${period_in_seconds} count=${count} assertor=${assertor} - [Return] ${result} + ${timeout_in_seconds} + ... ${period_in_seconds} + ... ${date_deadline} = + ... WaitUtils__Check_Sanity_And_Compute_Derived_Times + ... timeout=${timeout} + ... period=${period} + ... count=${count} + ${result} = Stateless_Assert_Closure_Has_To_Succeed_Consecutively_By_Deadline + ... date_deadline=${date_deadline} + ... period_in_seconds=${period_in_seconds} + ... count=${count} + ... assertor=${assertor} + RETURN ${result} Stateful_Assert_Closure_Has_To_Succeed_Consecutively_By_Deadline - [Arguments] ${date_deadline}=0 ${period_in_seconds}=1 ${count}=1 ${assertor}=${ScalarClosures__fail} ${initial_state}=${None} [Documentation] Pass only if $\{assertor} passes ${count} times in a row with ${period} between attempts. Keep assertor state in local variable. Less standard arguments. + [Arguments] ${date_deadline}=0 ${period_in_seconds}=1 ${count}=1 ${assertor}=${ScalarClosures__fail} ${initial_state}=${None} # TODO: Put default values into variables for users to override. ${result} = BuiltIn.Set_Variable No result yet. ${state} = BuiltIn.Set_Variable ${initial_state} # Do we have enough time to succeed? ${sleeps} = BuiltIn.Evaluate ${count} - 1 - WaitUtils__Is_Deadline_Reachable date_deadline=${date_deadline} period_in_seconds=${period_in_seconds} sleeps_left=${sleeps} message=Last result: ${result} + WaitUtils__Is_Deadline_Reachable + ... date_deadline=${date_deadline} + ... period_in_seconds=${period_in_seconds} + ... sleeps_left=${sleeps} + ... message=Last result: ${result} # Entering the main loop. FOR ${sleeps_left} IN RANGE ${count}-1 -1 -1 - ${state} ${result} = ScalarClosures.Run_Keyword_And_Collect_Garbage ScalarClosures.Run_Closure_After_Replacing_First_Argument ${assertor} ${state} + ${state} ${result} = ScalarClosures.Run_Keyword_And_Collect_Garbage + ... ScalarClosures.Run_Closure_After_Replacing_First_Argument + ... ${assertor} + ... ${state} # We have not failed yet. Was this the final try? - BuiltIn.Return_From_Keyword_If ${sleeps_left} <= 0 ${result} + IF ${sleeps_left} <= 0 RETURN ${result} # Is there enough time left? - WaitUtils__Is_Deadline_Reachable date_deadline=${date_deadline} period_in_seconds=${period_in_seconds} sleeps_left=${sleeps_left} message=Last result: ${result} + WaitUtils__Is_Deadline_Reachable + ... date_deadline=${date_deadline} + ... period_in_seconds=${period_in_seconds} + ... sleeps_left=${sleeps_left} + ... message=Last result: ${result} # We will do next try, byt we have to sleep before. BuiltIn.Sleep ${period_in_seconds} s END BuiltIn.Fail Logic error, we should have returned before. Stateful_Assert_Closure_Has_To_Succeed_Consecutively - [Arguments] ${timeout}=60s ${period}=1s ${count}=1 ${assertor}=${ScalarClosures__fail} ${initial_state}=${NONE} [Documentation] Pass only if \${assertor} passes ${count} times in a row with ${period} between attempts. Keep assertor state in local variable. Standard arguments. + [Arguments] ${timeout}=60s ${period}=1s ${count}=1 ${assertor}=${ScalarClosures__fail} ${initial_state}=${NONE} # TODO: Put default values into variables for users to override. - ${timeout_in_seconds} ${period_in_seconds} ${date_deadline} = WaitUtils__Check_Sanity_And_Compute_Derived_Times timeout=${timeout} period=${period} count=${count} - ${result} = Stateful_Assert_Closure_Has_To_Succeed_Consecutively_By_Deadline date_deadline=${date_deadline} period_in_seconds=${period_in_seconds} count=${count} assertor=${assertor} initial_state=${initial_state} - [Return] ${result} + ${timeout_in_seconds} + ... ${period_in_seconds} + ... ${date_deadline} = + ... WaitUtils__Check_Sanity_And_Compute_Derived_Times + ... timeout=${timeout} + ... period=${period} + ... count=${count} + ${result} = Stateful_Assert_Closure_Has_To_Succeed_Consecutively_By_Deadline + ... date_deadline=${date_deadline} + ... period_in_seconds=${period_in_seconds} + ... count=${count} + ... assertor=${assertor} + ... initial_state=${initial_state} + RETURN ${result} Getter_And_Safe_Stateful_Validator_Have_To_Succeed_Consecutively_By_Deadline - [Arguments] ${date_deadline}=0 ${period_in_seconds}=1 ${count}=1 ${getter}=${ScalarClosures__fail} ${safe_validator}=${ScalarClosures__fail} ${initial_state}=${NONE} [Documentation] Pass only if consecutively ${count} times in a row with ${period} between attempts: \${getter} creates data and \${safe_validator} passes. Validator updates its state even if it reports failure. Always return validator state, status and message. + [Arguments] ${date_deadline}=0 ${period_in_seconds}=1 ${count}=1 ${getter}=${ScalarClosures__fail} ${safe_validator}=${ScalarClosures__fail} ${initial_state}=${NONE} ${result} = BuiltIn.Set_Variable No result yet. ${state} = BuiltIn.Set_Variable ${initial_state} # Do we have enough time to succeed? ${sleeps} = BuiltIn.Evaluate ${count} - 1 - ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error WaitUtils__Is_Deadline_Reachable date_deadline=${date_deadline} period_in_seconds=${period_in_seconds} sleeps_left=${sleeps} + ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error + ... WaitUtils__Is_Deadline_Reachable + ... date_deadline=${date_deadline} + ... period_in_seconds=${period_in_seconds} + ... sleeps_left=${sleeps} ... message=Last result: ${result} - BuiltIn.Return_From_Keyword_If '''${status}''' != '''PASS''' ${state} ${status} ${message} + IF '''${status}''' != '''PASS''' + RETURN ${state} ${status} ${message} + END # Entering the main loop. FOR ${sleeps_left} IN RANGE ${count}-1 -1 -1 # Getter may fail, but this Keyword should return state, so we need RKAIE. - ${status} ${data} = BuiltIn.Run_Keyword_And_Ignore_Error ScalarClosures.Run_Keyword_And_Collect_Garbage ScalarClosures.Run_Closure_As_Is ${getter} - BuiltIn.Return_From_Keyword_If '''${status}''' != '''PASS''' ${state} ${status} Getter failed: ${data} + ${status} ${data} = BuiltIn.Run_Keyword_And_Ignore_Error + ... ScalarClosures.Run_Keyword_And_Collect_Garbage + ... ScalarClosures.Run_Closure_As_Is + ... ${getter} + IF '''${status}''' != '''PASS''' + RETURN ${state} ${status} Getter failed: ${data} + END # Is there enough time left? - ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error WaitUtils__Is_Deadline_Reachable date_deadline=${date_deadline} period_in_seconds=${period_in_seconds} - ... sleeps_left=${sleeps_left} message=Last result: ${result} - BuiltIn.Return_From_Keyword_If '''${status}''' != '''PASS''' ${state} ${status} ${message} - ${state} ${status} ${result} = ScalarClosures.Run_Keyword_And_Collect_Garbage ScalarClosures.Run_Closure_After_Replacing_First_Two_Arguments ${safe_validator} - ... ${state} ${data} + ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error + ... WaitUtils__Is_Deadline_Reachable + ... date_deadline=${date_deadline} + ... period_in_seconds=${period_in_seconds} + ... sleeps_left=${sleeps_left} + ... message=Last result: ${result} + IF '''${status}''' != '''PASS''' + RETURN ${state} ${status} ${message} + END + ${state} ${status} ${result} = ScalarClosures.Run_Keyword_And_Collect_Garbage + ... ScalarClosures.Run_Closure_After_Replacing_First_Two_Arguments + ... ${safe_validator} + ... ${state} + ... ${data} # Validator may have reported failure. - BuiltIn.Return_From_Keyword_If '''${status}''' != '''PASS''' ${state} ${status} Validator failed: ${result} + IF '''${status}''' != '''PASS''' + RETURN ${state} ${status} Validator failed: ${result} + END # Was this the final try? - BuiltIn.Return_From_Keyword_If ${sleeps_left} <= 0 ${state} ${status} ${result} + IF ${sleeps_left} <= 0 + RETURN ${state} ${status} ${result} + END # Is there enough time left? - ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error WaitUtils__Is_Deadline_Reachable date_deadline=${date_deadline} period_in_seconds=${period_in_seconds} - ... sleeps_left=${sleeps_left} message=Last result: ${result} - BuiltIn.Return_From_Keyword_If '''${status}''' != '''PASS''' ${state} ${status} ${message} + ${status} ${message} = BuiltIn.Run_Keyword_And_Ignore_Error + ... WaitUtils__Is_Deadline_Reachable + ... date_deadline=${date_deadline} + ... period_in_seconds=${period_in_seconds} + ... sleeps_left=${sleeps_left} + ... message=Last result: ${result} + IF '''${status}''' != '''PASS''' + RETURN ${state} ${status} ${message} + END # We will do next try, byt we have to sleep before. BuiltIn.Sleep ${period_in_seconds} s END BuiltIn.Fail Logic error, we should have returned before. Propagate_Fail_If_Message_Starts_With_Prefix - [Arguments] ${message}=${EMPTY} ${prefix}=magic [Documentation] Helper keyword to distinguish escalable failures by their prefix. If it is escalable, Fail without changing the message; otherwise Return comment. + [Arguments] ${message}=${EMPTY} ${prefix}=magic # TODO: Move to a more appropriate Resource. # Empty message cannot fit prefix. ${status} ${result} = BuiltIn.Run_Keyword_And_Ignore_Error BuiltIn.Should_Be_Empty ${message} - BuiltIn.Return_From_Keyword_If '${status}' == 'PASS' Got empty message. + IF '${status}' == 'PASS' RETURN Got empty message. # Is there anything except the prefix? - @{message_chunks}= String.Split_String ${message} ${prefix} + @{message_chunks} = String.Split_String ${message} ${prefix} # If there is something at the first chunk, the prefix was not at start. ${status} ${result} = BuiltIn.Run_Keyword_And_Ignore_Error BuiltIn.Should_Be_Empty ${message_chunks[0]} - BuiltIn.Return_From_Keyword_If '${status}' != 'PASS' ${message} does not start with ${prefix} + IF '${status}' != 'PASS' + RETURN ${message} does not start with ${prefix} + END # We got the fail to propagate BuiltIn.Fail ${message} Wait_For_Getter_And_Safe_Stateful_Validator_Consecutive_Success - [Arguments] ${timeout}=60s ${period}=1s ${count}=1 ${getter}=${ScalarClosures__fail} ${safe_validator}=${ScalarClosures__fail} ${initial_state}=${NONE} [Documentation] Analogue of Wait Until Keyword Succeeds, but it passes state of validator around. Calls GASSVHTSCBD to verify data is "stable". + [Arguments] ${timeout}=60s ${period}=1s ${count}=1 ${getter}=${ScalarClosures__fail} ${safe_validator}=${ScalarClosures__fail} ${initial_state}=${NONE} # FIXME: Document that Safe Stateful Validator has to return state, status and message (and never fail) - ${timeout_in_seconds} ${period_in_seconds} ${date_deadline} = WaitUtils__Check_Sanity_And_Compute_Derived_Times timeout=${timeout} period=${period} count=${count} + ${timeout_in_seconds} + ... ${period_in_seconds} + ... ${date_deadline} = + ... WaitUtils__Check_Sanity_And_Compute_Derived_Times + ... timeout=${timeout} + ... period=${period} + ... count=${count} # Maximum number of sleeps. TODO: Move to separate Keyword? - ${maximum_sleeps} = BuiltIn.Evaluate math.ceil(${timeout_in_seconds} / ${period_in_seconds}) + 1 modules=math + ${maximum_sleeps} = BuiltIn.Evaluate + ... math.ceil(${timeout_in_seconds} / ${period_in_seconds}) + 1 + ... modules=math ${result} = BuiltIn.Set_Variable No result yet. ${state} = BuiltIn.Set_Variable ${initial_state} # The loop for failures. FOR ${try} IN RANGE 1 ${maximum_sleeps}+2 # If maximum_sleeps is 2, for will go through 1, 2, and 3. - ${state} ${status} ${result} = Getter_And_Safe_Stateful_Validator_Have_To_Succeed_Consecutively_By_Deadline date_deadline=${date_deadline} period_in_seconds=${period_in_seconds} - ... count=${count} getter=${getter} safe_validator=${safe_validator} initial_state=${state} + ${state} + ... ${status} + ... ${result} = + ... Getter_And_Safe_Stateful_Validator_Have_To_Succeed_Consecutively_By_Deadline + ... date_deadline=${date_deadline} + ... period_in_seconds=${period_in_seconds} + ... count=${count} + ... getter=${getter} + ... safe_validator=${safe_validator} + ... initial_state=${state} # Have we passed? - BuiltIn.Return_From_Keyword_If '''${status}''' == '''PASS''' ${result} + IF '''${status}''' == '''PASS''' RETURN ${result} # Are we out of time? Propagate_Fail_If_Message_Starts_With_Prefix ${result} Not possible to succeed within the deadline. # We will do next try, but we have to sleep before. @@ -232,22 +353,36 @@ Wait_For_Getter_And_Safe_Stateful_Validator_Consecutive_Success BuiltIn.Fail Logic error, we should have returned before. Wait_For_Getter_Error_Or_Safe_Stateful_Validator_Consecutive_Success - [Arguments] ${timeout}=60s ${period}=1s ${count}=1 ${getter}=${ScalarClosures__fail} ${safe_validator}=${ScalarClosures__fail} ${initial_state}=${NONE} [Documentation] Analogue of Wait Until Keyword Succeeds, but it passes state of validator around and exits early on getter failure. Calls GASSVHTSCBD to verify data is "stable". + [Arguments] ${timeout}=60s ${period}=1s ${count}=1 ${getter}=${ScalarClosures__fail} ${safe_validator}=${ScalarClosures__fail} ${initial_state}=${NONE} # If this ever fails, we want to know the exact inputs passed to it. - ${tmp}= BuiltIn.Evaluate int(${count}) + ${tmp} = BuiltIn.Evaluate int(${count}) BuiltIn.Log count=${tmp} - ${timeout_in_seconds} ${period_in_seconds} ${date_deadline} = WaitUtils__Check_Sanity_And_Compute_Derived_Times timeout=${timeout} period=${period} count=${count} + ${timeout_in_seconds} + ... ${period_in_seconds} + ... ${date_deadline} = + ... WaitUtils__Check_Sanity_And_Compute_Derived_Times + ... timeout=${timeout} + ... period=${period} + ... count=${count} # Maximum number of sleeps. TODO: Move to separate Keyword or add into CSACDT? ${maximum_sleeps} = BuiltIn.Evaluate math.ceil(${timeout_in_seconds} / ${period_in_seconds}) modules=math ${result} = BuiltIn.Set_Variable No result yet. ${state} = BuiltIn.Set_Variable ${initial_state} # The loop for failures. FOR ${try} IN RANGE 1 ${maximum_sleeps}+2 # If maximum_sleeps is 2, for will go through 1, 2, and 3. - ${state} ${status} ${result} = Getter_And_Safe_Stateful_Validator_Have_To_Succeed_Consecutively_By_Deadline date_deadline=${date_deadline} period_in_seconds=${period_in_seconds} - ... count=${count} getter=${getter} safe_validator=${safe_validator} initial_state=${state} + ${state} + ... ${status} + ... ${result} = + ... Getter_And_Safe_Stateful_Validator_Have_To_Succeed_Consecutively_By_Deadline + ... date_deadline=${date_deadline} + ... period_in_seconds=${period_in_seconds} + ... count=${count} + ... getter=${getter} + ... safe_validator=${safe_validator} + ... initial_state=${state} # Have we passed? - BuiltIn.Return_From_Keyword_If '''${status}''' == '''PASS''' ${result} + IF '''${status}''' == '''PASS''' RETURN ${result} # Are we out of time? Look at ${result}. Propagate_Fail_If_Message_Starts_With_Prefix ${result} Not possible to succeed within the deadline. # Now check for getter error, by analysing ${result}. diff --git a/csit/libraries/WorkflowsL2switch.robot b/csit/libraries/WorkflowsL2switch.robot index 63b33c9296..abd48cf0ac 100644 --- a/csit/libraries/WorkflowsL2switch.robot +++ b/csit/libraries/WorkflowsL2switch.robot @@ -1,68 +1,127 @@ *** Settings *** -Documentation Resource for L2switch workflows. TODO: Refactor KWs once this test works in public. -Library RequestsLibrary -Resource Utils.robot -Resource FlowLib.robot -Resource MininetKeywords.robot -Resource ../variables/Variables.robot +Documentation Resource for L2switch workflows. TODO: Refactor KWs once this test works in public. + +Library RequestsLibrary +Resource Utils.robot +Resource FlowLib.robot +Resource MininetKeywords.robot +Resource ../variables/Variables.robot + *** Variables *** -${log_level} ERROR +${log_level} ERROR + *** Keywords *** Workflow Single Switch Multiple Hosts - [Arguments] ${hosts} ${sustain_time}=0 [Documentation] Workflow to bring a Linear topology of ${switches} switches, push flows, hold for ${sustain_time} seconds, delete flows and stop topology. ... This KW returns workflow state (PASS/FAIL), error message and topology discover time. + [Arguments] ${hosts} ${sustain_time}=0 # Define required variables - ${error_message}= BuiltIn.Set Variable Test has completed - ${host_discover_time}= BuiltIn.Set Variable ${0} + ${error_message} BuiltIn.Set Variable Test has completed + ${host_discover_time} BuiltIn.Set Variable ${0} # Workflow starts BuiltIn.Log to console ${\n} BuiltIn.Log To Console Starting mininet with one switch and ${hosts} hosts - ${status} ${result} BuiltIn.Run Keyword And Ignore Error MininetKeywords.Start Mininet Multiple Hosts ${hosts} mininet_timeout=${hosts} - BuiltIn.Return From Keyword If '${status}' == 'FAIL' ${status} Fail starting mininet ${host_discover_time} + ${status} ${result} BuiltIn.Run Keyword And Ignore Error + ... MininetKeywords.Start Mininet Multiple Hosts + ... ${hosts} + ... mininet_timeout=${hosts} + IF '${status}' == 'FAIL' + RETURN ${status} Fail starting mininet ${host_discover_time} + END BuiltIn.Log To Console Check 1 switch - ${status} ${result} BuiltIn.Run Keyword And Ignore Error Wait Until Keyword Succeeds ${hosts} 2s FlowLib.Check Switches In Inventory + ${status} ${result} BuiltIn.Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... ${hosts} + ... 2s + ... FlowLib.Check Switches In Inventory ... ${1} - BuiltIn.Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking switch ${host_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking switch ${host_discover_time} + END BuiltIn.Log To Console Ping all hosts - @{host_list}= MininetKeywords.Get Mininet Hosts - ${start_time}= DateTime.Get Current Date result_format=timestamp - ${status}= MininetKeywords.Ping All Hosts @{host_list} - BuiltIn.Return From Keyword If ${status} != ${0} ${status} Ping test fails ${host_discover_time} + @{host_list} MininetKeywords.Get Mininet Hosts + ${start_time} DateTime.Get Current Date result_format=timestamp + ${status} MininetKeywords.Ping All Hosts @{host_list} + IF ${status} != ${0} + RETURN ${status} Ping test fails ${host_discover_time} + END BuiltIn.Log To Console Verify controller is OK - ${status} ${result} BuiltIn.Run Keyword And Ignore Error Utils.Verify Controller Is Not Dead ${ODL_SYSTEM_IP} - Return From Keyword If '${status}' == 'FAIL' ${status} Controller is dead ${host_discover_time} - ${status} ${result} BuiltIn.Run Keyword And Ignore Error Utils.Verify Controller Has No Null Pointer Exceptions ${ODL_SYSTEM_IP} - Return From Keyword If '${status}' == 'FAIL' ${status} Controller has NPE ${host_discover_time} - ${status} ${result} BuiltIn.Run Keyword And Ignore Error Utils.Verify Controller Has No Runtime Exceptions ${ODL_SYSTEM_IP} - Return From Keyword If '${status}' == 'FAIL' ${status} Controller has RuntimeException ${topology_discover_time} + ${status} ${result} BuiltIn.Run Keyword And Ignore Error + ... Utils.Verify Controller Is Not Dead + ... ${ODL_SYSTEM_IP} + IF '${status}' == 'FAIL' + RETURN ${status} Controller is dead ${host_discover_time} + END + ${status} ${result} BuiltIn.Run Keyword And Ignore Error + ... Utils.Verify Controller Has No Null Pointer Exceptions + ... ${ODL_SYSTEM_IP} + IF '${status}' == 'FAIL' + RETURN ${status} Controller has NPE ${host_discover_time} + END + ${status} ${result} BuiltIn.Run Keyword And Ignore Error + ... Utils.Verify Controller Has No Runtime Exceptions + ... ${ODL_SYSTEM_IP} + IF '${status}' == 'FAIL' + RETURN ${status} Controller has RuntimeException ${topology_discover_time} + END Log To Console Check number of hosts in topology is ${hosts} - ${status} ${result} BuiltIn.Run Keyword And Ignore Error Wait Until Keyword Succeeds ${hosts} 2s FlowLib.Check Number Of Hosts + ${status} ${result} BuiltIn.Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... ${hosts} + ... 2s + ... FlowLib.Check Number Of Hosts ... ${hosts} - BuiltIn.Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking hosts ${host_discover_time} - ${end_time}= DateTime.Get Current Date result_format=timestamp - ${host_discover_time}= DateTime.Subtract Date From Date ${end_time} ${start_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking hosts ${host_discover_time} + END + ${end_time} DateTime.Get Current Date result_format=timestamp + ${host_discover_time} DateTime.Subtract Date From Date ${end_time} ${start_time} BuiltIn.Log To Console Host Discovery Time = ${host_discover_time} seconds BuiltIn.Log To Console Sleep for ${sustain_time} seconds BuiltIn.Sleep ${sustain_time} BuiltIn.Log To Console Stopping Mininet ${status} ${result} BuiltIn.Run Keyword And Ignore Error MininetKeywords.Stop Mininet And Exit - BuiltIn.Return From Keyword If '${status}' == 'FAIL' ${status} Fail stopping mininet ${host_discover_time} + IF '${status}' == 'FAIL' + RETURN + ... ${status} + ... Fail stopping mininet + ... ${host_discover_time} + END BuiltIn.Log To Console Checking No Switches - ${status} ${result} BuiltIn.Run Keyword And Ignore Error Wait Until Keyword Succeeds 5s 1s FlowLib.Check No Switches In Inventory + ${status} ${result} BuiltIn.Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... 5s + ... 1s + ... FlowLib.Check No Switches In Inventory ... ${1} - BuiltIn.Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking no switch ${host_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking no switch ${host_discover_time} + END BuiltIn.Log To Console Checking no hosts are present in operational database - ${status} ${result} BuiltIn.Run Keyword And Ignore Error Wait Until Keyword Succeeds 5s 1s FlowLib.Check No Hosts - BuiltIn.Return From Keyword If '${status}' == 'FAIL' ${status} Hosts are present ${host_discover_time} + ${status} ${result} BuiltIn.Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... 5s + ... 1s + ... FlowLib.Check No Hosts + IF '${status}' == 'FAIL' + RETURN ${status} Hosts are present ${host_discover_time} + END ${max-hosts} BuiltIn.Convert To String ${hosts} - [Return] PASS ${error_message} ${host_discover_time} + RETURN PASS ${error_message} ${host_discover_time} Workflow Setup - RequestsLibrary.Create Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} auth=${AUTH} headers=${HEADERS_XML} - BuiltIn.Wait Until Keyword Succeeds 3x 1s KarafKeywords.Issue Command On Karaf Console log:set ${log_level} + RequestsLibrary.Create Session + ... session + ... http://${ODL_SYSTEM_IP}:${RESTCONFPORT} + ... auth=${AUTH} + ... headers=${HEADERS_XML} + BuiltIn.Wait Until Keyword Succeeds + ... 3x + ... 1s + ... KarafKeywords.Issue Command On Karaf Console + ... log:set ${log_level} Workflow Teardown [Documentation] Cleanup when workflow is interrupt diff --git a/csit/libraries/WorkflowsOpenFlow.robot b/csit/libraries/WorkflowsOpenFlow.robot index 50ec659d44..dac5fe89fc 100644 --- a/csit/libraries/WorkflowsOpenFlow.robot +++ b/csit/libraries/WorkflowsOpenFlow.robot @@ -1,184 +1,361 @@ *** Settings *** -Documentation Resource for OpenFlow workflows. This library can be used for scalability and longevity tests. -Library SSHLibrary -Library DateTime -Library RequestsLibrary -Library ScaleClient.py -Library SwitchClasses/BaseSwitch.py -Resource Utils.robot -Resource FlowLib.robot -Resource CompareStream.robot -Resource MininetKeywords.robot -Resource KarafKeywords.robot -Resource ../variables/Variables.robot -Resource ../variables/openflowplugin/Variables.robot +Documentation Resource for OpenFlow workflows. This library can be used for scalability and longevity tests. + +Library SSHLibrary +Library DateTime +Library RequestsLibrary +Library ScaleClient.py +Library SwitchClasses/BaseSwitch.py +Resource Utils.robot +Resource FlowLib.robot +Resource CompareStream.robot +Resource MininetKeywords.robot +Resource KarafKeywords.robot +Resource ../variables/Variables.robot +Resource ../variables/openflowplugin/Variables.robot + *** Variables *** -${log_level} ERROR -${flow_count} 10000 -${swspread} linear -${tables} 10 -${tabspread} linear -${nrthreads} 1 +${log_level} ERROR +${flow_count} 10000 +${swspread} linear +${tables} 10 +${tabspread} linear +${nrthreads} 1 + *** Keywords *** Workflow Linear Topology - [Arguments] ${switches} ${sustain_time}=0 [Documentation] Workflow to bring a Linear topology of ${switches} switches, push flows, hold for ${sustain_time} seconds, delete flows and stop topology. ... This KW returns workflow state (PASS/FAIL), error message and topology discover time. + [Arguments] ${switches} ${sustain_time}=0 # Define required variables - ${error_message}= Set Variable Test has completed - ${topology_discover_time}= Set Variable ${0} - ${controller_list}= Create List ${ODL_SYSTEM_IP} - ${flow_count}= Convert to Integer ${flow_count} - ${flows_ovs_25}= Evaluate ${flow_count} + ${switches} - ${flows_before}= Set Variable ${switches} - ${flows_after}= Set Variable ${flows_ovs_25} - ${flows} ${notes} ScaleClient.Generate New Flow Details flows=${flow_count} switches=${switches} swspread=${swspread} tables=${tables} + ${error_message} Set Variable Test has completed + ${topology_discover_time} Set Variable ${0} + ${controller_list} Create List ${ODL_SYSTEM_IP} + ${flow_count} Convert to Integer ${flow_count} + ${flows_ovs_25} Evaluate ${flow_count} + ${switches} + ${flows_before} Set Variable ${switches} + ${flows_after} Set Variable ${flows_ovs_25} + ${flows} ${notes} ScaleClient.Generate New Flow Details + ... flows=${flow_count} + ... switches=${switches} + ... swspread=${swspread} + ... tables=${tables} ... tabspread=${tabspread} # Workflow starts Log to console ${\n} Log To Console Starting mininet linear ${switches} switches - ${status} ${result} Run Keyword And Ignore Error MininetKeywords.Start Mininet Linear ${switches} mininet_timeout=${switches*4} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail starting mininet ${topology_discover_time} - ${start_time}= DateTime.Get Current Date result_format=timestamp + ${status} ${result} Run Keyword And Ignore Error + ... MininetKeywords.Start Mininet Linear + ... ${switches} + ... mininet_timeout=${switches*4} + IF '${status}' == 'FAIL' + RETURN ${status} Fail starting mininet ${topology_discover_time} + END + ${start_time} DateTime.Get Current Date result_format=timestamp Log To Console Verify controller is OK ${status} ${result} Run Keyword And Ignore Error Utils.Verify Controller Is Not Dead ${ODL_SYSTEM_IP} - Return From Keyword If '${status}' == 'FAIL' ${status} Controller is dead ${topology_discover_time} - ${status} ${result} Run Keyword And Ignore Error Utils.Verify Controller Has No Null Pointer Exceptions ${ODL_SYSTEM_IP} - Return From Keyword If '${status}' == 'FAIL' ${status} Controller has NPE ${topology_discover_time} - ${status} ${result} Run Keyword And Ignore Error Utils.Verify Controller Has No Runtime Exceptions ${ODL_SYSTEM_IP} - Return From Keyword If '${status}' == 'FAIL' ${status} Controller has RuntimeException ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Controller is dead ${topology_discover_time} + END + ${status} ${result} Run Keyword And Ignore Error + ... Utils.Verify Controller Has No Null Pointer Exceptions + ... ${ODL_SYSTEM_IP} + IF '${status}' == 'FAIL' + RETURN ${status} Controller has NPE ${topology_discover_time} + END + ${status} ${result} Run Keyword And Ignore Error + ... Utils.Verify Controller Has No Runtime Exceptions + ... ${ODL_SYSTEM_IP} + IF '${status}' == 'FAIL' + RETURN ${status} Controller has RuntimeException ${topology_discover_time} + END Log To Console Checking ${switches} switches - ${status} ${result} Run Keyword And Ignore Error Wait Until Keyword Succeeds ${switches*2} 2s FlowLib.Check Switches In Inventory + ${status} ${result} Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... ${switches*2} + ... 2s + ... FlowLib.Check Switches In Inventory ... ${switches} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking switch ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking switch ${topology_discover_time} + END Log To Console Add table miss flows ${status} ${result} Run Keyword And Ignore Error FlowLib.Add Table Miss Flows ${switches} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail adding table Miss flows ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail adding table Miss flows ${topology_discover_time} + END Log To Console Checking Table Miss Flows - ${status} ${result} Run Keyword And Ignore Error Wait Until Keyword Succeeds ${switches} 2s FlowLib.Check Table Miss Flows + ${status} ${result} Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... ${switches} + ... 2s + ... FlowLib.Check Table Miss Flows ... ${switches} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking table miss flows ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking table miss flows ${topology_discover_time} + END Log To Console Checking Linear Topology - ${status} ${result} Run Keyword And Ignore Error Wait Until Keyword Succeeds ${switches} 2s FlowLib.Check Linear Topology + ${status} ${result} Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... ${switches} + ... 2s + ... FlowLib.Check Linear Topology ... ${switches} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking topology ${topology_discover_time} - ${end_time}= DateTime.Get Current Date result_format=timestamp - ${topology_discover_time}= DateTime.Subtract Date From Date ${end_time} ${start_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking topology ${topology_discover_time} + END + ${end_time} DateTime.Get Current Date result_format=timestamp + ${topology_discover_time} DateTime.Subtract Date From Date ${end_time} ${start_time} Log To Console Topology Discovery Time = ${topology_discover_time} seconds Log To Console Adding ${flow_count} flows - ${status} ${result} Run Keyword And Ignore Error ScaleClient.Configure Flows flow_details=${flows} controllers=${controller_list} nrthreads=${nrthreads} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail configuring flows ${topology_discover_time} + ${status} ${result} Run Keyword And Ignore Error + ... ScaleClient.Configure Flows + ... flow_details=${flows} + ... controllers=${controller_list} + ... nrthreads=${nrthreads} + IF '${status}' == 'FAIL' + RETURN ${status} Fail configuring flows ${topology_discover_time} + END Log To Console Checking ${flow_count} flows in Mininet - ${status} ${result} Run Keyword And Ignore Error MininetKeywords.Verify Aggregate Flow From Mininet Session ${mininet_conn_id} ${flows_after} ${switches} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking flows in mininet ${topology_discover_time} + ${status} ${result} Run Keyword And Ignore Error + ... MininetKeywords.Verify Aggregate Flow From Mininet Session + ... ${mininet_conn_id} + ... ${flows_after} + ... ${switches} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking flows in mininet ${topology_discover_time} + END Log To Console Checking ${flow_count} flows in Operational DS - ${status} ${result} Run Keyword And Ignore Error Wait Until Keyword Succeeds ${switches*4} 2s FlowLib.Check Flows Operational Datastore + ${status} ${result} Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... ${switches*4} + ... 2s + ... FlowLib.Check Flows Operational Datastore ... ${flows_after} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking flows in operational DS ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking flows in operational DS ${topology_discover_time} + END Log To Console Sleep for ${sustain_time} seconds Sleep ${sustain_time} Log To Console Deleting ${flow_count} flows - ${status} ${result} Run Keyword And Ignore Error ScaleClient.Deconfigure Flows flow_details=${flows} controllers=${controller_list} nrthreads=${nrthreads} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail deconfiguring flows ${topology_discover_time} + ${status} ${result} Run Keyword And Ignore Error + ... ScaleClient.Deconfigure Flows + ... flow_details=${flows} + ... controllers=${controller_list} + ... nrthreads=${nrthreads} + IF '${status}' == 'FAIL' + RETURN ${status} Fail deconfiguring flows ${topology_discover_time} + END Log To Console Checking no flows in Mininet - ${status} ${result} Run Keyword And Ignore Error MininetKeywords.Verify Aggregate Flow From Mininet Session ${mininet_conn_id} ${flows_before} ${switches} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking no flows in mininet ${topology_discover_time} + ${status} ${result} Run Keyword And Ignore Error + ... MininetKeywords.Verify Aggregate Flow From Mininet Session + ... ${mininet_conn_id} + ... ${flows_before} + ... ${switches} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking no flows in mininet ${topology_discover_time} + END Log To Console Checking no flows in Operational DS - ${status} ${result} Run Keyword And Ignore Error Wait Until Keyword Succeeds ${switches*4} 2s FlowLib.Check Flows Operational Datastore + ${status} ${result} Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... ${switches*4} + ... 2s + ... FlowLib.Check Flows Operational Datastore ... ${flows_before} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking no flows in operational DS ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking no flows in operational DS ${topology_discover_time} + END Log To Console Stopping Mininet ${status} ${result} Run Keyword And Ignore Error MininetKeywords.Stop Mininet And Exit - Return From Keyword If '${status}' == 'FAIL' ${status} Fail stopping mininet ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail stopping mininet ${topology_discover_time} + END Log To Console Checking No Switches - ${status} ${result} Run Keyword And Ignore Error Wait Until Keyword Succeeds 30s 2s FlowLib.Check No Switches In Inventory + ${status} ${result} Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... 30s + ... 2s + ... FlowLib.Check No Switches In Inventory ... ${switches} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking no switch ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking no switch ${topology_discover_time} + END Log To Console Checking No Topology - ${status} ${result} Run Keyword And Ignore Error Wait Until Keyword Succeeds 10s 2s FlowLib.Check No Switches In Topology + ${status} ${result} Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... 10s + ... 2s + ... FlowLib.Check No Switches In Topology ... ${switches} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking no topology ${topology_discover_time} - [Return] PASS ${error_message} ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking no topology ${topology_discover_time} + END + RETURN PASS ${error_message} ${topology_discover_time} Workflow Full Mesh Topology - [Arguments] ${switches} ${sustain_time}=0 [Documentation] Workflow to bring a Full mesh topology of ${switches} switches, push some flows, delete flows and stop topology. ... This KW returns workflow state (PASS/FAIL), error message and topology discover time. + [Arguments] ${switches} ${sustain_time}=0 # Define required variables - ${error_message}= Set Variable Test has completed - ${topology_discover_time}= Set Variable ${0} - ${mininet_timeout}= Evaluate ${switches} * ${switches} - ${links}= Evaluate ${switches} * ${switches-1} - ${controller_list}= Create List ${ODL_SYSTEM_IP} - ${flow_count}= Convert to Integer ${flow_count} - ${flows_ovs_25}= Evaluate ${flow_count} + ${switches} - ${flows_before}= Set Variable ${switches} - ${flows_after}= Set Variable ${flows_ovs_25} - ${flows} ${notes} ScaleClient.Generate New Flow Details flows=${flow_count} switches=${switches} swspread=${swspread} tables=${tables} + ${error_message} Set Variable Test has completed + ${topology_discover_time} Set Variable ${0} + ${mininet_timeout} Evaluate ${switches} * ${switches} + ${links} Evaluate ${switches} * ${switches-1} + ${controller_list} Create List ${ODL_SYSTEM_IP} + ${flow_count} Convert to Integer ${flow_count} + ${flows_ovs_25} Evaluate ${flow_count} + ${switches} + ${flows_before} Set Variable ${switches} + ${flows_after} Set Variable ${flows_ovs_25} + ${flows} ${notes} ScaleClient.Generate New Flow Details + ... flows=${flow_count} + ... switches=${switches} + ... swspread=${swspread} + ... tables=${tables} ... tabspread=${tabspread} # Workflow starts Log to console ${\n} Log To Console Start a mininet full mesh ${switches} switches - ${status} ${result} Run Keyword And Ignore Error MininetKeywords.Start Mininet Full Mesh ${switches} mininet_timeout=${mininet_timeout} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail starting mininet ${topology_discover_time} - ${start_time}= DateTime.Get Current Date result_format=timestamp + ${status} ${result} Run Keyword And Ignore Error + ... MininetKeywords.Start Mininet Full Mesh + ... ${switches} + ... mininet_timeout=${mininet_timeout} + IF '${status}' == 'FAIL' + RETURN ${status} Fail starting mininet ${topology_discover_time} + END + ${start_time} DateTime.Get Current Date result_format=timestamp Log To Console Verify controller is OK ${status} ${result} Run Keyword And Ignore Error Utils.Verify Controller Is Not Dead ${ODL_SYSTEM_IP} - Return From Keyword If '${status}' == 'FAIL' ${status} Controller is dead ${topology_discover_time} - ${status} ${result} Run Keyword And Ignore Error Utils.Verify Controller Has No Null Pointer Exceptions ${ODL_SYSTEM_IP} - Return From Keyword If '${status}' == 'FAIL' ${status} Controller has NPE ${topology_discover_time} - ${status} ${result} Run Keyword And Ignore Error Utils.Verify Controller Has No Runtime Exceptions ${ODL_SYSTEM_IP} - Return From Keyword If '${status}' == 'FAIL' ${status} Controller has RuntimeException ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Controller is dead ${topology_discover_time} + END + ${status} ${result} Run Keyword And Ignore Error + ... Utils.Verify Controller Has No Null Pointer Exceptions + ... ${ODL_SYSTEM_IP} + IF '${status}' == 'FAIL' + RETURN ${status} Controller has NPE ${topology_discover_time} + END + ${status} ${result} Run Keyword And Ignore Error + ... Utils.Verify Controller Has No Runtime Exceptions + ... ${ODL_SYSTEM_IP} + IF '${status}' == 'FAIL' + RETURN ${status} Controller has RuntimeException ${topology_discover_time} + END Log To Console Checking ${switches} switches - ${status} ${result} Run Keyword And Ignore Error Wait Until Keyword Succeeds 30s 2s FlowLib.Check Switches In Inventory + ${status} ${result} Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... 30s + ... 2s + ... FlowLib.Check Switches In Inventory ... ${switches} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking switch ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking switch ${topology_discover_time} + END Log To Console Check number of links in inventory is ${links} - ${status} ${result} Run Keyword And Ignore Error Wait Until Keyword Succeeds 10s 2s FlowLib.Check Number Of Links + ${status} ${result} Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... 10s + ... 2s + ... FlowLib.Check Number Of Links ... ${links} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking topology ${topology_discover_time} - ${end_time}= DateTime.Get Current Date result_format=timestamp - ${topology_discover_time}= DateTime.Subtract Date From Date ${end_time} ${start_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking topology ${topology_discover_time} + END + ${end_time} DateTime.Get Current Date result_format=timestamp + ${topology_discover_time} DateTime.Subtract Date From Date ${end_time} ${start_time} Log To Console Topology Discovery Time = ${topology_discover_time} seconds Log To Console Adding ${flow_count} flows - ${status} ${result} Run Keyword And Ignore Error ScaleClient.Configure Flows flow_details=${flows} controllers=${controller_list} nrthreads=${nrthreads} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail configuring flows ${topology_discover_time} + ${status} ${result} Run Keyword And Ignore Error + ... ScaleClient.Configure Flows + ... flow_details=${flows} + ... controllers=${controller_list} + ... nrthreads=${nrthreads} + IF '${status}' == 'FAIL' + RETURN ${status} Fail configuring flows ${topology_discover_time} + END Log To Console Checking ${flow_count} flows in Mininet - ${status} ${result} Run Keyword And Ignore Error MininetKeywords.Verify Aggregate Flow From Mininet Session ${mininet_conn_id} ${flows_after} ${switches} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking flows in mininet ${topology_discover_time} + ${status} ${result} Run Keyword And Ignore Error + ... MininetKeywords.Verify Aggregate Flow From Mininet Session + ... ${mininet_conn_id} + ... ${flows_after} + ... ${switches} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking flows in mininet ${topology_discover_time} + END Log To Console Checking ${flow_count} flows in Operational DS - ${status} ${result} Run Keyword And Ignore Error Wait Until Keyword Succeeds ${switches*4} 2s FlowLib.Check Flows Operational Datastore + ${status} ${result} Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... ${switches*4} + ... 2s + ... FlowLib.Check Flows Operational Datastore ... ${flows_after} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking flows in operational DS ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking flows in operational DS ${topology_discover_time} + END Log To Console Sleep for ${sustain_time} seconds Sleep ${sustain_time} Log To Console Deleting ${flow_count} flows - ${status} ${result} Run Keyword And Ignore Error ScaleClient.Deconfigure Flows flow_details=${flows} controllers=${controller_list} nrthreads=${nrthreads} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail deconfiguring flows ${topology_discover_time} + ${status} ${result} Run Keyword And Ignore Error + ... ScaleClient.Deconfigure Flows + ... flow_details=${flows} + ... controllers=${controller_list} + ... nrthreads=${nrthreads} + IF '${status}' == 'FAIL' + RETURN ${status} Fail deconfiguring flows ${topology_discover_time} + END Log To Console Checking no flows in Mininet - ${status} ${result} Run Keyword And Ignore Error MininetKeywords.Verify Aggregate Flow From Mininet Session ${mininet_conn_id} ${flows_before} ${switches} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking no flows in mininet ${topology_discover_time} + ${status} ${result} Run Keyword And Ignore Error + ... MininetKeywords.Verify Aggregate Flow From Mininet Session + ... ${mininet_conn_id} + ... ${flows_before} + ... ${switches} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking no flows in mininet ${topology_discover_time} + END Log To Console Checking no flows in Operational DS - ${status} ${result} Run Keyword And Ignore Error Wait Until Keyword Succeeds ${switches*4} 2s FlowLib.Check Flows Operational Datastore + ${status} ${result} Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... ${switches*4} + ... 2s + ... FlowLib.Check Flows Operational Datastore ... ${flows_before} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking no flows in operational DS ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking no flows in operational DS ${topology_discover_time} + END Log To Console Stopping Mininet ${status} ${result} Run Keyword And Ignore Error MininetKeywords.Stop Mininet And Exit - Return From Keyword If '${status}' == 'FAIL' ${status} Fail stopping mininet ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail stopping mininet ${topology_discover_time} + END Log To Console Checking No Switches - ${status} ${result} Run Keyword And Ignore Error Wait Until Keyword Succeeds 10s 2s FlowLib.Check No Switches In Inventory + ${status} ${result} Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... 10s + ... 2s + ... FlowLib.Check No Switches In Inventory ... ${switches} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking no switch ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking no switch ${topology_discover_time} + END Log To Console Checking No Topology - ${status} ${result} Run Keyword And Ignore Error Wait Until Keyword Succeeds 10s 2s FlowLib.Check No Switches In Topology + ${status} ${result} Run Keyword And Ignore Error + ... Wait Until Keyword Succeeds + ... 10s + ... 2s + ... FlowLib.Check No Switches In Topology ... ${switches} - Return From Keyword If '${status}' == 'FAIL' ${status} Fail checking no topology ${topology_discover_time} - [Return] PASS ${error_message} ${topology_discover_time} + IF '${status}' == 'FAIL' + RETURN ${status} Fail checking no topology ${topology_discover_time} + END + RETURN PASS ${error_message} ${topology_discover_time} Workflow Setup - RequestsLibrary.Create Session session http://${ODL_SYSTEM_IP}:${RESTCONFPORT} auth=${AUTH} headers=${HEADERS_XML} + RequestsLibrary.Create Session + ... session + ... http://${ODL_SYSTEM_IP}:${RESTCONFPORT} + ... auth=${AUTH} + ... headers=${HEADERS_XML} Wait Until Keyword Succeeds 3x 1s KarafKeywords.Issue Command On Karaf Console log:set ${log_level} Workflow Teardown diff --git a/csit/libraries/YangCollection.robot b/csit/libraries/YangCollection.robot index 515d6ebe45..72aa63a5a1 100644 --- a/csit/libraries/YangCollection.robot +++ b/csit/libraries/YangCollection.robot @@ -1,110 +1,122 @@ *** Settings *** -Documentation Resource for preparing various sets of Yang files to be used in testing. +Documentation Resource for preparing various sets of Yang files to be used in testing. ... -... Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... Keywords in this Resource assume there is an active SSH connection -... to system where a particular set of Yang files is to be created. -... The keywords will change current working directory used by SSHKeywords. +... Keywords in this Resource assume there is an active SSH connection +... to system where a particular set of Yang files is to be created. +... The keywords will change current working directory used by SSHKeywords. ... -... The two repos used in this suite ${YANGMODELS_REPO} and ${OPENCONFIG_REPO} -... have been updated: -... 11/11/2020 +... The two repos used in this suite ${YANGMODELS_REPO} and ${OPENCONFIG_REPO} +... have been updated: +... 11/11/2020 ... -Resource ${CURDIR}/SSHKeywords.robot + +Resource ${CURDIR}/SSHKeywords.robot + *** Variables *** -${YANGMODELS_REPO} https://github.com/YangModels/yang -${OPENCONFIG_REPO} https://github.com/openconfig/public -${YANGMODELS_REPO_COMMIT_HASH} cdd14114cdaf130be2b6bfce92538c05f6d7c07d # TODO: update docs with new date when changing -${OPENCONFIG_REPO_COMMIT_HASH} 8062b1b45208b952598ad3c3aa9e5ebc4f03cc67 # TODO: update docs with new date when changing +${YANGMODELS_REPO} https://github.com/YangModels/yang +${OPENCONFIG_REPO} https://github.com/openconfig/public +# TODO: update docs with new date when changing +${YANGMODELS_REPO_COMMIT_HASH} +... cdd14114cdaf130be2b6bfce92538c05f6d7c07d +# TODO: update docs with new date when changing +${OPENCONFIG_REPO_COMMIT_HASH} +... 8062b1b45208b952598ad3c3aa9e5ebc4f03cc67 # ${YANG_MODEL_PATHS} is needed to explicitly tell which paths to find yang files to build dependencies from to validate # the yang file being validated. There is an option (-r) to recursively parse so that you don't have to pass all of these # paths with the -p argument, but the recursive option makes the tool so slow that it would not work when testing so # many files -@{YANG_MODEL_PATHS} /home/jenkins/src/main/yang/experimental/ietf-extracted-YANG-modules -... /home/jenkins/src/main/yang/experimental/openconfig/release/models -... /home/jenkins/src/main/yang/standard/ietf/DRAFT -... /home/jenkins/src/main/yang/standard/ietf/RFC -... /home/jenkins/src/main/yang/experimental/ieee -... /home/jenkins/src/main/yang/experimental/ieee/1588 -... /home/jenkins/src/main/yang/experimental/ieee/1906.1 -... /home/jenkins/src/main/yang/experimental/ietf -... /home/jenkins/src/main/yang/experimental/mano-models -... /home/jenkins/src/main/yang/experimental/odp -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/acl -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/aft -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/bfd -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/bgp -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/catalog -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/interfaces -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/isis -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/lacp -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/lldp -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/local-routing -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/macsec -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/mpls -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/multicast -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/network-instance -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/openflow -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/optical-transport -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/ospf -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/platform -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/policy -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/policy-forwarding -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/probes -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/qos -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/relay-agent -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/rib -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/segment-routing -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/stp -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/system -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/telemetry -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/types -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/vlan -... /home/jenkins/src/main/yang/experimental/openconfig/release/models/wifi -... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/ABcu -... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/AEdk -... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/CBcv -... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/CBdb -... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/Qcr -... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/Qcw -... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/Qcx -... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/Qcz -... /home/jenkins/src/main/yang/standard/ieee/draft/1906.1 -... /home/jenkins/src/main/yang/standard/ieee/published/802.1 -... /home/jenkins/src/main/yang/standard/ieee/published/802.3 -... /home/jenkins/src/main/yang/vendor/ciena -... /home/jenkins/src/main/yang/vendor/fujitsu -... /home/jenkins/src/main/yang/vendor/huawei -... /home/jenkins/src/main/yang/vendor/nokia +@{YANG_MODEL_PATHS} +... /home/jenkins/src/main/yang/experimental/ietf-extracted-YANG-modules +... /home/jenkins/src/main/yang/experimental/openconfig/release/models +... /home/jenkins/src/main/yang/standard/ietf/DRAFT +... /home/jenkins/src/main/yang/standard/ietf/RFC +... /home/jenkins/src/main/yang/experimental/ieee +... /home/jenkins/src/main/yang/experimental/ieee/1588 +... /home/jenkins/src/main/yang/experimental/ieee/1906.1 +... /home/jenkins/src/main/yang/experimental/ietf +... /home/jenkins/src/main/yang/experimental/mano-models +... /home/jenkins/src/main/yang/experimental/odp +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/acl +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/aft +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/bfd +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/bgp +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/catalog +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/interfaces +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/isis +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/lacp +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/lldp +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/local-routing +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/macsec +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/mpls +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/multicast +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/network-instance +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/openflow +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/optical-transport +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/ospf +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/platform +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/policy +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/policy-forwarding +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/probes +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/qos +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/relay-agent +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/rib +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/segment-routing +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/stp +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/system +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/telemetry +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/types +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/vlan +... /home/jenkins/src/main/yang/experimental/openconfig/release/models/wifi +... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/ABcu +... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/AEdk +... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/CBcv +... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/CBdb +... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/Qcr +... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/Qcw +... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/Qcx +... /home/jenkins/src/main/yang/standard/ieee/draft/802.1/Qcz +... /home/jenkins/src/main/yang/standard/ieee/draft/1906.1 +... /home/jenkins/src/main/yang/standard/ieee/published/802.1 +... /home/jenkins/src/main/yang/standard/ieee/published/802.3 +... /home/jenkins/src/main/yang/vendor/ciena +... /home/jenkins/src/main/yang/vendor/fujitsu +... /home/jenkins/src/main/yang/vendor/huawei +... /home/jenkins/src/main/yang/vendor/nokia + *** Keywords *** Static_Set_As_Src - [Arguments] ${root_dir}=. [Documentation] Cleanup possibly leftover directories (src and target), clone git repos and remove unwanted paths. ... YangModels/yang and openconfig/public repos should be updated from time to time, but they are frozen to ... ${YANGMODELS_REPO_COMMIT_HASH} and ${OPENCONFIG_REPO_COMMIT_HASH} to prevent the chance that updates to those ... repos with problems will cause ODL CSIT to fail. There are obvious failures in these repos already, and those ... are addressed by removing those files/dirs with the Delete_Static_Paths keyword. + [Arguments] ${root_dir}=. SSHKeywords.Set_Cwd ${root_dir} SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -rf target src SSHKeywords.Execute_Command_At_Cwd_Should_Pass mkdir -p src/main SSHKeywords.Set_Cwd ${root_dir}/src/main SSHKeywords.Execute_Command_At_Cwd_Should_Pass git clone ${YANGMODELS_REPO} stderr_must_be_empty=False SSHKeywords.Set_Cwd ${root_dir}/src/main/yang - SSHKeywords.Execute_Command_At_Cwd_Should_Pass git checkout -b ytest ${YANGMODELS_REPO_COMMIT_HASH} stderr_must_be_empty=False + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... git checkout -b ytest ${YANGMODELS_REPO_COMMIT_HASH} + ... stderr_must_be_empty=False SSHKeywords.Set_Cwd ${root_dir}/src/main/yang/experimental SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -rf openconfig SSHKeywords.Execute_Command_At_Cwd_Should_Pass git clone ${OPENCONFIG_REPO} stderr_must_be_empty=False SSHKeywords.Execute_Command_At_Cwd_Should_Pass mv -v public openconfig SSHKeywords.Set_Cwd ${root_dir}/src/main/yang/experimental/openconfig - SSHKeywords.Execute_Command_At_Cwd_Should_Pass git checkout -b ytest ${OPENCONFIG_REPO_COMMIT_HASH} stderr_must_be_empty=False + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... git checkout -b ytest ${OPENCONFIG_REPO_COMMIT_HASH} + ... stderr_must_be_empty=False SSHKeywords.Set_Cwd ${root_dir}/src/main/yang Delete_Static_Paths @@ -119,446 +131,651 @@ Delete_Static_Paths ## DESCRIPTION is not valid substatement for OUTPUT, https://tools.ietf.org/html/rfc6020#section-7.13.3.1 SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/@2015-03-09.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/l3-unicast-igp-topology@2015-06-08.yang - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/abstract-topology@2014-07-01.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/abstract-topology@2014-07-01.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/alto-service-types@2015-03-22.yang (module alto-service-types) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/alto-service@2015-03-22.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/alto-service@2015-03-22.yang ## missing closing bracket '}' at the end of module - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/alto-service-types@2015-03-22.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/alto-service-types@2015-03-22.yang ## excluded depndency file cisco from test, (module SNMP-FRAMEWORK-MIB) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/BATTERY-MIB@2015-06-15.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/BATTERY-MIB@2015-06-15.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/bfd.yang (module bfd) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/bfd-routing-app@2015-02-14.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/bfd-routing-app@2015-02-14.yang ## missing key-stmt separator after 'key' on line 707 SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/bfd.yang ## REQUIRE_INSTANCE may be used with instance identifier https://tools.ietf.org/html/rfc6020#section-9.13.2 ## was used with type leafref on line 415 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/bgp@2015-05-15.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/bgp@2015-05-15.yang ## exluded dependency file from test experimental/ietf-extracted-YANG-modules/bgp@2015-05-15.yang, (module bgp) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/bgp-l3vpn@2015-10-15.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/bgp-l3vpn@2015-10-15.yang ## REQUIRE_INSTANCE can be used only with instance identifier, https://tools.ietf.org/html/rfc6020#section-9.13.2 ## was used with element type leafref on line 126 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/bgp-policy@2015-05-15.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/bgp-policy@2015-05-15.yang ## missing prefix acl definition, https://tools.ietf.org/html/rfc6020#section-6.4 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/cira-shg-mud@2019-07-08.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/cira-shg-mud@2019-07-08.yang ## missing dependency module ieee-types, nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/dot1q-tag-types@2016-07-08.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/dot1q-tag-types@2016-07-08.yang ## removed dependency file from test draft-gonzalez-netmod-5277-00@2016-03-20.yang, (module draft-gonzalez-netmod-5277-00) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/draft-gonzalez-netconf-5277bis-00@2016-03-20.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/draft-gonzalez-netconf-5277bis-00@2016-03-20.yang ## xpath wrong comparison operator, used '==', should be '=' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/draft-gonzalez-netmod-5277-00@2016-03-20.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/draft-gonzalez-netmod-5277-00@2016-03-20.yang ## wrong position of typedef dbm-t description, outside '{}' brackets - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/draft-ietf-ccamp-dwdm-if-param-yang-03@2020-03-09.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/draft-ietf-ccamp-dwdm-if-param-yang-03@2020-03-09.yang ## Mount points may only be defined at either a container or a list, not case, lines 212,.. ## https://tools.ietf.org/html/rfc8528#section-3.1 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/example-5g-core-network@2017-12-28.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/example-5g-core-network@2017-12-28.yang ## non existing augmention path "/rt:routing/rt:routing-tables/rt:routing-table..." - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/example-rip@2012-10-04.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/example-rip@2012-10-04.yang ## removed dependecy removed file from test experimental/ietf-extracted-YANG-modules/transitions@2016-03-15.yang (module transitions) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/finite-state-machine@2016-03-15.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/finite-state-machine@2016-03-15.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/dot1q-tag-types@2016-07-08.yang (module dot1q-tag-types) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/flexible-encapsulation@2015-10-19.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/flexible-encapsulation@2015-10-19.yang ## path is not allowed to contain new line character, https://tools.ietf.org/html/rfc6020#section-12 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/flexi-grid-TED@2015-07-01.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/flexi-grid-TED@2015-07-01.yang ## not ended type-stm (missing statend character), https://tools.ietf.org/html/rfc6020#section-12 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/gen-oam@2014-10-23.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/gen-oam@2014-10-23.yang ## missing dependecy yang-types, nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/hardware-entities.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/hardware-entities.yang ## on line 9, multistring contact, should be only single string https://tools.ietf.org/html/rfc6020#section-12 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/huawei-dhcp@2014-12-18.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/huawei-dhcp@2014-12-18.yang ## missing namespace, https://tools.ietf.org/html/rfc6020#section-7.1 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/huawei-ipte@2014-08-13.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/huawei-ipte@2014-08-13.yang ## missing stmtend character ';' after description on line 707 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/i2rs-rib@2015-04-03.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/i2rs-rib@2015-04-03.yang ## missing stmtend at the end of descriptions, https://tools.ietf.org/html/rfc6020#section-12 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/i2rs-service-topology@2015-07-07.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/i2rs-service-topology@2015-07-07.yang ## removed dependecy file from test experimental/ietf-extracted-YANG-modules/ietf-location@2014-05-08.yang, (module ietf-location) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/iana-civic-address-type@2014-05-08.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/iana-civic-address-type@2014-05-08.yang ## unescaped single quoate "'" character inside a quaoted text on line 59 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/iana-geo-uri-type@2014-05-08.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/iana-geo-uri-type@2014-05-08.yang ## wrong augment path node 'interfaces-state', not avaibale, used 'interfaces' inside eth-if - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ieee802-pse@2017-03-02.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ieee802-pse@2017-03-02.yang ## xpath wrong comparison operator, used '==', should be '=' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-5277-netmod@2016-06-15.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-5277-netmod@2016-06-15.yang ## dependency node access-control-list-ipv4-header-fields can not be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-acl@2015-03-04.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-acl@2015-03-04.yang ## newer revisions do not use access-list-entries node, only standard/ietf/DRAFT/ietf-access-control-list.yang - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-acl-dnsname@2016-01-14.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-acl-dnsname@2016-01-14.yang ## dependency node asymmetric-key-algorithm-t can not be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ambi@2019-08-25.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ambi@2019-08-25.yang ## missing dependency node 'lsps-state' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bfd-mpls-te@2018-08-01.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bfd-mpls-te@2018-08-01.yang ## missing dependency module ietf-bgp of revision 2016-01-06, avaibale only newer 2020-06-28 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bgp-extensions@2016-07-08.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bgp-extensions@2016-07-08.yang ## augmenting idnetity 'bgp' instead of container 'bgp', both have same identifier - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bgp-l3vpn@2018-04-17.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bgp-l3vpn@2018-04-17.yang ## missing depndency node 'policy-statements' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bgp-policy@2020-06-28.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bgp-policy@2020-06-28.yang ## uses missing grouping node 'bgp-extended-community-attr-state', https://tools.ietf.org/html/rfc6020#section-7.12 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bgp-rib-shared-attributes@2019-03-21.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bgp-rib-shared-attributes@2019-03-21.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-connectionless-oam@2017-09-06.yang - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bier-oam@2017-06-13.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bier-oam@2017-06-13.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-connectionless-oam-methods@2017-09-06.yang (module ietf-connectionless-oam-methods) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bier-rpcs@2018-08-28.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-bier-rpcs@2018-08-28.yang ## can not be found dependency node 'pinned-domain-cert' in refine path - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-brski-possession@2018-10-11.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-brski-possession@2018-10-11.yang ## Mount points may only be defined at either a container or a list, not anydata, line 790 ## https://tools.ietf.org/html/rfc8528#section-3.1 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-connectionless-oam@2017-09-06.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-connectionless-oam@2017-09-06.yang ## excluded dependency file from test standard/ietf/RFC/ietf-connectionless-oam@2019-04-16.yang (module ietf-connectionless-oam) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-connectionless-oam-methods@2017-09-06.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-connectionless-oam-methods@2017-09-06.yang ## excluded dependecy file from test experimental/ietf-extracted-YANG-modules/ietf-notification-capabilities@2020-03-23.yang (module ietf-notification-capabilities) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-data-export-capabilities.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-data-export-capabilities.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-diffserv-classifier@2015-04-07.yang (module ietf-diffserv-classifier) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-diffserv-action@2015-04-07.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-diffserv-action@2015-04-07.yang ## xpath wrong comparison operator, used '==', should be '=', line 288 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-diffserv-classifier@2015-04-07.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-diffserv-classifier@2015-04-07.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-diffserv-classifier@2015-04-07.yang (module ietf-diffserv-classifier) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-diffserv-policy@2015-04-07.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-diffserv-policy@2015-04-07.yang ## Duplicate identity definition, both define event-type - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dmm-fpc-base@2017-03-08.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dmm-fpc-base@2017-03-08.yang ## missing module ietf-dmm-fpc of revision-date 2017-03-08, found only newer - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dmm-fpc-pmip@2017-03-08.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dmm-fpc-pmip@2017-03-08.yang ## missing module ietf-dmm-fpc of revision-date 2017-03-08, found only newer - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dmm-fpc-policyext@2017-03-08.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dmm-fpc-policyext@2017-03-08.yang ## missing module ietf-dmm-fpc of revision-date 2017-03-08, found only newer - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dmm-threegpp@2017-03-08.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dmm-threegpp@2017-03-08.yang ## newer verions of ietf-access-control-list do not use node 'access-lists', augmented in this file - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dots-access-control-list@2017-11-29.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dots-access-control-list@2017-11-29.yang ## sx:structure should be augmented by 'sx:augment-structure' not by oridnary 'augment' ## https://tools.ietf.org/html/rfc6020#section-7.15 ## newer dependency ietf-dots-signal-channel uses sx:structure not container anymore - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dots-signal-call-home@2018-09-28.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dots-signal-call-home@2018-09-28.yang ## sx:structure should be augmented by 'sx:augment-structure' not by oridnary 'augment' ## https://tools.ietf.org/html/rfc6020#section-7.15 ## newer dependency ietf-dots-signal-channel uses sx:structure not container anymore - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dots-signal-control@2019-05-13.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dots-signal-control@2019-05-13.yang ## sx:structure should be augmented by 'sx:augment-structure' not by oridnary 'augment' ## https://tools.ietf.org/html/rfc6020#section-7.15 ## newer dependency ietf-dots-signal-channel uses sx:structure not container anymore - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dots-signal-control-filter@2019-02-15.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-dots-signal-control-filter@2019-02-15.yang ## derived-from-or-self takes 2 arguments, https://tools.ietf.org/html/rfc7950#section-10.4.1 ## used: derived-from-or-self(../class, "iana-entity", "sensor") - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-entity@2016-05-13.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-entity@2016-05-13.yang ## missing dependecy 'frequency-thz', cannot be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ext-xponder-wdm-if@2020-03-09.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ext-xponder-wdm-if@2020-03-09.yang ## missing dependency module with proper revision 2016-09-29, ## found in experimental/ietf-extracted-YANG-modules/ietf-fabric-types@2017-11-29.yang ## but constains also newer revision 2017-11-29, https://tools.ietf.org/html/rfc6020#section-7.1.5.1 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-fabric-capable-device@2016-09-29.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-fabric-capable-device@2016-09-29.yang ## missing dependency module with proper revision 2016-10-13, ## found in experimental/ietf-extracted-YANG-modules/ietf-fabric-types@2017-11-29.yang ## but constains also newer revision 2017-11-29, https://tools.ietf.org/html/rfc6020#section-7.1.5.1 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-fabric-endpoint@2017-06-29.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-fabric-endpoint@2017-06-29.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-fabric-service-types@2017-08-30.yang (module ietf-fabric-service-types) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-fabric-service@2017-08-30.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-fabric-service@2017-08-30.yang ## missing dependency module with proper revision 2016-09-29, ## found in experimental/ietf-extracted-YANG-modules/ietf-fabric-types@2017-11-29.yang - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-fabric-service-types@2017-08-30.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-fabric-service-types@2017-08-30.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-fb-rib-types@2017-03-13.yang (moduel ietf-fb-rib-types) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-fb-rib@2017-03-13.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-fb-rib@2017-03-13.yang ## missing dependency module ietf-access-control-lists, nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-fb-rib-types@2017-03-13.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-fb-rib-types@2017-03-13.yang ## wrong augment path, missing node sr:segment-routing, on line 265 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-flex-algo@2019-04-26.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-flex-algo@2019-04-26.yang ## Referenced base identity 'fec-type' doesn't exist in given scope module ietf-layer0-types - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-flex-grid-media-channel@2018-10-22.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-flex-grid-media-channel@2018-10-22.yang ## missing dependency node 'layer0-node-type', nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-flex-grid-topology@2018-10-22.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-flex-grid-topology@2018-10-22.yang ## Referenced base identity 'fec-type' doesn't exist in given scope module ietf-layer0-types - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-flexi-grid-media-channel@2019-03-24.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-flexi-grid-media-channel@2019-03-24.yang ## description for response list is put outside the scope of list, line 1141 ## list is enclosed with closing bracket '}', comment should be put before it - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-gen-oam@2015-04-09.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-gen-oam@2015-04-09.yang ## missing ending quoate cahracter '"' at teh end of description on line 29 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-gen-oam-ais@2016-06-25.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-gen-oam-ais@2016-06-25.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-gen-oam-ais@2016-06-25.yang (module ietf-gen-oam) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-gen-oam-pm@2015-01-07.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-gen-oam-pm@2015-01-07.yang ## xpath wrong comparison operator, used '==', should be '=', on line 70 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-gre@2015-07-02.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-gre@2015-07-02.yang ## referenced element routing-instance-ref can be found only in cisco yangs, which are excluded from the test - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-gre-tunnel@2015-10-13.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-gre-tunnel@2015-10-13.yang ## missing dependecy node 'inline-address', nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-http-subscribed-notifications@2018-06-11.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-http-subscribed-notifications@2018-06-11.yang ## unable to found dependency node 'ietf-routing:routing-instance-ref' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ipipv4-tunnel-02@2015-10-15.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ipipv4-tunnel-02@2015-10-15.yang ## referenced node routing-instance-ref can be found only in cisco yangs, which are excluded from test - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ipipv4-tunnel@2015-10-14.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ipipv4-tunnel@2015-10-14.yang ## missing base to type identityref on line 254, https://tools.ietf.org/html/rfc6020#section-9.10.2 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ip-tunnel@2016-06-20.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ip-tunnel@2016-06-20.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-ipv6-unicast-routing-2@2017-10-06.yang (module ietf-ipv6-unicast-routing-2 to which it belongs) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ipv6-router-advertisements-2@2017-10-05.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ipv6-router-advertisements-2@2017-10-05.yang ## missing dependency submodule ietf-ipv6-router-advertisements-2, revision 2017-10-06 ## found revision 2017-10-05 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ipv6-unicast-routing-2@2017-10-06.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ipv6-unicast-routing-2@2017-10-06.yang ## missing dependecy node 'ietf-routing:routing-instance', nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-isis-bfd@2015-11-18.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-isis-bfd@2015-11-18.yang ## missing augment target "l2vpn:l2vpn-state" in only l2vpn module, experimental/ietf-extracted-YANG-modules/ietf-l2vpn@2019-05-28.yang - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-l2vpn-igmp-mld-snooping@2017-03-13.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-l2vpn-igmp-mld-snooping@2017-03-13.yang ## excluded dependency file from test ietf-l3vpn-ntw@2020-10-16.yang, (module ietf-l3vpn-ntw) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-l3nm-te-service-mapping@2020-11-02.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-l3nm-te-service-mapping@2020-11-02.yang ## missing dependecy node 'ietf-routing:routing-instance', nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-l3vpn@2015-10-09.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-l3vpn@2015-10-09.yang ## choice cannot be substatement to choice, https://tools.ietf.org/html/rfc6020#section-7.9.1 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-l3vpn-ntw@2020-10-16.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-l3vpn-ntw@2020-10-16.yang ## can not use 'uses' to reference container, only grouping on line 37, https://tools.ietf.org/html/rfc6020#section-7.12 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-library-tags@2017-08-12.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-library-tags@2017-08-12.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-gen-oam@2015-04-09.yang, (module ietf-gen-oam) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-lime-bfd-extension@2014-08-30.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-lime-bfd-extension@2014-08-30.yang ## missing dependency node 'lisp-router-instances' to be augmented - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-lisp-petr@2016-06-30.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-lisp-petr@2016-06-30.yang ## missing dependency node 'lisp-router-instances' to be augmented - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-lisp-pitr@2016-06-30.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-lisp-pitr@2016-06-30.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/iana-civic-address-type@2014-05-08.yang, (module iana-civic-address-type) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-location@2014-05-08.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-location@2014-05-08.yang ## wrong augment path, missing node 'rt:control-plane-protocol', line 284 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-mldp@2018-10-22.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-mldp@2018-10-22.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-mpls-mldp@2018-10-22.yang, (module ietf-mpls-mldp@2018-10-22.yang) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-mldp-extended@2018-10-22.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-mldp-extended@2018-10-22.yang ## multiline path-arg , https://tools.ietf.org/html/rfc6020#section-12 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-te@2014-11-06.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-te@2014-11-06.yang ## multiline namespace, https://tools.ietf.org/html/rfc3986#appendix-A - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-te-global@2014-10-13.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-te-global@2014-10-13.yang ## missing prefix for module ietf-mpls-te-link - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-te-links@2014-10-13.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-te-links@2014-10-13.yang ## missing prefix for module ietf-mpls-te-lsps - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-te-lsps@2014-10-13.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-te-lsps@2014-10-13.yang ## multiline namespace, https://tools.ietf.org/html/rfc3986#appendix-A - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-te-tunnel-ifs@2014-10-13.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-te-tunnel-ifs@2014-10-13.yang ## augment-arg node identifier can not contain new line character, https://tools.ietf.org/html/rfc6020#section-6.2 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-tp-topology@2019-03-11.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-tp-topology@2019-03-11.yang ## missing dependency node 'path-computed-route-object', can not be found anywhere - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-tp-tunnel@2019-03-11.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mpls-tp-tunnel@2019-03-11.yang ## missing prefix acl definition, https://tools.ietf.org/html/rfc6020#section-6.4 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mud-quarantine@2019-12-27.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mud-quarantine@2019-12-27.yang ## used same identifier multiple times (frr on lines 276, 300 ), https://tools.ietf.org/html/rfc6020#section-6.2.1 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-multicast-service@2016-02-29.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-multicast-service@2016-02-29.yang ## excluded depndency file from test experimental/ietf-extracted-YANG-modules/ietf-bgp-l3vpn@2018-04-17.yang (module ietf-bgp-l3vpn) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mvpn@2019-12-02.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-mvpn@2019-12-02.yang ## required dependency module yuma-netconf, could not be found anywhere - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-netconf-error-parameters@2013-07-11.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-netconf-error-parameters@2013-07-11.yang ## missing ending bracket '}' for mudule definition - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-netconf-light@2012-01-12.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-netconf-light@2012-01-12.yang ## depends on 'client-auth', which is missing in newer revision experimental/ietf-extracted-YANG-modules/ietf-tls-server@2020-08-20.yang - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-netconf-server-new@2015-07-06.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-netconf-server-new@2015-07-06.yang ## missing base elment inline-address, nowhere defined - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-netconf-subscribed-notifications@2018-08-03.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-netconf-subscribed-notifications@2018-08-03.yang ## can not perform refine of 'DEFAULT' for the target 'LEAF_LIST', refine of default can be performed only on leaf or choice, line 220 ## https://tools.ietf.org/html/rfc6020#section-7.12.2 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-notification-capabilities@2020-03-23.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-notification-capabilities@2020-03-23.yang ## excluded dependecy file from test, experimental/ietf-extracted-YANG-modules/ietf-bgp-l3vpn@2018-04-17.yang (module ietf-bgp-l3vpn) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-nvo3@2019-04-01.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-nvo3@2019-04-01.yang ## many excluded (deleted) dependencies from this test, for example cisco afi-safi - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-nvo3-base@2020-08-26.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-nvo3-base@2020-08-26.yang ## module ietf-te-topology does not contain node 'schedule' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-odu-topology@2016-07-07.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-odu-topology@2016-07-07.yang ## excluded dependency file experimental/ietf-extracted-YANG-modules/ietf-OPSAWG-ute-tunnel.yang, (module ietf-OPSAWG-ute-tunnel) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-OPSAWG-te-tunnel.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-OPSAWG-te-tunnel.yang ## unquoted descriptions with included whitespaces, https://tools.ietf.org/html/rfc6020#section-6.1.3 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-OPSAWG-ute-tunnel.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-OPSAWG-ute-tunnel.yang ## new line character inside identifier, https://tools.ietf.org/html/rfc6020#section-6.2 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-optical-impairment-topology@2019-05-22.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-optical-impairment-topology@2019-05-22.yang ## incorrect path in augmentation, extra parameter instance - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ospf-bfd@2016-10-31.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ospf-bfd@2016-10-31.yang ## incorrect path in augmentation, twice repeted same node 'extended-prefix-tlvs' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ospf-ppr@2019-07-07.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ospf-ppr@2019-07-07.yang ## missing augment path target node 'state' on line 192 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-otn-service@2016-06-24.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-otn-service@2016-06-24.yang ## missing dependency node 'path-computed-route-object', nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-otn-tunnel@2020-03-09.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-otn-tunnel@2020-03-09.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ieee802-pse@2017-03-02.yang, (module ieee802-pse) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-poe-power-management@2017-03-09.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-poe-power-management@2017-03-09.yang ## MUST is not valid substatement for CASE, https://tools.ietf.org/html/rfc7950#section-7.9.2.1 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-qos@2016-10-20.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-qos@2016-10-20.yang ## excluded dependecy file from test experimental/ietf-extracted-YANG-modules/ietf-tpm-remote-attestation@2020-03-09.yang, (module ietf-tpm-remote-attestation) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-rats-attestation-stream@2020-03-06.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-rats-attestation-stream@2020-03-06.yang ## unable to find module ietf-restconf with revision-date 2015-01-30 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-restconf-collection@2015-01-30.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-restconf-collection@2015-01-30.yang ## multiline namespace name with end of line escaped with '\' character - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-restconf-list-pagination@2015-01-30.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-restconf-list-pagination@2015-01-30.yang ## cannot find node 'client-auth' inside 'tls-server-grouping' in ietf-tls-server, line 337 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-restconf-server-new@2015-07-06.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-restconf-server-new@2015-07-06.yang ## missing intermediary node 'key-chain' in augmention path on line 82 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-rfc7210@2015-03-09.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-rfc7210@2015-03-09.yang ## non unique identifire (repair-path used as grouping and also as container) ## https://tools.ietf.org/html/rfc6020#section-6.2.1 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-rib-extension@2020-09-18.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-rib-extension@2020-09-18.yang ## missing dependency node 'rsvp:session-attributes-state' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-rsvp-te@2020-03-09.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-rsvp-te@2020-03-09.yang ## missing dependency node 'lsps-state' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-rsvp-te-mpls@2020-03-09.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-rsvp-te-mpls@2020-03-09.yang ## augmenting identity rsvp instead of container, https://tools.ietf.org/html/rfc6020#section-7.15 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-rsvp-te-psc@2015-10-16.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-rsvp-te-psc@2015-10-16.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-yang-packages@2020-01-21.yang, (module ietf-yang-packages) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-schema-selection@2020-02-29.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-schema-selection@2020-02-29.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-yl-packages@2020-01-21.yang, (module ietf-yl-packages) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-schema-version-selection@2019-10-31.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-schema-version-selection@2019-10-31.yang ## unpaired, extra end of myltiline comment '*/' without start - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-sd-onos-service-l3vpn@2015-12-16.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-sd-onos-service-l3vpn@2015-12-16.yang ## same identifier 'qos-if-car' used for list and also for container, identifiers must be unique, https://tools.ietf.org/html/rfc6020#section-6.2.1 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-sd-onos-service-types@2015-12-16.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-sd-onos-service-types@2015-12-16.yang ## excluded depndency file from test experimental/ieee/1906.1/ieee1906-dot1-system.yang - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-service-pm@2020-07-13.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-service-pm@2020-07-13.yang ## excluded dependency file from test standard/ietf/RFC/ietf-connectionless-oam@2019-04-16.yang, (module ietf-connectionless-oam) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-sfc-oam@2016-11-21.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-sfc-oam@2016-11-21.yang ## multiline namespace, https://tools.ietf.org/html/rfc3986#appendix-A - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-supa-abstracted-l3vpn@2015-05-04.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-supa-abstracted-l3vpn@2015-05-04.yang ## missing closing bracket '}' for module - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-supa-ddc@2014-12-25.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-supa-ddc@2014-12-25.yang ## missing statment end ';' after 'when' statment on line 170, https://tools.ietf.org/html/rfc6020#section-12 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-supa-l3vpn@2015-02-04.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-supa-l3vpn@2015-02-04.yang ## missing module eca-policy-0910, nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-supa-service-flow@2015-08-05.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-supa-service-flow@2015-08-05.yang ## augmention path multiline, https://tools.ietf.org/html/rfc6020#section-6.2 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-supa-service-flow-policy@2015-10-10.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-supa-service-flow-policy@2015-10-10.yang ## missing dependency node private-key-grouping, nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-syslog@2018-03-15.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-syslog@2018-03-15.yang ## CHOICE is not valid for YANG_DATA, should only contain container substatement, https://tools.ietf.org/html/rfc8040#section-8 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-sztp-conveyed-info@2019-01-15.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-sztp-conveyed-info@2019-01-15.yang ## only a template file - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-template.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-template.yang ## missing augment target performance-metric-two-way, nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-te-mpls-types@2018-12-21.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-te-mpls-types@2018-12-21.yang ## uses missing node 'path-access-segment-info' from module ietf-te on line 519 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-te-path-computation@2019-03-11.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-te-path-computation@2019-03-11.yang ## augmention target 'te-link-event' is missing - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-te-topology-psc@2016-07-01.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-te-topology-psc@2016-07-01.yang ## missing dependency node 'resource-pool-attributes', nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-te-wson@2017-06-27.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-te-wson@2017-06-27.yang ## missing key node in list (key algo-registry-type not found in list), line 878 ##https://tools.ietf.org/html/rfc6020#section-7.8.2 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-tpm-remote-attestation@2020-03-09.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-tpm-remote-attestation@2020-03-09.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-gen-oam-ais@2016-06-25.yang (module ietf-gen-oam) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-trill-oam-pm@2015-01-11.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-trill-oam-pm@2015-01-11.yang ## missing refine node "cert", maybe should be used "cert-data" - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-trust-anchors@2019-04-29.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-trust-anchors@2019-04-29.yang ## missing dependency, module ieee-dot1Q-types, nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ucpe-ni-properties@2019-11-27.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-ucpe-ni-properties@2019-11-27.yang ## missing dependency module geo-location, nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-uses-geo-location@2019-02-02.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-uses-geo-location@2019-02-02.yang ## unable to find node 'routing-instance-ref' inside module 'ietf-routing' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-utunnel@2015-12-16.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-utunnel@2015-12-16.yang ## unable to find node 'bgp-parameters-grp' inside module 'ietf-evpn' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-vxlan@2018-08-29.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-vxlan@2018-08-29.yang ## missing dependency node 'path-computed-route-object', nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-wson-tunnel@2019-09-11.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-wson-tunnel@2019-09-11.yang ## missing type as substatement to annotation on line 66, https://tools.ietf.org/html/rfc7952#section-3 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-annotations@2014-11-28.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-annotations@2014-11-28.yang ## missing ending quoatation mark '"' for contact statment argument, line 22 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-hash@2016-02-10.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-hash@2016-02-10.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-yang-package-types@2020-01-21.yang, (module ietf-yang-package-types) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-inst-data-pkg@2020-01-21.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-inst-data-pkg@2020-01-21.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-yang-package-types@2020-01-21.yang, (module ietf-yang-package-types) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-library-packages@2018-11-26.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-library-packages@2018-11-26.yang ## WHEN is not valid for ANNOTATION, https://tools.ietf.org/html/rfc7952#section-3 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-opstate-metadata@2016-07-06.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-opstate-metadata@2016-07-06.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-yang-package-types@2020-01-21.yang, (module ietf-yang-package-types) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-package@2019-09-11.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-package@2019-09-11.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-yang-package-types@2020-01-21.yang, (module ietf-yang-package-types) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-package-instance@2020-01-21.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-package-instance@2020-01-21.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-yang-package-types@2020-01-21.yang, (module ietf-yang-package-types) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-packages@2020-01-21.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-packages@2020-01-21.yang ## missing depndency node 'name-revision', nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-package-types@2020-01-21.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-package-types@2020-01-21.yang ## missing closing and opening quoates, used concat symbol '+' inside string not to concat strings, line 95 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-push-ext@2019-02-01.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yang-push-ext@2019-02-01.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-yang-packages@2020-01-21.yang, (module ietf-yang-packages) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yl-packages@2020-01-21.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ietf-yl-packages@2020-01-21.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/dot1q-tag-types@2016-07-08.yang, (module dot1q-tag-types) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/if-l3-vlan@2015-10-19.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/if-l3-vlan@2015-10-19.yang ## derived-from-or-self takes 2 arguments, https://tools.ietf.org/html/rfc7950#section-10.4.1 ## used: derived-from(if:type, 'ietf-if-cmn', 'sub-interface'), line 353 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/interfaces-common@2015-10-19.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/interfaces-common@2015-10-19.yang ## incorrect prefix: prefix >"ct"y;< character 'y' after quatation, before stmtend on line 7 SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ipfix-psamp.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/l3-unicast-igp-topology@2015-06-08.yang, (module l3-unicast-igp-topology) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/isis-topology@2015-06-08.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/isis-topology@2015-06-08.yang ## skipped container node 'networks' in augmentation on line 247 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/l3-unicast-igp-topology@2015-06-08.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/l3-unicast-igp-topology@2015-06-08.yang ## exluded dependency file experimental/ietf-extracted-YANG-modules/bgp@2015-05-15.yang, (module bgp) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/l3vpn@2014-08-15.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/l3vpn@2014-08-15.yang ##multiline path with '-' character at the end of first line - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/layer-one-topology@2015-02-11.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/layer-one-topology@2015-02-11.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/ietf-gen-oam-ais@2016-06-25.yang (module ietf-gen-oam) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/lime-bfd-extension@2014-08-30.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/lime-bfd-extension@2014-08-30.yang ## unable to find type structural-mount - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/logical-network-element@2016-01-19.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/logical-network-element@2016-01-19.yang ## two string sperated by character ';' belonging to one contact statement SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/lora.yang ## whitespace in URI, are not allowed by ABNF for URI https://tools.ietf.org/html/rfc3986#page-49 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/media-channel@2014-06-05.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/media-channel@2014-06-05.yang ## excluded dependecy file from test experimental/ietf-extracted-YANG-modules/mpls-rsvp@2015-04-22.yang, (module mpls-rsvp) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/mpls@2014-12-12.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/mpls@2014-12-12.yang ## excluded dependecy file from test experimental/ietf-extracted-YANG-modules/mpls-rsvp@2015-04-22.yang, (module mpls-rsvp) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/mpls-igp@2014-07-07.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/mpls-igp@2014-07-07.yang ## missing closing bracket '}' at the end of module - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/mpls-rsvp@2015-04-22.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/mpls-rsvp@2015-04-22.yang ## excluded dependecy file from test experimental/ietf-extracted-YANG-modules/mpls-rsvp@2015-04-22.yang, (module mpls-rsvp) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/mpls-static@2015-02-01.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/mpls-static@2015-02-01.yang ## missing closing bracket '}' at the end of module, commented - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/mpls-te@2014-07-07.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/mpls-te@2014-07-07.yang ## unable to find type structural-mount - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/networking-instance@2016-01-20.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/networking-instance@2016-01-20.yang ## missiing type schema-mount, nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/network-instance@2016-02-22.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/network-instance@2016-02-22.yang ## missing dependency module nodes, nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/network-topology@2014-12-11.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/network-topology@2014-12-11.yang ## missing dependency file experimental/ietf-extracted-YANG-modules/gen-oam@2014-10-23.yang, (module gen-oam) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/nvo3-oam@2014-04-24.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/nvo3-oam@2014-04-24.yang ## REQUIRE_INSTANCE is not valid for TYPE, MAY be present if the type is ## "instance-identifier", https://tools.ietf.org/html/rfc6020#section-9.13.2 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/openconfig-mpls@2015-10-14.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/openconfig-mpls@2015-10-14.yang ## node 'igp-lsp-sr-setup' can not be found in module openconfig-mpls-sr from opencofig repository - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/openconfig-mpls-igp@2015-07-04.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/openconfig-mpls-igp@2015-07-04.yang ## missing closing bracket '}' for module - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/openconfig-mpls-rsvp@2015-09-18.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/openconfig-mpls-rsvp@2015-09-18.yang ## missing dependency node 'protection-type' cannot be found inside module 'openconfig-mpls-types' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/openconfig-mpls-te@2015-10-04.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/openconfig-mpls-te@2015-10-04.yang ## missing dependency node network-instance-type, newer version of opencofig, does not support it - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/openconfig-network-instance@2015-10-18.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/openconfig-network-instance@2015-10-18.yang ## wrong pattern on line 91, missing opening bracket '(' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/openconfig-network-instance-types@2015-10-18.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/openconfig-network-instance-types@2015-10-18.yang ## missing dependency node routing-instance-ref, can not be found inside module ietf-routing - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ospf@2014-09-17.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ospf@2014-09-17.yang ## excluded dependency file experimental/ietf-extracted-YANG-modules/l3-unicast-igp-topology@2015-06-08.yang, (module l3-unicast-igp-topology) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/ospf-topology@2015-06-08.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/ospf-topology@2015-06-08.yang ## TYPE is not valid for LIST, line 136 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/pbbevpn@2015-03-06.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/pbbevpn@2015-03-06.yang ## dependency module service-function-scheduler-type, nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/rendered-service-path@2014-07-01.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/rendered-service-path@2014-07-01.yang ## incorrect revision date format on line 38, https://tools.ietf.org/html/rfc6020#section-7.1.9 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/service-function@2014-29-04.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/service-function@2014-29-04.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/service-function@2014-29-04.yang, (module service-function) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/service-function-chain@2014-07-01.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/service-function-chain@2014-07-01.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/service-function@2014-29-04.yang, (module service-function) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/service-function-description-monitor@2014-12-01.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/service-function-description-monitor@2014-12-01.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/service-function@2014-29-04.yang, (module service-function) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/service-function-path@2014-07-01.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/service-function-path@2014-07-01.yang ## excluded dependency file from test experimental/ietf-extracted-YANG-modules/service-function@2014-29-04.yang, (module service-function) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/service-node@2014-07-01.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/service-node@2014-07-01.yang ## missing dependency file from test experimental/ietf-extracted-YANG-modules/gen-oam@2014-10-23.yang, (module gen-oam) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/sfc-oam@2014-09-04.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/sfc-oam@2014-09-04.yang ## Maximal count of CONTACT for MODULE is 1, detected 2, https://tools.ietf.org/html/rfc6020#section-7.1.1 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/sff-topology.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/sff-topology.yang ## missing closing bracket '}', probably for 'leaf active' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/softwire@2014-12-14.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/softwire@2014-12-14.yang ## missing dependency module inet-types, nowhere to be found - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/TCP-MIB@2005-02-18.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/TCP-MIB@2005-02-18.yang ## unable to find node datatree-filter inside module ietf-yang-push - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/transitions@2016-03-15.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/transitions@2016-03-15.yang ## missing dependency file experimental/ietf-extracted-YANG-modules/gen-oam@2014-10-23.yang, (module gen-oam) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/trill-oam@2014-04-16.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/trill-oam@2014-04-16.yang ## missing statment-end after comment on line 484, (missing ';' after comment) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/TUDA-V1-ATTESTATION-MIB@2017-10-30.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/TUDA-V1-ATTESTATION-MIB@2017-10-30.yang ## exluded dependency file from test experimental/ietf-extracted-YANG-modules/bgp@2015-05-15.yang, (module bgp) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/tunnel-management@2015-01-12.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/tunnel-management@2015-01-12.yang ## missing module closing brackte '}' - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/tunnel-policy@2018-09-15.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/tunnel-policy@2018-09-15.yang ## missing dependency module yang-types, nowhere to be found SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/udmcore.yang ## referenced node routing-instance-ref can be found only in cisco yangs, which are excluded from test - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/utunnel@2015-07-05.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/utunnel@2015-07-05.yang ## empty path argument, https://tools.ietf.org/html/rfc6020#section-9.9.2 - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf-extracted-YANG-modules/virtualizer@2016-02-24.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/ietf-extracted-YANG-modules/virtualizer@2016-02-24.yang ## missing dependency node 'private-key-grouping', nowhere to be found SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/ietf/SYSLOG-MODEL/ietf-syslog.yang ## missing dependency module config, nowhere to be found @@ -580,7 +797,8 @@ Delete_Static_Paths ## missing dependency module config, nowhere to be found SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/odp/toaster-provider.yang ## tries to deviate itself - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/openconfig/release/models/wifi/openconfig-ap-interfaces.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf experimental/openconfig/release/models/wifi/openconfig-ap-interfaces.yang ## dependency module Cisco-IOS-XR-types is avaible only in excluded cisco yangs SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf experimental/vendor/cisco/common/cisco-link-oam.yang ## excluded dependency file from test standard/ieee/draft/1906.1/ieee1906-dot1-properties.yang, (module ieee1906-dot1-properties) @@ -607,7 +825,8 @@ Delete_Static_Paths SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf standard/ieee/draft/802.1/Qcw/ieee802-types.yang ## depends on a specific node dot1q-types:transmission-selection-algorithm ## which most revision does not use, only Qcz version - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf standard/ieee/draft/802.1/Qcz/ieee802-dot1q-lldp-dcbx-tlv.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf standard/ieee/draft/802.1/Qcz/ieee802-dot1q-lldp-dcbx-tlv.yang ## dependency node 'data-resource-identifier' can not be found in module ietf-restconf SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf standard/ietf/DRAFT/example-jukebox.yang ## dependency node 'metadata' only avaible in older revision of module ietf-packet-fields @@ -641,7 +860,8 @@ Delete_Static_Paths ## https://tools.ietf.org/html/rfc8528#section-3.1 SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf standard/ietf/RFC/ietf-connectionless-oam@2019-04-16.yang ## removed depndency file from test standard/ietf/RFC/ietf-connectionless-oam@2019-04-16.yang (module ietf-connectionless-oam) - SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf standard/ietf/RFC/ietf-connectionless-oam-methods@2019-04-16.yang + SSHKeywords.Execute_Command_At_Cwd_Should_Pass + ... rm -vrf standard/ietf/RFC/ietf-connectionless-oam-methods@2019-04-16.yang ## removed dependecy file from test standard/ietf/RFC/ietf-connectionless-oam-methods@2019-04-16.yang SSHKeywords.Execute_Command_At_Cwd_Should_Pass rm -vrf standard/ietf/RFC/ietf-connectionless-oam-methods.yang ## removed dependency file from test standard/ietf/RFC/ietf-connectionless-oam@2019-04-16.yang diff --git a/csit/libraries/YangmanKeywords.robot b/csit/libraries/YangmanKeywords.robot index 715426a168..ef32ec0347 100644 --- a/csit/libraries/YangmanKeywords.robot +++ b/csit/libraries/YangmanKeywords.robot @@ -1,11 +1,13 @@ *** Settings *** -Documentation A resource file containing all global keywords to help -... Yangman GUI and functional testing. -Library Collections -Library Selenium2Library timeout=30 implicit_wait=30 run_on_failure=Selenium2Library.Log Source -Resource ../variables/Variables.robot -Resource GUIKeywords.robot -Resource ../variables/YangmanGUIVariables.robot +Documentation A resource file containing all global keywords to help +... Yangman GUI and functional testing. + +Library Collections +Library Selenium2Library timeout=30 implicit_wait=30 run_on_failure=Selenium2Library.Log Source +Resource ../variables/Variables.robot +Resource GUIKeywords.robot +Resource ../variables/YangmanGUIVariables.robot + *** Keywords *** Open DLUX And Login And Navigate To Yangman URL @@ -16,12 +18,12 @@ Open DLUX And Login And Navigate To Yangman URL Return List Of Operation IDs [Documentation] Returns list of IDs of Get, Put, Post and Delete options in expanded operation select menu. ${list}= BuiltIn.Create List ${GET_OPTION} ${PUT_OPTION} ${POST_OPTION} ${DELETE_OPTION} - [Return] ${list} + RETURN ${list} Return List Of Operation Names [Documentation] Returns list of operations names. ${list}= BuiltIn.Create List GET PUT POST DELETE - [Return] ${list} + RETURN ${list} Expand Operation Select Menu [Documentation] Clicks operation select menu to expand it. @@ -32,29 +34,39 @@ Exit Opened Application Dialog Selenium2Library.Click Element ${SELECT_BACKDROP} Select Operation - [Arguments] ${operation_id} [Documentation] Selects chosen operation from expanded operation select menu. - ${status}= BuiltIn.Run Keyword And Return Status GUIKeywords.Page Should Contain Element With Wait ${OPERATION_SELECT_MENU_EXPANDED} - BuiltIn.Run Keyword If "${status}"=="False" Expand Operation Select Menu ${OPERATION_SELECT_INPUT} + [Arguments] ${operation_id} + ${status}= BuiltIn.Run Keyword And Return Status + ... GUIKeywords.Page Should Contain Element With Wait + ... ${OPERATION_SELECT_MENU_EXPANDED} + IF "${status}"=="False" + Expand Operation Select Menu ${OPERATION_SELECT_INPUT} + END GUIKeywords.Focus And Click Element ${operation_id} Verify Selected Operation Is Displayed - [Arguments] ${selected_operation_name} [Documentation] Verifies that the selected operation is now displayed in collapsed operation select menu. - ${selected_operation_xpath}= BuiltIn.Set Variable ${OPERATION_SELECT_INPUT}//span/div[contains(text(), "${selected_operation_name}")] + [Arguments] ${selected_operation_name} + ${selected_operation_xpath}= BuiltIn.Set Variable + ... ${OPERATION_SELECT_INPUT}//span/div[contains(text(), "${selected_operation_name}")] GUIKeywords.Page Should Contain Element With Wait ${selected_operation_xpath} Select Operation And Verify Operation Has Been Selected - [Arguments] ${operation_id} ${selected_operation_name} [Documentation] Selects chosen operation from expanded operation select menu and verifies the operation has been selected. - ${status}= BuiltIn.Run Keyword And Return Status GUIKeywords.Page Should Contain Element With Wait ${OPERATION_SELECT_MENU_EXPANDED} - BuiltIn.Run Keyword If "${status}"=="False" Expand Operation Select Menu ${OPERATION_SELECT_INPUT} - ${selected_operation_xpath}= BuiltIn.Set Variable ${OPERATION_SELECT_INPUT}//span/div[contains(text(), "${selected_operation_name}")] + [Arguments] ${operation_id} ${selected_operation_name} + ${status}= BuiltIn.Run Keyword And Return Status + ... GUIKeywords.Page Should Contain Element With Wait + ... ${OPERATION_SELECT_MENU_EXPANDED} + IF "${status}"=="False" + Expand Operation Select Menu ${OPERATION_SELECT_INPUT} + END + ${selected_operation_xpath}= BuiltIn.Set Variable + ... ${OPERATION_SELECT_INPUT}//span/div[contains(text(), "${selected_operation_name}")] GUIKeywords.Patient Click ${operation_id} ${selected_operation_xpath} Expand Operation Select Menu And Select Operation - [Arguments] ${operation_id} ${selected_operation_name} [Documentation] Expands operation select menu and select operation provided as an argument. + [Arguments] ${operation_id} ${selected_operation_name} Expand Operation Select Menu Select Operation And Verify Operation Has Been Selected ${operation_id} ${selected_operation_name} @@ -64,9 +76,13 @@ Send Request Selenium2Library.Wait Until Page Contains Element ${HEADER_LINEAR_PROGRESSION_BAR_HIDDEN} Verify Request Status Code Matches Desired Code - [Arguments] ${desired_code_regexp} [Documentation] Verifies that execution status code matches regexp provided as an argument. - ${request_status}= BuiltIn.Wait Until Keyword Succeeds 30 s 5 s Selenium2Library.Get Text ${STATUS_VALUE} + [Arguments] ${desired_code_regexp} + ${request_status}= BuiltIn.Wait Until Keyword Succeeds + ... 30 s + ... 5 s + ... Selenium2Library.Get Text + ... ${STATUS_VALUE} BuiltIn.Should Match Regexp ${request_status} ${desired_code_regexp} Verify Request Execution Time Is Present @@ -80,36 +96,47 @@ Verify Request Execution Time Is Threedots BuiltIn.Should Contain ${time_value} ${THREE_DOTS_DEFAULT_STATUS_AND_TIME} Send Request And Verify Request Status Code Matches Desired Code - [Arguments] ${desired_code_regexp} [Documentation] Sends request and verifies that execution status code matches regexp provided as an argument. + [Arguments] ${desired_code_regexp} Send Request Verify Request Status Code Matches Desired Code ${desired_code_regexp} Verify Request Execution Time Is Present Execute Chosen Operation From Form - [Arguments] ${operation_id} ${selected_operation_name} ${selected_true_false} [Documentation] Selects operation, selects or unselects fill form with received data after execution checkbox. + [Arguments] ${operation_id} ${selected_operation_name} ${selected_true_false} Expand Operation Select Menu And Select Operation ${operation_id} ${selected_operation_name} Select Fill Form With Received Data After Execution Checkbox ${selected_true_false} Send Request Execute Chosen Operation From Form And Check Status Code - [Arguments] ${operation_id} ${selected_operation_name} ${selected_true_false} ${desired_code_regexp} [Documentation] Selects operation, selects or unselects fill form with received data after execution checkbox and ... verifies that execution status matches regexp provided as an argument. + [Arguments] ${operation_id} ${selected_operation_name} ${selected_true_false} ${desired_code_regexp} Expand Operation Select Menu And Select Operation ${operation_id} ${selected_operation_name} Select Fill Form With Received Data After Execution Checkbox ${selected_true_false} Send Request - BuiltIn.Run Keyword If "${desired_code_regexp}"=="${THREE_DOTS_DEFAULT_STATUS_AND_TIME}" BuiltIn.Run Keywords Verify Request Status Code Matches Desired Code ${THREE_DOTS_DEFAULT_STATUS_AND_TIME} - ... AND Verify Request Execution Time Is Threedots - BuiltIn.Run Keyword If "${desired_code_regexp}"!="${THREE_DOTS_DEFAULT_STATUS_AND_TIME}" BuiltIn.Run Keywords Verify Request Status Code Matches Desired Code ${desired_code_regexp} - ... AND Verify Request Execution Time Is Present + IF "${desired_code_regexp}"=="${THREE_DOTS_DEFAULT_STATUS_AND_TIME}" + BuiltIn.Run Keywords + ... Verify Request Status Code Matches Desired Code + ... ${THREE_DOTS_DEFAULT_STATUS_AND_TIME} + ... AND + ... Verify Request Execution Time Is Threedots + END + IF "${desired_code_regexp}"!="${THREE_DOTS_DEFAULT_STATUS_AND_TIME}" + BuiltIn.Run Keywords + ... Verify Request Status Code Matches Desired Code + ... ${desired_code_regexp} + ... AND + ... Verify Request Execution Time Is Present + END Return Labelled Api Path Input - [Arguments] ${branch_label_without_curly_braces_part} [Documentation] Returns Xpath of labelled API path input field. - ${labelled_api_path_input}= BuiltIn.Set Variable ${API_PATH}//span[contains(text(), "/${branch_label_without_curly_braces_part}")]//parent::md-input-container//following-sibling::md-input-container[last()]/input - [Return] ${labelled_api_path_input} + [Arguments] ${branch_label_without_curly_braces_part} + ${labelled_api_path_input}= BuiltIn.Set Variable + ... ${API_PATH}//span[contains(text(), "/${branch_label_without_curly_braces_part}")]//parent::md-input-container//following-sibling::md-input-container[last()]/input + RETURN ${labelled_api_path_input} Verify Yangman Home Page Elements [Documentation] Verifies presence of Yangman home page elements. @@ -134,13 +161,21 @@ Verify Yangman Home Page Elements Select Form View [Documentation] Click Form radiobutton to display form view. - ${status}= BuiltIn.Run Keyword And Return Status Selenium2Library.Page Should Contain Element ${FORM_RADIOBUTTON_SELECTED} - BuiltIn.Run Keyword If "${status}"=="False" GUIKeywords.Patient Click ${FORM_RADIOBUTTON_UNSELECTED} ${FORM_RADIOBUTTON_SELECTED} + ${status}= BuiltIn.Run Keyword And Return Status + ... Selenium2Library.Page Should Contain Element + ... ${FORM_RADIOBUTTON_SELECTED} + IF "${status}"=="False" + GUIKeywords.Patient Click ${FORM_RADIOBUTTON_UNSELECTED} ${FORM_RADIOBUTTON_SELECTED} + END Select Json View [Documentation] Click Json radiobutton to display json view. - ${status}= BuiltIn.Run Keyword And Return Status Selenium2Library.Page Should Contain Element ${JSON_RADIOBUTTON_SELECTED} - BuiltIn.Run Keyword If "${status}"=="False" GUIKeywords.Patient Click ${JSON_RADIOBUTTON_UNSELECTED} ${JSON_RADIOBUTTON_SELECTED} + ${status}= BuiltIn.Run Keyword And Return Status + ... Selenium2Library.Page Should Contain Element + ... ${JSON_RADIOBUTTON_SELECTED} + IF "${status}"=="False" + GUIKeywords.Patient Click ${JSON_RADIOBUTTON_UNSELECTED} ${JSON_RADIOBUTTON_SELECTED} + END Modules Tab Is Selected [Documentation] Verifies that module tab is selected and history and collection tabs are unselected. @@ -150,10 +185,10 @@ Modules Tab Is Selected Selenium2Library.Page Should Contain Element ${COLLECTIONS_TAB_UNSELECTED} Return Number Of Modules Loaded - [Arguments] ${module_xpath} [Documentation] Returns number of modules loaded in Modules tab. + [Arguments] ${module_xpath} ${number_of_modules}= Selenium2Library.Get Matching Xpath Count ${module_xpath} - [Return] ${number_of_modules} + RETURN ${number_of_modules} Verify Any Module Is Loaded [Documentation] Verifies that at least one module has been loaded in Modules tab. @@ -161,135 +196,151 @@ Verify Any Module Is Loaded BuiltIn.Should Be True ${number_of_modules_loaded}>0 Return Module List Indexed Module - [Arguments] ${index} [Documentation] Returns indexed Xpath of the module. ${index} is a number. + [Arguments] ${index} ${module_index}= BuiltIn.Set Variable ${MODULE_ID_LABEL}${index} - ${module_list_item_indexed}= BuiltIn.Set Variable ${MODULE_TAB_CONTENT}//md-list-item[@id="${module_index}"]//div[@class="pointer title layout-align-center-center layout-row"] - [Return] ${module_list_item_indexed} + ${module_list_item_indexed}= BuiltIn.Set Variable + ... ${MODULE_TAB_CONTENT}//md-list-item[@id="${module_index}"]//div[@class="pointer title layout-align-center-center layout-row"] + RETURN ${module_list_item_indexed} Return Indexed Module Operations Label - [Arguments] ${index} [Documentation] Returns Xpath of the indexed module's operations item in Modules tab. + [Arguments] ${index} ${module_list_item_indexed}= Return Module List Indexed Module ${index} - ${indexed_module_operations_label}= BuiltIn.Set Variable ${module_list_item_indexed}//following-sibling::md-list[@aria-hidden="false"]//p[contains(., "${OPERATIONS_LABEL}")] - [Return] ${indexed_module_operations_label} + ${indexed_module_operations_label}= BuiltIn.Set Variable + ... ${module_list_item_indexed}//following-sibling::md-list[@aria-hidden="false"]//p[contains(., "${OPERATIONS_LABEL}")] + RETURN ${indexed_module_operations_label} Return Indexed Module Operational Label - [Arguments] ${index} [Documentation] Returns Xpath of the indexed module`s operational in Modules tab. + [Arguments] ${index} ${module_list_item_indexed}= Return Module List Indexed Module ${index} - ${indexed_module_operational_label}= BuiltIn.Set Variable ${module_list_item_indexed}//following-sibling::md-list[@aria-hidden="false"]//p[contains(., "${OPERATIONAL_LABEL}")] - [Return] ${indexed_module_operational_label} + ${indexed_module_operational_label}= BuiltIn.Set Variable + ... ${module_list_item_indexed}//following-sibling::md-list[@aria-hidden="false"]//p[contains(., "${OPERATIONAL_LABEL}")] + RETURN ${indexed_module_operational_label} Return Indexed Module Config Label - [Arguments] ${index} [Documentation] Returns Xpath of the indexed module`s config in Modules tab. + [Arguments] ${index} ${module_list_item_indexed}= Return Module List Indexed Module ${index} - ${indexed_module_config_label}= BuiltIn.Set Variable ${module_list_item_indexed}//following-sibling::md-list[@aria-hidden="false"]//p[contains(., "${CONFIG_LABEL}")] - [Return] ${indexed_module_config_label} + ${indexed_module_config_label}= BuiltIn.Set Variable + ... ${module_list_item_indexed}//following-sibling::md-list[@aria-hidden="false"]//p[contains(., "${CONFIG_LABEL}")] + RETURN ${indexed_module_config_label} Click Indexed Module Operations To Load Module Detail Operations Tab - [Arguments] ${index} [Documentation] Clicks indexed module`s operations to load module detail operations tab. + [Arguments] ${index} ${indexed_module_operations}= Return Indexed Module Operations Label ${index} Selenium2Library.Wait Until Page Contains Element ${indexed_module_operations} GUIKeywords.Focus And Click Element ${indexed_module_operations} Selenium2Library.Wait Until Page Contains Element ${MODULE_DETAIL_OPERATIONS_TAB_SELECTED} Click Indexed Module Operational To Load Module Detail Operational Tab - [Arguments] ${index} [Documentation] Clicks indexed module`s operational to load module detail operational tab. + [Arguments] ${index} ${indexed_module_operational}= Return Indexed Module Operational Label ${index} Selenium2Library.Wait Until Page Contains Element ${indexed_module_operational} GUIKeywords.Focus And Click Element ${indexed_module_operational} Selenium2Library.Wait Until Page Contains Element ${MODULE_DETAIL_OPERATIONAL_TAB_SELECTED} Click Indexed Module Config To Load Module Detail Config Tab - [Arguments] ${index} [Documentation] Clicks indexed module`s config to load module detail config tab. + [Arguments] ${index} ${indexed_module_config}= Return Indexed Module Config Label ${index} Selenium2Library.Wait Until Page Contains Element ${indexed_module_config} GUIKeywords.Focus And Click Element ${indexed_module_config} Selenium2Library.Wait Until Page Contains Element ${MODULE_DETAIL_CONFIG_TAB_SELECTED} Return Module ID Index From Module Name - [Arguments] ${module_name} [Documentation] Returns number - module id index from module name. - ${testing_module_xpath}= BuiltIn.Set Variable ${MODULE_TAB_CONTENT}//p[contains(., "${module_name}")]//ancestor::md-list-item[contains(@id, "${MODULE_ID_LABEL}")] + [Arguments] ${module_name} + ${testing_module_xpath}= BuiltIn.Set Variable + ... ${MODULE_TAB_CONTENT}//p[contains(., "${module_name}")]//ancestor::md-list-item[contains(@id, "${MODULE_ID_LABEL}")] ${module_id}= Selenium2Library.Get Element Attribute ${testing_module_xpath}@id ${module_id_index}= String.Fetch From Right ${module_id} ${MODULE_ID_LABEL} - [Return] ${module_id_index} + RETURN ${module_id_index} Return Indexed Module From Module Name - [Arguments] ${module_name} [Documentation] Returns indexed Xpath of the module from the module`s name. + [Arguments] ${module_name} ${module_id_index}= Return Module ID Index From Module Name ${module_name} ${module_list_item_indexed}= Return Module List Indexed Module ${module_id_index} - [Return] ${module_list_item_indexed} + RETURN ${module_list_item_indexed} Return Module List Item Collapsed Indexed - [Arguments] ${index} [Documentation] Returns Xpath of collapsed indexed module. + [Arguments] ${index} ${indexed_module}= Return Module List Indexed Module ${index} - ${module_list_item_collapsed_indexed}= BuiltIn.Set Variable ${indexed_module}//following-sibling::md-list[@aria-hidden="true"] - [Return] ${module_list_item_collapsed_indexed} + ${module_list_item_collapsed_indexed}= BuiltIn.Set Variable + ... ${indexed_module}//following-sibling::md-list[@aria-hidden="true"] + RETURN ${module_list_item_collapsed_indexed} Return Module List Item Expanded Indexed - [Arguments] ${index} [Documentation] Returns Xpath of expanded indexed module. + [Arguments] ${index} ${indexed_module}= Return Module List Indexed Module ${index} - ${module_list_item_expanded_indexed}= BuiltIn.Set Variable ${indexed_module}//following-sibling::md-list[@aria-hidden="false"] - [Return] ${module_list_item_expanded_indexed} + ${module_list_item_expanded_indexed}= BuiltIn.Set Variable + ... ${indexed_module}//following-sibling::md-list[@aria-hidden="false"] + RETURN ${module_list_item_expanded_indexed} Return Indexed Module Expander Icon - [Arguments] ${index} [Documentation] Returns xpath of indexed module expander icon. + [Arguments] ${index} ${indexed_module}= Return Module List Indexed Module ${index} ${indexed_module_expander_icon}= BuiltIn.Set Variable ${indexed_module}/md-icon - [Return] ${indexed_module_expander_icon} + RETURN ${indexed_module_expander_icon} Expand Module - [Arguments] ${module_name} ${module_id_index} [Documentation] Clicks module list item in modules tab to expand the item and display its operations/ operational/ config items. ... Arguments are either module name, or module id index, that is a number, or ${EMPTY}, if the option is not used. - ${module_list_item_indexed}= BuiltIn.Run Keyword If "${module_name}"!= "${EMPTY}" Return Indexed Module From Module Name ${module_name} - ${module_list_item_indexed}= BuiltIn.Run Keyword If "${module_id_index}"!= "${EMPTY}" Return Module List Indexed Module ${module_id_index} - ${module_list_item_expanded_indexed}= BuiltIn.Set Variable ${module_list_item_indexed}//following-sibling::md-list[@aria-hidden="false"] + [Arguments] ${module_name} ${module_id_index} + IF "${module_name}"!= "${EMPTY}" + ${module_list_item_indexed}= Return Indexed Module From Module Name ${module_name} + ELSE + ${module_list_item_indexed}= Set Variable ${None} + END + IF "${module_id_index}"!= "${EMPTY}" + ${module_list_item_indexed}= Return Module List Indexed Module ${module_id_index} + ELSE + ${module_list_item_indexed}= Set Variable ${None} + END + ${module_list_item_expanded_indexed}= BuiltIn.Set Variable + ... ${module_list_item_indexed}//following-sibling::md-list[@aria-hidden="false"] GUIKeywords.Mouse Down And Mouse Up Click Element ${module_list_item_indexed} Selenium2Library.Wait Until Page Contains Element ${module_list_item_expanded_indexed} Expand Module And Click Module Operational Item - [Arguments] ${module_name} ${module_id_index} [Documentation] Clicks module list item in modules tab and then clicks its operational item to load operational tab in module detail. ... Arguments are either module name, or module id index, that is a number, or ${EMPTY}, if the option is not used. + [Arguments] ${module_name} ${module_id_index} Expand Module ${module_name} ${module_id_index} Click Indexed Module Operational To Load Module Detail Operational Tab ${module_id_index} Expand Module And Click Module Config Item - [Arguments] ${module_name} ${module_id_index} [Documentation] Clicks module list item in modules tab and then clicks its config item to load operational tab in module detail. ... Arguments are either module name, or module id index, that is a number, or ${EMPTY}, if the option is not used. + [Arguments] ${module_name} ${module_id_index} Expand Module ${module_name} ${module_id_index} Click Indexed Module Config To Load Module Detail Config Tab ${module_id_index} Navigate From Yangman Submenu To Testing Module Operational Tab - [Arguments] ${testing_module_name} [Documentation] Navigates from loaded Yangman URL to testing module detail operational tab. + [Arguments] ${testing_module_name} ${module_id_index}= YangmanKeywords.Return Module ID Index From Module Name ${testing_module_name} Selenium2Library.Wait Until Page Does Not Contain Element ${MODULES_WERE_LOADED_ALERT} Expand Module And Click Module Operational Item ${EMPTY} ${module_id_index} Navigate From Yangman Submenu To Testing Module Config Tab - [Arguments] ${testing_module_name} [Documentation] Navigates from loaded Yangman URL to testing module detail config tab. + [Arguments] ${testing_module_name} ${module_id_index}= YangmanKeywords.Return Module ID Index From Module Name ${testing_module_name} Selenium2Library.Wait Until Page Does Not Contain Element ${MODULES_WERE_LOADED_ALERT} Expand Module And Click Module Config Item ${EMPTY} ${module_id_index} Compose Branch Id - [Arguments] ${index} [Documentation] Composes and returns string - branch id in the format branch-${index}. - BuiltIn.Return From Keyword ${BRANCH_ID_LABEL}${index} + [Arguments] ${index} + RETURN ${BRANCH_ID_LABEL}${index} Toggle Module Detail To Modules Or History Or Collections Tab [Documentation] Click toggle module detail button to toggle from module detail to modules or history or collections tab. @@ -298,14 +349,22 @@ Toggle Module Detail To Modules Or History Or Collections Tab Select Module Detail Operational Tab [Documentation] Selects operational tab in module detail. - ${status}= BuiltIn.Run Keyword And Return Status Selenium2Library.Page Should Contain Element ${MODULE_DETAIL_OPERATIONAL_TAB_SELECTED} - BuiltIn.Run Keyword If "${status}"=="False" Selenium2Library.Click Element ${MODULE_DETAIL_OPERATIONAL_TAB_DESELECTED} + ${status}= BuiltIn.Run Keyword And Return Status + ... Selenium2Library.Page Should Contain Element + ... ${MODULE_DETAIL_OPERATIONAL_TAB_SELECTED} + IF "${status}"=="False" + Selenium2Library.Click Element ${MODULE_DETAIL_OPERATIONAL_TAB_DESELECTED} + END Selenium2Library.Wait Until Page Contains Element ${MODULE_DETAIL_OPERATIONAL_TAB_SELECTED} Select Module Detail Config Tab [Documentation] Selects config tab in module detail. - ${status}= BuiltIn.Run Keyword And Return Status Selenium2Library.Page Should Contain Element ${MODULE_DETAIL_CONFIG_TAB_SELECTED} - BuiltIn.Run Keyword If "${status}"=="False" Selenium2Library.Click Element ${MODULE_DETAIL_CONFIG_TAB_DESELECTED} + ${status}= BuiltIn.Run Keyword And Return Status + ... Selenium2Library.Page Should Contain Element + ... ${MODULE_DETAIL_CONFIG_TAB_SELECTED} + IF "${status}"=="False" + Selenium2Library.Click Element ${MODULE_DETAIL_CONFIG_TAB_DESELECTED} + END Selenium2Library.Wait Until Page Contains Element ${MODULE_DETAIL_CONFIG_TAB_SELECTED} Expand All Branches In Module Detail Content Active Tab @@ -313,8 +372,12 @@ Expand All Branches In Module Detail Content Active Tab Selenium2Library.Wait Until Element Is Visible ${MODULE_DETAIL_EXPAND_BRANCH_BUTTON} FOR ${i} IN RANGE 1 1000 ${count}= Selenium2Library.Get Matching Xpath Count ${MODULE_DETAIL_EXPAND_BRANCH_BUTTON} - BuiltIn.Exit For Loop If ${count}==0 - BuiltIn.Wait Until Keyword Succeeds 30 s 5 s GUIKeywords.Focus And Click Element ${MODULE_DETAIL_EXPAND_BRANCH_BUTTON} + IF ${count}==0 BREAK + BuiltIn.Wait Until Keyword Succeeds + ... 30 s + ... 5 s + ... GUIKeywords.Focus And Click Element + ... ${MODULE_DETAIL_EXPAND_BRANCH_BUTTON} END Selenium2Library.Wait Until Page Does Not Contain Element ${MODULE_DETAIL_EXPAND_BRANCH_BUTTON} @@ -323,112 +386,134 @@ Collapse All Branches In Module Detail Content Active Tab Selenium2Library.Wait Until Element Is Visible ${MODULE_DETAIL_COLLAPSE_BRANCH_BUTTON} FOR ${i} IN RANGE 1 1000 ${count}= Selenium2Library.Get Matching Xpath Count ${MODULE_DETAIL_COLLAPSE_BRANCH_BUTTON} - BuiltIn.Exit For Loop If ${count}==0 - BuiltIn.Wait Until Keyword Succeeds 30 s 5 s GUIKeywords.Focus And Click Element ${MODULE_DETAIL_COLLAPSE_BRANCH_BUTTON} + IF ${count}==0 BREAK + BuiltIn.Wait Until Keyword Succeeds + ... 30 s + ... 5 s + ... GUIKeywords.Focus And Click Element + ... ${MODULE_DETAIL_COLLAPSE_BRANCH_BUTTON} END Selenium2Library.Wait Until Page Does Not Contain Element ${MODULE_DETAIL_COLLAPSE_BRANCH_BUTTON} Return Module Detail Labelled Branch Xpath - [Arguments] ${branch_label} [Documentation] Returns xpath of module detail labelled branch. - ${labelled_branch_xpath}= BuiltIn.Set Variable ${MODULE_DETAIL_BRANCH}//span[contains(@class, "indented tree-label ng-binding flex") and contains(text(), "${branch_label}")] - [Return] ${labelled_branch_xpath} + [Arguments] ${branch_label} + ${labelled_branch_xpath}= BuiltIn.Set Variable + ... ${MODULE_DETAIL_BRANCH}//span[contains(@class, "indented tree-label ng-binding flex") and contains(text(), "${branch_label}")] + RETURN ${labelled_branch_xpath} Return Module Detail Branch ID From Branch Label - [Arguments] ${branch_label} [Documentation] Returns string - module detail branch id in the format branch-${index}. + [Arguments] ${branch_label} ${labelled_branch_xpath}= Return Module Detail Labelled Branch Xpath ${branch_label} - ${branch_id}= Selenium2Library.Get Element Attribute ${labelled_branch_xpath}//ancestor::md-list-item[contains(@id, "${BRANCH_ID_LABEL}")]@id - [Return] ${branch_id} + ${branch_id}= Selenium2Library.Get Element Attribute + ... ${labelled_branch_xpath}//ancestor::md-list-item[contains(@id, "${BRANCH_ID_LABEL}")]@id + RETURN ${branch_id} Return Module Detail Branch Indexed - [Arguments] ${branch_id} [Documentation] Returns indexed Xpath of the module detail branch. Argument is ${branch_id} in the form "branch-"${index}"". - ${module_detail_branch_indexed}= BuiltIn.Set Variable ${MODULE_DETAIL_ACTIVE_TAB_CONTENT}//md-list-item[contains(@id, "${branch_id}")] - [Return] ${module_detail_branch_indexed} + [Arguments] ${branch_id} + ${module_detail_branch_indexed}= BuiltIn.Set Variable + ... ${MODULE_DETAIL_ACTIVE_TAB_CONTENT}//md-list-item[contains(@id, "${branch_id}")] + RETURN ${module_detail_branch_indexed} Return Indexed Branch Label - [Arguments] ${module_detail_branch_indexed} [Documentation] Returns string - label of indexed branch in module detail. - ${branch_label}= Selenium2Library.Get Text ${module_detail_branch_indexed}//span[@class="indented tree-label ng-binding flex"] - [Return] ${branch_label} + [Arguments] ${module_detail_branch_indexed} + ${branch_label}= Selenium2Library.Get Text + ... ${module_detail_branch_indexed}//span[@class="indented tree-label ng-binding flex"] + RETURN ${branch_label} Return Branch Label Without Curly Braces Part - [Arguments] ${branch_label} [Documentation] Returns string - part of label of indexed branch in module detail without curly braces part. + [Arguments] ${branch_label} ${branch_label_without_curly_braces_part}= String.Fetch From Left ${branch_label} ${SPACE} - [Return] ${branch_label_without_curly_braces_part} + RETURN ${branch_label_without_curly_braces_part} Return Branch Label Curly Braces Part Without Braces - [Arguments] ${branch_label} [Documentation] Returns string - curly braces part of label of indexed branch in module detail without curly braces. + [Arguments] ${branch_label} ${branch_label_curly_braces_part}= String.Fetch From Right ${branch_label} ${SPACE} ${branch_label_curly_braces_part}= String.Strip String ${branch_label_curly_braces_part} characters={} - [Return] ${branch_label_curly_braces_part} + RETURN ${branch_label_curly_braces_part} Return Labelled Branch Toggle Button - [Arguments] ${labelled_branch_xpath} [Documentation] Returns xpath of toggle button of labelled branch in module detail. - ${labelled_branch_toggle_button}= BuiltIn.Set Variable ${labelled_branch_xpath}//preceding-sibling::md-icon[contains(@id, "toggle-branch-")] - [Return] ${labelled_branch_toggle_button} + [Arguments] ${labelled_branch_xpath} + ${labelled_branch_toggle_button}= BuiltIn.Set Variable + ... ${labelled_branch_xpath}//preceding-sibling::md-icon[contains(@id, "toggle-branch-")] + RETURN ${labelled_branch_toggle_button} Return Branch Toggle Button From Branch Label And Click - [Arguments] ${branch_label} [Documentation] Returns xpath toggle button of labelled branch in module detail and clicks it. + [Arguments] ${branch_label} ${labelled_branch_xpath}= Return Module Detail Labelled Branch Xpath ${branch_label} ${labelled_branch_toggle_button}= Return Labelled Branch Toggle Button ${labelled_branch_xpath} Selenium2Library.Page Should Contain Element ${labelled_branch_toggle_button} Selenium2Library.Click Element ${labelled_branch_toggle_button} Click Module Detail Branch Indexed - [Arguments] ${module_detail_branch_indexed} [Documentation] Click indexed branch in module detail. + [Arguments] ${module_detail_branch_indexed} Selenium2Library.Page Should Contain Element ${module_detail_branch_indexed} GUIKeywords.Mouse Down And Mouse Up Click Element ${module_detail_branch_indexed} Return And Click Module Detail Branch Indexed - [Arguments] ${branch_label} [Documentation] Returns and click Click indexed branch in module detail. + [Arguments] ${branch_label} ${branch_id}= Return Module Detail Branch ID From Branch Label ${branch_label} ${module_detail_branch_indexed}= Return Module Detail Branch Indexed ${branch_id} Click Module Detail Branch Indexed ${module_detail_branch_indexed} Verify Module Detail Branch Is List Branch - [Arguments] ${module_detail_branch_indexed} [Documentation] Returns status "True" if module detail branch is a list branch and "False" if module detail branch is not a list brnach. + [Arguments] ${module_detail_branch_indexed} ${branch_label}= Return Indexed Branch Label ${module_detail_branch_indexed} - ${branch_is_list_evaluation}= BuiltIn.Run Keyword And Return Status BuiltIn.Should Contain ${branch_label} { - [Return] ${branch_is_list_evaluation} + ${branch_is_list_evaluation}= BuiltIn.Run Keyword And Return Status + ... BuiltIn.Should Contain + ... ${branch_label} + ... { + RETURN ${branch_is_list_evaluation} Return Form Top Element Label [Documentation] Returns string - form top element label. ${form_top_element_label}= Selenium2Library.Get Text ${FORM_TOP_ELEMENT_LABEL_XPATH} - [Return] ${form_top_element_label} + RETURN ${form_top_element_label} Return Form Top Element Labelled - [Arguments] ${label} [Documentation] Returns xpath of form top element with label. - ${form_top_element_labelled}= BuiltIn.Set Variable ${FORM_TOP_ELEMENT_POINTER}//span[contains(@class, "ng-binding ng-scope") and contains(text(), "${label}")] - [Return] ${form_top_element_labelled} + [Arguments] ${label} + ${form_top_element_labelled}= BuiltIn.Set Variable + ... ${FORM_TOP_ELEMENT_POINTER}//span[contains(@class, "ng-binding ng-scope") and contains(text(), "${label}")] + RETURN ${form_top_element_labelled} Return Form List Item With Index Or Key - [Arguments] ${branch_label} ${branch_label_curly_braces_part} ${index_or_key} [Documentation] Returns string - catenated branch label and index, in the form "label [${index_or_key}]" or "label <${branch_label_curly_braces_part}:${index_or_key}>". + [Arguments] ${branch_label} ${branch_label_curly_braces_part} ${index_or_key} ${branch_label_without_curly_braces_part}= Return Branch Label Without Curly Braces Part ${branch_label} ${key_part}= BuiltIn.Set Variable <${branch_label_curly_braces_part}:${index_or_key}> - ${list_item_with_index_or_key}= BuiltIn.Set Variable If "${branch_label_curly_braces_part}"=="${EMPTY}" ${FORM_TOP_ELEMENT_LIST_ITEM_LABEL}[contains(text(), "${branch_label_without_curly_braces_part}") and contains(text(), "[${index_or_key}]")] ${FORM_TOP_ELEMENT_LIST_ITEM_LABEL}[contains(text(), "${branch_label_without_curly_braces_part}") and contains(text(), "${key_part}")] - [Return] ${list_item_with_index_or_key} + ${list_item_with_index_or_key}= BuiltIn.Set Variable If + ... "${branch_label_curly_braces_part}"=="${EMPTY}" + ... ${FORM_TOP_ELEMENT_LIST_ITEM_LABEL}[contains(text(), "${branch_label_without_curly_braces_part}") and contains(text(), "[${index_or_key}]")] + ... ${FORM_TOP_ELEMENT_LIST_ITEM_LABEL}[contains(text(), "${branch_label_without_curly_braces_part}") and contains(text(), "${key_part}")] + RETURN ${list_item_with_index_or_key} Click Form List Item With Index Or Key - [Arguments] ${branch_label} ${id/ref/prefix_part} ${index/key} [Documentation] Clicks form list item with given index or key is visible. - ${list_item_with_index_or_key}= Return Form List Item With Index Or Key ${branch_label} ${id/ref/prefix_part} ${index/key} + [Arguments] ${branch_label} ${id/ref/prefix_part} ${index/key} + ${list_item_with_index_or_key}= Return Form List Item With Index Or Key + ... ${branch_label} + ... ${id/ref/prefix_part} + ... ${index/key} Selenium2Library.Click Element ${list_item_with_index_or_key} Verify List Item With Index Or Key Is Visible - [Arguments] ${branch_label} ${branch_label_curly_braces_part} ${index_or_key} [Documentation] Verifies that form list item with given index or key is visible. - ${list_item_with_index_or_key}= Return Form List Item With Index Or Key ${branch_label} ${branch_label_curly_braces_part} ${index_or_key} + [Arguments] ${branch_label} ${branch_label_curly_braces_part} ${index_or_key} + ${list_item_with_index_or_key}= Return Form List Item With Index Or Key + ... ${branch_label} + ... ${branch_label_curly_braces_part} + ... ${index_or_key} Selenium2Library.Wait Until Element Is Visible ${list_item_with_index_or_key} Load And Expand Network Topology In Form @@ -442,8 +527,12 @@ Load Topology Topology Id Node In Form [Documentation] Expands network-topology branch in testing module detail and clicks topology {topology-id} branch to load topology list node in form. Select Form View ${topology_topology_id_branch}= Return Module Detail Labelled Branch Xpath ${TOPOLOGY_TOPOLOGY_ID_LABEL} - ${status}= BuiltIn.Run Keyword And Return Status Selenium2Library.Element Should Be Visible ${topology_topology_id_branch} - BuiltIn.Run Keyword If "${status}"=="False" Return Branch Toggle Button From Branch Label And Click ${NETWORK_TOPOLOGY_LABEL} + ${status}= BuiltIn.Run Keyword And Return Status + ... Selenium2Library.Element Should Be Visible + ... ${topology_topology_id_branch} + IF "${status}"=="False" + Return Branch Toggle Button From Branch Label And Click ${NETWORK_TOPOLOGY_LABEL} + END YangmanKeywords.Return Branch Toggle Button From Branch Label And Click ${TOPOLOGY_TOPOLOGY_ID_LABEL} Verify List Item With Index Or Key Is Visible ${TOPOLOGY_TOPOLOGY_ID_LABEL} ${EMPTY} 0 @@ -451,68 +540,78 @@ Load Node Node Id Node In Form [Documentation] Expands network-topology branch in testing module detail and clicks topology {topology-id} branch to load topology list node in form. Select Form View ${node_node_id_branch}= Return Module Detail Labelled Branch Xpath ${NODE_NODE_ID_LABEL} - ${node_branch_is_visible}= BuiltIn.Run Keyword And Return Status Selenium2Library.Element Should Be Visible ${node_node_id_branch} - BuiltIn.Run Keyword If "${node_branch_is_visible}"=="False" Run Keywords Load Topology Topology Id Node In Form - ... AND Return Branch Toggle Button From Branch Label And Click ${TOPOLOGY_TOPOLOGY_ID_LABEL} + ${node_branch_is_visible}= BuiltIn.Run Keyword And Return Status + ... Selenium2Library.Element Should Be Visible + ... ${node_node_id_branch} + IF "${node_branch_is_visible}"=="False" + Load Topology Topology Id Node In Form + Return Branch Toggle Button From Branch Label And Click ${TOPOLOGY_TOPOLOGY_ID_LABEL} + END YangmanKeywords.Return And Click Module Detail Branch Indexed ${NODE_NODE_ID_LABEL} Verify List Item With Index Or Key Is Visible ${NODE_NODE_ID_LABEL} ${EMPTY} 0 Return Labelled Element Yangmenu - [Arguments] ${label} [Documentation] Returns xpath of labelled element yangmenu in form. + [Arguments] ${label} ${form_top_element_labelled}= Return Form Top Element Labelled ${label} - ${form_labelled_element_yangmenu}= BuiltIn.Set Variable ${form_top_element_labelled}//following::yang-form-menu - [Return] ${form_labelled_element_yangmenu} + ${form_labelled_element_yangmenu}= BuiltIn.Set Variable + ... ${form_top_element_labelled}//following::yang-form-menu + RETURN ${form_labelled_element_yangmenu} Return And Click Labelled Element Yangmenu - [Arguments] ${label} [Documentation] Returns xpath of labelled element yangmenu in form and clicks the yangmenu. + [Arguments] ${label} ${form_labelled_element_yangmenu}= Return Labelled Element Yangmenu ${label} Selenium2Library.Element Should Be Visible ${form_labelled_element_yangmenu} GUIKeywords.Mouse Down And Mouse Up Click Element ${form_labelled_element_yangmenu} Return Labelled Element Show Previous Item Arrow - [Arguments] ${label} [Documentation] Returns xpath of labelled element show previous list item icon in form. + [Arguments] ${label} ${form_top_element_labelled}= Return Form Top Element Labelled ${label} - ${labelled_show_previous_item_arrow}= BuiltIn.Set Variable ${form_top_element_labelled}//following::md-prev-button[@aria-label="Previous Page"] - [Return] ${labelled_show_previous_item_arrow} + ${labelled_show_previous_item_arrow}= BuiltIn.Set Variable + ... ${form_top_element_labelled}//following::md-prev-button[@aria-label="Previous Page"] + RETURN ${labelled_show_previous_item_arrow} Return Labelled Element Show Next Item Arrow - [Arguments] ${label} [Documentation] Returns xpath of labelled element show next list item icon. + [Arguments] ${label} ${form_top_element_labelled}= Return Form Top Element Labelled ${label} - ${labelled_show_next_item_arrow}= BuiltIn.Set Variable ${form_top_element_labelled}//following::md-next-button[@aria-label="Next Page"] - [Return] ${labelled_show_next_item_arrow} + ${labelled_show_next_item_arrow}= BuiltIn.Set Variable + ... ${form_top_element_labelled}//following::md-next-button[@aria-label="Next Page"] + RETURN ${labelled_show_next_item_arrow} Return Labelled Form Input Field - [Arguments] ${branch_label_curly_braces_part} [Documentation] Returns xpath of labelled form input field. - ${labelled_input_field}= BuiltIn.Set Variable ${FORM_CONTENT}//span[contains(@class, "ng-binding ng-scope") and contains(text(), "${branch_label_curly_braces_part}")]//following::input - [Return] ${labelled_input_field} + [Arguments] ${branch_label_curly_braces_part} + ${labelled_input_field}= BuiltIn.Set Variable + ... ${FORM_CONTENT}//span[contains(@class, "ng-binding ng-scope") and contains(text(), "${branch_label_curly_braces_part}")]//following::input + RETURN ${labelled_input_field} Return Labelled Form Select - [Arguments] ${branch_label_curly_braces_part} [Documentation] Returns labelled form input field. - ${labelled_select}= BuiltIn.Set Variable ${FORM_CONTENT}//span[contains(@class, "ng-binding ng-scope") and contains(text(), "${branch_label_curly_braces_part}")]//following::md-select - [Return] ${labelled_select} + [Arguments] ${branch_label_curly_braces_part} + ${labelled_select}= BuiltIn.Set Variable + ... ${FORM_CONTENT}//span[contains(@class, "ng-binding ng-scope") and contains(text(), "${branch_label_curly_braces_part}")]//following::md-select + RETURN ${labelled_select} Input Text To Labelled Form Input Field - [Arguments] ${branch_label_curly_braces_part} ${text} [Documentation] Returns labelled form input field and inputs the text provided as an argument into it. + [Arguments] ${branch_label_curly_braces_part} ${text} ${labelled_input_field}= Return Labelled Form Input Field ${branch_label_curly_braces_part} Selenium2Library.Input Text ${labelled_input_field} ${text} Verify Form Contains Error Message - [Arguments] ${error_message} [Documentation] Verifies that the form contains error message that is provided as an argument. - ${form_error_message}= BuiltIn.Set Variable //p[contains(@id, "form-error-message") and contains (text(), "${error_message}")] + [Arguments] ${error_message} + ${form_error_message}= BuiltIn.Set Variable + ... //p[contains(@id, "form-error-message") and contains (text(), "${error_message}")] Selenium2Library.Page Should Contain Element ${form_error_message} Verify No Data Are Displayed In Code Mirror Code - [Arguments] ${code_mirror_code} [Documentation] Verifies that there are no data displayed in either sent or received data code mirror. ... Value for ${code_mirror_code} is either ${SENT_DATA_CODE_MIRROR_CODE} or ${RECEIVED_DATA_CODE_MIRROR_CODE}. + [Arguments] ${code_mirror_code} ${number_of_lines_in_code_mirror}= Selenium2Library.Get Matching Xpath Count ${code_mirror_code}/div BuiltIn.Should Be Equal ${number_of_lines_in_code_mirror} 1 diff --git a/csit/libraries/controller/CsCommon.robot b/csit/libraries/controller/CsCommon.robot index 1b3fb3ccbf..7bfdbcb33b 100644 --- a/csit/libraries/controller/CsCommon.robot +++ b/csit/libraries/controller/CsCommon.robot @@ -1,34 +1,37 @@ *** Settings *** -Documentation Cluster Singleton testing: Common Keywords +Documentation Cluster Singleton testing: Common Keywords ... -... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... -... Cluster Singleton service is designed to ensure that only one instance of an -... application is registered globally in the cluster. +... Cluster Singleton service is designed to ensure that only one instance of an +... application is registered globally in the cluster. ... -... Creates and uses the following suite variables: -... Created by Cluster_Singleton_Init: -... ${cs_all_indices} -... ${cs_exp_candidates} -... Created by Get_And_Save_Present_CsOwner_And_CsCandidates: -... ${cs_owner} -... ${cs_candidates} -... Created by Isolate_Owner_And_Verify_Isolated -... ${cs_isolated_index} -Library Collections -Resource ${CURDIR}/../ClusterManagement.robot -Resource ${CURDIR}/../MdsalLowlevel.robot -Resource ${CURDIR}/../ShardStability.robot -Resource ${CURDIR}/../WaitForFailure.robot +... Creates and uses the following suite variables: +... Created by Cluster_Singleton_Init: +... ${cs_all_indices} +... ${cs_exp_candidates} +... Created by Get_And_Save_Present_CsOwner_And_CsCandidates: +... ${cs_owner} +... ${cs_candidates} +... Created by Isolate_Owner_And_Verify_Isolated +... ${cs_isolated_index} + +Library Collections +Resource ${CURDIR}/../ClusterManagement.robot +Resource ${CURDIR}/../MdsalLowlevel.robot +Resource ${CURDIR}/../ShardStability.robot +Resource ${CURDIR}/../WaitForFailure.robot + *** Variables *** -${CS_DEVICE_NAME} get-singleton-constant-service'] -${CS_DEVICE_TYPE} org.opendaylight.mdsal.ServiceEntityType -${CS_CONSTANT_PREFIX} constant- +${CS_DEVICE_NAME} get-singleton-constant-service'] +${CS_DEVICE_TYPE} org.opendaylight.mdsal.ServiceEntityType +${CS_CONSTANT_PREFIX} constant- + *** Keywords *** Cluster_Singleton_Init @@ -40,60 +43,71 @@ Cluster_Singleton_Init BuiltIn.Set_Suite_Variable ${cs_all_indices} Register_Singleton_And_Update_Expected_Candidates - [Arguments] ${member_index} ${constant} [Documentation] Register the singleton candidate and add it to the list of ${cs_exp_candidates}. + [Arguments] ${member_index} ${constant} MdsalLowlevel.Register_Singleton_Constant ${member_index} ${constant} Collections.Append_To_List ${cs_exp_candidates} ${member_index} Collections.Sort_List ${cs_exp_candidates} Unregister_Singleton_And_Update_Expected_Candidates - [Arguments] ${member_index} [Documentation] Unregister the singleton candidate. Also remove it from the list of ${cs_exp_candidates}. + [Arguments] ${member_index} MdsalLowlevel.Unregister_Singleton_Constant ${member_index} Collections.Remove_Values_From_List ${cs_exp_candidates} ${member_index} Verify_Owner_And_Candidates_Stable - [Arguments] ${owner_index} [Documentation] Fail if the actual owner is different from ${owner_index} or if the actual candidate list is different from ${cs_exp_candidates}. - ${actual_owner} ${actual_candidates} ClusterManagement.Check_Old_Owner_Stays_Elected_For_Device ${CS_DEVICE_NAME} ${CS_DEVICE_TYPE} ${owner_index} ${owner_index} + [Arguments] ${owner_index} + ${actual_owner} ${actual_candidates} = ClusterManagement.Check_Old_Owner_Stays_Elected_For_Device + ... ${CS_DEVICE_NAME} + ... ${CS_DEVICE_TYPE} + ... ${owner_index} + ... ${owner_index} Collections.Lists_Should_Be_Equal ${cs_exp_candidates} ${actual_candidates} Monitor_Owner_And_Candidates_Stability - [Arguments] ${monitoring_duration} ${owner_index} [Documentation] Verify that the owner remains on the same node after non-owner candidate is unregistered. - WaitForFailure.Verify_Keyword_Does_Not_Fail_Within_Timeout ${monitoring_duration} 3s Verify_Owner_And_Candidates_Stable ${owner_index} + [Arguments] ${monitoring_duration} ${owner_index} + WaitForFailure.Verify_Keyword_Does_Not_Fail_Within_Timeout + ... ${monitoring_duration} + ... 3s + ... Verify_Owner_And_Candidates_Stable + ... ${owner_index} Register_Singleton_Constant_On_Nodes - [Arguments] ${index_list} [Documentation] Register a candidate application on given nodes. + [Arguments] ${index_list} FOR ${index} IN @{index_list} Register_Singleton_And_Update_Expected_Candidates ${index} ${CS_CONSTANT_PREFIX}${index} END Unregister_Singleton_Constant_On_Nodes - [Arguments] ${index_list} [Documentation] Unregister the application from given nodes. + [Arguments] ${index_list} FOR ${index} IN @{index_list} Unregister_Singleton_And_Update_Expected_Candidates ${index} END Get_And_Save_Present_CsOwner_And_CsCandidates - [Arguments] ${node_to_ask} [Documentation] Store owner index into suite variables. - ${cs_owner} ${cs_candidates} ClusterManagement.Get_Owner_And_Candidates_For_Device ${CS_DEVICE_NAME} ${CS_DEVICE_TYPE} ${node_to_ask} + [Arguments] ${node_to_ask} + ${cs_owner} ${cs_candidates} = ClusterManagement.Get_Owner_And_Candidates_For_Device + ... ${CS_DEVICE_NAME} + ... ${CS_DEVICE_TYPE} + ... ${node_to_ask} BuiltIn.Set_Suite_Variable ${cs_owner} BuiltIn.Set_Suite_Variable ${cs_candidates} - BuiltIn.Return_From_Keyword ${cs_owner} ${cs_candidates} + RETURN ${cs_owner} ${cs_candidates} Verify_Singleton_Constant_On_Node - [Arguments] ${node_to_ask} ${cs_exp_constant} [Documentation] Verify that the expected constant is return from the given node. + [Arguments] ${node_to_ask} ${cs_exp_constant} ${constant} = MdsalLowlevel.Get_Singleton_Constant ${node_to_ask} BuiltIn.Should_Be_Equal ${cs_exp_constant} ${constant} Verify_Singleton_Constant_On_Nodes - [Arguments] ${index_list} ${cs_exp_constant} [Documentation] Iterate over all cluster nodes and all should return expected constant. + [Arguments] ${index_list} ${cs_exp_constant} FOR ${index} IN @{index_list} Verify_Singleton_Constant_On_Node ${index} ${cs_exp_constant} END @@ -101,43 +115,69 @@ Verify_Singleton_Constant_On_Nodes Verify_Singleton_Constant_During_Isolation [Documentation] Iterate over all non-isolated cluster nodes. They should return the correct constant. FOR ${index} IN @{cs_all_indices} - BuiltIn.Run_Keyword_If "${index}" == "${cs_isolated_index}" BuiltIn.Log Node not triggered, behavior not well described, see bugs 8207, 8214. - BuiltIn.Run_Keyword_If "${index}" != "${cs_isolated_index}" Verify_Singleton_Constant_On_Node ${index} ${CS_CONSTANT_PREFIX}${cs_owner} + IF "${index}" == "${cs_isolated_index}" + BuiltIn.Log Node not triggered, behavior not well described, see bugs 8207, 8214. + END + IF "${index}" != "${cs_isolated_index}" + Verify_Singleton_Constant_On_Node ${index} ${CS_CONSTANT_PREFIX}${cs_owner} + END END Isolate_Owner_And_Verify_Isolated [Documentation] Isolate the owner cluster node. Wait until the new owner is elected and store new values of owner and candidates. ClusterManagement.Isolate_Member_From_List_Or_All ${cs_owner} BuiltIn.Set_Suite_Variable ${cs_isolated_index} ${cs_owner} - ${non_isolated_list} = ClusterManagement.List_Indices_Minus_Member ${cs_isolated_index} member_index_list=${cs_all_indices} + ${non_isolated_list} = ClusterManagement.List_Indices_Minus_Member + ... ${cs_isolated_index} + ... member_index_list=${cs_all_indices} ${node_to_ask} = Collections.Get_From_list ${non_isolated_list} 0 - BuiltIn.Wait_Until_Keyword_Succeeds 70s 10s ShardStability.Shards_Stability_Get_Details ${DEFAULT_SHARD_LIST} member_index_list=${non_isolated_list} - BuiltIn.Wait_Until_Keyword_Succeeds 30s 2s ClusterManagement.Check_New_Owner_Got_Elected_For_Device ${CS_DEVICE_NAME} ${CS_DEVICE_TYPE} ${cs_isolated_index} - ... ${node_to_ask} http_timeout=125 + BuiltIn.Wait_Until_Keyword_Succeeds + ... 70s + ... 10s + ... ShardStability.Shards_Stability_Get_Details + ... ${DEFAULT_SHARD_LIST} + ... member_index_list=${non_isolated_list} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 30s + ... 2s + ... ClusterManagement.Check_New_Owner_Got_Elected_For_Device + ... ${CS_DEVICE_NAME} + ... ${CS_DEVICE_TYPE} + ... ${cs_isolated_index} + ... ${node_to_ask} + ... http_timeout=125 Get_And_Save_Present_CsOwner_And_CsCandidates ${node_to_ask} BuiltIn.Wait_Until_Keyword_Succeeds 60s 3s Verify_Singleton_Constant_During_Isolation Rejoin_Node_And_Verify_Rejoined [Documentation] Rejoin isolated node. ClusterManagement.Rejoin_Member_From_List_Or_All ${cs_isolated_index} - BuiltIn.Wait_Until_Keyword_Succeeds 70s 10s ShardStability.Shards_Stability_Get_Details ${DEFAULT_SHARD_LIST} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 70s + ... 10s + ... ShardStability.Shards_Stability_Get_Details + ... ${DEFAULT_SHARD_LIST} Register_Flapping_Singleton_On_Nodes - [Arguments] ${index_list} [Documentation] Register a candidate application on each node which starts the test. + [Arguments] ${index_list} FOR ${index} IN @{index_list} MdsalLowlevel.Register_Flapping_Singleton ${index} END Unregister_Flapping_Singleton_On_Nodes_And_Validate_Results - [Arguments] ${index_list} ${rate_limit_to_pass} ${test_duration} [Documentation] Unregister the testing service and check recevied statistics. + [Arguments] ${index_list} ${rate_limit_to_pass} ${test_duration} ${movements_count} = BuiltIn.Set_Variable ${0} FOR ${index} IN @{index_list} ${count} = MdsalLowlevel.Unregister_Flapping_Singleton ${index} - BuiltIn.Run_Keyword_If ${count} < 0 BuiltIn.Fail No failure should have occured during the ${test_duration} timeout. + IF ${count} < 0 + BuiltIn.Fail No failure should have occured during the ${test_duration} timeout. + END ${movements_count} = BuiltIn.Evaluate ${movements_count}+${count} END ${seconds} = DateTime.Convert_Time ${test_duration} ${rate} = BuiltIn.Evaluate ${movements_count}/${seconds} - BuiltIn.Run_Keyword_If ${rate} < ${rate_limit_to_pass} BuiltIn.Fail Acceptance rate ${rate_limit_to_pass} not reached, actual rate is ${rate}. + IF ${rate} < ${rate_limit_to_pass} + BuiltIn.Fail Acceptance rate ${rate_limit_to_pass} not reached, actual rate is ${rate}. + END diff --git a/csit/libraries/controller/DdbCommons.robot b/csit/libraries/controller/DdbCommons.robot index a121064a12..ee262d9a0a 100644 --- a/csit/libraries/controller/DdbCommons.robot +++ b/csit/libraries/controller/DdbCommons.robot @@ -1,151 +1,255 @@ *** Settings *** -Documentation DOMDataBroker testing: Common keywords +Documentation DOMDataBroker testing: Common keywords ... -... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... -... This resource file implements various test cases templates. -... FIXME: add a link to a document (when published) where the scenarios are defined +... This resource file implements various test cases templates. +... FIXME: add a link to a document (when published) where the scenarios are defined ... -... TODO: When checking first response in isolation scenarior, make sure it comes from the expected member. -Library ${CURDIR}/../MdsalLowlevelPy.py -Resource ${CURDIR}/../ClusterAdmin.robot -Resource ${CURDIR}/../ClusterManagement.robot -Resource ${CURDIR}/../KarafKeywords.robot -Resource ${CURDIR}/../MdsalLowlevel.robot -Resource ${CURDIR}/../TemplatedRequests.robot -Resource ${CURDIR}/../ShardStability.robot -Resource ${CURDIR}/../WaitForFailure.robot +... TODO: When checking first response in isolation scenarior, make sure it comes from the expected member. + +Library ${CURDIR}/../MdsalLowlevelPy.py +Resource ${CURDIR}/../ClusterAdmin.robot +Resource ${CURDIR}/../ClusterManagement.robot +Resource ${CURDIR}/../KarafKeywords.robot +Resource ${CURDIR}/../MdsalLowlevel.robot +Resource ${CURDIR}/../TemplatedRequests.robot +Resource ${CURDIR}/../ShardStability.robot +Resource ${CURDIR}/../WaitForFailure.robot + *** Variables *** -${SHARD_NAME} default -${SHARD_TYPE} config -${TRANSACTION_RATE_1K} ${1000} -${TRANSACTION_PRODUCTION_TIME_2X_REQ_TIMEOUT} ${2*${REQUEST_TIMEOUT}} -${TRANSACTION_PRODUCTION_TIME} ${40} -${SLEEP_AFTER_TRANSACTIONS_INIT} 5s -${ID_PREFIX} prefix- -${ID_PREFIX2} prefix- # different-prefix- has been used before, but currently is neither needed nor supported -${SIMPLE_TX} ${False} -${CHAINED_TX} ${True} -${ISOLATED_TRANS_TRUE} ${True} -${ISOLATED_TRANS_FALSE} ${False} -${JAVA_INTERNAL_RECONNECT_TIMEOUT} ${30} -${REQUEST_TIMEOUT} ${120} -${HEAL_WITHIN_REQUEST_TIMEOUT} ${${JAVA_INTERNAL_RECONNECT_TIMEOUT}+10} -${HEAL_AFTER_REQUEST_TIMEOUT} ${${REQUEST_TIMEOUT}+10} -@{TRANSACTION_FAILED} ${500} -${PREF_BASED_SHARD} id-ints -${TEST_LOG_LEVEL} info -@{TEST_LOG_COMPONENTS} org.opendaylight.controller.cluster.sharding org.opendaylight.controller.cluster.datastore -${HEAL_WITHIN_TRANS_TIMEOUT} ${0} +${SHARD_NAME} default +${SHARD_TYPE} config +${TRANSACTION_RATE_1K} ${1000} +${TRANSACTION_PRODUCTION_TIME_2X_REQ_TIMEOUT} ${2*${REQUEST_TIMEOUT}} +${TRANSACTION_PRODUCTION_TIME} ${40} +${SLEEP_AFTER_TRANSACTIONS_INIT} 5s +${ID_PREFIX} prefix- +# different-prefix- has been used before, but currently is neither needed nor supported +${ID_PREFIX2} +... prefix- +${SIMPLE_TX} ${False} +${CHAINED_TX} ${True} +${ISOLATED_TRANS_TRUE} ${True} +${ISOLATED_TRANS_FALSE} ${False} +${JAVA_INTERNAL_RECONNECT_TIMEOUT} ${30} +${REQUEST_TIMEOUT} ${120} +${HEAL_WITHIN_REQUEST_TIMEOUT} ${${JAVA_INTERNAL_RECONNECT_TIMEOUT}+10} +${HEAL_AFTER_REQUEST_TIMEOUT} ${${REQUEST_TIMEOUT}+10} +@{TRANSACTION_FAILED} ${500} +${PREF_BASED_SHARD} id-ints +${TEST_LOG_LEVEL} info +@{TEST_LOG_COMPONENTS} +... org.opendaylight.controller.cluster.sharding +... org.opendaylight.controller.cluster.datastore +${HEAL_WITHIN_TRANS_TIMEOUT} ${0} + *** Keywords *** Explicit_Leader_Movement_Test_Templ - [Arguments] ${leader_from} ${leader_to} ${shard_name}=${SHARD_NAME} ${shard_type}=${SHARD_TYPE} [Documentation] Implements explicit leader movement test scenario. - ${idx_from} ${idx_to} ${idx_trans} = Get_Node_Indexes_For_The_ELM_Test ${leader_from} ${leader_to} ${shard_name} + [Arguments] ${leader_from} ${leader_to} ${shard_name}=${SHARD_NAME} ${shard_type}=${SHARD_TYPE} + ${idx_from} ${idx_to} ${idx_trans} = Get_Node_Indexes_For_The_ELM_Test + ... ${leader_from} + ... ${leader_to} + ... ${shard_name} ... ${shard_type} - KarafKeywords.Log_Message_To_Controller_Karaf Starting leader movement from node${idx_from} to node${idx_to}, transaction producer at node${idx_trans}. + KarafKeywords.Log_Message_To_Controller_Karaf + ... Starting leader movement from node${idx_from} to node${idx_to}, transaction producer at node${idx_trans}. ${ip_trans_as_list} = BuiltIn.Create_List ${ODL_SYSTEM_${idx_trans}_IP} ${idx_trans_as_list} = BuiltIn.Create_List ${idx_trans} - MdsalLowlevelPy.Start_Write_Transactions_On_Nodes ${ip_trans_as_list} ${idx_trans_as_list} ${ID_PREFIX} ${TRANSACTION_PRODUCTION_TIME} ${TRANSACTION_RATE_1K} chained_flag=${CHAINED_TX} + MdsalLowlevelPy.Start_Write_Transactions_On_Nodes + ... ${ip_trans_as_list} + ... ${idx_trans_as_list} + ... ${ID_PREFIX} + ... ${TRANSACTION_PRODUCTION_TIME} + ... ${TRANSACTION_RATE_1K} + ... chained_flag=${CHAINED_TX} BuiltIn.Sleep ${SLEEP_AFTER_TRANSACTIONS_INIT} ClusterAdmin.Make_Leader_Local ${idx_to} ${shard_name} ${shard_type} - ${new_leader} ${new_followers} = BuiltIn.Wait_Until_Keyword_Succeeds 60s 5s ClusterManagement.Verify_Shard_Leader_Elected ${shard_name} - ... ${shard_type} ${True} ${idx_from} verify_restconf=False + ${new_leader} ${new_followers} = BuiltIn.Wait_Until_Keyword_Succeeds + ... 60s + ... 5s + ... ClusterManagement.Verify_Shard_Leader_Elected + ... ${shard_name} + ... ${shard_type} + ... ${True} + ... ${idx_from} + ... verify_restconf=False BuiltIn.Should_Be_Equal ${idx_to} ${new_leader} ${resp_list} = MdsalLowlevelPy.Wait_For_Transactions Check_Status_Of_First_Response ${resp_list} Explicit_Leader_Movement_PrefBasedShard_Test_Templ - [Arguments] ${leader_from} ${leader_to} ${shard_name}=${PREF_BASED_SHARD} ${shard_type}=${SHARD_TYPE} [Documentation] Implements explicit leader movement test scenario. - ${idx_from} ${idx_to} ${idx_trans} = Get_Node_Indexes_For_The_ELM_Test ${leader_from} ${leader_to} ${shard_name}!! + [Arguments] ${leader_from} ${leader_to} ${shard_name}=${PREF_BASED_SHARD} ${shard_type}=${SHARD_TYPE} + ${idx_from} ${idx_to} ${idx_trans} = Get_Node_Indexes_For_The_ELM_Test + ... ${leader_from} + ... ${leader_to} + ... ${shard_name}!! ... ${shard_type} ${ip_trans_as_list} = BuiltIn.Create_List ${ODL_SYSTEM_${idx_trans}_IP} ${idx_trans_as_list} = BuiltIn.Create_List ${idx_trans} - MdsalLowlevelPy.Start_Produce_Transactions_On_Nodes ${ip_trans_as_list} ${idx_trans_as_list} ${ID_PREFIX} ${TRANSACTION_PRODUCTION_TIME} ${TRANSACTION_RATE_1K} + MdsalLowlevelPy.Start_Produce_Transactions_On_Nodes + ... ${ip_trans_as_list} + ... ${idx_trans_as_list} + ... ${ID_PREFIX} + ... ${TRANSACTION_PRODUCTION_TIME} + ... ${TRANSACTION_RATE_1K} BuiltIn.Sleep ${SLEEP_AFTER_TRANSACTIONS_INIT} MdsalLowlevel.Become_Prefix_Leader ${idx_to} ${shard_name} - ${new_leader} ${new_followers} = BuiltIn.Wait_Until_Keyword_Succeeds 60s 5s ClusterManagement.Verify_Shard_Leader_Elected ${shard_name}!! - ... ${shard_type} ${True} ${idx_from} verify_restconf=False + ${new_leader} ${new_followers} = BuiltIn.Wait_Until_Keyword_Succeeds + ... 60s + ... 5s + ... ClusterManagement.Verify_Shard_Leader_Elected + ... ${shard_name}!! + ... ${shard_type} + ... ${True} + ... ${idx_from} + ... verify_restconf=False BuiltIn.Should_Be_Equal ${idx_to} ${new_leader} ${resp_list} = MdsalLowlevelPy.Wait_For_Transactions Check_Status_Of_First_Response ${resp_list} Get_Node_Indexes_For_The_ELM_Test - [Arguments] ${leader_from} ${leader_to} ${shard_name} ${shard_type} [Documentation] Return indexes for explicit leader movement test case, indexes of present to next leader node and index where transaction ... producer should be deployed. - ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=${shard_name} shard_type=${shard_type} verify_restconf=False + [Arguments] ${leader_from} ${leader_to} ${shard_name} ${shard_type} + ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=${shard_name} + ... shard_type=${shard_type} + ... verify_restconf=False ${idx_from} = BuiltIn.Set_Variable ${leader} ${idx_to} = BuiltIn.Set_Variable ${follower_list}[0] - ${idx_trans} = BuiltIn.Set_Variable_If "${leader_from}" == "remote" and "${leader_to}" == "remote" ${follower_list}[1] "${leader_from}" == "local" ${leader} "${leader_to}" == "local" + ${idx_trans} = BuiltIn.Set_Variable_If + ... "${leader_from}" == "remote" and "${leader_to}" == "remote" + ... ${follower_list}[1] + ... "${leader_from}" == "local" + ... ${leader} + ... "${leader_to}" == "local" ... ${follower_list}[0] - BuiltIn.Return_From_Keyword ${idx_from} ${idx_to} ${idx_trans} + RETURN ${idx_from} ${idx_to} ${idx_trans} Clean_Leader_Shutdown_Test_Templ - [Arguments] ${leader_location} ${shard_name}=${SHARD_NAME} ${shard_type}=${SHARD_TYPE} [Documentation] Implements clean leader shutdown test scenario. - ${producer_idx} ${actual_leader} ${follower_list} = Get_Node_Indexes_For_Clean_Leader_Shutdown_Test ${leader_location} ${shard_name} ${shard_type} + [Arguments] ${leader_location} ${shard_name}=${SHARD_NAME} ${shard_type}=${SHARD_TYPE} + ${producer_idx} ${actual_leader} ${follower_list} = Get_Node_Indexes_For_Clean_Leader_Shutdown_Test + ... ${leader_location} + ... ${shard_name} + ... ${shard_type} ${producer_ip_as_list} = BuiltIn.Create_List ${ODL_SYSTEM_${producer_idx}_IP} ${producer_idx_as_list} = BuiltIn.Create_List ${producer_idx} - MdsalLowlevelPy.Start_Write_Transactions_On_Nodes ${producer_ip_as_list} ${producer_idx_as_list} ${ID_PREFIX} ${TRANSACTION_PRODUCTION_TIME} ${TRANSACTION_RATE_1K} chained_flag=${CHAINED_TX} + MdsalLowlevelPy.Start_Write_Transactions_On_Nodes + ... ${producer_ip_as_list} + ... ${producer_idx_as_list} + ... ${ID_PREFIX} + ... ${TRANSACTION_PRODUCTION_TIME} + ... ${TRANSACTION_RATE_1K} + ... chained_flag=${CHAINED_TX} BuiltIn.Sleep ${SLEEP_AFTER_TRANSACTIONS_INIT} BuiltIn.Comment Bug 8794 workaround: Use remove-shard-replica until shutdown starts behaving properly. ClusterAdmin.Remove_Shard_Replica ${actual_leader} ${shard_name} member-${actual_leader} ${shard_type} - BuiltIn.Wait_Until_Keyword_Succeeds 60s 5s Verify_Shard_Replica_Not_Present ${actual_leader} ${shard_name} ${shard_type} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 60s + ... 5s + ... Verify_Shard_Replica_Not_Present + ... ${actual_leader} + ... ${shard_name} + ... ${shard_type} ${resp_list} = MdsalLowlevelPy.Wait_For_Transactions Check_Status_Of_First_Response ${resp_list} [Teardown] BuiltIn.Run_Keyword_And_Ignore_Error BuiltIn.Wait_Until_Keyword_Succeeds 120s 5s ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=${shard_name} ... shard_type=${shard_type} member_index_list=${follower_list} verify_restconf=False Clean_Leader_Shutdown_PrefBasedShard_Test_Templ - [Arguments] ${leader_location} ${shard_name}=${PREF_BASED_SHARD} ${shard_type}=${SHARD_TYPE} [Documentation] Implements clean leader shutdown test scenario. - ${producer_idx} ${actual_leader} ${follower_list} = Get_Node_Indexes_For_Clean_Leader_Shutdown_Test ${leader_location} ${shard_name}!! ${shard_type} + [Arguments] ${leader_location} ${shard_name}=${PREF_BASED_SHARD} ${shard_type}=${SHARD_TYPE} + ${producer_idx} ${actual_leader} ${follower_list} = Get_Node_Indexes_For_Clean_Leader_Shutdown_Test + ... ${leader_location} + ... ${shard_name}!! + ... ${shard_type} ${producer_ip_as_list} = BuiltIn.Create_List ${ODL_SYSTEM_${producer_idx}_IP} ${producer_idx_as_list} = BuiltIn.Create_List ${producer_idx} - MdsalLowlevelPy.Start_Produce_Transactions_On_Nodes ${producer_ip_as_list} ${producer_idx_as_list} ${ID_PREFIX} ${TRANSACTION_PRODUCTION_TIME} ${TRANSACTION_RATE_1K} + MdsalLowlevelPy.Start_Produce_Transactions_On_Nodes + ... ${producer_ip_as_list} + ... ${producer_idx_as_list} + ... ${ID_PREFIX} + ... ${TRANSACTION_PRODUCTION_TIME} + ... ${TRANSACTION_RATE_1K} BuiltIn.Sleep ${SLEEP_AFTER_TRANSACTIONS_INIT} BuiltIn.Comment Bug 8794 workaround: Use remove-shard-replica until shutdown starts behaving properly. - ClusterAdmin.Remove_Prefix_Shard_Replica ${actual_leader} ${shard_name} member-${actual_leader} ${shard_type} - BuiltIn.Wait_Until_Keyword_Succeeds 60s 5s Verify_Shard_Replica_Not_Present ${actual_leader} ${shard_name}!! ${shard_type} + ClusterAdmin.Remove_Prefix_Shard_Replica + ... ${actual_leader} + ... ${shard_name} + ... member-${actual_leader} + ... ${shard_type} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 60s + ... 5s + ... Verify_Shard_Replica_Not_Present + ... ${actual_leader} + ... ${shard_name}!! + ... ${shard_type} ${resp_list} = MdsalLowlevelPy.Wait_For_Transactions Check_Status_Of_First_Response ${resp_list} [Teardown] BuiltIn.Run_Keyword_And_Ignore_Error BuiltIn.Wait_Until_Keyword_Succeeds 120s 5s ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=${shard_name}!! ... shard_type=${shard_type} member_index_list=${follower_list} verify_restconf=False Get_Node_Indexes_For_Clean_Leader_Shutdown_Test - [Arguments] ${leader_location} ${shard_name} ${shard_type} [Documentation] Return indexes for clean leader shudown test case, index where transaction producer shoudl be deployed and a shard leader index. - ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=${shard_name} shard_type=${shard_type} verify_restconf=False + [Arguments] ${leader_location} ${shard_name} ${shard_type} + ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=${shard_name} + ... shard_type=${shard_type} + ... verify_restconf=False ${follower_list_leangth} = BuiltIn.Evaluate ${NUM_ODL_SYSTEM}-1 BuiltIn.Length_Should_Be ${follower_list} ${follower_list_leangth} ${producer_idx} = BuiltIn.Set_Variable_If "${leader_location}" == "local" ${leader} ${follower_list}[0] - BuiltIn.Return_From_Keyword ${producer_idx} ${leader} ${follower_list} + RETURN ${producer_idx} ${leader} ${follower_list} Leader_Isolation_Test_Templ - [Arguments] ${heal_timeout} ${shard_name}=${SHARD_NAME} ${shard_type}=${SHARD_TYPE} [Documentation] Implements leader isolation test scenario. - ${li_isolated} BuiltIn.Set_Variable ${False} - ${producing_transactions_time} = BuiltIn.Set_Variable_If ${heal_timeout}<${REQUEST_TIMEOUT} ${${REQUEST_TIMEOUT}+60} ${2*${REQUEST_TIMEOUT}} + [Arguments] ${heal_timeout} ${shard_name}=${SHARD_NAME} ${shard_type}=${SHARD_TYPE} + ${li_isolated} = BuiltIn.Set_Variable ${False} + ${producing_transactions_time} = BuiltIn.Set_Variable_If + ... ${heal_timeout}<${REQUEST_TIMEOUT} + ... ${${REQUEST_TIMEOUT}+60} + ... ${2*${REQUEST_TIMEOUT}} ${all_indices} = ClusterManagement.List_All_Indices - ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=${shard_name} shard_type=${shard_type} member_index_list=${all_indices} verify_restconf=False + ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=${shard_name} + ... shard_type=${shard_type} + ... member_index_list=${all_indices} + ... verify_restconf=False ${all_ip_list} = ClusterManagement.Resolve_IP_Address_For_Members ${all_indices} - MdsalLowlevelPy.Start_Write_Transactions_On_Nodes ${all_ip_list} ${all_indices} ${ID_PREFIX} ${producing_transactions_time} ${TRANSACTION_RATE_1K} chained_flag=${CHAINED_TX} + MdsalLowlevelPy.Start_Write_Transactions_On_Nodes + ... ${all_ip_list} + ... ${all_indices} + ... ${ID_PREFIX} + ... ${producing_transactions_time} + ... ${TRANSACTION_RATE_1K} + ... chained_flag=${CHAINED_TX} BuiltIn.Sleep ${SLEEP_AFTER_TRANSACTIONS_INIT} ${date_start} = DateTime.Get_Current_Date ${date_end} = DateTime.Add_Time_To_Date ${date_start} ${producing_transactions_time} KarafKeywords.Log_Message_To_Controller_Karaf Isolating node ${leader} ClusterManagement.Isolate_Member_From_List_Or_All ${leader} - ${li_isolated} BuiltIn.Set_Variable ${True} - BuiltIn.Wait_Until_Keyword_Succeeds 60s 5s ClusterManagement.Verify_Shard_Leader_Elected ${shard_name} ${shard_type} ${True} - ... ${leader} member_index_list=${follower_list} verify_restconf=False + ${li_isolated} = BuiltIn.Set_Variable ${True} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 60s + ... 5s + ... ClusterManagement.Verify_Shard_Leader_Elected + ... ${shard_name} + ... ${shard_type} + ... ${True} + ... ${leader} + ... member_index_list=${follower_list} + ... verify_restconf=False ${heal_date} = DateTime.Add_Time_To_Date ${date_start} ${heal_timeout} ${sleep_to_heal} = Get_Seconds_To_Time ${heal_date} ${resp} = MdsalLowlevelPy.Get_Next_Transactions_Response @@ -153,32 +257,65 @@ Leader_Isolation_Test_Templ BuiltIn.Sleep ${sleep_to_heal} KarafKeywords.Log_Message_To_Controller_Karaf Rejoining node ${leader} ClusterManagement.Rejoin_Member_From_List_Or_All ${leader} - ${li_isolated} BuiltIn.Set_Variable ${False} - BuiltIn.Wait_Until_Keyword_Succeeds 70s 10s ShardStability.Shards_Stability_Get_Details ${DEFAULT_SHARD_LIST} - BuiltIn.Wait_Until_Keyword_Succeeds 60s 5s ClusterManagement.Get_Leader_And_Followers_For_Shard ${shard_name} ${shard_type} verify_restconf=False + ${li_isolated} = BuiltIn.Set_Variable ${False} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 70s + ... 10s + ... ShardStability.Shards_Stability_Get_Details + ... ${DEFAULT_SHARD_LIST} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 60s + ... 5s + ... ClusterManagement.Get_Leader_And_Followers_For_Shard + ... ${shard_name} + ... ${shard_type} + ... verify_restconf=False ${time_to_finish} = Get_Seconds_To_Time ${date_end} - BuiltIn.Run_Keyword_If ${heal_timeout} < ${REQUEST_TIMEOUT} Leader_Isolation_Heal_Within_Rt - ... ELSE Module_Leader_Isolation_Heal_Default ${leader} ${time_to_finish} + IF ${heal_timeout} < ${REQUEST_TIMEOUT} + Leader_Isolation_Heal_Within_Rt + ELSE + Module_Leader_Isolation_Heal_Default ${leader} ${time_to_finish} + END [Teardown] BuiltIn.Run_Keyword_If ${li_isolated} BuiltIn.Run_Keywords ClusterManagement.Rejoin_Member_From_List_Or_All ${leader} ... AND BuiltIn.Wait_Until_Keyword_Succeeds 70s 10s ShardStability.Shards_Stability_Get_Details ${DEFAULT_SHARD_LIST} Leader_Isolation_PrefBasedShard_Test_Templ - [Arguments] ${heal_timeout} ${shard_name}=${PREF_BASED_SHARD} ${shard_type}=${SHARD_TYPE} [Documentation] Implements leader isolation test scenario. - ${li_isolated} BuiltIn.Set_Variable ${False} - ${producing_transactions_time} = BuiltIn.Set_Variable_If ${heal_timeout}<${REQUEST_TIMEOUT} ${${REQUEST_TIMEOUT}+60} ${2*${REQUEST_TIMEOUT}} + [Arguments] ${heal_timeout} ${shard_name}=${PREF_BASED_SHARD} ${shard_type}=${SHARD_TYPE} + ${li_isolated} = BuiltIn.Set_Variable ${False} + ${producing_transactions_time} = BuiltIn.Set_Variable_If + ... ${heal_timeout}<${REQUEST_TIMEOUT} + ... ${${REQUEST_TIMEOUT}+60} + ... ${2*${REQUEST_TIMEOUT}} ${all_indices} = ClusterManagement.List_All_Indices - ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=${shard_name}!! shard_type=${shard_type} member_index_list=${all_indices} verify_restconf=False + ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=${shard_name}!! + ... shard_type=${shard_type} + ... member_index_list=${all_indices} + ... verify_restconf=False ${all_ip_list} = ClusterManagement.Resolve_IP_Address_For_Members ${all_indices} - MdsalLowlevelPy.Start_Produce_Transactions_On_Nodes ${all_ip_list} ${all_indices} ${ID_PREFIX} ${producing_transactions_time} ${TRANSACTION_RATE_1K} + MdsalLowlevelPy.Start_Produce_Transactions_On_Nodes + ... ${all_ip_list} + ... ${all_indices} + ... ${ID_PREFIX} + ... ${producing_transactions_time} + ... ${TRANSACTION_RATE_1K} BuiltIn.Sleep ${SLEEP_AFTER_TRANSACTIONS_INIT} ${date_start} = DateTime.Get_Current_Date ${date_end} = DateTime.Add_Time_To_Date ${date_start} ${producing_transactions_time} KarafKeywords.Log_Message_To_Controller_Karaf Isolating node ${leader} ClusterManagement.Isolate_Member_From_List_Or_All ${leader} - ${li_isolated} BuiltIn.Set_Variable ${True} - BuiltIn.Wait_Until_Keyword_Succeeds 60s 5s ClusterManagement.Verify_Shard_Leader_Elected ${shard_name}!! ${shard_type} ${True} - ... ${leader} member_index_list=${follower_list} verify_restconf=False + ${li_isolated} = BuiltIn.Set_Variable ${True} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 60s + ... 5s + ... ClusterManagement.Verify_Shard_Leader_Elected + ... ${shard_name}!! + ... ${shard_type} + ... ${True} + ... ${leader} + ... member_index_list=${follower_list} + ... verify_restconf=False ${heal_date} = DateTime.Add_Time_To_Date ${date_start} ${heal_timeout} ${sleep_to_heal} = Get_Seconds_To_Time ${heal_date} ${resp} = MdsalLowlevelPy.Get_Next_Transactions_Response @@ -186,12 +323,25 @@ Leader_Isolation_PrefBasedShard_Test_Templ BuiltIn.Sleep ${sleep_to_heal} KarafKeywords.Log_Message_To_Controller_Karaf Rejoining node ${leader} ClusterManagement.Rejoin_Member_From_List_Or_All ${leader} - ${li_isolated} BuiltIn.Set_Variable ${False} - BuiltIn.Wait_Until_Keyword_Succeeds 70s 10s ShardStability.Shards_Stability_Get_Details ${DEFAULT_SHARD_LIST} - BuiltIn.Wait_Until_Keyword_Succeeds 60s 5s ClusterManagement.Get_Leader_And_Followers_For_Shard ${shard_name}!! ${shard_type} verify_restconf=False + ${li_isolated} = BuiltIn.Set_Variable ${False} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 70s + ... 10s + ... ShardStability.Shards_Stability_Get_Details + ... ${DEFAULT_SHARD_LIST} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 60s + ... 5s + ... ClusterManagement.Get_Leader_And_Followers_For_Shard + ... ${shard_name}!! + ... ${shard_type} + ... verify_restconf=False ${time_to_finish} = Get_Seconds_To_Time ${date_end} - BuiltIn.Run_Keyword_If ${heal_timeout} < ${REQUEST_TIMEOUT} Leader_Isolation_Heal_Within_Rt - ... ELSE Prefix_Leader_Isolation_Heal_Default ${leader} ${time_to_finish} + IF ${heal_timeout} < ${REQUEST_TIMEOUT} + Leader_Isolation_Heal_Within_Rt + ELSE + Prefix_Leader_Isolation_Heal_Default ${leader} ${time_to_finish} + END [Teardown] BuiltIn.Run_Keyword_If ${li_isolated} BuiltIn.Run_Keywords ClusterManagement.Rejoin_Member_From_List_Or_All ${leader} ... AND BuiltIn.Wait_Until_Keyword_Succeeds 70s 10s ShardStability.Shards_Stability_Get_Details ${DEFAULT_SHARD_LIST} @@ -204,17 +354,26 @@ Leader_Isolation_Heal_Within_Rt END Module_Leader_Isolation_Heal_Default - [Arguments] ${isolated_node} ${time_to_finish} [Documentation] The leader isolation test case end. The transaction producer on isolated node should fail and should be restarted. ... Then all write transaction producers should finish without error. + [Arguments] ${isolated_node} ${time_to_finish} ${resp} = MdsalLowlevelPy.Get_Next_Transactions_Response BuiltIn.Log ${resp} - BuiltIn.Should_Not_Be_Equal ${NONE} ${resp} Write-transaction should have returned error from isolated leader node. + BuiltIn.Should_Not_Be_Equal + ... ${NONE} + ... ${resp} + ... Write-transaction should have returned error from isolated leader node. # TODO: check on response status code - ${restart_producer_node_idx_as_list} BuiltIn.Create_List ${isolated_node} + ${restart_producer_node_idx_as_list} = BuiltIn.Create_List ${isolated_node} ${restart_producer_node_ip} = ClusterManagement.Resolve_IP_Address_For_Member ${isolated_node} - ${restart_producer_node_ip_as_list} BuiltIn.Create_List ${restart_producer_node_ip} - MdsalLowlevelPy.Start_Write_Transactions_On_Nodes ${restart_producer_node_ip_as_list} ${restart_producer_node_idx_as_list} ${ID_PREFIX2} ${time_to_finish} ${TRANSACTION_RATE_1K} chained_flag=${CHAINED_TX} + ${restart_producer_node_ip_as_list} = BuiltIn.Create_List ${restart_producer_node_ip} + MdsalLowlevelPy.Start_Write_Transactions_On_Nodes + ... ${restart_producer_node_ip_as_list} + ... ${restart_producer_node_idx_as_list} + ... ${ID_PREFIX2} + ... ${time_to_finish} + ... ${TRANSACTION_RATE_1K} + ... chained_flag=${CHAINED_TX} ... reset_globals=${False} ${resp_list} = MdsalLowlevelPy.Wait_For_Transactions FOR ${resp} IN @{resp_list} @@ -222,40 +381,62 @@ Module_Leader_Isolation_Heal_Default END Prefix_Leader_Isolation_Heal_Default - [Arguments] ${isolated_node} ${time_to_finish} [Documentation] The leader isolation test case end. The transaction producer on isolated node shoudl fail and should be restarted. ... Then all write transaction producers shoudl finish without error. + [Arguments] ${isolated_node} ${time_to_finish} ${resp} = MdsalLowlevelPy.Get_Next_Transactions_Response BuiltIn.Log ${resp} - BuiltIn.Should_Not_Be_Equal ${NONE} ${resp} Produce-transaction should have returned error from isolated leader node. + BuiltIn.Should_Not_Be_Equal + ... ${NONE} + ... ${resp} + ... Produce-transaction should have returned error from isolated leader node. # TODO: check on response status code - ${restart_producer_node_idx_as_list} BuiltIn.Create_List ${isolated_node} + ${restart_producer_node_idx_as_list} = BuiltIn.Create_List ${isolated_node} ${restart_producer_node_ip} = ClusterManagement.Resolve_IP_Address_For_Member ${isolated_node} - ${restart_producer_node_ip_as_list} BuiltIn.Create_List ${restart_producer_node_ip} - MdsalLowlevelPy.Start_Produce_Transactions_On_Nodes ${restart_producer_node_ip_as_list} ${restart_producer_node_idx_as_list} ${ID_PREFIX2} ${time_to_finish} ${TRANSACTION_RATE_1K} reset_globals=${False} + ${restart_producer_node_ip_as_list} = BuiltIn.Create_List ${restart_producer_node_ip} + MdsalLowlevelPy.Start_Produce_Transactions_On_Nodes + ... ${restart_producer_node_ip_as_list} + ... ${restart_producer_node_idx_as_list} + ... ${ID_PREFIX2} + ... ${time_to_finish} + ... ${TRANSACTION_RATE_1K} + ... reset_globals=${False} ${resp_list} = MdsalLowlevelPy.Wait_For_Transactions FOR ${resp} IN @{resp_list} TemplatedRequests.Check_Status_Code ${resp}[2] END Client_Isolation_Test_Templ - [Arguments] ${listener_node_role} ${trans_chain_flag} ${shard_name}=${SHARD_NAME} ${shard_type}=${SHARD_TYPE} [Documentation] Implements client isolation test scenario. + [Arguments] ${listener_node_role} ${trans_chain_flag} ${shard_name}=${SHARD_NAME} ${shard_type}=${SHARD_TYPE} ${all_indices} = ClusterManagement.List_All_Indices - ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=${shard_name} shard_type=${shard_type} member_index_list=${all_indices} verify_restconf=False + ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=${shard_name} + ... shard_type=${shard_type} + ... member_index_list=${all_indices} + ... verify_restconf=False ${follower1} = Collections.Get_From_List ${follower_list} ${0} ${client_node_dst} = BuiltIn.Set_Variable_If "${listener_node_role}" == "leader" ${leader} ${follower1} ${client_node_ip} = ClusterManagement.Resolve_IP_Address_For_Member ${client_node_dst} - ${client_node_ip_as_list} BuiltIn.Create_List ${client_node_ip} - ${client_node_idx_as_list} BuiltIn.Create_List ${client_node_dst} - ${start_date} DateTime.Get_Current_Date + ${client_node_ip_as_list} = BuiltIn.Create_List ${client_node_ip} + ${client_node_idx_as_list} = BuiltIn.Create_List ${client_node_dst} + ${start_date} = DateTime.Get_Current_Date ${abort_date} = DateTime.Add_Time_To_Date ${start_date} ${REQUEST_TIMEOUT} - MdsalLowlevelPy.Start_Write_Transactions_On_Nodes ${client_node_ip_as_list} ${client_node_idx_as_list} ${ID_PREFIX} ${TRANSACTION_PRODUCTION_TIME_2X_REQ_TIMEOUT} ${TRANSACTION_RATE_1K} chained_flag=${trans_chain_flag} + MdsalLowlevelPy.Start_Write_Transactions_On_Nodes + ... ${client_node_ip_as_list} + ... ${client_node_idx_as_list} + ... ${ID_PREFIX} + ... ${TRANSACTION_PRODUCTION_TIME_2X_REQ_TIMEOUT} + ... ${TRANSACTION_RATE_1K} + ... chained_flag=${trans_chain_flag} BuiltIn.Sleep ${SLEEP_AFTER_TRANSACTIONS_INIT} KarafKeywords.Log_Message_To_Controller_Karaf Isolating node ${client_node_dst} ClusterManagement.Isolate_Member_From_List_Or_All ${client_node_dst} ${rpc_timeout} = Get_Seconds_To_Time ${abort_date} - WaitForFailure.Verify_Keyword_Does_Not_Fail_Within_Timeout ${rpc_timeout} 1s Ongoing_Transactions_Not_Failed_Yet + WaitForFailure.Verify_Keyword_Does_Not_Fail_Within_Timeout + ... ${rpc_timeout} + ... 1s + ... Ongoing_Transactions_Not_Failed_Yet BuiltIn.Wait_Until_Keyword_Succeeds 20s 2s Ongoing_Transactions_Failed [Teardown] BuiltIn.Run Keywords KarafKeywords.Log_Message_To_Controller_Karaf Rejoining node ${client_node_dst} ... AND ClusterManagement.Rejoin_Member_From_List_Or_All ${client_node_dst} @@ -263,23 +444,36 @@ Client_Isolation_Test_Templ ... AND MdsalLowlevelPy.Wait_For_Transactions Client_Isolation_PrefBasedShard_Test_Templ - [Arguments] ${listener_node_role} ${isolated_transactions_flag} ${shard_name}=${PREF_BASED_SHARD} ${shard_type}=${SHARD_TYPE} [Documentation] Implements client isolation test scenario. + [Arguments] ${listener_node_role} ${isolated_transactions_flag} ${shard_name}=${PREF_BASED_SHARD} ${shard_type}=${SHARD_TYPE} ${all_indices} = ClusterManagement.List_All_Indices - ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=${shard_name}!! shard_type=${shard_type} member_index_list=${all_indices} verify_restconf=False + ${leader} ${follower_list} = ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=${shard_name}!! + ... shard_type=${shard_type} + ... member_index_list=${all_indices} + ... verify_restconf=False ${follower1} = Collections.Get_From_List ${follower_list} ${0} ${client_node_dst} = BuiltIn.Set_Variable_If "${listener_node_role}" == "leader" ${leader} ${follower1} ${client_node_ip} = ClusterManagement.Resolve_IP_Address_For_Member ${client_node_dst} - ${client_node_ip_as_list} BuiltIn.Create_List ${client_node_ip} - ${client_node_idx_as_list} BuiltIn.Create_List ${client_node_dst} - ${start_date} DateTime.Get_Current_Date + ${client_node_ip_as_list} = BuiltIn.Create_List ${client_node_ip} + ${client_node_idx_as_list} = BuiltIn.Create_List ${client_node_dst} + ${start_date} = DateTime.Get_Current_Date ${abort_date} = DateTime.Add_Time_To_Date ${start_date} ${REQUEST_TIMEOUT} - MdsalLowlevelPy.Start_Produce_Transactions_On_Nodes ${client_node_ip_as_list} ${client_node_idx_as_list} ${ID_PREFIX} ${TRANSACTION_PRODUCTION_TIME_2X_REQ_TIMEOUT} ${TRANSACTION_RATE_1K} isolated_transactions_flag=${isolated_transactions_flag} + MdsalLowlevelPy.Start_Produce_Transactions_On_Nodes + ... ${client_node_ip_as_list} + ... ${client_node_idx_as_list} + ... ${ID_PREFIX} + ... ${TRANSACTION_PRODUCTION_TIME_2X_REQ_TIMEOUT} + ... ${TRANSACTION_RATE_1K} + ... isolated_transactions_flag=${isolated_transactions_flag} BuiltIn.Sleep ${SLEEP_AFTER_TRANSACTIONS_INIT} KarafKeywords.Log_Message_To_Controller_Karaf Isolating node ${client_node_dst} ClusterManagement.Isolate_Member_From_List_Or_All ${client_node_dst} ${rpc_timeout} = Get_Seconds_To_Time ${abort_date} - WaitForFailure.Verify_Keyword_Does_Not_Fail_Within_Timeout ${rpc_timeout} 1s Ongoing_Transactions_Not_Failed_Yet + WaitForFailure.Verify_Keyword_Does_Not_Fail_Within_Timeout + ... ${rpc_timeout} + ... 1s + ... Ongoing_Transactions_Not_Failed_Yet BuiltIn.Wait_Until_Keyword_Succeeds 20s 2s Ongoing_Transactions_Failed [Teardown] BuiltIn.Run Keywords KarafKeywords.Log_Message_To_Controller_Karaf Rejoining node ${client_node_dst} ... AND ClusterManagement.Rejoin_Member_From_List_Or_All ${client_node_dst} @@ -297,27 +491,43 @@ Ongoing_Transactions_Failed Check_Status_Code ${resp}[2] explicit_status_codes=${TRANSACTION_FAILED} Get_Seconds_To_Time - [Arguments] ${date_in_future} [Documentation] Return number of seconds remaining to ${date_in_future}. + [Arguments] ${date_in_future} ${date_now} = DateTime.Get_Current_Date ${duration} = DateTime.Subtract_Date_From_Date ${date_in_future} ${date_now} BuiltIn.Run_Keyword_And_Return BuiltIn.Convert_To_Integer ${duration} Listener_Stability_Test_Templ - [Arguments] ${leader_from} ${leader_to} ${shard_name}=${SHARD_NAME} ${shard_type}=${SHARD_TYPE} [Documentation] Implements listener stability test scenario for module-based shards. + [Arguments] ${leader_from} ${leader_to} ${shard_name}=${SHARD_NAME} ${shard_type}=${SHARD_TYPE} ${subscribed} = BuiltIn.Set_Variable ${False} ${all_indices} = ClusterManagement.List_All_Indices - ${idx_from} ${idx_to} ${idx_listen} = Get_Node_Indexes_For_The_ELM_Test ${leader_from} ${leader_to} ${shard_name} + ${idx_from} ${idx_to} ${idx_listen} = Get_Node_Indexes_For_The_ELM_Test + ... ${leader_from} + ... ${leader_to} + ... ${shard_name} ... ${shard_type} MdsalLowlevel.Subscribe_Dtcl ${idx_listen} ${subscribed} = BuiltIn.Set_Variable ${True} ${all_ip_list} = ClusterManagement.Resolve_IP_Address_For_Members ${all_indices} - MdsalLowlevelPy.Start_Write_Transactions_On_Nodes ${all_ip_list} ${all_indices} ${ID_PREFIX} ${TRANSACTION_PRODUCTION_TIME} ${TRANSACTION_RATE_1K} chained_flag=${CHAINED_TX} + MdsalLowlevelPy.Start_Write_Transactions_On_Nodes + ... ${all_ip_list} + ... ${all_indices} + ... ${ID_PREFIX} + ... ${TRANSACTION_PRODUCTION_TIME} + ... ${TRANSACTION_RATE_1K} + ... chained_flag=${CHAINED_TX} BuiltIn.Sleep ${SLEEP_AFTER_TRANSACTIONS_INIT} ClusterAdmin.Make_Leader_Local ${idx_to} ${shard_name} ${shard_type} - ${new_leader} ${new_followers} = BuiltIn.Wait_Until_Keyword_Succeeds 60s 5s ClusterManagement.Verify_Shard_Leader_Elected ${shard_name} - ... ${shard_type} ${True} ${idx_from} verify_restconf=False + ${new_leader} ${new_followers} = BuiltIn.Wait_Until_Keyword_Succeeds + ... 60s + ... 5s + ... ClusterManagement.Verify_Shard_Leader_Elected + ... ${shard_name} + ... ${shard_type} + ... ${True} + ... ${idx_from} + ... verify_restconf=False BuiltIn.Should_Be_Equal ${idx_to} ${new_leader} ${resp_list} = MdsalLowlevelPy.Wait_For_Transactions FOR ${resp} IN @{resp_list} @@ -329,20 +539,35 @@ Listener_Stability_Test_Templ [Teardown] BuiltIn.Run_Keyword_If ${subscribed} MdsalLowlevel.Unsubscribe_Dtcl ${idx_listen} Listener_Stability_PrefBasedShard_Test_Templ - [Arguments] ${leader_from} ${leader_to} ${shard_name}=${PREF_BASED_SHARD} ${shard_type}=${SHARD_TYPE} [Documentation] Implements listener stability test scenario for prefix-based shards. + [Arguments] ${leader_from} ${leader_to} ${shard_name}=${PREF_BASED_SHARD} ${shard_type}=${SHARD_TYPE} ${subscribed} = BuiltIn.Set_Variable ${False} ${all_indices} = ClusterManagement.List_All_Indices - ${idx_from} ${idx_to} ${idx_listen} = Get_Node_Indexes_For_The_ELM_Test ${leader_from} ${leader_to} ${shard_name}!! + ${idx_from} ${idx_to} ${idx_listen} = Get_Node_Indexes_For_The_ELM_Test + ... ${leader_from} + ... ${leader_to} + ... ${shard_name}!! ... ${shard_type} MdsalLowlevel.Subscribe_Ddtl ${idx_listen} ${subscribed} = BuiltIn.Set_Variable ${True} ${all_ip_list} = ClusterManagement.Resolve_IP_Address_For_Members ${all_indices} - MdsalLowlevelPy.Start_Produce_Transactions_On_Nodes ${all_ip_list} ${all_indices} ${ID_PREFIX} ${TRANSACTION_PRODUCTION_TIME} ${TRANSACTION_RATE_1K} + MdsalLowlevelPy.Start_Produce_Transactions_On_Nodes + ... ${all_ip_list} + ... ${all_indices} + ... ${ID_PREFIX} + ... ${TRANSACTION_PRODUCTION_TIME} + ... ${TRANSACTION_RATE_1K} BuiltIn.Sleep ${SLEEP_AFTER_TRANSACTIONS_INIT} MdsalLowlevel.Become_Prefix_Leader ${idx_to} ${shard_name} - ${new_leader} ${new_followers} = BuiltIn.Wait_Until_Keyword_Succeeds 60s 5s ClusterManagement.Verify_Shard_Leader_Elected ${shard_name}!! - ... ${shard_type} ${True} ${idx_from} verify_restconf=False + ${new_leader} ${new_followers} = BuiltIn.Wait_Until_Keyword_Succeeds + ... 60s + ... 5s + ... ClusterManagement.Verify_Shard_Leader_Elected + ... ${shard_name}!! + ... ${shard_type} + ... ${True} + ... ${idx_from} + ... verify_restconf=False BuiltIn.Should_Be_Equal ${idx_to} ${new_leader} ${resp_list} = MdsalLowlevelPy.Wait_For_Transactions FOR ${resp} IN @{resp_list} @@ -354,17 +579,23 @@ Listener_Stability_PrefBasedShard_Test_Templ [Teardown] BuiltIn.Run_Keyword_If ${subscribed} MdsalLowlevel.Unsubscribe_Ddtl ${idx_listen} Create_Prefix_Based_Shard_And_Verify - [Arguments] ${prefix}=${PREF_BASED_SHARD} [Documentation] Create prefix based shard with replicas on all nodes + [Arguments] ${prefix}=${PREF_BASED_SHARD} ${all_indices} = ClusterManagement.List_All_Indices ${node_to_trigger} = Collections.Get_From_List ${all_indices} ${0} MdsalLowlevel.Create_Prefix_Shard ${node_to_trigger} ${prefix} ${all_indices} - BuiltIn.Wait_Until_Keyword_Succeeds 60s 5s ClusterManagement.Get_Leader_And_Followers_For_Shard shard_name=${prefix}!! shard_type=${SHARD_TYPE} member_index_list=${all_indices} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 60s + ... 5s + ... ClusterManagement.Get_Leader_And_Followers_For_Shard + ... shard_name=${prefix}!! + ... shard_type=${SHARD_TYPE} + ... member_index_list=${all_indices} ... verify_restconf=False Remove_Prefix_Based_Shard_And_Verify - [Arguments] ${prefix}=${PREF_BASED_SHARD} [Documentation] Remove prefix based shard with all replicas + [Arguments] ${prefix}=${PREF_BASED_SHARD} ${all_indices} = ClusterManagement.List_All_Indices ${node_to_trigger} = Collections.Get_From_List ${all_indices} ${0} MdsalLowlevel.Remove_Prefix_Shard ${node_to_trigger} ${prefix} @@ -374,12 +605,13 @@ Remove_Prefix_Based_Shard_And_Verify END Verify_Shard_Replica_Not_Present - [Arguments] ${member_index} ${shard_name} ${shard_type} [Documentation] Verify that shard is removed. Jolokia return 404 for shard memeber. + [Arguments] ${member_index} ${shard_name} ${shard_type} ${session} = Resolve_Http_Session_For_Member member_index=${member_index} ${type_class} = Resolve_Shard_Type_Class shard_type=${shard_type} - ${uri} = BuiltIn.Set_Variable /jolokia/read/org.opendaylight.controller:Category=Shards,name=member-${member_index}-shard-${shard_name}-${shard_type},type=${type_class} - ${text} TemplatedRequests.Get_From_Uri uri=${uri} session=${session} + ${uri} = BuiltIn.Set_Variable + ... /jolokia/read/org.opendaylight.controller:Category=Shards,name=member-${member_index}-shard-${shard_name}-${shard_type},type=${type_class} + ${text} = TemplatedRequests.Get_From_Uri uri=${uri} session=${session} BuiltIn.Should_Contain ${text} "status":404 javax.management.InstanceNotFoundException Restart_Test_Templ @@ -387,21 +619,34 @@ Restart_Test_Templ ClusterManagement.Stop_Members_From_List_Or_All ClusterManagement.Clean_Directories_On_List_Or_All tmp_dir=/tmp ClusterManagement.Start_Members_From_List_Or_All - BuiltIn.Wait_Until_Keyword_Succeeds 300s 10s ShardStability.Shards_Stability_Get_Details ${DEFAULT_SHARD_LIST} verify_restconf=True + BuiltIn.Wait_Until_Keyword_Succeeds + ... 300s + ... 10s + ... ShardStability.Shards_Stability_Get_Details + ... ${DEFAULT_SHARD_LIST} + ... verify_restconf=True ClusterManagement.Run_Bash_Command_On_List_Or_All ps -ef | grep java Check_Status_Of_First_Response - [Arguments] ${resp_list} [Documentation] Extract first item from the list, third item of the tuple and call TemplatedRequests to check the http status code. + [Arguments] ${resp_list} # ${resp_list}[0][2] does not work ${tuple} = BuiltIn.Set_Variable ${resp_list}[0] TemplatedRequests.Check_Status_Code ${tuple}[2] Change_Use_Tell_Based_Protocol - [Arguments] ${status} ${DATASTORE_CFG} [Documentation] Change status use-tell-based-protocol to True or False - ClusterManagement.Check_Bash_Command_On_List_Or_All sed -ie "s/^#use-tell-based-protocol=true/use-tell-based-protocol=true/g" ${DATASTORE_CFG} - ClusterManagement.Check_Bash_Command_On_List_Or_All sed -ie "s/^#use-tell-based-protocol=false/use-tell-based-protocol=false/g" ${DATASTORE_CFG} - BuiltIn.Run_Keyword_And_Return_If "${status}" == "True" ClusterManagement.Check_Bash_Command_On_List_Or_All sed -ie "s/^use-tell-based-protocol=false/use-tell-based-protocol=true/g" ${DATASTORE_CFG} - BuiltIn.Run_Keyword_And_Return_If "${status}" == "False" ClusterManagement.Check_Bash_Command_On_List_Or_All sed -ie "s/^use-tell-based-protocol=true/use-tell-based-protocol=false/g" ${DATASTORE_CFG} + [Arguments] ${status} ${DATASTORE_CFG} + ClusterManagement.Check_Bash_Command_On_List_Or_All + ... sed -ie "s/^#use-tell-based-protocol=true/use-tell-based-protocol=true/g" ${DATASTORE_CFG} + ClusterManagement.Check_Bash_Command_On_List_Or_All + ... sed -ie "s/^#use-tell-based-protocol=false/use-tell-based-protocol=false/g" ${DATASTORE_CFG} + BuiltIn.Run_Keyword_And_Return_If + ... "${status}" == "True" + ... ClusterManagement.Check_Bash_Command_On_List_Or_All + ... sed -ie "s/^use-tell-based-protocol=false/use-tell-based-protocol=true/g" ${DATASTORE_CFG} + BuiltIn.Run_Keyword_And_Return_If + ... "${status}" == "False" + ... ClusterManagement.Check_Bash_Command_On_List_Or_All + ... sed -ie "s/^use-tell-based-protocol=true/use-tell-based-protocol=false/g" ${DATASTORE_CFG} BuiltIn.Fail Failure in status. Status can be True or False. diff --git a/csit/libraries/controller/DnbCommons.robot b/csit/libraries/controller/DnbCommons.robot index ab5ac8f935..01308dab80 100644 --- a/csit/libraries/controller/DnbCommons.robot +++ b/csit/libraries/controller/DnbCommons.robot @@ -1,34 +1,38 @@ *** Settings *** -Documentation DOMNotificationBroker testing: Common keywords +Documentation DOMNotificationBroker testing: Common keywords ... -... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html -Library Collections -Resource ${CURDIR}/../MdsalLowlevel.robot -Resource ${CURDIR}/../ScalarClosures.robot -Resource ${CURDIR}/../WaitUtils.robot +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html + +Library Collections +Resource ${CURDIR}/../MdsalLowlevel.robot +Resource ${CURDIR}/../ScalarClosures.robot +Resource ${CURDIR}/../WaitUtils.robot + *** Variables *** # There is half a megabyte of output.xml per check. # Even with check period of 15 seconds that makes more than 2 GB of output, # which is too much for processing into log.html (out of memory errors). -${DNB_CHECK_PERIOD_IN_SECONDS} 600 -${DNB_CHECK_TOLERANCE_IN_SECONDS} ${${DNB_CHECK_PERIOD_IN_SECONDS}*1.2} -${DNB_PUBLISHER_SUBSCRIBER_PAIR_RATE} ${5000} -${DNB_PUBLISHER_LISTENER_PREFIX} working-pair- -${DNB_TESTED_MEMBER_INDEX} 1 +${DNB_CHECK_PERIOD_IN_SECONDS} 600 +${DNB_CHECK_TOLERANCE_IN_SECONDS} ${${DNB_CHECK_PERIOD_IN_SECONDS}*1.2} +${DNB_PUBLISHER_SUBSCRIBER_PAIR_RATE} ${5000} +${DNB_PUBLISHER_LISTENER_PREFIX} working-pair- +${DNB_TESTED_MEMBER_INDEX} 1 + *** Keywords *** Dom_Notification_Broker_Test_Templ - [Arguments] ${total_notification_rate} ${test_duration_in_seconds} [Documentation] Test case template. Input parameter ${total_notification_rate} determines, how many publisher/subscriber ... pais take part in the test case. For every ${DNB_PUBLISHER_SUBSCRIBER_PAIR_RATE} one pair is created. ... The test case itself firstly subscribe listeners, then run publishers and at the end unsubscribe listeners ... and check achieved rates. - BuiltIn.Log Overall requested rate: ${total_notification_rate}, test duration: ${test_duration_in_seconds} seconds. + [Arguments] ${total_notification_rate} ${test_duration_in_seconds} + BuiltIn.Log + ... Overall requested rate: ${total_notification_rate}, test duration: ${test_duration_in_seconds} seconds. WaitUtils.WU_Setup ${count} = BuiltIn.Set_variable ${0} FOR ${suffix} IN RANGE ${DNB_PUBLISHER_SUBSCRIBER_PAIR_RATE} ${total_notification_rate}+1 ${DNB_PUBLISHER_SUBSCRIBER_PAIR_RATE} @@ -37,17 +41,32 @@ Dom_Notification_Broker_Test_Templ END ${count} = BuiltIn.Convert_To_Integer ${count} FOR ${index} IN RANGE 1 ${count}+1 - MdsalLowlevel.Start_Publish_Notifications ${DNB_TESTED_MEMBER_INDEX} ${DNB_PUBLISHER_LISTENER_PREFIX}${index} ${test_duration_in_seconds} ${DNB_PUBLISHER_SUBSCRIBER_PAIR_RATE} + MdsalLowlevel.Start_Publish_Notifications + ... ${DNB_TESTED_MEMBER_INDEX} + ... ${DNB_PUBLISHER_LISTENER_PREFIX}${index} + ... ${test_duration_in_seconds} + ... ${DNB_PUBLISHER_SUBSCRIBER_PAIR_RATE} END - ${getter} = ScalarClosures.Closure_From_Keyword_And_Arguments Get_Notifications_Active_Status ${DNB_TESTED_MEMBER_INDEX} ${count} - ${validator} = ScalarClosures.Closure_From_Keyword_And_Arguments Check_Notifications_Active_Status data_holder - ${validation_timeout_in_seconds} = BuiltIn.Evaluate ${test_duration_in_seconds}+${DNB_CHECK_TOLERANCE_IN_SECONDS} - WaitUtils.Wait_For_Getter_Failure_Or_Stateless_Validator_Pass timeout=${validation_timeout_in_seconds}s period=${DNB_CHECK_PERIOD_IN_SECONDS}s getter=${getter} stateless_validator=${validator} - ${sum_local_number} BuiltIn.Set_Variable ${0} + ${getter} = ScalarClosures.Closure_From_Keyword_And_Arguments + ... Get_Notifications_Active_Status + ... ${DNB_TESTED_MEMBER_INDEX} + ... ${count} + ${validator} = ScalarClosures.Closure_From_Keyword_And_Arguments + ... Check_Notifications_Active_Status + ... data_holder + ${validation_timeout_in_seconds} = BuiltIn.Evaluate + ... ${test_duration_in_seconds}+${DNB_CHECK_TOLERANCE_IN_SECONDS} + WaitUtils.Wait_For_Getter_Failure_Or_Stateless_Validator_Pass + ... timeout=${validation_timeout_in_seconds}s + ... period=${DNB_CHECK_PERIOD_IN_SECONDS}s + ... getter=${getter} + ... stateless_validator=${validator} + ${sum_local_number} = BuiltIn.Set_Variable ${0} ${low_limit_pair_rate} = BuiltIn.Evaluate 0.9*${DNB_PUBLISHER_SUBSCRIBER_PAIR_RATE} ${high_limit_pair_rate} = BuiltIn.Evaluate 1.1*${DNB_PUBLISHER_SUBSCRIBER_PAIR_RATE} FOR ${index} IN RANGE 1 ${count}+1 - ${all_not} ${id_not} ${err_not} ${local_number} = MdsalLowlevel.Unsubscribe_Ynl ${DNB_TESTED_MEMBER_INDEX} + ${all_not} ${id_not} ${err_not} ${local_number} = MdsalLowlevel.Unsubscribe_Ynl + ... ${DNB_TESTED_MEMBER_INDEX} ... ${DNB_PUBLISHER_LISTENER_PREFIX}${index} BuiltIn.Should_Be_Equal_As_Numbers ${err_not} ${0} BuiltIn.Should_Not_Be_Equal_As_Numbers ${local_number} ${0} @@ -67,11 +86,13 @@ Get_Notifications_Active_Status [Arguments] ${node_to_ask} ${nr_pairs} ${active_list} = BuiltIn.Create_List FOR ${index} IN RANGE 1 ${nr_pairs}+1 - ${active} ${publ_count} ${last_error} MdsalLowlevel.Check_Publish_Notifications ${node_to_ask} ${DNB_PUBLISHER_LISTENER_PREFIX}${index} + ${active} ${publ_count} ${last_error} = MdsalLowlevel.Check_Publish_Notifications + ... ${node_to_ask} + ... ${DNB_PUBLISHER_LISTENER_PREFIX}${index} Collections.Append_To_List ${active_list} ${active} BuiltIn.Should_Be_Equal ${EMPTY} ${last_error} END - BuiltIn.Return_From_Keyword ${active_list} + RETURN ${active_list} Check_Notifications_Active_Status [Arguments] ${active_list} diff --git a/csit/libraries/controller/DrbCommons.robot b/csit/libraries/controller/DrbCommons.robot index 1bbd0ab208..992f54ba8c 100644 --- a/csit/libraries/controller/DrbCommons.robot +++ b/csit/libraries/controller/DrbCommons.robot @@ -1,42 +1,45 @@ *** Settings *** -Documentation DOMRpcBroker testing: Common keywords +Documentation DOMRpcBroker testing: Common keywords ... -... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... -... The aim of this resource is to groups reusable blocks of commands into -... keywords. It should be initiated by DrbCommons_Init. It creates -... ${all_indices}, ${registered_indices}, ${nonregistered_indices} and -... ${possible_constants} suite variables. -... ${registered_indices} - list of indexes where rpc is registered; including -... isolated mebers; exluding killed/stopped members -... ${nonregistered_indices} - list of indexes where rpc is not registrated; -... including isolated mebers; exluding killed/stopped -... members -... ${possible_constants} - list of valid constants responded from the cluster; -... constant from isolated node with regirered rpc is -... invalid -... ${active_indices} - list of indexes of non-isolated, non-stopped/killed nodes +... The aim of this resource is to groups reusable blocks of commands into +... keywords. It should be initiated by DrbCommons_Init. It creates +... ${all_indices}, ${registered_indices}, ${nonregistered_indices} and +... ${possible_constants} suite variables. +... ${registered_indices} - list of indexes where rpc is registered; including +... isolated mebers; exluding killed/stopped members +... ${nonregistered_indices} - list of indexes where rpc is not registrated; +... including isolated mebers; exluding killed/stopped +... members +... ${possible_constants} - list of valid constants responded from the cluster; +... constant from isolated node with regirered rpc is +... invalid +... ${active_indices} - list of indexes of non-isolated, non-stopped/killed nodes ... -... Akka can create spurious UnreachableMember events, see -... https://bugs.opendaylight.org/show_bug.cgi?id=8430 -... so some keywords contain "tolerance" argument which applies BuiltIn.Wait_Until_Keyword_Succeeds. +... Akka can create spurious UnreachableMember events, see +... https://bugs.opendaylight.org/show_bug.cgi?id=8430 +... so some keywords contain "tolerance" argument which applies BuiltIn.Wait_Until_Keyword_Succeeds. ... -... The delay before subsequent ReachableMember is significantly higher than -... RPC registration delay documented at -... http://docs.opendaylight.org/en/latest/developer-guide/controller.html#rpcs-and-cluster -Library Collections -Resource ${CURDIR}/../ClusterManagement.robot -Resource ${CURDIR}/../MdsalLowlevel.robot -Resource ${CURDIR}/../ShardStability.robot +... The delay before subsequent ReachableMember is significantly higher than +... RPC registration delay documented at +... http://docs.opendaylight.org/en/latest/developer-guide/controller.html#rpcs-and-cluster + +Library Collections +Resource ${CURDIR}/../ClusterManagement.robot +Resource ${CURDIR}/../MdsalLowlevel.robot +Resource ${CURDIR}/../ShardStability.robot + *** Variables *** -${CONSTANT_PREFIX} constant- -${CONTEXT} context -${BUG_8430_TOLERANCE} 10 +${CONSTANT_PREFIX} constant- +${CONTEXT} context +${BUG_8430_TOLERANCE} 10 + *** Keywords *** DrbCommons_Init @@ -54,211 +57,237 @@ DrbCommons_Init BuiltIn.Set_Suite_Variable ${registered_indices} Register_Rpc_And_Update_Possible_Constants - [Arguments] ${member_index} [Documentation] Register global rpc on given node of the cluster. + [Arguments] ${member_index} MdsalLowlevel.Register_Constant ${member_index} ${CONSTANT_PREFIX}${member_index} DrbCommons__Add_Possible_Constant ${member_index} DrbCommons__Register_Index ${member_index} Unregister_Rpc_And_Update_Possible_Constants - [Arguments] ${member_index} [Documentation] Unregister global rpc on given node of the cluster. + [Arguments] ${member_index} MdsalLowlevel.Unregister_Constant ${member_index} DrbCommons__Rem_Possible_Constant ${member_index} DrbCommons__Deregister_Index ${member_index} Register_Action_And_Update_Possible_Constants - [Arguments] ${member_index} [Documentation] Register routed rpc on given node of the cluster. + [Arguments] ${member_index} MdsalLowlevel.Register_Bound_Constant ${member_index} ${CONTEXT} ${CONSTANT_PREFIX}${member_index} DrbCommons__Add_Possible_Constant ${member_index} DrbCommons__Register_Index ${member_index} Unregister_Action_And_Update_Possible_Constants - [Arguments] ${member_index} [Documentation] Unregister routed rpc on given node of the cluster. + [Arguments] ${member_index} MdsalLowlevel.Unregister_Bound_Constant ${member_index} ${CONTEXT} DrbCommons__Rem_Possible_Constant ${member_index} DrbCommons__Deregister_Index ${member_index} Register_Rpc_On_Nodes - [Arguments] ${index_list} [Documentation] Register global rpc on given nodes of the cluster. + [Arguments] ${index_list} FOR ${index} IN @{index_list} Register_Rpc_And_Update_Possible_Constants ${index} END Unregister_Rpc_On_Nodes - [Arguments] ${index_list} [Documentation] Unregister global rpc on given nodes of the cluster. + [Arguments] ${index_list} FOR ${index} IN @{index_list} Unregister_Rpc_And_Update_Possible_Constants ${index} END Register_Action_On_Nodes - [Arguments] ${index_list} [Documentation] Register global rpc on given nodes of the cluster. + [Arguments] ${index_list} FOR ${index} IN @{index_list} Register_Action_And_Update_Possible_Constants ${index} END Unregister_Action_On_Nodes - [Arguments] ${index_list} [Documentation] Unregister global rpc on given nodes of the cluster. + [Arguments] ${index_list} FOR ${index} IN @{index_list} Unregister_Action_And_Update_Possible_Constants ${index} END Verify_Constant_On_Registered_Node - [Arguments] ${member_index} [Documentation] Verify that the rpc response comes from the local node. + [Arguments] ${member_index} ${constant} = MdsalLowlevel.Get_Constant ${member_index} BuiltIn.Should_Be_Equal_As_Strings ${CONSTANT_PREFIX}${member_index} ${constant} - BuiltIn.Return_From_Keyword ${constant} + RETURN ${constant} Verify_Constant_On_Unregistered_Node - [Arguments] ${member_index} [Documentation] Verify that the response comes from other nodes with rpc registered. Verification ... passes for registered nodes too. + [Arguments] ${member_index} ${constant} = MdsalLowlevel.Get_Constant ${member_index} Collections.List_Should_Contain_Value ${possible_constants} ${constant} - BuiltIn.Return_From_Keyword ${constant} + RETURN ${constant} Verify_Contexted_Constant_On_Registered_Node - [Arguments] ${member_index} [Documentation] Verify that the rpc response comes from the local node. + [Arguments] ${member_index} ${constant} = MdsalLowlevel.Get_Contexted_Constant ${member_index} ${CONTEXT} BuiltIn.Should_Be_Equal_As_Strings ${CONSTANT_PREFIX}${member_index} ${constant} - BuiltIn.Return_From_Keyword ${constant} + RETURN ${constant} Verify_Contexted_Constant_On_Unregistered_Node - [Arguments] ${member_index} [Documentation] Verify that the response comes from other nodes with rpc registered. Verification ... passes for registered nodes too. + [Arguments] ${member_index} ${constant} = MdsalLowlevel.Get_Contexted_Constant ${member_index} ${CONTEXT} Collections.List_Should_Contain_Value ${possible_constants} ${constant} - BuiltIn.Return_From_Keyword ${constant} + RETURN ${constant} Verify_Constant_On_Registered_Nodes - [Arguments] ${index_list} [Documentation] Verify that the rpc response comes from the local node for every node in the list. + [Arguments] ${index_list} FOR ${index} IN @{index_list} Verify_Constant_On_Registered_Node ${index} END Verify_Contexted_Constant_On_Registered_Nodes - [Arguments] ${index_list} [Documentation] Verify that the rpc response comes from the local node for every node in the list. + [Arguments] ${index_list} FOR ${index} IN @{index_list} Verify_Contexted_Constant_On_Registered_Node ${index} END Verify_Constant_On_Unregistered_Nodes - [Arguments] ${index_list} [Documentation] Verify that the rpc response comes from the remote node for every node in the list. + [Arguments] ${index_list} FOR ${index} IN @{index_list} Verify_Constant_On_Unregistered_Node ${index} END Verify_Constant_On_Active_Nodes - [Arguments] ${tolerance}=${BUG_8430_TOLERANCE} [Documentation] Verify that the rpc response comes from the local node for every node in the list. ... As a workaround for Bug 8430, \${tolerance} can be set as duration (number of seconds) for WUKS. + [Arguments] ${tolerance}=${BUG_8430_TOLERANCE} # TODO: Rename most Verify_* keywords to Check_* and use the Verify prefix for the WUKS versions. - BuiltIn.Run_Keyword_And_Return_If ${tolerance} BuiltIn.Wait_Until_Keyword_Succeeds ${tolerance} 1s Verify_Constant_On_Active_Nodes tolerance=0 + BuiltIn.Run_Keyword_And_Return_If + ... ${tolerance} + ... BuiltIn.Wait_Until_Keyword_Succeeds + ... ${tolerance} + ... 1s + ... Verify_Constant_On_Active_Nodes + ... tolerance=0 FOR ${index} IN @{active_indices} - BuiltIn.Run_Keyword_If ${index} in ${registered_indices} Verify_Constant_On_Registered_Node ${index} - ... ELSE Verify_Constant_On_Unregistered_Node ${index} + IF ${index} in ${registered_indices} + Verify_Constant_On_Registered_Node ${index} + ELSE + Verify_Constant_On_Unregistered_Node ${index} + END END Verify_Contexted_Constant_On_Active_Nodes - [Arguments] ${tolerance}=${BUG_8430_TOLERANCE} [Documentation] Verify that the rpc response comes from the local node for every node in the list. ... As a workaround for Bug 8430, \${tolerance} can be set as duration (number of seconds) for WUKS. + [Arguments] ${tolerance}=${BUG_8430_TOLERANCE} # TODO: Rename most Verify_* keywords to Check_* and use the Verify prefix for the WUKS versions. - BuiltIn.Run_Keyword_And_Return_If ${tolerance} BuiltIn.Wait_Until_Keyword_Succeeds ${tolerance} 1s Verify_Contexted_Constant_On_Active_Nodes tolerance=0 + BuiltIn.Run_Keyword_And_Return_If + ... ${tolerance} + ... BuiltIn.Wait_Until_Keyword_Succeeds + ... ${tolerance} + ... 1s + ... Verify_Contexted_Constant_On_Active_Nodes + ... tolerance=0 FOR ${index} IN @{active_indices} - BuiltIn.Run_Keyword_If ${index} in ${registered_indices} Verify_Contexted_Constant_On_Registered_Node ${index} - ... ELSE Verify_Contexted_Constant_On_Unregistered_Node ${index} + IF ${index} in ${registered_indices} + Verify_Contexted_Constant_On_Registered_Node ${index} + ELSE + Verify_Contexted_Constant_On_Unregistered_Node ${index} + END END Verify_Expected_Constant_On_Nodes - [Arguments] ${index_list} ${exp_constant} [Documentation] Verify that the rpc response comes only from one node only for every node in the list. + [Arguments] ${index_list} ${exp_constant} FOR ${index} IN @{index_list} ${const_index} = Get_Constant_Index_From_Node ${index} BuiltIn.Should_Be_Equal_As_Strings ${exp_constant} ${CONSTANT_PREFIX}${const_index} END Get_Constant_Index_From_Node - [Arguments] ${member_index} [Documentation] Ivoke get-constant rpc on given member index. Returns the index of ... the node where the constant came from. + [Arguments] ${member_index} ${constant} = MdsalLowlevel.Get_Constant ${member_index} ${index} = String.Replace_String ${constant} ${CONSTANT_PREFIX} ${EMPTY} ${index} = BuiltIn.Convert_To_Integer ${index} - BuiltIn.Return_From_Keyword ${index} + RETURN ${index} Get_Contexted_Constant_Index_From_Node - [Arguments] ${member_index} [Documentation] Ivoke get-contexted-constant rpc on given member index. Returns the index of ... the node where the constant came from. + [Arguments] ${member_index} ${constant} = MdsalLowlevel.Get_Contexted_Constant ${member_index} ${CONTEXT} ${index} = String.Replace_String ${constant} ${CONSTANT_PREFIX} ${EMPTY} ${index} = BuiltIn.Convert_To_Integer ${index} - BuiltIn.Return_From_Keyword ${index} + RETURN ${index} Isolate_Node - [Arguments] ${member_index} [Documentation] Isolate a member and update appropriate suite variables. + [Arguments] ${member_index} ClusterManagement.Isolate_Member_From_List_Or_All ${member_index} DrbCommons__Update_Active_Nodes_List deactivate_idx=${member_index} - BuiltIn.Return_From_Keyword_If ${member_index} not in ${registered_indices} + IF ${member_index} not in ${registered_indices} RETURN DrbCommons__Rem_Possible_Constant ${member_index} Rejoin_Node - [Arguments] ${member_index} [Documentation] Rejoin a member and update appropriate suite variables. + [Arguments] ${member_index} ClusterManagement.Rejoin_Member_From_List_Or_All ${member_index} - BuiltIn.Wait_Until_Keyword_Succeeds 70s 10s ShardStability.Shards_Stability_Get_Details ${DEFAULT_SHARD_LIST} + BuiltIn.Wait_Until_Keyword_Succeeds + ... 70s + ... 10s + ... ShardStability.Shards_Stability_Get_Details + ... ${DEFAULT_SHARD_LIST} DrbCommons__Update_Active_Nodes_List activate_idx=${member_index} - BuiltIn.Return_From_Keyword_If ${member_index} not in ${registered_indices} + IF ${member_index} not in ${registered_indices} RETURN DrbCommons__Add_Possible_Constant ${member_index} DrbCommons__Update_Active_Nodes_List - [Arguments] ${activate_idx}=${EMPTY} ${deactivate_idx}=${EMPTY} [Documentation] Add or remove member index to/from the list of active nodes. - BuiltIn.Run_Keyword_If "${activate_idx}" != "${EMPTY}" Collections.Append_To_List ${active_indices} ${activate_idx} - BuiltIn.Run_Keyword_If "${deactivate_idx}" != "${EMPTY}" Collections.Remove_Values_From_List ${active_indices} ${deactivate_idx} + [Arguments] ${activate_idx}=${EMPTY} ${deactivate_idx}=${EMPTY} + IF "${activate_idx}" != "${EMPTY}" + Collections.Append_To_List ${active_indices} ${activate_idx} + END + IF "${deactivate_idx}" != "${EMPTY}" + Collections.Remove_Values_From_List ${active_indices} ${deactivate_idx} + END Collections.Sort_List ${active_indices} DrbCommons__Register_Index - [Arguments] ${member_index} [Documentation] Add member index to the list of indices with registered rpc. ... Isolated nodes are included in the list. + [Arguments] ${member_index} Collections.Append_To_List ${registered_indices} ${member_index} Collections.Remove_Values_From_List ${nonregistered_indices} ${member_index} Collections.Sort_List ${registered_indices} Collections.Sort_List ${nonregistered_indices} DrbCommons__Deregister_Index - [Arguments] ${member_index} [Documentation] Remove member index from the list of indices with registered rpc. ... Isolated nodes are included in the list. + [Arguments] ${member_index} Collections.Remove_Values_From_List ${registered_indices} ${member_index} Collections.Append_To_List ${nonregistered_indices} ${member_index} Collections.Sort_List ${registered_indices} Collections.Sort_List ${nonregistered_indices} DrbCommons__Add_Possible_Constant - [Arguments] ${member_index} [Documentation] Add a constant to the ${possible_constants} list. The list is about to maintain ... all valid constants possibly responded from the odl cluster (excluding isolated nodes). + [Arguments] ${member_index} Collections.Append_To_List ${possible_constants} ${CONSTANT_PREFIX}${member_index} Collections.Sort_List ${possible_constants} DrbCommons__Rem_Possible_Constant - [Arguments] ${member_index} [Documentation] Remove a constant from the ${possible_constants} list. The list is about to maintain ... all valid constants possibly responded from the odl cluster (excluding isolated nodes). + [Arguments] ${member_index} Collections.Remove_Values_From_List ${possible_constants} ${CONSTANT_PREFIX}${member_index} diff --git a/csit/libraries/distribution/StreamDistro.robot b/csit/libraries/distribution/StreamDistro.robot index 93c020055f..b815e08d61 100644 --- a/csit/libraries/distribution/StreamDistro.robot +++ b/csit/libraries/distribution/StreamDistro.robot @@ -1,17 +1,19 @@ *** Settings *** -Documentation Distribution testing: generate stream-dependent values. +Documentation Distribution testing: generate stream-dependent values. ... -... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. +... Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. ... -... This program and the accompanying materials are made available under the -... terms of the Eclipse Public License v1.0 which accompanies this distribution, -... and is available at http://www.eclipse.org/legal/epl-v10.html +... This program and the accompanying materials are made available under the +... terms of the Eclipse Public License v1.0 which accompanies this distribution, +... and is available at http://www.eclipse.org/legal/epl-v10.html ... ... -... As newer ODL versions are released, some values evolve from previously hardcoded constants. -... This Resource contains keywords for optaining the correct value for currently testes stream. -Library Collections -Resource ${CURDIR}/../CompareStream.robot +... As newer ODL versions are released, some values evolve from previously hardcoded constants. +... This Resource contains keywords for optaining the correct value for currently testes stream. + +Library Collections +Resource ${CURDIR}/../CompareStream.robot + *** Keywords *** Compose_Zip_Filename_Prefix @@ -20,4 +22,7 @@ Compose_Zip_Filename_Prefix Compose_Test_Feature_Repo_Name [Documentation] Return "features-test" if at least Nitrogen, else return "features-integration-test". - BuiltIn.Run_Keyword_And_Return CompareStream.Set_Variable_If_At_Least_Nitrogen features-test features-integration-test + BuiltIn.Run_Keyword_And_Return + ... CompareStream.Set_Variable_If_At_Least_Nitrogen + ... features-test + ... features-integration-test -- 2.36.6