TestSuite changes for VGC
Change-Id: I180edb346c309827d125e371083f9accc2014f0e
diff --git a/Makefile b/Makefile
index 5613b84..01ff850 100644
--- a/Makefile
+++ b/Makefile
@@ -40,7 +40,9 @@
# Robot config
ROBOT_SANITY_SINGLE_PON_FILE ?= $(ROOT_DIR)/tests/data/bbsim-kind.yaml
ROBOT_SANITY_DT_SINGLE_PON_FILE ?= $(ROOT_DIR)/tests/data/bbsim-kind-dt.yaml
+ROBOT_SANITY_DT_SINGLE_PON_FILE_VGC ?= $(ROOT_DIR)/tests/data/bbsim-kind-dt-vgc.yaml
ROBOT_SANITY_MULTIPLE_OLT_FILE ?= $(ROOT_DIR)/tests/data/bbsim-kind-2OLTx2ONUx2PON.yaml
+ROBOT_SANITY_MULTIPLE_OLT_FILE_VGC ?= $(ROOT_DIR)/tests/data/bbsim-kind-2OLTx2ONUx2PON_VGC.yaml
ROBOT_SANITY_DT_MULTIPLE_OLT_FILE ?= $(ROOT_DIR)/tests/data/bbsim-kind-2OLTx2ONUx2PON-dt.yaml
ROBOT_SANITY_TT_MULTIPLE_OLT_FILE ?= $(ROOT_DIR)/tests/data/bbsim-kind-2OLTx2ONUx2PON-tt.yaml
ROBOT_FAIL_SINGLE_PON_FILE ?= $(ROOT_DIR)/tests/data/bbsim-kind.yaml
@@ -60,6 +62,7 @@
ROBOT_SANITY_TT_MULTI_UNI_SINGLE_PON_FILE ?= $(ROOT_DIR)/tests/data/bbsim-kind-multi-uni-tt.yaml
ROBOT_SANITY_TT_MULTI_UNI_MULTIPLE_OLT_FILE ?= $(ROOT_DIR)/tests/data/bbsim-kind-multi-uni-2OLTx2ONUx2PON-tt.yaml
ROBOT_SANITY_DT_FTTB_SINGLE_PON_FILE ?= $(ROOT_DIR)/tests/data/bbsim-kind-dt-fttb-1OLTx1PONx2ONUx2UNI.yaml
+ROBOT_SANITY_DT_FTTB_SINGLE_PON_FILE_VGC ?= $(ROOT_DIR)/tests/data/bbsim-kind-dt-fttb-1OLTx1PONx2ONUx2UNI.yaml
ROBOT_SANITY_TIM_SINGLE_PON_FILE ?= $(ROOT_DIR)/tests/data/bbsim-kind-tim.yaml
ROBOT_SANITY_TIM_SINGLE_PON_MULTI_ONU_FILE ?= $(ROOT_DIR)/tests/data/bbsim-kind-tim-OLTxPONx2ONU.yaml
ROBOT_SANITY_TIM_MULTI_PON_MULTI_ONU_FILE ?= $(ROOT_DIR)/tests/data/bbsim-kind-tim-OLTx2PONx2ONU.yaml
@@ -102,12 +105,24 @@
sanity-kind-dt: ROBOT_FILE := Voltha_DT_PODTests.robot
sanity-kind-dt: voltha-dt-test
+# target to invoke DT Workflow Sanity for VGC
+sanity-kind-dt-vgc: ROBOT_MISC_ARGS += -i sanityDt $(ROBOT_DEBUG_LOG_OPT)
+sanity-kind-dt-vgc: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_DT_SINGLE_PON_FILE_VGC)
+sanity-kind-dt-vgc: ROBOT_FILE := Voltha_DT_PODTests_VGC.robot
+sanity-kind-dt-vgc: voltha-dt-test
+
# target to invoke DT FTTB Workflow Sanity
sanity-kind-dt-fttb: ROBOT_MISC_ARGS += -i sanityDtFttb $(ROBOT_DEBUG_LOG_OPT)
sanity-kind-dt-fttb: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_DT_FTTB_SINGLE_PON_FILE)
sanity-kind-dt-fttb: ROBOT_FILE := Voltha_DT_FTTB_Tests.robot
sanity-kind-dt-fttb: voltha-dt-test
+# target to invoke DT FTTB Workflow Sanity for VGC
+sanity-kind-dt-fttb-vgc: ROBOT_MISC_ARGS += -i sanityDtFttb $(ROBOT_DEBUG_LOG_OPT)
+sanity-kind-dt-fttb-vgc: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_DT_FTTB_SINGLE_PON_FILE_VGC)
+sanity-kind-dt-fttb-vgc: ROBOT_FILE := Voltha_DT_FTTB_Tests_VGC.robot
+sanity-kind-dt-fttb-vgc: voltha-dt-test
+
functional-single-kind: ROBOT_MISC_ARGS += -i sanityORfunctional -e PowerSwitch $(ROBOT_DEBUG_LOG_OPT)
functional-single-kind: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_SINGLE_PON_FILE)
functional-single-kind: bbsim-kind
@@ -121,6 +136,13 @@
functional-single-kind-dt: ROBOT_FILE := Voltha_DT_PODTests.robot
functional-single-kind-dt: voltha-dt-test
+# target to invoke DT Workflow Functional scenarios
+functional-single-kind-dt-vgc: ROBOT_MISC_ARGS += -i sanityDtORfunctionalDt -e PowerSwitch $(ROBOT_DEBUG_LOG_OPT)
+functional-single-kind-dt-vgc: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_DT_SINGLE_PON_FILE_VGC)
+functional-single-kind-dt-vgc: ROBOT_FILE := Voltha_DT_PODTests_VGC.robot
+functional-single-kind-dt-vgc: voltha-dt-test
+
+
# target to invoke TT Workflow Sanity
sanity-kind-tt: ROBOT_MISC_ARGS += -i sanityTT $(ROBOT_DEBUG_LOG_OPT)
sanity-kind-tt: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_TT_SINGLE_PON_FILE)
@@ -442,6 +464,16 @@
bbsim-multiolt-kind-dt: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_MULTIPLE_OLT_FILE)
bbsim-multiolt-kind-dt: voltha-dt-test
+bbsim-multiolt-kind-dt-vgc: ROBOT_MISC_ARGS += -X $(ROBOT_DEBUG_LOG_OPT) -e PowerSwitch -e MultiOLTPhysicalRebootDt
+bbsim-multiolt-kind-dt-vgc: ROBOT_FILE := Voltha_DT_MultiOLT_Tests_VGC.robot
+bbsim-multiolt-kind-dt-vgc: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_MULTIPLE_OLT_FILE_VGC)
+bbsim-multiolt-kind-dt-vgc: voltha-dt-test
+
+multiolt-kind-dt-vgc: ROBOT_MISC_ARGS += -X $(ROBOT_DEBUG_LOG_OPT) -i functionalDt
+multiolt-kind-dt-vgc: ROBOT_FILE := Voltha_DT_MultiOLT_Tests_VGC.robot
+multiolt-kind-dt-vgc: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_MULTIPLE_OLT_FILE_VGC)
+multiolt-kind-dt-vgc: voltha-dt-test
+
multiolt-kind-dt: ROBOT_MISC_ARGS += -X $(ROBOT_DEBUG_LOG_OPT) -i functionalDt
multiolt-kind-dt: ROBOT_FILE := Voltha_DT_MultiOLT_Tests.robot
multiolt-kind-dt: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_MULTIPLE_OLT_FILE)
diff --git a/VERSION b/VERSION
index dcb27a7..e464374 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.12.5
+2.12.6
diff --git a/libraries/utils_vgc.robot b/libraries/utils_vgc.robot
new file mode 100755
index 0000000..65e0912
--- /dev/null
+++ b/libraries/utils_vgc.robot
@@ -0,0 +1,1191 @@
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# robot test functions
+
+*** Settings ***
+Documentation Library for various utilities
+Library SSHLibrary
+Library String
+Library DateTime
+Library Process
+Library Collections
+Library RequestsLibrary
+Library OperatingSystem
+Library CORDRobot
+Library ImportResource resources=CORDRobot
+Resource ./voltctl.robot
+Resource ./vgc.robot
+
+*** Keywords ***
+Check CLI Tools Configured
+ [Documentation] Tests that use 'voltctl' and 'kubectl' should execute this keyword in suite setup
+ # check voltctl and kubectl configured
+ ${voltctl_rc} ${voltctl_output}= Run And Return Rc And Output voltctl -c ${VOLTCTL_CONFIG} device list
+ Log ${voltctl_output}
+ ${kubectl_rc} ${kubectl_output}= Run And Return Rc And Output kubectl get pods
+ Log ${kubectl_output}
+ Run Keyword If ${voltctl_rc} != 0 or ${kubectl_rc} != 0 FATAL ERROR
+ ... VOLTCTL and KUBECTL not configured. Please configure before executing tests.
+
+Common Test Suite Setup
+ [Documentation] Setup the test suite
+ Set Global Variable ${KUBECTL_CONFIG} export KUBECONFIG=%{KUBECONFIG}
+ Set Global Variable ${VOLTCTL_CONFIG} %{VOLTCONFIG}
+ ${k8s_node_ip}= Evaluate ${nodes}[0].get("ip")
+ ${VGC_REST_IP}= Get Environment Variable VGC_REST_IP ${k8s_node_ip}
+ ${VGC_SSH_IP}= Get Environment Variable VGC_SSH_IP ${k8s_node_ip}
+ Set Global Variable ${VGC_REST_IP}
+ Set Global Variable ${VGC_SSH_IP}
+ ${k8s_node_user}= Evaluate ${nodes}[0].get("user")
+ ${k8s_node_pass}= Evaluate ${nodes}[0].get("pass")
+ Check CLI Tools Configured
+ ${HEADERS} Create Dictionary Content-Type=application/json
+ Create VGC Session
+ ${num_olts} Get Length ${olts}
+ ${list_olts} Create List
+ # Create olt list from the configuration file
+ FOR ${I} IN RANGE 0 ${num_olts}
+ ${ip} Evaluate ${olts}[${I}].get("ip")
+ ${user} Evaluate ${olts}[${I}].get("user")
+ ${pass} Evaluate ${olts}[${I}].get("pass")
+ ${serial_number} Evaluate ${olts}[${I}].get("serial")
+ ${olt_ssh_ip} Evaluate ${olts}[${I}].get("sship")
+ ${type} Evaluate ${olts}[${I}].get("type")
+ ${power_switch_port} Evaluate ${olts}[${I}].get("power_switch_port")
+ ${orig_olt_port} Evaluate ${olts}[${I}].get("oltPort")
+ ${port}= Set Variable If "${orig_olt_port}" == "None" ${OLT_PORT} ${orig_olt_port}
+ ${onu_count}= Get ONU Count For OLT ${hosts.src} ${serial_number}
+ ${onu_list}= Get ONU List For OLT ${hosts.src} ${serial_number}
+ ${olt} Create Dictionary ip ${ip} user ${user} pass
+ ... ${pass} sn ${serial_number} onucount ${onu_count} type ${type}
+ ... sship ${olt_ssh_ip} oltport ${port} powerswitchport ${power_switch_port}
+ ... onus ${onu_list}
+ Append To List ${list_olts} ${olt}
+ END
+ ${num_all_onus}= Get Length ${hosts.src}
+ ${num_all_onus}= Convert to String ${num_all_onus}
+ #send sadis file to vgc
+ ${sadis_file}= Get Variable Value ${sadis.file}
+ Log To Console \nSadis File:${sadis_file}
+ Run Keyword Unless '${sadis_file}' is '${None}' Send File To VGC ${sadis_file} # apps/
+ Set Suite Variable ${num_all_onus}
+ Set Suite Variable ${num_olts}
+ Set Suite Variable ${list_olts}
+ ${olt_count}= Get Length ${list_olts}
+ Set Suite Variable ${olt_count}
+ @{container_list}= Create List ${OLT_ADAPTER_APP_LABEL} adapter-open-onu voltha-api-server
+ ... voltha-ro-core voltha-rw-core-11 voltha-rw-core-12 voltha-ofagent
+ Set Suite Variable ${container_list}
+ ${datetime}= Get Current Date
+ Set Suite Variable ${datetime}
+
+Get ONU Count For OLT
+ [Arguments] ${src} ${serial_number}
+ [Documentation] Gets ONU Count for the specified OLT
+ ${src_length}= Get Length ${src}
+ ${count}= Set Variable 0
+ FOR ${I} IN RANGE 0 ${src_length}
+ ${sn} Evaluate ${src}[${I}].get("olt")
+ ${count}= Run Keyword If '${serial_number}' == '${sn}' Evaluate ${count} + 1
+ ... ELSE Set Variable ${count}
+ END
+ [Return] ${count}
+
+Get ONU List For OLT
+ [Arguments] ${src} ${serial_number}
+ [Documentation] Gets ONU List for the specified OLT
+ ${src_length}= Get Length ${src}
+ ${onu_list}= Create List
+ FOR ${I} IN RANGE 0 ${src_length}
+ ${sn} Evaluate ${src}[${I}].get("olt")
+ Run Keyword If '${serial_number}' == '${sn}' Append To List ${onu_list} ${src}[${I}][onu]
+ ... ELSE Set Variable ${onu_list}
+ END
+ [Return] ${onu_list}
+
+WPA Reassociate
+ [Documentation] Executes a particular wpa_cli reassociate, which performs force reassociation
+ [Arguments] ${iface} ${ip} ${user} ${pass}=${None}
+ ... ${container_type}=${None} ${container_name}=${None}
+ #Below for loops are used instead of sleep time, to execute reassociate command and check status
+ FOR ${i} IN RANGE 70
+ ${output}= Login And Run Command On Remote System
+ ... wpa_cli -i ${iface} reassociate ${ip} ${user}
+ ... ${pass} ${container_type} ${container_name}
+ ${passed}= Run Keyword And Return Status Should Contain ${output} OK
+ Exit For Loop If ${passed}
+ END
+ Should Be True ${passed} Status does not contain 'SUCCESS'
+ FOR ${i} IN RANGE 70
+ ${output}= Login And Run Command On Remote System
+ ... wpa_cli -i ${iface} status | grep SUCCESS ${ip} ${user}
+ ... ${pass} ${container_type} ${container_name}
+ ${passed}= Run Keyword And Return Status Should Contain ${output} SUCCESS
+ Exit For Loop If ${passed}
+ END
+ Should Be True ${passed} Status does not contain 'SUCCESS'
+
+Validate Authentication After Reassociate
+ [Arguments] ${auth_pass} ${iface} ${ip} ${user} ${pass}=${None}
+ ... ${container_type}=${None} ${container_name}=${None}
+ [Documentation]
+ ... Executes a particular reassociate request on the RG using wpa_cli.
+ ... auth_pass determines if authentication should pass
+ ${wpa_log}= Catenate SEPARATOR=. /tmp/wpa ${iface} log
+ ${output}= Login And Run Command On Remote System truncate -s 0 ${wpa_log}; cat ${wpa_log}
+ ... ${ip} ${user} ${pass} ${container_type} ${container_name}
+ Log ${output}
+ Should Not Contain ${output} authentication completed successfully
+ WPA Reassociate ${iface} ${ip} ${user} ${pass} ${container_type} ${container_name}
+ Run Keyword If '${auth_pass}' == 'True' Wait Until Keyword Succeeds ${timeout} 2s
+ ... Check Remote File Contents True ${wpa_log} ${iface}.*authentication completed successfully
+ ... ${ip} ${user} ${pass} ${container_type} ${container_name}
+ Run Keyword If '${auth_pass}' == 'False' Sleep 20s
+ Run Keyword If '${auth_pass}' == 'False' Check Remote File Contents False /tmp/wpa.log
+ ... ${iface}.*authentication completed successfully ${ip} ${user} ${pass}
+ ... ${container_type} ${container_name}
+
+Send Dhclient Request To Release Assigned IP
+ [Arguments] ${iface} ${ip} ${user} ${path_dhcpleasefile} ${pass}=${None}
+ ... ${container_type}=${None} ${container_name}=${None}
+ [Documentation] Executes a dhclient with option to release ip against a particular interface on the RG (src)
+ ${result}= Login And Run Command On Remote System
+ ... dhclient -nw -r ${iface} && rm ${path_dhcpleasefile}/dhclient.* ${ip} ${user}
+ ... ${pass} ${container_type} ${container_name}
+ Log ${result}
+ #Should Contain ${result} DHCPRELEASE
+ [Return] ${result}
+
+Check Remote File Contents For WPA Logs
+ [Arguments] ${file_should_exist} ${file} ${pattern} ${ip} ${user} ${pass}=${None}
+ ... ${container_type}=${None} ${container_name}=${None} ${prompt}=~$
+ [Documentation] Checks for particular pattern count in a file
+ ${result}= Login And Run Command On Remote System
+ ... cat ${file} | grep '${pattern}' | wc -l ${ip} ${user} ${pass}
+ ... ${container_type} ${container_name} ${prompt}
+ [Return] ${result}
+
+Perform Sanity Test DT
+ [Documentation] This keyword iterate all OLTs and performs Sanity Test Procedure for DT workflow
+ ... For repeating sanity test without subscriber changes set flag supress_add_subscriber=True.
+ ... In all other (common) cases flag has to be set False (default).
+ [Arguments] ${supress_add_subscriber}=False
+ FOR ${J} IN RANGE 0 ${num_olts}
+ ${olt_serial_number}= Set Variable ${list_olts}[${J}][sn]
+ ${num_onus}= Set Variable ${list_olts}[${J}][onucount]
+ ${olt_device_id}= Get OLTDeviceID From OLT List ${olt_serial_number}
+ ${of_id}= Wait Until Keyword Succeeds ${timeout} 15s Validate OLT Device in VGC
+ ... ${olt_serial_number}
+ Set Global Variable ${of_id}
+ ${nni_port}= Wait Until Keyword Succeeds ${timeout} 2s Get NNI Port in VGC ${of_id}
+ Perform Sanity Test DT Per OLT ${of_id} ${nni_port} ${olt_serial_number} ${num_onus}
+ ... ${supress_add_subscriber}
+ # Verify VGC Flows
+ # Number of Access Flows on VGC equals 4 * the Number of Active ONUs (2 for each downstream and upstream)
+ ${vgc_flows_count}= Evaluate 4 * ${num_onus}
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Subscriber Access Flows Added Count DT ${VGC_SSH_IP} ${VGC_SSH_PORT} ${of_id}
+ ... ${vgc_flows_count}
+ # Verify LLDP flow in VGC
+ #Wait Until Keyword Succeeds ${timeout} 5s
+ #... Verify LLDP Flow Added ${VGC_SSH_IP} ${VGC_SSH_PORT} ${of_id} 1
+ # Verify VOLTHA Flows
+ # Number of per OLT Flows equals Twice the Number of Active ONUs (each for downstream and upstream) + 1 for LLDP
+ ${olt_flows}= Evaluate 2 * ${num_onus}
+ # Number of per ONU Flows equals 2 (one each for downstream and upstream)
+ ${onu_flows}= Set Variable 2
+ Run Keyword Wait Until Keyword Succeeds ${timeout} 5s Validate OLT Flows
+ ... ${olt_flows} ${olt_device_id}
+ ${List_ONU_Serial} Create List
+ Set Suite Variable ${List_ONU_Serial}
+ Build ONU SN List ${List_ONU_Serial} ${olt_serial_number}
+ Log ${List_ONU_Serial}
+ Wait Until Keyword Succeeds ${timeout} 5s Validate ONU Flows
+ ... ${List_ONU_Serial} ${onu_flows}
+ END
+
+
+Perform Sanity Test DT Per OLT
+ [Arguments] ${of_id} ${nni_port} ${olt_serial_number} ${num_onus} ${supress_add_subscriber}=False
+ [Documentation] This keyword performs Sanity Test Procedure for DT Workflow
+ ... Sanity test performs dhcp and pings (without EAPOL and DHCP flows) for all the ONUs given for the POD
+ ... This keyword can be used to call in any other tests where sanity check is required
+ ... and avoids duplication of code.
+ ... For repeating sanity test without subscriber changes set flag supress_add_subscriber=True.
+ ... In all other (common) cases flag has to be set False (default).
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ Continue For Loop If "${olt_serial_number}"!="${src['olt']}"
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ ${onu_port}= Wait Until Keyword Succeeds ${timeout} 2s
+ ... Get ONU Port in VGC ${src['onu']} ${of_id} ${src['uni_id']}
+ # Check ONU port is Enabled in VGC
+ Wait Until Keyword Succeeds 120s 2s
+ ... Verify UNI Port Is Enabled ${src['onu']} ${src['uni_id']}
+ Run Keyword Unless ${supress_add_subscriber}
+ ... Add Subscriber Details ${of_id} ${onu_port}
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Subscriber Access Flows Added For ONU DT in VGC ${VGC_SSH_IP} ${VGC_SSH_PORT} ${of_id}
+ ... ${onu_port} ${nni_port} ${src['s_tag']}
+ # Verify ONU state in voltha
+ ${onu_reasons}= Create List omci-flows-pushed
+ Run Keyword If ${supress_add_subscriber} Append To List ${onu_reasons} onu-reenabled
+ Wait Until Keyword Succeeds ${timeout} 5s Validate Device
+ ... ENABLED ACTIVE REACHABLE
+ ... ${src['onu']} onu=True onu_reason=${onu_reasons}
+ # Verify Meters in VGC
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Meters in VGC Ietf ${VGC_SSH_IP} ${VGC_SSH_PORT} ${of_id} ${onu_port}
+ # TODO: Yet to Verify on the GPON based Physical POD (VOL-2652)
+ Run Keyword If ${has_dataplane} Validate DHCP and Ping True
+ ... True ${src['dp_iface_name']} ${src['s_tag']} ${src['c_tag']} ${dst['dp_iface_ip_qinq']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ ... ${dst['dp_iface_name']} ${dst['ip']} ${dst['user']} ${dst['pass']} ${dst['container_type']}
+ ... ${dst['container_name']}
+ END
+
+Perform Sanity Test DT FTTB
+ [Documentation] This keyword iterate all OLTs and performs Sanity Test Procedure for DT-FTTB workflow
+ ... For repeating sanity test without subscriber changes set flag supress_add_subscriber=True.
+ ... In all other (common) cases flag has to be set False (default).
+ [Arguments] ${supress_add_subscriber}=False
+ FOR ${J} IN RANGE 0 ${num_olts}
+ ${olt_serial_number}= Set Variable ${list_olts}[${J}][sn]
+ ${olt_device_id}= Get OLTDeviceID From OLT List ${olt_serial_number}
+ ${of_id}= Wait Until Keyword Succeeds ${timeout} 15s Validate OLT Device in VGC
+ ... ${olt_serial_number}
+ ${nni_port}= Wait Until Keyword Succeeds ${timeout} 2s Get NNI Port in VGC ${of_id}
+ Perform Sanity Test DT FTTB Per OLT ${of_id} ${nni_port} ${olt_serial_number}
+ ... ${supress_add_subscriber}
+ END
+
+Perform Sanity Test DT FTTB Per OLT
+ [Arguments] ${of_id} ${nni_port} ${olt_serial_number} ${supress_add_subscriber}=False
+ [Documentation] This keyword performs Sanity Test Procedure for DT-FTTB Workflow
+ ... Sanity test performs dhcp and pings (without EAPOL and DHCP flows) for all the ONUs given for the POD
+ ... This keyword can be used to call in any other tests where sanity check is required
+ ... and avoids duplication of code.
+ ... For repeating sanity test without subscriber changes set flag supress_add_subscriber=True.
+ ... In all other (common) cases flag has to be set False (default).
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ Continue For Loop If "${olt_serial_number}"!="${src['olt']}"
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ ${onu_port}= Wait Until Keyword Succeeds ${timeout} 2s
+ ... Get ONU Port in VGC ${src['onu']} ${of_id} ${src['uni_id']}
+ # Check ONU port is Enabled in VGC
+ Wait Until Keyword Succeeds 120s 2s
+ ... Verify UNI Port Is Enabled ${src['onu']} ${src['uni_id']}
+ Run Keyword Unless ${supress_add_subscriber}
+ ... Add Subscriber Details ${of_id} ${onu_port}
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify VGC Flows Added For DT FTTB ${of_id}
+ ... ${onu_port} ${nni_port} ${src['service']}
+ # Verify that the Subscriber is present at the given location
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Programmed Subscribers DT FTTB ${of_id}
+ ... ${onu_port} ${src['service']}
+ # Verify ONU state in voltha
+ ${onu_reasons}= Create List omci-flows-pushed
+ Run Keyword If ${supress_add_subscriber} Append To List ${onu_reasons} onu-reenabled
+ Wait Until Keyword Succeeds ${timeout} 5s Validate Device
+ ... ENABLED ACTIVE REACHABLE
+ ... ${src['onu']} onu=True onu_reason=${onu_reasons}
+ # Verify Meters in VGC
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Meters in VGC Ietf ${VGC_SSH_IP} ${VGC_SSH_PORT} ${of_id} ${onu_port}
+ ... FTTB_SUBSCRIBER_TRAFFIC
+ Run Keyword If ${has_dataplane} Validate DHCP and Ping True
+ ... True ${src['dp_iface_name']} ${src['s_tag']} ${src['c_tag']} ${dst['dp_iface_ip_qinq']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ ... ${dst['dp_iface_name']} ${dst['ip']} ${dst['user']} ${dst['pass']} ${dst['container_type']}
+ ... ${dst['container_name']}
+ END
+
+Validate All OLT Flows
+ [Documentation] This keyword iterate all OLTs and performs Sanity Test Procedure for DT workflow
+ FOR ${J} IN RANGE 0 ${num_olts}
+ ${olt_serial_number}= Set Variable ${list_olts}[${J}][sn]
+ ${num_onus}= Set Variable ${list_olts}[${J}][onucount]
+ ${olt_device_id}= Get OLTDeviceID From OLT List ${olt_serial_number}
+ ${of_id}= Wait Until Keyword Succeeds ${timeout} 15s Validate OLT Device in VGC
+ ... ${olt_serial_number}
+ Set Global Variable ${of_id}
+ # Verify VGC Flows
+ # Number of Access Flows on VGC equals 4 * the Number of Active ONUs (2 for each downstream and upstream)
+ ${vgc_flows_count}= Evaluate 4 * ${num_onus}
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Subscriber Access Flows Added Count DT ${VGC_SSH_IP} ${VGC_SSH_PORT} ${of_id}
+ ... ${vgc_flows_count}
+ # Verify VOLTHA Flows
+ # Number of per OLT Flows equals Twice the Number of Active ONUs (each for downstream and upstream) + 1 for LLDP
+ ${olt_flows}= Evaluate 2 * ${num_onus}
+ # Number of per ONU Flows equals 2 (one each for downstream and upstream)
+ ${onu_flows}= Set Variable 2
+ Run Keyword Wait Until Keyword Succeeds ${timeout} 5s Validate OLT Flows ${olt_flows}
+ ... ${olt_device_id}
+ ${List_ONU_Serial} Create List
+ Set Suite Variable ${List_ONU_Serial}
+ Build ONU SN List ${List_ONU_Serial} ${olt_serial_number}
+ Log ${List_ONU_Serial}
+ Run Keyword Wait Until Keyword Succeeds ${timeout} 5s Validate ONU Flows
+ ... ${List_ONU_Serial} ${onu_flows}
+ END
+
+Setup Soak
+ [Documentation] Pre-test Setup for Soak Job
+ ${olt_ids} Create List
+ FOR ${I} IN RANGE 0 ${num_olts}
+ ${olt_serial_number}= Set Variable ${list_olts}[${I}][sn]
+ ${olt_device_id}= Get Device ID From SN ${olt_serial_number}
+ ${logical_id}= Get Logical Device ID From SN ${olt_serial_number}
+ ${of_id}= Wait Until Keyword Succeeds ${timeout} 15s Validate OLT Device in VGC
+ ... ${olt_serial_number}
+ ${nni_port}= Wait Until Keyword Succeeds ${timeout} 2s Get NNI Port in VGC ${of_id}
+ ${olt} Create Dictionary device_id ${olt_device_id} logical_id ${logical_id}
+ ... of_id ${of_id} sn ${olt_serial_number}
+ Append To List ${olt_ids} ${olt}
+ END
+ Set Global Variable ${olt_ids}
+
+Setup
+ [Documentation] Pre-test Setup
+ [Arguments] ${skip_empty_device_list_test}=False
+ #test for empty device list
+ Run Keyword If '${skip_empty_device_list_test}'=='False' Test Empty Device List
+ # TBD: Need for this Sleep
+ Run Keyword If ${has_dataplane} Sleep 180s
+ # Create a list of olt ids (logical and device_id)
+ ${olt_ids} Create List
+ FOR ${I} IN RANGE 0 ${num_olts}
+ #create/preprovision device
+ ${olt_device_id}= Run Keyword If "${list_olts}[${I}][type]" == "${None}"
+ ... Create Device ${list_olts}[${I}][ip] ${list_olts}[${I}][oltport]
+ ... ELSE Create Device ${list_olts}[${I}][ip] ${list_olts}[${I}][oltport] ${list_olts}[${I}][type]
+ ${olt_serial_number}= Set Variable ${list_olts}[${I}][sn]
+ #Set Suite Variable ${olt_device_id}
+ #validate olt states
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate OLT Device PREPROVISIONED UNKNOWN UNKNOWN ${olt_device_id} by_dev_id=True
+ Sleep 5s
+ Enable Device ${olt_device_id}
+ # Increasing the timer to incorporate wait time for in-band
+ Wait Until Keyword Succeeds 540s 5s
+ ... Validate OLT Device ENABLED ACTIVE REACHABLE ${olt_serial_number}
+ ${logical_id}= Get Logical Device ID From SN ${olt_serial_number}
+ # Set Suite Variable ${logical_id}
+ ${of_id}= Wait Until Keyword Succeeds ${timeout} 15s Validate OLT Device in VGC
+ ... ${olt_serial_number}
+ ${olt} Create Dictionary device_id ${olt_device_id} logical_id ${logical_id}
+ ... of_id ${of_id} sn ${olt_serial_number}
+ Append To List ${olt_ids} ${olt}
+ END
+ Set Global Variable ${olt_ids}
+
+Get ofID From OLT List
+ [Documentation] Retrieves the corresponding of_id for the OLT serial number specified
+ [Arguments] ${serial_number}
+ FOR ${I} IN RANGE 0 ${olt_count}
+ ${sn}= Get From Dictionary ${olt_ids}[${I}] sn
+ ${of_id}= Run Keyword IF "${serial_number}"=="${sn}"
+ ... Get From Dictionary ${olt_ids}[${I}] of_id ELSE Set Variable ${of_id}
+ END
+ [Return] ${of_id}
+
+Get OLTDeviceID From OLT List
+ [Documentation] Retrieves the corresponding olt_device_id for the OLT serial number specified
+ [Arguments] ${serial_number}
+ ${olt_device_id}= Set Variable 0
+ FOR ${I} IN RANGE 0 ${olt_count}
+ ${sn}= Get From Dictionary ${olt_ids}[${I}] sn
+ ${olt_device_id}= Run Keyword IF "${serial_number}"=="${sn}"
+ ... Get From Dictionary ${olt_ids}[${I}] device_id ELSE Set Variable ${olt_device_id}
+ END
+ [Return] ${olt_device_id}
+
+Get Num of Onus From OLT SN
+ [Documentation] Retrieves the corresponding number of ONUs for a given OLT based on serial number specified
+ [Arguments] ${serial_number}
+ ${num_of_olt_onus}= Set Variable 0
+ FOR ${I} IN RANGE 0 ${olt_count}
+ ${sn}= Get From Dictionary ${olt_ids}[${I}] sn
+ ${num_of_olt_onus}= Run Keyword IF "${serial_number}"=="${sn}"
+ ... Get From Dictionary ${list_olts}[${I}] onucount ELSE Set Variable ${num_of_olt_onus}
+ END
+ [Return] ${num_of_olt_onus}
+
+Validate ONUs After OLT Disable
+ [Documentation] Validates the ONUs state in Voltha, ONUs port state in VGC
+ ... and that pings do not succeed After corresponding OLT is Disabled
+ [Arguments] ${num_onus} ${olt_serial_number}
+ FOR ${I} IN RANGE 0 ${num_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ Continue For Loop If "${olt_serial_number}"!="${src['olt']}"
+ ${of_id}= Get ofID From OLT List ${src['olt']}
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ ${onu_port}= Wait Until Keyword Succeeds ${timeout} 2s Get ONU Port in VGC ${src['onu']}
+ ... ${of_id}
+ ${valid_onu_states}= Create List stopping-openomci omci-flows-deleted
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate Device ENABLED DISCOVERED
+ ... UNREACHABLE ${src['onu']} onu=True onu_reason=${valid_onu_states}
+ Wait Until Keyword Succeeds ${timeout} 2s
+ ... Verify UNI Port Is Disabled ${VGC_SSH_IP} ${VGC_SSH_PORT} ${src['onu']} ${src['uni_id']}
+ Run Keyword If ${has_dataplane} Run Keyword And Continue On Failure
+ ... Wait Until Keyword Succeeds ${timeout} 2s
+ ... Check Ping False ${dst['dp_iface_ip_qinq']} ${src['dp_iface_name']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ END
+
+Delete All Devices and Verify
+ [Documentation] Remove any devices from VOLTHA and VGC
+ [Arguments] ${maclearning_enabled}=False
+ # Clear devices from VOLTHA
+ ${resp}= Get Request VGC devices
+ ${jsondata}= To Json ${resp.content}
+ ${length}= Get Length ${jsondata['devices']}
+ ${matched}= Set Variable False
+ ${matched}= Set Variable If '${length}' == '${num_olts}' True False
+ Run Keyword If ${matched} Disable Devices In Voltha Root=true
+ Wait Until Keyword Succeeds ${timeout} 2s Test Devices Disabled In Voltha Root=true
+ Delete Devices In Voltha Root=true
+ Wait Until Keyword Succeeds ${timeout} 2s Test Empty Device List
+ FOR ${I} IN RANGE 0 ${length}
+ ${value}= Get From List ${jsondata['devices']} ${I}
+ ${device_id}= Get From Dictionary ${value} id
+ ${olt_serial_number}= Get From Dictionary ${value} serial
+ #${olt_serial_number}= Set Variable ${list_olts}[${I}][sn]
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate Deleted Device Cleanup In VGC ${VGC_SSH_IP} ${VGC_SSH_PORT} ${olt_serial_number} ${device_id}
+ ... ${maclearning_enabled}
+ END
+ Wait Until Keyword Succeeds ${timeout} 5s Validate Cleanup In ETCD ${INFRA_NAMESPACE}
+
+Teardown
+ [Documentation] kills processes and cleans up interfaces on src+dst servers
+ Run Keyword If ${has_dataplane} Clean Up Linux
+
+Teardown Suite
+ [Documentation] Clean up device if desired
+ Start Logging Setup or Teardown Teardown-${SUITE NAME}
+ Run Keyword If ${has_dataplane} Clean Up Linux
+ Run Keyword If ${teardown_device} Deactivate Subscribers In VGC
+ Run Keyword If ${teardown_device} Delete All Devices and Verify
+ Run Keyword And Continue On Failure Collect Logs
+ #Close All VGC SSH Connections
+ Run Keyword If ${has_dataplane} Clean Up All Nodes
+ Stop Logging Setup or Teardown Teardown-${SUITE NAME}
+
+Delete Device and Verify
+ [Arguments] ${olt_serial_number}
+ [Documentation] Disable -> Delete devices via voltctl and verify its removed
+ ${olt_device_id}= Get Device ID From SN ${olt_serial_number}
+ ${rc} ${output}= Run and Return Rc and Output
+ ... voltctl -c ${VOLTCTL_CONFIG} device disable ${olt_device_id}
+ Should Be Equal As Integers ${rc} 0
+ Sleep 5s
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate OLT Device DISABLED UNKNOWN REACHABLE ${olt_serial_number}
+ ${rc} ${output}= Run and Return Rc and Output
+ ... voltctl -c ${VOLTCTL_CONFIG} device delete ${olt_device_id}
+ Sleep 50s
+ Should Be Equal As Integers ${rc} 0
+ Wait Until Keyword Succeeds ${timeout} 5s Validate Device Removed ${olt_device_id}
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 15s
+ ... Validate Deleted Device Cleanup In VGC ${VGC_SSH_IP} ${VGC_SSH_PORT} ${olt_serial_number} ${olt_device_id}
+
+Disable Enable PON Port Per OLT DT
+ [Arguments] ${olt_serial_number}
+ [Documentation] This keyword disables and then enables OLT PON port and
+ ... also validate ONUs for each corresponding case
+ ${olt_device_id}= Get OLTDeviceID From OLT List ${olt_serial_number}
+ ${olt_pon_port_list}= Retrieve OLT PON Ports ${olt_device_id}
+ ${olt_pon_port_list_len}= Get Length ${olt_pon_port_list}
+ FOR ${INDEX0} IN RANGE 0 ${olt_pon_port_list_len}
+ ${olt_pon_port}= Get From List ${olt_pon_port_list} ${INDEX0}
+ ${olt_peer_list}= Retrieve Peer List From OLT PON Port ${olt_device_id} ${olt_pon_port}
+ ${olt_peer_list_len}= Get Length ${olt_peer_list}
+ # Disable the OLT PON Port and Validate OLT Device
+ DisableOrEnable OLT PON Port disable ${olt_device_id} ${olt_pon_port}
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate OLT PON Port Status ${olt_device_id} ${olt_pon_port}
+ ... DISABLED DISCOVERED
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate OLT Device ENABLED ACTIVE REACHABLE
+ ... ${olt_serial_number}
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate ONUs for PON OLT Disable DT ${olt_serial_number} ${olt_peer_list}
+ # Enable the OLT PON Port back, and check ONU status are back to "ACTIVE"
+ DisableOrEnable OLT PON Port enable ${olt_device_id} ${olt_pon_port}
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate OLT PON Port Status ${olt_device_id} ${olt_pon_port}
+ ... ENABLED ACTIVE
+ ${olt_peer_list_new}= Wait Until Keyword Succeeds ${timeout} 5s
+ ... Retrieve Peer List From OLT PON Port ${olt_device_id} ${olt_pon_port} ${olt_peer_list_len}
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate ONUs for PON OLT Enable DT ${olt_serial_number} ${olt_peer_list_new}
+ END
+
+Validate ONUs for PON OLT Disable DT
+ [Arguments] ${olt_sn} ${olt_peer_list}
+ [Documentation] This keyword validates that Ping fails for ONUs connected to Disabled OLT PON port
+ ... And Pings succeed for other Active OLT PON port ONUs
+ ... Also it removes subscriber and deletes ONUs for Disabled OLT PON port to replicate DT workflow
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ Continue For Loop If "${olt_sn}"!="${src['olt']}"
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ ${of_id}= Wait Until Keyword Succeeds ${timeout} 15s Validate OLT Device in VGC ${src['olt']}
+ ${onu_port}= Wait Until Keyword Succeeds ${timeout} 2s Get ONU Port in VGC ${src['onu']}
+ ... ${of_id} ${src['uni_id']}
+ ${matched}= Match ONU in PON OLT Peer List ${olt_peer_list} ${onu_device_id}
+ ${valid_onu_states}= Create List stopping-openomci omci-flows-deleted
+ Run Keyword If ${matched}
+ ... Run Keywords
+ ... Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate Device ENABLED DISCOVERED
+ ... UNREACHABLE ${src['onu']} onu=True onu_reason=${valid_onu_states}
+ ... AND Wait Until Keyword Succeeds ${timeout} 2s
+ ... Verify UNI Port Is Disabled ${VGC_SSH_IP} ${VGC_SSH_PORT} ${src['onu']} ${src['uni_id']}
+ ... AND Run Keyword If ${has_dataplane} Run Keyword And Continue On Failure
+ ... Wait Until Keyword Succeeds ${timeout} 2s
+ ... Check Ping False ${dst['dp_iface_ip_qinq']} ${src['dp_iface_name']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']}
+ ... ${src['container_name']}
+ # Remove Subscriber Access (To replicate DT workflow)
+ ... AND Wait Until Keyword Succeeds ${timeout} 2s Remove Subscriber Access ${of_id} ${onu_port}
+ #Execute VGC CLI Command use single connection
+ #... ${VGC_SSH_IP} ${VGC_SSH_PORT} volt-remove-subscriber-access ${of_id} ${onu_port}
+ # Delete ONU Device (To replicate DT workflow)
+ ... AND Delete Device ${onu_device_id}
+ # Additional Sleep to let subscriber and ONU delete process
+ ... AND Sleep 10s
+ ... ELSE
+ ... Run Keyword If ${has_dataplane} Run Keyword And Continue On Failure
+ ... Wait Until Keyword Succeeds ${timeout} 2s
+ ... Check Ping True ${dst['dp_iface_ip_qinq']} ${src['dp_iface_name']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']}
+ ... ${src['container_name']}
+ END
+
+Validate ONUs for PON OLT Enable DT
+ [Arguments] ${olt_sn} ${olt_peer_list}
+ [Documentation] This keyword validates Ping succeeds for all Enabled/Acitve OLT PON ports
+ ... Also performs subscriberAdd/DHCP/Ping for the ONUs on Re-Enabled OLT PON port
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ Continue For Loop If "${olt_sn}"!="${src['olt']}"
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ ${of_id}= Wait Until Keyword Succeeds ${timeout} 15s Validate OLT Device in VGC ${src['olt']}
+ ${nni_port}= Wait Until Keyword Succeeds ${timeout} 2s Get NNI Port in VGC ${of_id}
+ ${onu_port}= Wait Until Keyword Succeeds ${timeout} 2s Get ONU Port in VGC ${src['onu']}
+ ... ${of_id} ${src['uni_id']}
+ ${matched}= Match ONU in PON OLT Peer List ${olt_peer_list} ${onu_device_id}
+ Run Keyword If ${matched}
+ ... Run Keywords
+ # Perform Cleanup
+ ... Run Keyword If ${has_dataplane} Clean Up Linux ${onu_device_id}
+ # Verify ONU port status
+ ... AND Wait Until Keyword Succeeds 120s 2s
+ ... Verify UNI Port Is Enabled ${src['onu']} ${src['uni_id']}
+ ... AND Wait Until Keyword Succeeds ${timeout} 2
+ # ... Execute VGC CLI Command use single connection ${VGC_SSH_IP} ${VGC_SSH_PORT}
+ # ... volt-add-subscriber-access ${of_id} ${onu_port}
+ ... Add Subscriber Details ${of_id} ${onu_port}
+ # Verify ONU state in voltha
+ ... AND Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate Device ENABLED ACTIVE REACHABLE
+ ... ${src['onu']} onu=True onu_reason=omci-flows-pushed
+ # Verify subscriber access flows are added for the ONU port
+ ... AND Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Subscriber Access Flows Added For ONU DT In VGC ${VGC_SSH_IP} ${VGC_SSH_PORT} ${of_id}
+ ... ${onu_port} ${nni_port} ${src['s_tag']}
+ ... AND Run Keyword If ${has_dataplane}
+ ... Run Keyword And Continue On Failure Validate DHCP and Ping True
+ ... True ${src['dp_iface_name']} ${src['s_tag']} ${src['c_tag']} ${dst['dp_iface_ip_qinq']}
+ ... ${src['ip']} ${src['user']} ${src['pass']}
+ ... ${src['container_type']} ${src['container_name']}
+ ... ${dst['dp_iface_name']} ${dst['ip']} ${dst['user']} ${dst['pass']}
+ ... ${dst['container_type']} ${dst['container_name']}
+ ... ELSE
+ ... Run Keyword If ${has_dataplane} Run Keyword And Continue On Failure
+ ... Wait Until Keyword Succeeds ${timeout} 2s
+ ... Check Ping True ${dst['dp_iface_ip_qinq']} ${src['dp_iface_name']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']}
+ ... ${src['container_name']}
+ END
+
+Match ONU in PON OLT Peer List
+ [Arguments] ${olt_peer_list} ${onu_device_id}
+ [Documentation] This keyword matches if ONU device is present in OLT PON port peer list
+ ${matched}= Set Variable False
+ FOR ${olt_peer} IN @{olt_peer_list}
+ ${matched}= Set Variable If '${onu_device_id}' == '${olt_peer}' True False
+ Exit For Loop If ${matched}
+ END
+ [Return] ${matched}
+
+Collect Logs
+ [Documentation] Collect Logs from voltha for various commands
+ Run Keyword and Ignore Error Get Device List from Voltha
+ FOR ${I} IN RANGE 0 ${num_olts}
+ Run Keyword and Ignore Error Get Device Output from Voltha ${olt_ids}[${I}][device_id]
+ Run Keyword and Ignore Error Get Logical Device Output from Voltha ${olt_ids}[${I}][logical_id]
+ END
+
+Verify ping is successful except for given device
+ [Arguments] ${num_onus} ${exceptional_onu}
+ [Documentation] Checks that ping for all the devices are successful except the given ONU.
+ ${pingStatus} Set Variable True
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${pingStatus} Run Keyword If '${src['onu']}' == '${exceptional_onu}' Set Variable False
+ Run Keyword If ${has_dataplane} Run Keyword And Continue On Failure
+ ... Wait Until Keyword Succeeds 60s 2s
+ ... Check Ping ${pingStatus} ${dst['dp_iface_ip_qinq']} ${src['dp_iface_name']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ END
+
+Verify ping is successful for ONUs not on this OLT
+ [Arguments] ${num_all_onus} ${exceptional_olt_id}
+ [Documentation] Checks that pings work for all the ONUs except for the ONUs on the given OLT.
+ #${pingStatus} Set Variable True
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${olt_device_id}= Get Device ID From SN ${src['olt']}
+ Continue For Loop If "${olt_device_id}"=="${exceptional_olt_id}"
+ #${pingStatus} Run Keyword If '${olt_device_id}' == '${exceptional_olt_id}' Set Variable False
+ Run Keyword If ${has_dataplane} Run Keyword And Continue On Failure
+ ... Wait Until Keyword Succeeds 60s 2s
+ ... Check Ping True ${dst['dp_iface_ip_qinq']} ${src['dp_iface_name']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ END
+
+Echo Message to OLT Logs
+ [Arguments] ${message}
+ [Documentation] Echoes ${message} into the OLT logs
+ FOR ${I} IN RANGE 0 ${num_olts}
+ ${olt_user} Evaluate ${olts}[${I}].get("user")
+ ${olt_pass} Evaluate ${olts}[${I}].get("pass")
+ ${olt_ssh_ip} Evaluate ${olts}[${I}].get("sship")
+ ${olt_type} Evaluate ${olts}[${I}].get("type")
+ Continue For Loop If "${olt_user}" == "${None}"
+ Continue For Loop If "${olt_pass}" == "${None}"
+ ${command_timeout}= Set Variable If "${olt_type}"=="adtranolt" 300s 180s
+ Wait Until Keyword Succeeds ${command_timeout} 10s Execute Remote Command
+ ... printf '%s\n' '' '' '${message}' '' >> /var/log/openolt.log
+ ... ${olt_ssh_ip} ${olt_user} ${olt_pass}
+ Wait Until Keyword Succeeds ${command_timeout} 10s Execute Remote Command
+ ... printf '%s\n' '' '' '${message}' '' >> /var/log/dev_mgmt_daemon.log
+ ... ${olt_ssh_ip} ${olt_user} ${olt_pass}
+ Wait Until Keyword Succeeds ${command_timeout} 10s Execute Remote Command
+ ... printf '%s\n' '' '' '${message}' '' >> /var/log/openolt_process_watchdog.log
+ ... ${olt_ssh_ip} ${olt_user} ${olt_pass}
+ END
+
+Start Logging
+ [Arguments] ${label}
+ [Documentation] Start logging for test ${label}
+ ${kail_process}= Run Keyword If "${container_log_dir}" != "${None}" Start Process kail -n ${NAMESPACE}
+ ... -n ${INFRA_NAMESPACE} cwd=${container_log_dir} stdout=${label}-combined.log
+ Set Test Variable ${kail_process}
+ Run Keyword If ${has_dataplane} Echo Message to OLT Logs START ${label}
+
+Start Logging Setup or Teardown
+ [Arguments] ${label}
+ [Documentation] Start logging for suite ${label}
+ ${file}= Replace String ${label} ${SPACE} -
+ ${kail_process}= Run Keyword If "${container_log_dir}" != "${None}" Start Process kail -n ${NAMESPACE}
+ ... -n ${INFRA_NAMESPACE} cwd=${container_log_dir} stdout=${file}-combined.log
+ Set Suite Variable ${kail_process}
+ Run Keyword If ${has_dataplane} Echo Message to OLT Logs START ${label}
+
+Stop Logging Setup or Teardown
+ [Arguments] ${label}
+ [Documentation] End logging for suite;
+ Run sync
+ Run Keyword If ${kail_process} Terminate Process ${kail_process}
+ ${test_logfile}= Run Keyword If "${container_log_dir}" != "${None}"
+ ... Join Path ${container_log_dir} ${label}-combined.log
+ Run Keyword If ${has_dataplane} Echo Message to OLT Logs END ${label}
+
+Stop Logging
+ [Arguments] ${label}
+ [Documentation] End logging for test; remove logfile if test passed and ${logging} is set to False
+ Run sync
+ Run Keyword If ${kail_process} Terminate Process ${kail_process}
+ ${test_logfile}= Run Keyword If "${container_log_dir}" != "${None}"
+ ... Join Path ${container_log_dir} ${label}-combined.log
+ Run Keyword If Test Passed
+ ... Run Keyword If "${logging}" == "False"
+ ... Run Keyword If "${test_logfile}" != "${None}"
+ ... Remove File ${test_logfile}
+ Run Keyword If ${has_dataplane} Echo Message to OLT Logs END ${label}
+
+Clean Up Linux
+ [Documentation] Kill processes and clean up interfaces on src+dst servers
+ [Arguments] ${onu_id}=${EMPTY}
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ Continue For Loop If '${onu_id}' != '${EMPTY}' and '${onu_id}' != '${onu_device_id}'
+ Execute Remote Command sudo pkill wpa_supplicant ${src['ip']}
+ ... ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ Execute Remote Command sudo pkill dhclient ${src['ip']}
+ ... ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ Execute Remote Command sudo pkill mausezahn ${src['ip']}
+ ... ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ Run Keyword If '${dst['ip']}' != '${None}' Execute Remote Command pkill dhcpd
+ ... ${dst['ip']} ${dst['user']} ${dst['pass']} ${dst['container_type']} ${dst['container_name']}
+ Delete IP Addresses from Interface on Remote Host ${src['dp_iface_name']} ${src['ip']}
+ ... ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ Run Keyword If '${dst['ip']}' != '${None}' Delete Interface on Remote Host
+ ... ${dst['dp_iface_name']}.${src['s_tag']} ${dst['ip']} ${dst['user']} ${dst['pass']}
+ ... ${dst['container_type']} ${dst['container_name']}
+ ${bng_ip}= Get Variable Value ${dst['noroot_ip']}
+ ${bng_user}= Get Variable Value ${dst['noroot_user']}
+ ${bng_pass}= Get Variable Value ${dst['noroot_pass']}
+ Run Keyword If "${bng_ip}" != "${NONE}" and "${bng_user}" != "${NONE}" and "${bng_pass}" != "${NONE}"
+ ... Execute Remote Command sudo pkill mausezahn ${bng_ip} ${bng_user} ${bng_pass}
+ ... ${dst['container_type']} ${dst['container_name']}
+ END
+
+Clean Up Linux Per OLT
+ [Documentation] Kill processes and clean up interfaces on src+dst servers
+ [Arguments] ${olt_serial_number}
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ ${sn}= Get Device ID From SN ${src['olt']}
+ #Continue For Loop If '${onu_id}' != '${EMPTY}' and '${onu_id}' != '${onu_device_id}'
+ Continue For Loop If '${olt_serial_number}' == '${sn}'
+ Execute Remote Command sudo pkill wpa_supplicant ${src['ip']}
+ ... ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ Execute Remote Command sudo pkill dhclient ${src['ip']}
+ ... ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ Execute Remote Command sudo pkill mausezahn ${src['ip']}
+ ... ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ Run Keyword If '${dst['ip']}' != '${None}' Execute Remote Command pkill dhcpd
+ ... ${dst['ip']} ${dst['user']} ${dst['pass']} ${dst['container_type']} ${dst['container_name']}
+ Delete IP Addresses from Interface on Remote Host ${src['dp_iface_name']} ${src['ip']}
+ ... ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ Run Keyword If '${dst['ip']}' != '${None}' Delete Interface on Remote Host
+ ... ${dst['dp_iface_name']}.${src['s_tag']} ${dst['ip']} ${dst['user']} ${dst['pass']}
+ ... ${dst['container_type']} ${dst['container_name']}
+ ${bng_ip}= Get Variable Value ${dst['noroot_ip']}
+ ${bng_user}= Get Variable Value ${dst['noroot_user']}
+ ${bng_pass}= Get Variable Value ${dst['noroot_pass']}
+ Run Keyword If "${bng_ip}" != "${NONE}" and "${bng_user}" != "${NONE}" and "${bng_pass}" != "${NONE}"
+ ... Execute Remote Command sudo pkill mausezahn ${bng_ip} ${bng_user} ${bng_pass}
+ ... ${dst['container_type']} ${dst['container_name']}
+ END
+
+Clean dhclient
+ [Documentation] Kills dhclient processes only for all RGs
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ Execute Remote Command sudo pkill dhclient ${src['ip']}
+ ... ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ END
+
+Clean WPA Process
+ [Documentation] Kills wpa_supplicant processes only for all RGs
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ Run Keyword And Ignore Error Kill Linux Process [w]pa_supplicant ${src['ip']}
+ ... ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ END
+
+Should Be Larger Than
+ [Documentation] Verify that value_1 is > value_2
+ [Arguments] ${value_1} ${value_2}
+ Run Keyword If ${value_1} <= ${value_2}
+ ... Fail The value ${value_1} is not larger than ${value_2}
+
+Should Be Larger Than Or Equal To
+ [Documentation] Verify that value_1 is >= value_2
+ [Arguments] ${value_1} ${value_2}
+ Run Keyword If ${value_1} < ${value_2}
+ ... Fail The value ${value_1} is not larger than or equal to ${value_2}
+
+Should Be Lower Than
+ [Documentation] Verify that value_1 is < value_2
+ [Arguments] ${value_1} ${value_2}
+ Run Keyword If ${value_1} >= ${value_2}
+ ... Fail The value ${value_1} is not lower than ${value_2}
+
+Should Be Float
+ [Documentation] Verify that value is a floating point number type
+ [Arguments] ${value}
+ ${type} Evaluate type(${value}).__name__
+ Should Be Equal ${type} float
+
+Should Be Newer Than Or Equal To
+ [Documentation] Compare two RFC3339 dates
+ [Arguments] ${value_1} ${value_2}
+ ${unix_v1} Parse RFC3339 ${value_1}
+ ${unix_v2} Parse RFC3339 ${value_2}
+ Run Keyword If ${unix_v1} < ${unix_v2}
+ ... Fail The value ${value_1} is not newer than or equal to ${value_2}
+
+Get Current Time
+ [Documentation] Return the current time in RFC3339 format
+ ${output}= Run date -u +"%FT%T%:z"
+ [return] ${output}
+
+Parse RFC3339
+ [Documentation] Parse an RFC3339 timestamp
+ [Arguments] ${dateStr}
+ ${rc} ${output}= Run and Return Rc and Output date --date="${dateStr}" "+%s"
+ Should Be Equal As Numbers ${rc} 0
+ [return] ${output}
+
+Execute Remote Command
+ [Documentation] SSH into a remote host and execute a command on the bare host or in a container.
+ ... This replaces and simplifies the Login And Run Command On Remote System keyword in CORDRobot.
+ [Arguments] ${cmd} ${ip} ${user} ${pass}=${None}
+ ... ${container_type}=${None} ${container_name}=${None} ${timeout}=${None}
+ ${conn_id}= SSHLibrary.Open Connection ${ip}
+ Run Keyword If '${pass}' != '${None}'
+ ... SSHLibrary.Login ${user} ${pass}
+ ... ELSE
+ ... SSHLibrary.Login With Public Key ${user} %{HOME}/.ssh/id_rsa
+ ${namespace}= Run Keyword If '${container_type}' == 'K8S' SSHLibrary.Execute Command
+ ... kubectl get pods --all-namespaces | grep ${container_name} | awk '{print $1}'
+ ${stdout} ${stderr} ${rc}= Run Keyword If '${container_type}' == 'LXC'
+ ... SSHLibrary.Execute Command lxc exec ${container_name} -- ${cmd}
+ ... return_stderr=True return_rc=True timeout=${timeout}
+ ... ELSE IF '${container_type}' == 'K8S'
+ ... SSHLibrary.Execute Command kubectl -n ${namespace} exec ${container_name} -- ${cmd}
+ ... return_stderr=True return_rc=True timeout=${timeout}
+ ... ELSE
+ ... SSHLibrary.Execute Command ${cmd} return_stderr=True return_rc=True timeout=${timeout}
+
+ Log ${stdout}
+ Log ${stderr}
+ Log ${rc}
+ SSHLibrary.Close Connection
+ [Return] ${stdout} ${stderr} ${rc}
+
+Start Remote Command
+ [Documentation] SSH into a remote host and execute a command on the bare host or in a container.
+ ... This replaces and simplifies the Login And Run Command On Remote System keyword in CORDRobot.
+ [Arguments] ${cmd} ${ip} ${user} ${pass}=${None}
+ ... ${container_type}=${None} ${container_name}=${None}
+ ${conn_id}= SSHLibrary.Open Connection ${ip}
+ Run Keyword If '${pass}' != '${None}'
+ ... SSHLibrary.Login ${user} ${pass}
+ ... ELSE
+ ... SSHLibrary.Login With Public Key ${user} %{HOME}/.ssh/id_rsa
+ ${namespace}= Run Keyword If '${container_type}' == 'K8S' SSHLibrary.Execute Command
+ ... kubectl get pods --all-namespaces | grep ${container_name} | awk '{print $1}'
+ Run Keyword If '${container_type}' == 'LXC'
+ ... SSHLibrary.Start Command lxc exec ${container_name} -- ${cmd}
+ ... ELSE IF '${container_type}' == 'K8S'
+ ... SSHLibrary.Start Command kubectl -n ${namespace} exec ${container_name} -- ${cmd}
+ ... ELSE
+ ... SSHLibrary.Start Command ${cmd}
+ # It seems that closing the connection immediately will sometimes kill the command
+ Sleep 1s
+ SSHLibrary.Close Connection
+
+Run Iperf3 Test Client
+ [Arguments] ${src} ${server} ${args}
+ [Documentation] Login to ${src} and run the iperf3 client against ${server} using ${args}.
+ ... Return a Dictionary containing the results of the test.
+ ${output} ${stderr} ${rc}= Execute Remote Command iperf3 -J -c ${server} ${args} -l 1024 -M 1350 | jq -M -c '.'
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ Should Be Equal As Integers ${rc} 0
+ ${object}= Evaluate json.loads(r'''${output}''') json
+ [Return] ${object}
+
+Run Iperf Test Client for MCAST
+ [Arguments] ${src} ${server} ${args}
+ [Documentation] Login to ${src} and run the iperf client against ${server} using ${args}.
+ ... Return a Dictionary containing the results of the test.
+ ${output} ${stderr} ${rc}= Execute Remote Command sudo iperf -c ${server} ${args} | jq -M -c '.'
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ Should Be Equal As Integers ${rc} 0
+ ${object}= Evaluate json.loads(r'''${output}''') json
+ [Return] ${object}
+
+Run Ping In Background
+ [Arguments] ${output_file} ${dst_ip} ${iface} ${ip} ${user} ${pass}=${None}
+ ... ${container_type}=${None} ${container_name}=${None}
+ [Documentation] Runs the 'ping' on remote system in background and stores the result in a file
+ ${result}= Login And Run Command On Remote System
+ ... echo "ping -I ${iface} ${dst_ip} > ${output_file} &" > ping.sh; chmod +x ping.sh; ./ping.sh
+ ... ${ip} ${user} ${pass} ${container_type} ${container_name}
+ Log ${result}
+
+Stop Ping Running In Background
+ [Arguments] ${ip} ${user} ${pass}=${None}
+ ... ${container_type}=${None} ${container_name}=${None}
+ [Documentation] Stops the 'ping' running in background on remote system
+ ${cmd}= Run Keyword If '${container_type}' == 'LXC' or '${container_type}' == 'K8S'
+ ... Set Variable kill -SIGINT `pgrep ping`
+ ... ELSE
+ ... Set Variable sudo kill -SIGINT `pgrep ping`
+ ${result}= Login And Run Command On Remote System
+ ... ${cmd} ${ip} ${user} ${pass} ${container_type} ${container_name}
+ Log ${result}
+
+Retrieve Remote File Contents
+ [Documentation] Retrieves the contents of the file on remote system
+ [Arguments] ${file} ${ip} ${user} ${pass}=${None}
+ ... ${container_type}=${None} ${container_name}=${None} ${prompt}=~$
+ ${output}= Login And Run Command On Remote System
+ ... cat ${file}
+ ... ${ip} ${user} ${pass} ${container_type} ${container_name} ${prompt}
+ [Return] ${output}
+
+RestoreONUs
+ [Documentation] Restore all connected ONUs
+ [Arguments] ${num_all_onus}
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${container_type}= Get Variable Value ${src['container_type']} "null"
+ ${container_name}= Get Variable Value ${src['container_name']} "null"
+ ${onu_type}= Get Variable Value ${src['onu_type']} "null"
+ #Get ens6f0 from ens6f0.22
+ ${if_name}= Replace String Using Regexp ${src['dp_iface_name']} \\..* \
+ Run Keyword IF '${onu_type}' == 'alpha' AlphaONURestoreDefault ${src['ip']} ${src['user']}
+ ... ${src['pass']} ${if_name} admin admin ${container_type} ${container_name}
+ END
+
+AlphaONURestoreDefault
+ [Documentation] Restore the Alpha ONU to factory setting
+ [Arguments] ${rg_ip} ${rg_user} ${rg_pass} ${onu_ifname}
+ ... ${onu_user} ${onu_pass} ${container_type}=${None} ${container_name}=${None}
+ ${output}= Login And Run Command On Remote System sudo ifconfig ${onu_ifname} 192.168.1.3/24
+ ... ${rg_ip} ${rg_user} ${rg_pass} ${container_type} ${container_name}
+ ${cmd} Catenate
+ ... (echo open "192.168.1.1"; sleep 1;
+ ... echo "${onu_user}"; sleep 1;
+ ... echo "${onu_pass}"; sleep 1;
+ ... echo "restoredefault"; sleep 1) | telnet
+ ${output}= Login And Run Command On Remote System ${cmd}
+ ... ${rg_ip} ${rg_user} ${rg_pass} ${container_type} ${container_name}
+ Log To Console ${output}
+ ${output}= Login And Run Command On Remote System sudo ifconfig ${onu_ifname} 0
+ ... ${rg_ip} ${rg_user} ${rg_pass} ${container_type} ${container_name}
+
+Create traffic with each pbit and capture at other end
+ [Documentation] Generates upstream traffic using Mausezahn tool
+ ... with each pbit and validates reception at other end using tcpdump
+ [Arguments] ${target_ip} ${target_iface} ${src_iface}
+ ... ${packet_count} ${packet_type} ${c_vlan} ${s_vlan} ${direction} ${tcpdump_filter}
+ ... ${dst_ip} ${dst_user} ${dst_pass} ${dst_container_type} ${dst_container_name}
+ ... ${src_ip} ${src_user} ${src_pass} ${src_container_type} ${src_container_name}
+ FOR ${pbit} IN RANGE 8
+ Execute Remote Command sudo pkill mausezahn
+ ... ${src_ip} ${src_user} ${src_pass} ${src_container_type} ${src_container_name}
+ ${var1}= Set Variable sudo mausezahn ${src_iface} -B ${target_ip} -c ${packet_count}
+ ${var2}= Run Keyword If "${direction}"=="downstream"
+ ... Set Variable -t ${packet_type} "dp=80, flags=rst, p=aa:aa:aa" -Q ${pbit}:${s_vlan},${pbit}:${c_vlan}
+ ... ELSE
+ ... Set Variable -t ${packet_type} "dp=80, flags=rst, p=aa:aa:aa" -Q ${pbit}:${c_vlan}
+ ${cmd}= Set Variable ${var1} ${var2}
+ Start Remote Command ${cmd} ${src_ip} ${src_user} ${src_pass}
+ ... ${src_container_type} ${src_container_name}
+ ${output} ${stderr} ${rc}= Execute Remote Command
+ ... sudo tcpdump -l -U -c 30 -i ${target_iface} -e ${tcpdump_filter}
+ ... ${dst_ip} ${dst_user} ${dst_pass} ${dst_container_type} ${dst_container_name}
+ ... timeout=30 seconds
+ Execute Remote Command sudo pkill mausezahn
+ ... ${src_ip} ${src_user} ${src_pass} ${src_container_type} ${src_container_name}
+ Run Keyword If "${tcpdump_filter}"=="tcp"
+ ... Should Match Regexp ${output} , p ${pbit},
+ END
+
+Determine Number Of ONU
+ [Arguments] ${olt_serial_number}=${EMPTY} ${num_onus}=${num_all_onus}
+ [Documentation] Determine the number of different ONUs for the given OLT taken from host.src
+ ${onu_list} Create List
+ FOR ${INDEX} IN RANGE 0 ${num_onus}
+ Continue For Loop If "${olt_serial_number}"!="${hosts.src[${INDEX}].olt}" and "${olt_serial_number}"!="${EMPTY}"
+ ${onu_id}= Get Index From List ${onu_list} ${hosts.src[${INDEX}].onu}
+ Run Keyword If -1 == ${onu_id} Append To List ${onu_list} ${hosts.src[${INDEX}].onu}
+ END
+ ${real_num_onus}= Get Length ${onu_list}
+ [Return] ${real_num_onus}
+
+Validate Cleanup In ETCD
+ [Documentation] The keyword verifies that device, ports, flows, meters are all cleared in ETCD
+ [Arguments] ${namespace}=default ${defaultkvstoreprefix}=voltha/voltha_voltha
+ ${podname}= Set Variable etcd
+ ${kvstoreprefix}= Get Kv Store Prefix ${defaultkvstoreprefix}
+ # Log Devices Output and Verify Output Should be Empty
+ ${commandget}= Catenate
+ ... /bin/sh -c 'ETCDCTL_API=3 etcdctl get --prefix service/${kvstoreprefix}/devices --keys-only'
+ ${result}= Exec Pod In Kube ${namespace} ${podname} ${commandget}
+ Log ${result}
+ Should Be Empty ${result} Stale Devices Data in Etcd!
+ # Log Flows Output and Verify Output Should be Empty
+ ${commandget}= Catenate
+ ... /bin/sh -c 'ETCDCTL_API=3 etcdctl get --prefix service/${kvstoreprefix}/flows --keys-only'
+ ${result}= Exec Pod In Kube ${namespace} ${podname} ${commandget}
+ Log ${result}
+ Should Be Empty ${result} Stale Flows Data in Etcd!
+ # Log LogicalDevices Output and Verify Output Should be Empty
+ ${commandget}= Catenate
+ ... /bin/sh -c 'ETCDCTL_API=3 etcdctl get --prefix service/${kvstoreprefix}/logical_devices --keys-only'
+ ${result}= Exec Pod In Kube ${namespace} ${podname} ${commandget}
+ Log ${result}
+ Should Be Empty ${result} Stale Logical Devices Data in Etcd!
+ # Log LogicalFlows Output and Verify Output Should be Empty
+ ${commandget}= Catenate
+ ... /bin/sh -c 'ETCDCTL_API=3 etcdctl get --prefix service/${kvstoreprefix}/logical_flows --keys-only'
+ ${result}= Exec Pod In Kube ${namespace} ${podname} ${commandget}
+ Log ${result}
+ Should Be Empty ${result} Stale Logical Flows Data in Etcd!
+ # Log LogicalMeters Output and Verify Output Should be Empty
+ ${commandget}= Catenate
+ ... /bin/sh -c 'ETCDCTL_API=3 etcdctl get --prefix service/${kvstoreprefix}/logical_meters --keys-only'
+ ${result}= Exec Pod In Kube ${namespace} ${podname} ${commandget}
+ Log ${result}
+ Should Be Empty ${result} Stale Logical Meters Data in Etcd!
+ # Log LogicalPorts Output and Verify Output Should be Empty
+ ${commandget}= Catenate
+ ... /bin/sh -c 'ETCDCTL_API=3 etcdctl get --prefix service/${kvstoreprefix}/logical_ports --keys-only'
+ ${result}= Exec Pod In Kube ${namespace} ${podname} ${commandget}
+ Log ${result}
+ Should Be Empty ${result} Stale Logical Ports Data in Etcd!
+ # Log Openolt Output and Verify Output Should be Empty
+ ${commandget}= Catenate
+ ... /bin/sh -c 'ETCDCTL_API=3 etcdctl get --prefix service/${kvstoreprefix}/openolt --keys-only'
+ ${result}= Exec Pod In Kube ${namespace} ${podname} ${commandget}
+ Log ${result}
+ Should Be Empty ${result} Stale Openolt Data in Etcd!
+ # Log Openonu Output and Verify Output Should be Empty
+ ${commandget}= Catenate
+ ... /bin/sh -c 'ETCDCTL_API=3 etcdctl get --prefix service/${kvstoreprefix}/openonu --keys-only'
+ ${result}= Exec Pod In Kube ${namespace} ${podname} ${commandget}
+ Log ${result}
+ Should Be Empty ${result} Stale Openonu Data in Etcd!
+ # Log Ports Output and Verify Output Should be Empty
+ ${commandget}= Catenate
+ ... /bin/sh -c 'ETCDCTL_API=3 etcdctl get --prefix service/${kvstoreprefix}/ports --keys-only'
+ ${result}= Exec Pod In Kube ${namespace} ${podname} ${commandget}
+ Log ${result}
+ Should Be Empty ${result} Stale Ports Data in Etcd!
+ # Log ResourceInstances Output and Verify Output Should be Empty
+ ${commandget}= Catenate
+ ... /bin/sh -c 'ETCDCTL_API=3 etcdctl get --prefix service/${kvstoreprefix}/resource_instances --keys-only'
+ ${result}= Exec Pod In Kube ${namespace} ${podname} ${commandget}
+ Log ${result}
+ Should Be Empty ${result} Stale Resource Instances Data in Etcd!
+ # Log ResourceManager Output and Verify Output Should be Empty
+ ${commandget}= Catenate
+ ... /bin/sh -c 'ETCDCTL_API=3 etcdctl get --prefix service/${kvstoreprefix}/resource_manager --keys-only'
+ ${result}= Exec Pod In Kube ${namespace} ${podname} ${commandget}
+ Log ${result}
+ Should Be Empty ${result} Stale Resource Manager Data in Etcd!
+
+Clean Up All Nodes
+ [Documentation] Login to each node and kill all stale lxc prcoesses
+ ${num_nodes}= Get Length ${nodes}
+ FOR ${I} IN RANGE 0 ${num_nodes}
+ ${node_ip}= Evaluate ${nodes}[${I}].get("ip")
+ ${node_user}= Evaluate ${nodes}[${I}].get("user")
+ ${node_pass}= Evaluate ${nodes}[${I}].get("pass")
+ Run Keyword And Continue On Failure Start Remote Command kill -9 `pidof lxc`
+ ... ${node_ip} ${node_user} ${node_pass}
+ END
+
+Reboot XGSPON ONU
+ [Documentation] Reboots the XGSPON ONU and verifies the ONU state after the reboot
+ [Arguments] ${olt_sn} ${onu_sn} ${reason}
+ FOR ${I} IN RANGE 0 ${num_olts}
+ ${serial_number} Evaluate ${olts}[${I}].get("serial")
+ Continue For Loop If "${serial_number}"!="${olt_sn}"
+ ${board_tech} Evaluate ${olts}[${I}].get("board_technology")
+ ${onu_device_id}= Get Device ID From SN ${onu_sn}
+ Run Keyword If "${board_tech}"=="XGS-PON" Run Keywords
+ ... Reboot Device ${onu_device_id}
+ ... AND Wait Until Keyword Succeeds 120s 5s
+ ... Validate Device ENABLED ACTIVE
+ ... REACHABLE ${onu_sn} onu=True onu_reason=${reason}
+ END
+
+Set Non-Critical Tag for XGSPON Tech
+ [Documentation] Dynamically sets the test tag for xgs-pon based to non-critical
+ FOR ${I} IN RANGE 0 ${num_olts}
+ ${board_tech} Evaluate ${olts}[${I}].get("board_technology")
+ Run Keyword If "${board_tech}"=="XGS-PON" Run Keywords
+ ... Set Tags non-critical
+ ... AND Exit For Loop
+ END
+
+Perform Reboot ONUs and OLTs Physically
+ [Documentation] This keyword reboots ONUs and OLTs physically
+ ... It runs only on the PODs that are configured with PowerSwitch that
+ ... controls the power off/on ONUs/OLT remotely (simulating a physical reboot)
+ [Arguments] ${power_cycle_olt}=False
+ Power Switch Connection Suite ${web_power_switch.ip} ${web_power_switch.user} ${web_power_switch.password}
+ @{onu_list}= Create List
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ # If the power switch port is not specified, continue
+ Continue For Loop If '${src["power_switch_port"]}' == '${None}'
+ # Skip if we have already handled this ONU
+ ${sn}= Set Variable ${src['onu']}
+ ${onu_id}= Get Index From List ${onu_list} ${sn}
+ Continue For Loop If -1 != ${onu_id}
+ Append To List ${onu_list} ${sn}
+ Disable Switch Outlet ${src['power_switch_port']}
+ Sleep 10s
+ Enable Switch Outlet ${src['power_switch_port']}
+ END
+ Pass Execution If '${power_cycle_olt}'=='False' Skipping OLT(s) Power Switch Reboot
+ # Waiting extra time for the ONUs to come up
+ Sleep 30s
+ FOR ${I} IN RANGE 0 ${olt_count}
+ ${olt_serial_number}= Get From Dictionary ${list_olts}[${I}] sn
+ ${power_switch_port}= Get From Dictionary ${list_olts}[${I}] powerswitchport
+ ${olt_ssh_ip}= Get From Dictionary ${list_olts}[${I}] sship
+ # If the power switch port is not specified, continue
+ Continue For Loop If '${power_switch_port}' == '${None}'
+ Disable Switch Outlet ${power_switch_port}
+ Sleep 10s
+ Enable Switch Outlet ${power_switch_port}
+ Run Keyword If ${has_dataplane} Wait Until Keyword Succeeds 120s 10s
+ ... Check Remote System Reachability True ${olt_ssh_ip}
+ END
+ # Waiting extra time for the ONUs to come up
+ Sleep 60s
+
+Count Number of UNI ports for OLT
+ [Documentation] Count Provisioned UNI ports, for ONUs connected with specified OLT
+ [Arguments] ${olt_serial_number} ${type_of_service}
+ ${num_of_provisioned_onus_ports}= Evaluate 0
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ Continue For Loop If "${olt_serial_number}"!="${src['olt']}"
+ Continue For Loop If "${type_of_service}"!="${src['service_type']}"
+ ${num_of_provisioned_onus_ports}= Evaluate ${num_of_provisioned_onus_ports} + 1
+ END
+ [Return] ${num_of_provisioned_onus_ports}
diff --git a/libraries/vgc.robot b/libraries/vgc.robot
new file mode 100755
index 0000000..508f48f
--- /dev/null
+++ b/libraries/vgc.robot
@@ -0,0 +1,812 @@
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# vgc common functions
+
+*** Settings ***
+Documentation Library for various utilities
+Library SSHLibrary
+Library String
+Library DateTime
+Library Process
+Library Collections
+Library RequestsLibrary
+Library OperatingSystem
+
+*** Variables ***
+@{connection_list}
+${alias} VGC_SSH
+${ssh_read_timeout} 60s
+${ssh_prompt} karaf@root >
+${ssh_regexp_prompt} REGEXP:k.*a.*r.*a.*f.*@.*r.*o.*o.*t.* .*>.*
+${regexp_prompt} (?ms)(.*)k(.*)a(.*)r(.*)a(.*)f(.*)@(.*)r(.*)o(.*)o(.*)t(.*) (.*)>(.*)
+${ssh_width} 400
+${disable_highlighter} setopt disable-highlighter
+# ${keep_alive_interval} is set to 0s means sending the keepalive packet is disabled!
+${keep_alive_interval} 0s
+${INFRA_DT_NAMESPACE} infra
+
+
+*** Keywords ***
+Create VGC Session
+ [Documentation] Creates a VGC session
+ Create Session VGC http://${VGC_REST_IP}:${VGC_REST_PORT}/vgc/v1
+
+Validate OLT Device in VGC
+ # FIXME use volt-olts to check that the OLT is VGC
+ [Arguments] ${serial_number}
+ [Documentation] Checks if olt has been connected to VGC
+ Create VGC Session
+ ${resp}= Get Request VGC devices
+ Log ${resp}
+ ${jsondata}= To Json ${resp.content}
+ Should Not Be Empty ${jsondata['devices']}
+ ${length}= Get Length ${jsondata['devices']}
+ @{serial_numbers}= Create List
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${value}= Get From List ${jsondata['devices']} ${INDEX}
+ ${of_id}= Get From Dictionary ${value} id
+ ${sn}= Get From Dictionary ${value} serial
+ ${matched}= Set Variable If '${sn}' == '${serial_number}' True False
+ Exit For Loop If ${matched}
+ END
+ Should Be True ${matched} No match for ${serial_number} found
+ [Return] ${of_id}
+
+
+
+Validate Deleted Device Cleanup In VGC
+ [Arguments] ${ip} ${port} ${olt_serial_number} ${olt_of_id} ${maclearning_enabled}=False
+ [Documentation] The keyword verifies that ports, flows, meters, subscribers, dhcp are all cleared in VGC
+ # Verify Ports are Removed
+ ${ports}= Get Request VGC devices/ports
+ ${port_json_resp}= To Json ${ports.content}
+ Should Not Contain ${port_json_resp} ${olt_of_id} Ports have not been removed from VGC after cleanup
+ # Verify Subscribers are Removed
+ ${sub}= Get Request VGC programmed-subscribers
+ ${sub_json_resp}= To Json ${sub.content}
+ Should Not Contain ${sub_json_resp} ${olt_of_id} Subscriber have not been removed from VGC after cleanup
+ # Verify Flows are Removed
+ ${flows}= Get Request VGC flows
+ ${flow_json_resp}= To Json ${flows.content}
+ Should Not Contain ${flow_json_resp} ${olt_of_id} Flows have not been removed from VGC after cleanup
+ # Verify Meters are Removed
+ ${meter}= Get Request VGC meters
+ ${meter_json_resp}= To Json ${meter.content}
+ Should Not Contain ${meter_json_resp} ${olt_of_id} Meter have not been removed from VGC after cleanup
+ # Verify AAA-Users are Removed
+ # ${aaa}= Execute ONOS CLI Command use single connection ${ip} ${port}
+ #... aaa-users ${olt_of_id}
+ # ${aaa_count}= Get Line Count ${aaa}
+ #Should Be Equal As Integers ${aaa_count} 0 AAA Users have not been removed from ONOS after cleanup
+ # Verify Dhcp-Allocations are Removed
+ ${dhcp}= Get Request VGC allocations/${olt_of_id}
+ ${dhcp_json_resp}= To Json ${dhcp.content}
+ ${dhcp_count} = Get Length ${dhcp_json_resp}
+ #Should Be Equal ${dhcp_json_resp} ${None} DHCP Allocations have not been removed from VGC after cleanup
+ Should Be Equal As Integers ${dhcp_count} 0 DHCP Allocations have not been removed from VGC after cleanup
+ # Verify MAC Learner Mappings are Removed
+ # ${mac}= Run Keyword If ${maclearning_enabled} Execute ONOS CLI Command use single connection ${ip} ${port}
+ # ... mac-learner-get-mapping | grep -v INFO
+ # ${mac_count}= Run Keyword If ${maclearning_enabled} Get Line Count ${mac}
+ # ... ELSE Set Variable 0
+ # Should Be Equal As Integers ${mac_count} 0 Client MAC Learner Mappings have not been removed from ONOS after cleanup
+
+
+Get NNI Port in VGC
+ [Arguments] ${olt_of_id}
+ [Documentation] Retrieves NNI port for the OLT in VGC
+ ${resp}= Get Request VGC devices/${olt_of_id}/ports
+ ${jsondata}= To Json ${resp.content}
+ Should Not Be Empty ${jsondata['ports']}
+ ${length}= Get Length ${jsondata['ports']}
+ @{ports}= Create List
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${value}= Get From List ${jsondata['ports']} ${INDEX}
+ ${annotations}= Get From Dictionary ${value} annotations
+ ${nni_port}= Get From Dictionary ${value} port
+ ${nniPortName}= Catenate SEPARATOR= nni- ${nni_port}
+ ${portName}= Get From Dictionary ${annotations} portName
+ ${matched}= Set Variable If '${portName}' == '${nniPortName}' True False
+ Exit For Loop If ${matched}
+ END
+ Should Be True ${matched} No match for NNI found for ${olt_of_id}
+ [Return] ${nni_port}
+
+
+
+Get ONU Port in VGC
+ [Arguments] ${onu_serial_number} ${olt_of_id} ${onu_uni_id}=1
+ [Documentation] Retrieves ONU port for the ONU in VGC
+ ${onu_serial_number}= Catenate SEPARATOR=- ${onu_serial_number} ${onu_uni_id}
+ ${resp}= Get Request VGC devices/${olt_of_id}/ports
+ ${jsondata}= To Json ${resp.content}
+ Should Not Be Empty ${jsondata['ports']}
+ ${length}= Get Length ${jsondata['ports']}
+ @{ports}= Create List
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${value}= Get From List ${jsondata['ports']} ${INDEX}
+ ${annotations}= Get From Dictionary ${value} annotations
+ ${onu_port}= Get From Dictionary ${value} port
+ ${portName}= Get From Dictionary ${annotations} portName
+ ${matched}= Set Variable If '${portName}' == '${onu_serial_number}' True False
+ Exit For Loop If ${matched}
+ END
+ Should Be True ${matched} No match for ${onu_serial_number} found
+ [Return] ${onu_port}
+
+
+
+Verify UNI Port Is Enabled
+ [Arguments] ${onu_name} ${onu_uni_id}=1
+ [Documentation] Verifies if the ONU's UNI port is enabled in VGC
+ ${onu_serial_number}= Catenate SEPARATOR=- ${onu_name} ${onu_uni_id}
+ ${resp}= Get Request VGC devices/ports
+ ${jsondata}= To Json ${resp.content}
+ Should Not Be Empty ${jsondata['ports']}
+ ${length}= Get Length ${jsondata['ports']}
+ @{ports}= Create List
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${value}= Get From List ${jsondata['ports']} ${INDEX}
+ ${annotations}= Get From Dictionary ${value} annotations
+ ${onu_port}= Get From Dictionary ${value} port
+ ${portName}= Get From Dictionary ${annotations} portName
+ ${portstatus}= Get From Dictionary ${value} isEnabled
+ ${matched}= Set Variable If '${portName}' == '${onu_serial_number}' True False
+ Exit For Loop If ${matched}
+ END
+ Should Be True ${matched} No match for ${onu_serial_number} found
+ Should be Equal ${portstatus} ${True}
+
+
+Verify UNI Port Is Disabled
+ [Arguments] ${ip} ${port} ${onu_name} ${onu_uni_id}=1
+ [Documentation] Verifies if the ONU's UNI port is enabled in VGC
+ ${onu_serial_number}= Catenate SEPARATOR=- ${onu_name} ${onu_uni_id}
+ ${resp}= Get Request VGC devices/ports
+ ${jsondata}= To Json ${resp.content}
+ Should Not Be Empty ${jsondata['ports']}
+ ${length}= Get Length ${jsondata['ports']}
+ @{ports}= Create List
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${value}= Get From List ${jsondata['ports']} ${INDEX}
+ ${annotations}= Get From Dictionary ${value} annotations
+ ${onu_port}= Get From Dictionary ${value} port
+ ${portName}= Get From Dictionary ${annotations} portName
+ ${portstatus}= Get From Dictionary ${value} isEnabled
+ ${matched}= Set Variable If '${portName}' == '${onu_serial_number}' True False
+ Exit For Loop If ${matched}
+ END
+ Should Be True ${matched} No match for ${onu_serial_number} found
+ Should be Equal ${portstatus} ${False}
+
+Close All VGC SSH Connections
+ [Documentation] Close all VGC Connection and clear connection list.
+ SSHLibrary.Close All Connections
+ @{connection_list} Create List
+
+
+
+Verify Subscriber Access Flows Added For ONU DT in VGC
+ [Arguments] ${ip} ${port} ${olt_of_id} ${onu_port} ${nni_port} ${s_tag}
+ [Documentation] Verifies if the Subscriber Access Flows are added in VGC for the ONU
+ # Get all flows from VGC
+ ${resp}= Get Request VGC flows/${olt_of_id}
+ ${jsondata}= To Json ${resp.content}
+ Should Not Be Empty ${jsondata['flows']}
+ # Verify upstream table=0 flow
+ ${length}= Get Length ${jsondata['flows']}
+ @{flows}= Create List
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${flow}= Get From List ${jsondata['flows']} ${INDEX}
+ ${tableid}= Get Table Id From Flow ${flow}
+ ${inport}= Get In Port From Flow ${flow}
+ ${vlanvid}= Get Vlan VId From Flow ${flow}
+ ${outport}= Get Out Port From Flow ${flow}
+ ${matched}= Set Variable If
+ ... '${tableid}' == '0' and '${inport}' == '${onu_port}' and '${vlanvid}' == '4096' and '${outport}' == '1'
+ ... True False
+ Exit For Loop If ${matched}
+ END
+ Should Be True ${matched} No match for upstream table 0 flow found
+ # Verify upstream table=1 flow
+ ${matched1}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${flow}= Get From List ${jsondata['flows']} ${INDEX}
+ ${inport}= Get In Port From Flow ${flow}
+ ${vlanvid}= Get Vlan VId From Flow ${flow}
+ ${outport}= Get Out Port From Flow ${flow}
+ ${subtype}= Get Subtype From Flow ${flow}
+ ${vlanid}= Get Vlan Id From Flow ${flow}
+ ${res1}= Evaluate '${inport}' == '${onu_port}'
+ ${res2}= Evaluate '${vlanvid}' == '4096' and '${outport}' == '${nni_port}'
+ ${res3}= Evaluate '${subtype}' == 'VLAN_PUSH' and '${vlanid}' == '${s_tag}'
+ ${matched1}= Set Variable If ${res1} and ${res2} and ${res3} True False
+ Exit For Loop If ${matched1}
+ END
+ Should Be True ${matched1} No match for upstream table 1 flow found
+ # Verify downstream table=0 flow
+ ${matched2}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${flow}= Get From List ${jsondata['flows']} ${INDEX}
+ ${inport}= Get In Port From Flow ${flow}
+ ${vlanvid}= Get Vlan VId From Flow ${flow}
+ ${outport}= Get Out Port From Flow ${flow}
+ ${subtype}= Get Subtype From Flow ${flow}
+ ${res1}= Evaluate '${inport}' == '${nni_port}'
+ ${res2}= Evaluate '${vlanvid}' == '${s_tag}' and '${outport}' == '1'
+ ${res3}= Evaluate '${subtype}' == 'VLAN_POP'
+ ${matched2}= Set Variable If ${res1} and ${res2} and ${res3} True False
+ Exit For Loop If ${matched2}
+ END
+ Should Be True ${matched2} No match for downstream table 0 flow found
+ # Verify downstream table=1 flow
+ ${matched3}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${flow}= Get From List ${jsondata['flows']} ${INDEX}
+ ${inport}= Get In Port From Flow ${flow}
+ ${vlanvid}= Get Vlan VId From Flow ${flow}
+ ${outport}= Get Out Port From Flow ${flow}
+ ${matched3}= Set Variable If
+ ... '${inport}' == '${nni_port}' and '${vlanvid}' == '4096' and '${outport}' == '${onu_port}'
+ ... True False
+ Exit For Loop If ${matched3}
+ END
+ Should Be True ${matched3} "No match for downstream table 1 flow found"
+
+Verify Subscriber Access Flows Added for DT FTTB
+ [Arguments] ${olt_of_id} ${onu_port} ${nni_port} ${s_tag} ${c_tag}
+ [Documentation] Verifies if the Subscriber Access Flows are added in ONOS for the ONU
+ # Get all flows from VGC
+ ${resp}= Get Request VGC flows/${olt_of_id}
+ ${jsondata}= To Json ${resp.content}
+ Should Not Be Empty ${jsondata['flows']}
+ # Upstream
+ # ONU
+ ${length}= Get Length ${jsondata['flows']}
+ @{flows}= Create List
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${flow}= Get From List ${jsondata['flows']} ${INDEX}
+ ${tableid}= Get Table Id From Flow ${flow}
+ ${inport}= Get In Port From Flow ${flow}
+ ${vlanvid}= Get Vlan VId From Flow ${flow}
+ ${outport}= Get Out Port From Flow ${flow}
+ ${matched}= Set Variable If
+ ... '${inport}' == '${onu_port}' and '${vlanvid}' == '${c_tag}' and '${outport}' == '1'
+ ... True False
+ Exit For Loop If ${matched}
+ END
+ Should Be True ${matched} No match for upstream ONU flow found
+ # OLT
+ ${matched1}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${flow}= Get From List ${jsondata['flows']} ${INDEX}
+ ${inport}= Get In Port From Flow ${flow}
+ ${vlanvid}= Get Vlan VId From Flow ${flow}
+ ${outport}= Get Out Port From Flow ${flow}
+ ${vlanid}= Get Vlan Id From Flow For Fttb ${flow}
+ ${res1}= Evaluate '${inport}' == '${onu_port}'
+ ${res2}= Evaluate '${vlanvid}' == '${c_tag}' and '${vlanid}' == '${s_tag}'
+ ${res3}= Evaluate '${outport}' == '${nni_port}'
+ ${matched1}= Set Variable If ${res1} and ${res2} and ${res3} True False
+ Exit For Loop If ${matched1}
+ END
+ Should Be True ${matched1} No match for upstream OLT found
+ # Downstream
+ # OLT
+ ${matched2}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${flow}= Get From List ${jsondata['flows']} ${INDEX}
+ ${inport}= Get In Port From Flow ${flow}
+ ${vlanvid}= Get Vlan VId From Flow ${flow}
+ ${outport}= Get Out Port From Flow ${flow}
+ ${vlanid}= Get Vlan Id From Flow For Fttb ${flow}
+ ${res1}= Evaluate '${inport}' == '${nni_port}'
+ ${res2}= Evaluate '${vlanvid}' == '${s_tag}' and '${vlanid}' == '${c_tag}'
+ ${res3}= Evaluate '${outport}' == '1'
+ ${matched2}= Set Variable If ${res1} and ${res2} and ${res3} True False
+ Exit For Loop If ${matched2}
+ END
+ Should Be True ${matched2} No match for downstream OLT found
+ # ONU
+ ${matched3}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${flow}= Get From List ${jsondata['flows']} ${INDEX}
+ ${inport}= Get In Port From Flow ${flow}
+ ${vlanvid}= Get Vlan VId From Flow ${flow}
+ ${tableid}= Get Table Id From Flow ${flow}
+ ${outport}= Get Out Port From Flow ${flow}
+ ${vlanid}= Get Vlan Id From Flow For Fttb ${flow}
+ ${res1}= Evaluate '${inport}' == '${nni_port}'
+ ${res2}= Evaluate '${vlanvid}' == '${c_tag}' and '${outport}' == '${onu_port}'
+ ${matched3}= Set Variable If ${res1} and ${res2} True False
+ Exit For Loop If ${matched3}
+ END
+ Should Be True ${matched3} No match for downstream ONU found
+
+Verify DPU MGMT Flows Added for DT FTTB
+ [Arguments] ${olt_of_id} ${onu_port} ${nni_port} ${s_tag} ${c_tag}
+ [Documentation] Verifies if the DPU MGMT Flows are added in VGC for the ONU
+ # Get all flows from VGC
+ ${resp}= Get Request VGC flows/${olt_of_id}
+ ${jsondata}= To Json ${resp.content}
+ Should Not Be Empty ${jsondata['flows']}
+ # Upstream
+ # ONU
+ ${length}= Get Length ${jsondata['flows']}
+ @{flows}= Create List
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${flow}= Get From List ${jsondata['flows']} ${INDEX}
+ ${tableid}= Get Table Id From Flow ${flow}
+ ${inport}= Get In Port From Flow ${flow}
+ ${vlanvid}= Get Vlan VId From Flow ${flow}
+ ${vlanid}= Get Vlan Id From Flow For Fttb ${flow}
+ ${outport}= Get Out Port From Flow ${flow}
+ ${res1}= Evaluate '${inport}' == '${onu_port}'
+ ${res2}= Evaluate '${vlanvid}' == '${c_tag}' and '${vlanid}' == '${s_tag}'
+ ${res3}= Evaluate '${outport}' == '1'
+ ${matched}= Set Variable If ${res1} and ${res2} and ${res3} True False
+ Exit For Loop If ${matched}
+ END
+ Should Be True ${matched} No match for upstream ONU flow found
+ # OLT
+ ${matched1}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${flow}= Get From List ${jsondata['flows']} ${INDEX}
+ ${inport}= Get In Port From Flow ${flow}
+ ${vlanvid}= Get Vlan VId From Flow ${flow}
+ ${outport}= Get Out Port From Flow ${flow}
+ ${vlanid}= Get Vlan Id From Flow For Fttb ${flow}
+ ${matched1}= Set Variable If
+ ... '${inport}' == '${onu_port}' and '${vlanvid}' == '${s_tag}' and '${outport}' == '${nni_port}'
+ ... True False
+ ${matched1}= Set Variable If ${res1} and ${res2} and ${res3} True False
+ Log To Console "bbb",'${inport}' == '${onu_port}' '${vlanvid}' == '${s_tag}' '${outport}' == '${nni_port}'
+ Exit For Loop If ${matched1}
+ END
+ Should Be True ${matched1} No match for upstream OLT found
+ # Downstream
+ # OLT
+ ${matched2}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${flow}= Get From List ${jsondata['flows']} ${INDEX}
+ ${inport}= Get In Port From Flow ${flow}
+ ${vlanvid}= Get Vlan VId From Flow ${flow}
+ ${outport}= Get Out Port From Flow ${flow}
+ ${vlanid}= Get Vlan Id From Flow For Fttb ${flow}
+ ${matched3}= Set Variable If
+ ... '${inport}' == '${nni_port}' and '${vlanvid}' == '${s_tag}' and '${outport}' == '1'
+ ... True False
+ Exit For Loop If ${matched3}
+ END
+ Should Be True ${matched3} No match for downstream OLT found
+ # ONU
+ ${matched4}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${flow}= Get From List ${jsondata['flows']} ${INDEX}
+ ${inport}= Get In Port From Flow ${flow}
+ ${vlanvid}= Get Vlan VId From Flow ${flow}
+ ${tableid}= Get Table Id From Flow ${flow}
+ ${outport}= Get Out Port From Flow ${flow}
+ ${vlanid}= Get Vlan Id From Flow For Fttb ${flow}
+ ${res1}= Evaluate '${inport}' == '${nni_port}'
+ ${res2}= Evaluate '${vlanvid}' == '${s_tag}' and '${vlanid}' == '${c_tag}'
+ ${res3}= Evaluate '${outport}' == '${onu_port}'
+ ${matched4}= Set Variable If ${res1} and ${res2} and ${res3} True False
+ Exit For Loop If ${matched4}
+ END
+ Should Be True ${matched4} No match for downstream ONU found
+
+Verify VGC Flows Added for DT FTTB
+ [Arguments] ${olt_of_id} ${onu_port} ${nni_port} ${service}
+ [Documentation] Verifies if the Flows are added in ONOS for the ONU
+ ${num_services}= Get Length ${service}
+ FOR ${I} IN RANGE 0 ${num_services}
+ ${service_name}= Set Variable ${service[${I}]['name']}
+ ${stag}= Set Variable ${service[${I}]['s_tag']}
+ ${ctag}= Set Variable ${service[${I}]['c_tag']}
+ Run Keyword If '${service_name}' == 'FTTB_SUBSCRIBER_TRAFFIC'
+ ... Verify Subscriber Access Flows Added for DT FTTB ${olt_of_id}
+ ... ${onu_port} ${nni_port} ${stag} ${ctag}
+ ... Verify DPU MGMT Flows Added for DT FTTB ${olt_of_id}
+ ... ${onu_port} ${nni_port} ${stag} ${ctag}
+ END
+
+
+Add Subscriber Details
+ [Documentation] Adds a particular subscriber
+ [Arguments] ${of_id} ${onu_port}
+ ${resp}= Post Request VGC services/${of_id}/${onu_port}
+ Log ${resp}
+ Should Be Equal As Strings ${resp.status_code} 200
+
+Remove Subscriber Access
+ [Documentation] Removes a particular subscriber
+ [Arguments] ${of_id} ${onu_port}
+ ${resp}= Delete Request VGC services/${of_id}/${onu_port}
+ Log ${resp}
+ Should Be Equal As Strings ${resp.status_code} 200
+
+Send File To VGC
+ [Documentation] Send the content of the file to VGC to selected section of configuration
+ ... using Post Request
+ [Arguments] ${CONFIG_FILE} #${section}=${EMPTY}
+ ${Headers}= Create Dictionary Content-Type application/json
+ ${File_Data}= OperatingSystem.Get File ${CONFIG_FILE}
+ Log ${Headers}
+ Log ${File_Data}
+ ${resp}= Post Request VGC
+ ... network/configurations headers=${Headers} data=${File_Data}
+ Should Be Equal As Strings ${resp.status_code} 200
+
+Verify No Pending Flows For ONU
+ [Arguments] ${ip} ${port} ${onu_port}
+ [Documentation] Verifies that there are no flows "PENDING" state for the ONU in VGC
+ ${resp}= Get Request VGC flows/pending
+ ${jsondata}= To Json ${resp.content}
+ ${length}= Get Length ${jsondata['flows']}
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${flow}= Get From List ${jsondata['flows']} ${INDEX}
+ ${inport}= Get In Port From Flow ${flow}
+ ${matched}= Run Keyword If '${inport}' == '${onu_port}' Set Variable ${TRUE}
+ Exit For Loop If ${matched}
+ END
+ Should Be Equal ${matched} False No match for pending flow found
+
+Get Pending Flow Count
+ [Documentation] Get the count for flows "PENDING" state for the ONU in VGC
+ ${resp}= Get Request VGC flows/pending
+ ${jsondata}= To Json ${resp.content}
+ ${length}= Get Length ${jsondata['flows']}
+ [Return] ${length}
+
+Get In Port From Flow
+ [Documentation] Fetches the port Record for IN_PORT
+ [Arguments] ${flow}
+ ${selector}= Get From Dictionary ${flow} selector
+ ${len}= Get Length ${selector['criteria']}
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${len}
+ ${criteria}= Get From List ${selector['criteria']} ${INDEX}
+ ${type}= Get From Dictionary ${criteria} type
+ ${port}= Run Keyword If '${type}' == 'IN_PORT' Get From Dictionary ${criteria} port
+ ${matched}= Set Variable If '${type}' == 'IN_PORT' True False
+ Exit For Loop If ${matched}
+ END
+ [Return] ${port}
+
+
+
+Get Vlan VId From Flow
+ [Documentation] Fetches the vlan Id
+ [Arguments] ${flow}
+ ${selector}= Get From Dictionary ${flow} selector
+ ${len}= Get Length ${selector['criteria']}
+ ${matched}= Set Variable False
+ ${vlanid}= Set Variable
+ FOR ${INDEX} IN RANGE 0 ${len}
+ ${criteria}= Get From List ${selector['criteria']} ${INDEX}
+ ${type}= Get From Dictionary ${criteria} type
+ ${vlanid}= Run Keyword If '${type}' == 'VLAN_VID' Get From Dictionary ${criteria} vlanId
+ ${matched}= Set Variable If '${type}' == 'VLAN_VID' True False
+ Exit For Loop If ${matched}
+ END
+ [Return] ${vlanid}
+
+
+Get Out Port From Flow
+ [Documentation] Fetches the port for OUTPUT
+ [Arguments] ${flow}
+ ${treatment}= Get From Dictionary ${flow} treatment
+ ${len}= Get Length ${treatment['instructions']}
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${len}
+ ${instructions}= Get From List ${treatment['instructions']} ${INDEX}
+ ${type}= Get From Dictionary ${instructions} type
+ ${outport}= Run Keyword If '${type}' == 'OUTPUT' Get From Dictionary ${instructions} port
+ ${matched}= Set Variable If '${type}' == 'OUTPUT' True False
+ Exit For Loop If ${matched}
+ END
+ [Return] ${outport}
+
+
+Get Subtype From Flow
+ [Documentation] Fetches the L2MODIFICATION subtype
+ [Arguments] ${flow}
+ ${treatment}= Get From Dictionary ${flow} treatment
+ ${len}= Get Length ${treatment['instructions']}
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${len}
+ ${instructions}= Get From List ${treatment['instructions']} ${INDEX}
+ ${type}= Get From Dictionary ${instructions} type
+ ${subtype}= Run Keyword If '${type}' == 'L2MODIFICATION' Get From Dictionary ${instructions} subtype
+ ${matched}= Set Variable If '${type}' == 'L2MODIFICATION' True False
+ Exit For Loop If ${matched}
+ END
+ [Return] ${subtype}
+
+Get Vlan Id From Flow For Fttb
+ [Documentation] Fetch the VLAN id for L2MODIFICATION
+ [Arguments] ${flow}
+ ${treatment}= Get From Dictionary ${flow} treatment
+ ${len}= Get Length ${treatment['instructions']}
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${len}
+ ${instructions}= Get From List ${treatment['instructions']} ${INDEX}
+ ${type}= Get From Dictionary ${instructions} type
+ ${subtype}= Run Keyword If '${type}' == 'L2MODIFICATION' Get From Dictionary ${instructions} subtype
+ ${vlanId}= Run Keyword If '${type}' == 'L2MODIFICATION' and '${subtype}' == 'VLAN_SET'
+ ... Get From Dictionary ${instructions} vlanId
+ ${matched}= Set Variable If '${type}' == 'L2MODIFICATION' and '${subtype}' == 'VLAN_SET' True False
+ Exit For Loop If ${matched}
+ END
+ [Return] ${vlanId}
+
+Get Table Id From Flow
+ [Documentation] Fetch the TableId
+ [Arguments] ${flow}
+ ${tableid}= Get From Dictionary ${flow} tableId
+ [Return] ${tableid}
+
+Get Vlan Id From Flow
+ [Documentation] Fetch the VLAN id for L2MODIFICATION
+ [Arguments] ${flow}
+ ${treatment}= Get From Dictionary ${flow} treatment
+ ${len}= Get Length ${treatment['instructions']}
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${len}
+ ${instructions}= Get From List ${treatment['instructions']} ${INDEX}
+ ${type}= Get From Dictionary ${instructions} type
+ ${subtype}= Run Keyword If '${type}' == 'L2MODIFICATION' Get From Dictionary ${instructions} subtype
+ ${vlanId}= Run Keyword If '${type}' == 'L2MODIFICATION' and '${subtype}' == 'VLAN_ID'
+ ... Get From Dictionary ${instructions} vlanId
+ ${matched}= Set Variable If '${type}' == 'L2MODIFICATION' and '${subtype}' == 'VLAN_ID' True False
+ Exit For Loop If ${matched}
+ END
+ [Return] ${vlanId}
+
+Get Subscribers for a Particular Service
+ [Documentation] Filters the subscriber for a particular service
+ [Arguments] ${olt_of_id} ${subscriber_json} ${filter}
+ ${subscribers_info}= Get From Dictionary ${subscriber_json} subscribers
+ ${num_subscribers}= Get Length ${subscribers_info}
+ ${subscriber_list} Create List
+ Return From Keyword If '${filter}' == '${EMPTY}' ${subscribers_info}
+ FOR ${INDEX} IN RANGE 0 ${num_subscribers}
+ ${subscriber}= Get From List ${subscribers_info} ${INDEX}
+ ${res1}= Evaluate '${olt_of_id}' == '${subscriber["location"]}'
+ ${tag_subscriber_info}= Get From Dictionary ${subscriber} tagInfo
+ ${ServiceName}= Get From Dictionary ${tag_subscriber_info} serviceName
+ ${res2}= Evaluate '${filter}' == '${ServiceName}'
+ Run Keyword If ${res1} and ${res2}
+ ... Append To List ${subscriber_list} ${subscriber}
+ ${matched}= Set Variable If ${res1} and ${res2} True False
+ Exit For Loop If ${matched}
+ END
+ Should Be True ${matched} No matching subscriber for OLT
+ [Return] ${subscriber_list}
+
+Get Programmed Subscribers
+ [Arguments] ${olt_of_id} ${onu_port} ${filter}=${EMPTY}
+ [Documentation] Retrieves the subscriber details at a given location
+ ${programmed_sub}= Get Request VGC programmed-subscribers
+ ${programmed_sub_json_resp}= To Json ${programmed_sub.content}
+ ${filtered_subscriber_list}= Get Subscribers for a Particular Service ${olt_of_id} ${programmed_sub_json_resp}
+ ... ${filter}
+ [Return] ${filtered_subscriber_list}
+
+Verify Programmed Subscribers DT FTTB
+ [Arguments] ${olt_of_id} ${onu_port} ${service}
+ [Documentation] Verifies the subscriber is present at a given location
+ ${num_services}= Get Length ${service}
+ FOR ${I} IN RANGE 0 ${num_services}
+ ${service_name}= Set Variable ${service[${I}]['name']}
+ ${programmed_subscriber}= Get Programmed Subscribers ${olt_of_id} ${onu_port}
+ ... ${service_name}
+ Log ${programmed_subscriber}
+ Should Not Be Empty ${programmed_subscriber}
+ END
+
+Verify Meters in VGC Ietf
+ [Arguments] ${ip} ${port} ${olt_of_id} ${onu_port} ${filter}=${EMPTY}
+ [Documentation] Verifies the meters with BW Ietf format (currently, DT workflow uses this format)
+ ${programmed_sub_json_resp}= Get Programmed Subscribers ${olt_of_id} ${onu_port}
+ ... ${filter}
+ Log ${programmed_sub_json_resp}
+ ${us_bw_profile} ${ds_bw_profile} Get Upstream and Downstream Bandwidth Profile Name
+ ... ${programmed_sub_json_resp}
+ # Get upstream bandwidth profile details
+ ${us_cir} ${us_cbs} ${us_pir} ${us_pbs} ${us_gir} Get Bandwidth Profile Details Ietf Rest
+ ... ${us_bw_profile}
+ # Verify meter for upstream bandwidth profile
+ ${meter}= Get Request VGC meters
+ ${meter_json_resp}= To Json ${meter.content}
+ Log ${meter_json_resp}
+ ${rate} ${burst_size} Get Meter Param In Details
+ ... ${meter_json_resp} 1
+ Log ${rate}
+ Log ${burst_size}
+ # for cir & cbs
+ ${matched}= Set Variable If '${rate}' == '${us_cir}' and '${burst_size}' == '${us_cbs}' True False
+ Should Be True ${matched}
+ ${res1}= Evaluate '${rate}' == '${us_cir}' and '${burst_size}' == '${us_cbs}'
+ #for pir & pbs
+ ${rate} ${burst_size} Get Meter Param In Details
+ ... ${meter_json_resp} 2
+ ${matched}= Set Variable If '${rate}' == '${us_pir}' and '${burst_size}' == '${us_pbs}' True False
+ Should Be True ${matched}
+ ${res2}= Evaluate '${rate}' == '${us_pir}' and '${burst_size}' == '${us_pbs}'
+ #for gir
+ Run Keyword if ${us_gir} != 0 Validate Guarenteed Information Rate ${us_gir} ${meter_json_resp}
+ # Get downstream bandwidth profile details
+ ${ds_cir} ${ds_cbs} ${ds_pir} ${ds_pbs} ${ds_gir} Get Bandwidth Profile Details Ietf Rest
+ ... ${ds_bw_profile}
+ # Verify meter for downstream bandwidth profile
+ ${meter}= Get Request VGC meters
+ ${meter_json_resp}= To Json ${meter.content}
+ Log ${meter_json_resp}
+ ${rate} ${burst_size} Get Meter Param In Details
+ ... ${meter_json_resp} 1
+ Log ${rate}
+ Log ${burst_size}
+ # for cir & cbs
+ ${matched}= Set Variable If '${rate}' == '${ds_cir}' and '${burst_size}' == '${ds_cbs}' True False
+ Should Be True ${matched}
+ #for pir & pbs
+ ${rate} ${burst_size} Get Meter Param In Details
+ ... ${meter_json_resp} 2
+ ${matched}= Set Variable If '${rate}' == '${ds_pir}' and '${burst_size}' == '${ds_pbs}' True False
+ Should Be True ${matched}
+ #for gir
+ Run Keyword If ${ds_gir} != 0
+ ... Validate Guarenteed Information Rate ${ds_gir} ${meter_json_resp}
+
+Validate Guarenteed Information Rate
+ [Documentation] Validate gir for both upstream and downstream meters
+ [Arguments] ${gir} ${meter_json_resp}
+ ${rate} ${burst_size} Get Meter Param In Details
+ ... ${meter_json_resp} 3
+ ${matched}= Set Variable If '${rate}' == '${gir}' and '${burst_size}' == '0' True False
+ Should Be True ${matched}
+ [Return] ${matched}
+
+Get Bandwidth Profile Details Ietf Rest
+ [Arguments] ${bw_profile_id}
+ [Documentation] Retrieves the details of the given Ietf standard based bandwidth profile using REST API
+ ${bw_profile_id}= Remove String ${bw_profile_id} ' "
+ ${resp}= Get Request VGC profiles/${bw_profile_id}
+ Log ${resp}
+ ${jsondata}= To Json ${resp.content}
+ Should Not Be Empty ${jsondata}
+ ${matched}= Set Variable False
+ ${bw_id}= Get From Dictionary ${jsondata} id
+ ${matched}= Set Variable If '${bw_id}' == '${bw_profile_id}' True False
+ ${pir}= Get From Dictionary ${jsondata} pir
+ ${pbs}= Get From Dictionary ${jsondata} pbs
+ ${cir}= Get From Dictionary ${jsondata} cir
+ ${cbs}= Get From Dictionary ${jsondata} cbs
+ ${gir}= Get From Dictionary ${jsondata} gir
+ Should Be True ${matched} No bandwidth profile found for id: ${bw_profile_id}
+ [Return] ${cir} ${cbs} ${pir} ${pbs} ${gir}
+
+
+Get Upstream and Downstream Bandwidth Profile Name
+ [Arguments] ${programmed_sub}
+ [Documentation] Retrieves the upstream and downstream bandwidth profile name
+ ... from the programmed subscriber
+ ${length}= Get Length ${programmed_sub}
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${value}= Get From List ${programmed_sub} ${INDEX}
+ ${tagInfo_id}= Get From Dictionary ${value} tagInfo
+ Log ${tagInfo_id}
+ ${us_bw_profile}= Get From Dictionary ${tagInfo_id} upstreamBandwidthProfile
+ Log ${us_bw_profile}
+ ${ds_bw_profile}= Get From Dictionary ${tagInfo_id} downstreamBandwidthProfile
+ Log ${ds_bw_profile}
+ END
+ [Return] ${us_bw_profile} ${ds_bw_profile}
+
+Verify Subscriber Access Flows Added Count DT
+ [Arguments] ${ip} ${port} ${olt_of_id} ${expected_flows}
+ [Documentation] Matches for total number of subscriber access flows added for all onus
+ ${resp}= Get Request VGC flows/${olt_of_id}
+ ${jsondata}= To Json ${resp.content}
+ ${access_flows_added_count}= Get Length ${jsondata['flows']}
+ Should Be Equal As Integers ${access_flows_added_count} ${expected_flows}
+
+Get Meter Param In Details
+ [Arguments] ${meter_json} ${length}
+ [Documentation] Retrieves the meter rate state burst-size
+ ${metername}= Get From Dictionary ${meter_json} meters
+ Log ${metername}
+ ${value}= Get From List ${metername} 0
+ ${bands_info}= Get From Dictionary ${value} bands
+ Log ${bands_info}
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${value}= Get From List ${bands_info} ${INDEX}
+ ${burst_size}= Get From Dictionary ${value} burstSize
+ ${rate}= Get From Dictionary ${value} rate
+ END
+ [Return] ${rate} ${burst_size}
+
+Delete Subscribers And BW Profile In VGC
+ [Documentation] Delete Subscribers and bw profile In VGC
+ Create VGC Session
+ ${resp}= Get Request VGC programmed-subscribers
+ Log ${resp}
+ ${jsondata}= To Json ${resp.content}
+ ${length}= Get Length ${jsondata['subscribers']}
+ @{serial_numbers}= Create List
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${value}= Get From List ${jsondata['subscribers']} ${INDEX}
+ ${taginfo}= Get From Dictionary ${value} tagInfo
+ ${service_id}= Get From Dictionary ${taginfo} serviceName
+ ${upstream_bw_id}= Get From Dictionary ${taginfo} upstreamBandwidthProfile
+ ${downstream_bw_id}= Get From Dictionary ${taginfo} downstreamBandwidthProfile
+ Delete Request VGC subscribers/${service_id}
+ Delete Request VGC profiles/${upstream_bw_id}
+ Delete Request VGC profiles/${downstream_bw_id}
+ END
+
+Deactivate Subscribers In VGC
+ [Documentation] Deactivate Subscribers In VGC
+ Create VGC Session
+ ${resp}= Get Request VGC devices/ports
+ Log ${resp}
+ ${jsondata}= To Json ${resp.content}
+ ${length}= Get Length ${jsondata['ports']}
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${value}= Get From List ${jsondata['ports']} ${INDEX}
+ ${annotations}= Get From Dictionary ${value} annotations
+ ${portname}= Get From Dictionary ${annotations} portName
+ Delete Request VGC services/${portname}
+ END
+
+Verify Device Flows Removed
+ [Arguments] ${ip} ${port} ${olt_of_id}
+ [Documentation] Verifies all flows are removed from the device
+ ${resp}= Get Request VGC flows/${olt_of_id}
+ ${jsondata}= To Json ${resp.content}
+ ${flow_count}= Get Length ${jsondata['flows']}
+ Should Be Equal As Integers ${flow_count} 0 Flows not removed
+
+Device Is Available In VGC
+ [Arguments] ${olt_of_id} ${available}=true
+ [Documentation] Validates the device exists and it has the expected availability in VGC
+ ${resp}= Get Request VGC devices
+ ${jsondata}= To Json ${resp.content}
+ Should Not Be Empty ${jsondata['devices']}
+ ${length}= Get Length ${jsondata['devices']}
+ ${matched}= Set Variable False
+ FOR ${INDEX} IN RANGE 0 ${length}
+ ${value}= Get From List ${jsondata['devices']} ${INDEX}
+ ${of_id}= Get From Dictionary ${value} id
+ ${availability}= Get From Dictionary ${value} available
+ Log ${olt_of_id}
+ Log ${of_id}
+ ${matched}= Set Variable If '${of_id}' == '${olt_of_id}' and '${available}' == '${availability}' True False
+ Exit For Loop If ${matched}
+ END
+ Should Be True ${matched} No match for '${olt_of_id}' found
+ Should Be Equal ${available} ${availability}
+
diff --git a/libraries/voltctl.robot b/libraries/voltctl.robot
index 650c289..c212ada 100755
--- a/libraries/voltctl.robot
+++ b/libraries/voltctl.robot
@@ -22,7 +22,7 @@
Library Collections
Library RequestsLibrary
Library OperatingSystem
-Resource ./utils.robot
+#Resource ./utils.robot
Resource ./flows.robot
*** Variables ***
diff --git a/tests/data/bbsim-kind-2OLTx2ONUx2PON_VGC.yaml b/tests/data/bbsim-kind-2OLTx2ONUx2PON_VGC.yaml
new file mode 100755
index 0000000..cf9841c
--- /dev/null
+++ b/tests/data/bbsim-kind-2OLTx2ONUx2PON_VGC.yaml
@@ -0,0 +1,102 @@
+---
+
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Automated deployment configuration for systems running BBSim
+
+# Change default values in tests
+has_dataplane: false
+external_libs: false
+teardown_device: true
+VGC_REST_PORT: 8181
+VGC_SSH_PORT: 8101
+OLT_PORT: 50060
+
+
+# Actual Unused sadis.file but ready to future implementation
+sadis.file: ../data/dt-sadis-multiolt-config-vgc.json
+
+
+nodes:
+ -
+ ip: '127.0.0.1'
+
+olts:
+ -
+ ip: bbsim0.voltha.svc
+ serial: BBSIM_OLT_10
+ -
+ ip: bbsim1.voltha.svc
+ serial: BBSIM_OLT_11
+
+hosts:
+ src:
+ -
+ onu: 'BBSM000a0001'
+ c_tag: '4096'
+ s_tag: '900'
+ olt: 'BBSIM_OLT_10'
+ uni_id: '1'
+ -
+ onu: 'BBSM000a0002'
+ c_tag: '4096'
+ s_tag: '904'
+ olt: 'BBSIM_OLT_10'
+ uni_id: '1'
+ -
+ onu: 'BBSM000a0101'
+ olt: 'BBSIM_OLT_10'
+ c_tag: '4096'
+ s_tag: '908'
+ uni_id: '1'
+ -
+ onu: 'BBSM000a0102'
+ olt: 'BBSIM_OLT_10'
+ c_tag: '4096'
+ s_tag: '912'
+ uni_id: '1'
+ -
+ onu: 'BBSM000b0001'
+ c_tag: '4096'
+ s_tag: '900'
+ olt: 'BBSIM_OLT_11'
+ uni_id: '1'
+ -
+ onu: 'BBSM000b0002'
+ c_tag: '4096'
+ s_tag: '904'
+ olt: 'BBSIM_OLT_11'
+ uni_id: '1'
+ -
+ onu: 'BBSM000b0101'
+ olt: 'BBSIM_OLT_11'
+ c_tag: '4096'
+ s_tag: '908'
+ uni_id: '1'
+ -
+ onu: 'BBSM000b0102'
+ olt: 'BBSIM_OLT_11'
+ c_tag: '4096'
+ s_tag: '912'
+ uni_id: '1'
+ dst:
+ - ip: null
+ - ip: null
+ - ip: null
+ - ip: null
+ - ip: null
+ - ip: null
+ - ip: null
+ - ip: null
diff --git a/tests/data/bbsim-kind-dt-vgc.yaml b/tests/data/bbsim-kind-dt-vgc.yaml
new file mode 100755
index 0000000..73824ca
--- /dev/null
+++ b/tests/data/bbsim-kind-dt-vgc.yaml
@@ -0,0 +1,51 @@
+---
+
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Automated deployment configuration for systems running BBSim
+
+# Change default values in tests
+workflow: DT
+has_dataplane: false
+teardown_device: true
+VGC_REST_PORT: 8181
+VGC_SSH_PORT: 8101
+OLT_PORT: 50060
+
+
+# Actual Unused sadis.file but ready to future implementation
+sadis.file: ../data/dt-sadis-config.json
+
+
+nodes:
+ -
+ ip: '127.0.0.1'
+
+olts:
+ -
+ ip: bbsim0
+ serial: BBSIM_OLT_10
+
+hosts:
+ src:
+ -
+ onu: 'BBSM000a0001'
+ olt: 'BBSIM_OLT_10'
+ c_tag: '4096'
+ s_tag: '900'
+ uni_id: '1'
+
+ dst:
+ - ip: null
diff --git a/tests/data/dt-sadis-config.json b/tests/data/dt-sadis-config.json
new file mode 100644
index 0000000..6284e18
--- /dev/null
+++ b/tests/data/dt-sadis-config.json
@@ -0,0 +1,49 @@
+{
+ "apps": {
+ "org.opencord.sadis": {
+ "bandwidthprofile": {
+ "entries": [
+ {
+ "id": "High-Speed-Internet",
+ "gir": 50000,
+ "cbs": 10000,
+ "cir": 50000,
+ "pbs": 1000,
+ "pir": 300000
+ }
+ ]
+ },
+ "sadis": {
+ "entries": [
+ {
+ "id": "BBSIM_OLT_10",
+ "nasId": "BBSIM_OLT_10",
+ "hardwareIdentifier": "28:b9:d9:e2:93:d6",
+ "uplinkPort": "16777216"
+ },
+ {
+ "id": "BBSM000a0001",
+ "nasPortId": "BBSM000a0001-1",
+ "circuitId": "BBSM000a0001-1",
+ "remoteId": "BBSM000a0001",
+ "uniTagList": [
+ {
+ "uniTagMatch": 4096,
+ "ponCTag": 4096,
+ "ponSTag": 900,
+ "usPonCTagPriority": 0,
+ "usPonSTagPriority": 0,
+ "dsPonCTagPriority": 0,
+ "dsPonSTagPriority": 0,
+ "technologyProfileId": 64,
+ "downstreamBandwidthProfile": "High-Speed-Internet",
+ "upstreamBandwidthProfile": "High-Speed-Internet",
+ "serviceName": "HSIA"
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/tests/data/dt-sadis-multiolt-config-vgc.json b/tests/data/dt-sadis-multiolt-config-vgc.json
new file mode 100644
index 0000000..e2460f1
--- /dev/null
+++ b/tests/data/dt-sadis-multiolt-config-vgc.json
@@ -0,0 +1,203 @@
+{
+ "apps": {
+ "org.opencord.sadis": {
+ "bandwidthprofile": {
+ "entries": [
+ {
+ "id": "High-Speed-Internet",
+ "gir": 50000,
+ "cbs": 10000,
+ "cir": 50000,
+ "pbs": 1000,
+ "pir": 300000
+ }
+ ]
+ },
+ "sadis": {
+ "entries": [
+ {
+ "id": "BBSIM_OLT_10",
+ "nasId": "BBSIM_OLT_10",
+ "hardwareIdentifier": "28:b9:d9:e2:93:d6",
+ "uplinkPort": "16777216"
+ },
+ {
+ "id": "BBSM000a0001",
+ "nasPortId": "BBSM000a0001-1",
+ "circuitId": "BBSM000a0001-1",
+ "remoteId": "BBSM000a0001",
+ "uniTagList": [
+ {
+ "uniTagMatch": 4096,
+ "ponCTag": 4096,
+ "ponSTag": 900,
+ "usPonCTagPriority": 0,
+ "usPonSTagPriority": 0,
+ "dsPonCTagPriority": 0,
+ "dsPonSTagPriority": 0,
+ "technologyProfileId": 64,
+ "downstreamBandwidthProfile": "High-Speed-Internet",
+ "upstreamBandwidthProfile": "High-Speed-Internet",
+ "serviceName": "HSIA"
+ }
+ ]
+ },
+ {
+ "id": "BBSM000a0002",
+ "nasPortId": "BBSM000a0002-1",
+ "circuitId": "BBSM000a0002-1",
+ "remoteId": "BBSM000a0002",
+ "uniTagList": [
+ {
+ "uniTagMatch": 4096,
+ "ponCTag": 4096,
+ "ponSTag": 904,
+ "usPonCTagPriority": 0,
+ "usPonSTagPriority": 0,
+ "dsPonCTagPriority": 0,
+ "dsPonSTagPriority": 0,
+ "technologyProfileId": 64,
+ "downstreamBandwidthProfile": "High-Speed-Internet",
+ "upstreamBandwidthProfile": "High-Speed-Internet",
+ "serviceName": "HSIA"
+ }
+ ]
+ },
+ {
+ "id": "BBSM000a0101",
+ "nasPortId": "BBSM000a0101-1",
+ "circuitId": "BBSM000a0101-1",
+ "remoteId": "BBSM000a0101",
+ "uniTagList": [
+ {
+ "uniTagMatch": 4096,
+ "ponCTag": 4096,
+ "ponSTag": 908,
+ "usPonCTagPriority": 0,
+ "usPonSTagPriority": 0,
+ "dsPonCTagPriority": 0,
+ "dsPonSTagPriority": 0,
+ "technologyProfileId": 64,
+ "downstreamBandwidthProfile": "High-Speed-Internet",
+ "upstreamBandwidthProfile": "High-Speed-Internet",
+ "serviceName": "HSIA"
+ }
+ ]
+ },
+ {
+ "id": "BBSM000a0102",
+ "nasPortId": "BBSM000a0102-1",
+ "circuitId": "BBSM000a0102-1",
+ "remoteId": "BBSM000a0102",
+ "uniTagList": [
+ {
+ "uniTagMatch": 4096,
+ "ponCTag": 4096,
+ "ponSTag": 912,
+ "usPonCTagPriority": 0,
+ "usPonSTagPriority": 0,
+ "dsPonCTagPriority": 0,
+ "dsPonSTagPriority": 0,
+ "technologyProfileId": 64,
+ "downstreamBandwidthProfile": "High-Speed-Internet",
+ "upstreamBandwidthProfile": "High-Speed-Internet",
+ "serviceName": "HSIA"
+ }
+ ]
+ },
+ {
+ "id": "BBSIM_OLT_11",
+ "nasId": "BBSIM_OLT_11",
+ "hardwareIdentifier": "28:b9:d9:e2:93:d6",
+ "uplinkPort": "16777216"
+ },
+ {
+ "id": "BBSM000b0001",
+ "nasPortId": "BBSM000b0001-1",
+ "circuitId": "BBSM000b0001-1",
+ "remoteId": "BBSM000b0001",
+ "uniTagList": [
+ {
+ "uniTagMatch": 4096,
+ "ponCTag": 4096,
+ "ponSTag": 900,
+ "usPonCTagPriority": 0,
+ "usPonSTagPriority": 0,
+ "dsPonCTagPriority": 0,
+ "dsPonSTagPriority": 0,
+ "technologyProfileId": 64,
+ "downstreamBandwidthProfile": "High-Speed-Internet",
+ "upstreamBandwidthProfile": "High-Speed-Internet",
+ "serviceName": "HSIA"
+ }
+ ]
+ },
+ {
+ "id": "BBSM000b0002",
+ "nasPortId": "BBSM000b0002-1",
+ "circuitId": "BBSM000b0002-1",
+ "remoteId": "BBSM000b0002",
+ "uniTagList": [
+ {
+ "uniTagMatch": 4096,
+ "ponCTag": 4096,
+ "ponSTag": 904,
+ "usPonCTagPriority": 0,
+ "usPonSTagPriority": 0,
+ "dsPonCTagPriority": 0,
+ "dsPonSTagPriority": 0,
+ "technologyProfileId": 64,
+ "downstreamBandwidthProfile": "High-Speed-Internet",
+ "upstreamBandwidthProfile": "High-Speed-Internet",
+ "serviceName": "HSIA"
+ }
+ ]
+ },
+ {
+ "id": "BBSM000b0101",
+ "nasPortId": "BBSM000b0101-1",
+ "circuitId": "BBSM000b0101-1",
+ "remoteId": "BBSM000b0101",
+ "uniTagList": [
+ {
+ "uniTagMatch": 4096,
+ "ponCTag": 4096,
+ "ponSTag": 908,
+ "usPonCTagPriority": 0,
+ "usPonSTagPriority": 0,
+ "dsPonCTagPriority": 0,
+ "dsPonSTagPriority": 0,
+ "technologyProfileId": 64,
+ "downstreamBandwidthProfile": "High-Speed-Internet",
+ "upstreamBandwidthProfile": "High-Speed-Internet",
+ "serviceName": "HSIA"
+ }
+ ]
+ },
+ {
+ "id": "BBSM000b0102",
+ "nasPortId": "BBSM000b0102-1",
+ "circuitId": "BBSM000b0102-1",
+ "remoteId": "BBSM000b0102",
+ "uniTagList": [
+ {
+ "uniTagMatch": 4096,
+ "ponCTag": 4096,
+ "ponSTag": 912,
+ "usPonCTagPriority": 0,
+ "usPonSTagPriority": 0,
+ "dsPonCTagPriority": 0,
+ "dsPonSTagPriority": 0,
+ "technologyProfileId": 64,
+ "downstreamBandwidthProfile": "High-Speed-Internet",
+ "upstreamBandwidthProfile": "High-Speed-Internet",
+ "serviceName": "HSIA"
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
+
diff --git a/tests/dt-workflow/Voltha_DT_FTTB_Tests_VGC.robot b/tests/dt-workflow/Voltha_DT_FTTB_Tests_VGC.robot
new file mode 100644
index 0000000..63c89fe
--- /dev/null
+++ b/tests/dt-workflow/Voltha_DT_FTTB_Tests_VGC.robot
@@ -0,0 +1,86 @@
+# Copyright 2022 - present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# FIXME Can we use the same test against BBSim and Hardware?
+
+*** Settings ***
+Documentation Test various DT FTTB end-to-end scenarios
+Suite Setup Setup Suite
+Test Setup Setup
+Test Teardown Teardown
+Suite Teardown Teardown Suite
+Library Collections
+Library String
+Library OperatingSystem
+Library XML
+Library RequestsLibrary
+Library ../../libraries/DependencyLibrary.py
+Resource ../../libraries/vgc.robot
+Resource ../../libraries/voltctl.robot
+Resource ../../libraries/voltha.robot
+Resource ../../libraries/utils_vgc.robot
+Resource ../../libraries/k8s.robot
+Resource ../../variables/variables.robot
+Resource ../../libraries/power_switch.robot
+
+
+*** Variables ***
+${POD_NAME} flex-ocp-cord
+${KUBERNETES_CONF} ${KUBERNETES_CONFIGS_DIR}/${POD_NAME}.conf
+${KUBERNETES_CONFIGS_DIR} ~/pod-configs/kubernetes-configs
+#${KUBERNETES_CONFIGS_DIR} ${KUBERNETES_CONFIGS_DIR}/${POD_NAME}.conf
+${KUBERNETES_YAML} ${KUBERNETES_CONFIGS_DIR}/${POD_NAME}.yml
+${HELM_CHARTS_DIR} ~/helm-charts
+${VOLTHA_POD_NUM} 8
+${NAMESPACE} voltha
+${INFRA_NAMESPACE} default
+${timeout} 60s
+${of_id} 0
+${logical_id} 0
+${uprate} 0
+${dnrate} 0
+${has_dataplane} True
+${teardown_device} True
+${scripts} ../../scripts
+
+# Per-test logging on failure is turned off by default; set this variable to enable
+${container_log_dir} ${None}
+
+# logging flag to enable Collect Logs, can be passed via the command line too
+# example: -v logging:False
+${logging} True
+
+*** Test Cases ***
+Sanity E2E Test for OLT/ONU on POD for DT FTTB
+ [Documentation] Validates E2E Ping Connectivity and object states for the given scenario:
+ ... Validate successful DHCP/E2E ping (no EAPOL and DHCP flows) for the tech profile that is used
+ ... Traffic sent with same vlan from different RGs,
+ ... should reach the NNI port on the OLT with the expected double tagged vlan ids
+ ... Inner vlans from the RG should not change
+ [Tags] sanityDtFttb
+ [Setup] Start Logging SanityTestDtFttb
+ [Teardown] Run Keywords Run Keyword If ${logging} Collect Logs
+ ... AND Stop Logging SanityTestDtFttb
+ Setup
+ Run Keyword If ${has_dataplane} Clean Up Linux
+ Perform Sanity Test DT FTTB
+
+*** Keywords ***
+Setup Suite
+ [Documentation] Set up the test suite
+ Common Test Suite Setup
+ #Restore all ONUs
+ #Run Keyword If ${has_dataplane} RestoreONUs ${num_all_onus}
+ #power_switch.robot needs it to support different vendor's power switch
+ ${switch_type}= Get Variable Value ${web_power_switch.type}
+ Run Keyword If "${switch_type}"!="" Set Global Variable ${powerswitch_type} ${switch_type}
diff --git a/tests/dt-workflow/Voltha_DT_MultiOLT_Tests_VGC.robot b/tests/dt-workflow/Voltha_DT_MultiOLT_Tests_VGC.robot
new file mode 100755
index 0000000..654ebb1
--- /dev/null
+++ b/tests/dt-workflow/Voltha_DT_MultiOLT_Tests_VGC.robot
@@ -0,0 +1,189 @@
+# Copyright 2020 - present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+*** Settings ***
+Documentation Test various end-to-end scenarios involing Multiple OLTs
+Suite Setup Setup Suite
+Test Setup Setup
+Test Teardown Teardown
+Suite Teardown Teardown Suite
+Library Collections
+Library String
+Library OperatingSystem
+Library XML
+Library RequestsLibrary
+Library ../../libraries/DependencyLibrary.py
+Resource ../../libraries/vgc.robot
+Resource ../../libraries/voltctl.robot
+Resource ../../libraries/voltha.robot
+Resource ../../libraries/utils_vgc.robot
+Resource ../../libraries/k8s.robot
+Resource ../../variables/variables.robot
+Resource ../../libraries/power_switch.robot
+
+*** Variables ***
+${POD_NAME} flex-ocp-cord
+${KUBERNETES_CONF} ${KUBERNETES_CONFIGS_DIR}/${POD_NAME}.conf
+${KUBERNETES_CONFIGS_DIR} ~/pod-configs/kubernetes-configs
+#${KUBERNETES_CONFIGS_DIR} ${KUBERNETES_CONFIGS_DIR}/${POD_NAME}.conf
+${KUBERNETES_YAML} ${KUBERNETES_CONFIGS_DIR}/${POD_NAME}.yml
+${HELM_CHARTS_DIR} ~/helm-charts
+${VOLTHA_POD_NUM} 8
+${NAMESPACE} voltha
+${INFRA_NAMESPACE} default
+# For below variable value, using deployment name as using grep for
+# parsing radius pod name, we can also use full radius pod name
+${RESTART_POD_NAME} radius
+${timeout} 60s
+${of_id} 0
+${logical_id} 0
+${has_dataplane} True
+${teardown_device} False
+${scripts} ../../scripts
+
+# Per-test logging on failure is turned off by default; set this variable to enable
+${container_log_dir} ${None}
+
+# logging flag to enable Collect Logs, can be passed via the command line too
+# example: -v logging:False
+${logging} True
+
+*** Test Cases ***
+Verify OLT after Rebooting Physically for DT - Multiple OLT
+ [Documentation] Test the physical reboot of the OLT
+ ... Assuming that all the ONUs are DHCP/pingable (i.e. assuming sanityDt test was executed)
+ ... Test performs a physical reboot, performs "reboot" from the OLT CLI
+ ... Test runs when more than one OLT exists
+ ... Only one OLT is rebooted in the test, while verifying if the ONUs on the
+ ... other OLT are still functional
+ [Tags] functionalDt MultiOLTPhysicalRebootDt
+ [Setup] Start Logging MultiOlt_Physical_Dt
+ [Teardown] Run Keywords Collect Logs
+ ... AND Stop Logging MultiOlt_Physical_Dt
+ # Execute the test when the number of OLTs are greater than one
+ Pass Execution If ${olt_count} == 1 Skipping test: just one OLT
+ Clear All Devices Then Perform Setup And Sanity
+ # Reboot the first OLT from the list of olts - rebooting from the OLT CLI
+ ${olt_user}= Get From Dictionary ${list_olts}[0] user
+ ${olt_pass}= Get From Dictionary ${list_olts}[0] pass
+ ${olt_ssh_ip}= Get From Dictionary ${list_olts}[0] sship
+ ${olt_serial_number}= Get From Dictionary ${list_olts}[0] sn
+ ${olt_device_id}= Get OLTDeviceID From OLT List ${olt_serial_number}
+ Run Keyword If ${has_dataplane} Login And Run Command On Remote System
+ ... reboot ${olt_ssh_ip} ${olt_user} ${olt_pass} prompt=#
+ # validate that the ONUs on the other OLTs are still functional
+ Verify ping is successful for ONUs not on this OLT ${num_all_onus} ${olt_device_id}
+
+ # validate that the ONUs on the rebooted OLT are not pingable
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${olt_serial_number}= Get From Dictionary ${list_olts}[0] sn
+ Continue For Loop If "${olt_serial_number}"!="${src['olt']}"
+ Run Keyword If ${has_dataplane} Run Keyword And Continue On Failure
+ ... Wait Until Keyword Succeeds ${timeout} 2s
+ ... Check Ping False ${dst['dp_iface_ip_qinq']} ${src['dp_iface_name']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ END
+ # Wait for the rebooted OLT to come back up
+ ${olt_user}= Get From Dictionary ${list_olts}[0] user
+ ${olt_pass}= Get From Dictionary ${list_olts}[0] pass
+ ${olt_ssh_ip}= Get From Dictionary ${list_olts}[0] sship
+ ${olt_serial_number}= Get From Dictionary ${list_olts}[0] sn
+ ${olt_device_id}= Get OLTDeviceID From OLT List ${olt_serial_number}
+ Run Keyword If ${has_dataplane} Wait Until Keyword Succeeds 120s 10s
+ ... Check Remote System Reachability True ${olt_ssh_ip}
+ Wait Until Keyword Succeeds 360s 5s
+ ... Validate OLT Device ENABLED ACTIVE
+ ... REACHABLE ${olt_serial_number}
+ # Waiting extra time for the ONUs to come up
+ Sleep 60s
+ Run Keyword If ${has_dataplane} Clean Up Linux
+ Perform Sanity Test DT
+
+Verify OLT Soft Reboot for DT - Multiple OLT
+ [Documentation] Test soft reboot of the OLT using voltctl command
+ ... Test runs when more than one OLT exists
+ ... Only one OLT is rebooted in the test, while verifying if the ONUs on the
+ ... other OLT are still functional
+ [Tags] MultiOLTSoftRebootDt functionalDt
+ [Setup] Start Logging MultiOLTSoftRebootDt
+ [Teardown] Run Keywords Collect Logs
+ ... AND Delete All Devices and Verify
+ ... AND Run Keyword If ${logging} Collect Logs
+ ... AND Stop Logging MultiOLTSoftRebootDt
+ Pass Execution If ${olt_count} == 1 Skipping test: just one OLT
+ Clear All Devices Then Perform Setup And Sanity
+ # Reboot the first OLT
+ ${olt_user}= Get From Dictionary ${list_olts}[0] user
+ ${olt_pass}= Get From Dictionary ${list_olts}[0] pass
+ ${olt_ssh_ip}= Get From Dictionary ${list_olts}[0] sship
+ ${olt_serial_number}= Get From Dictionary ${list_olts}[0] sn
+ ${olt_device_id}= Get OLTDeviceID From OLT List ${olt_serial_number}
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds 360s 5s
+ ... Validate OLT Device ENABLED ACTIVE
+ ... REACHABLE ${olt_serial_number}
+ # Reboot the OLT using "voltctl device reboot" command
+ Reboot Device ${olt_device_id}
+ # Wait for the OLT to actually go down
+ Wait Until Keyword Succeeds 360s 5s Validate OLT Device ENABLED UNKNOWN UNREACHABLE
+ ... ${olt_serial_number}
+ # validate that the ONUs on the other OLTs are still functional
+ Verify ping is successful for ONUs not on this OLT ${num_all_onus} ${olt_device_id}
+ #Verify that ping fails for the ONUs where the OLT has been rebooted
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${olt_serial_number}= Get From Dictionary ${list_olts}[0] sn
+ Continue For Loop If "${olt_serial_number}"!="${src['olt']}"
+ Run Keyword If ${has_dataplane} Run Keyword And Continue On Failure
+ ... Wait Until Keyword Succeeds ${timeout} 2s
+ ... Check Ping False ${dst['dp_iface_ip_qinq']} ${src['dp_iface_name']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ END
+ # Check OLT state
+ ${olt_serial_number}= Get From Dictionary ${list_olts}[0] sn
+ ${olt_ssh_ip}= Get From Dictionary ${list_olts}[0] sship
+ ${olt_device_id}= Get OLTDeviceID From OLT List ${olt_serial_number}
+ # Wait for the OLT to come back up
+ Run Keyword If ${has_dataplane} Wait Until Keyword Succeeds 120s 10s
+ ... Check Remote System Reachability True ${olt_ssh_ip}
+ # Check OLT states
+ Wait Until Keyword Succeeds 360s 5s
+ ... Validate OLT Device ENABLED ACTIVE
+ ... REACHABLE ${olt_serial_number}
+ # Waiting extra time for the ONUs to come up
+ Sleep 60s
+ #Check after reboot that ONUs are active, DHCP and pingable
+ Run Keyword If ${has_dataplane} Clean Up Linux
+ Perform Sanity Test DT
+
+*** Keywords ***
+Setup Suite
+ [Documentation] Set up the test suite
+ Common Test Suite Setup
+ #power_switch.robot needs it to support different vendor's power switch
+ ${switch_type}= Get Variable Value ${web_power_switch.type}
+ Run Keyword If "${switch_type}"!="" Set Global Variable ${powerswitch_type} ${switch_type}
+
+Clear All Devices Then Perform Setup And Sanity
+ [Documentation] Remove any devices from VOLTHA and Verify in VGC
+ ... Create New Device through Setup and Perform Sanity
+ # Remove all devices from voltha and nos
+ Delete All Devices and Verify
+ # Execute normal test Setup Keyword
+ Setup
+ # Performing Sanity Test to make sure subscribers are all DHCP and pingable
+ Run Keyword If ${has_dataplane} Clean Up Linux
+ Perform Sanity Test DT
diff --git a/tests/dt-workflow/Voltha_DT_PODTests_VGC.robot b/tests/dt-workflow/Voltha_DT_PODTests_VGC.robot
new file mode 100755
index 0000000..42d2a0d
--- /dev/null
+++ b/tests/dt-workflow/Voltha_DT_PODTests_VGC.robot
@@ -0,0 +1,503 @@
+# Copyright 2017 - present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# FIXME Can we use the same test against BBSim and Hardware?
+
+*** Settings ***
+Documentation Test various end-to-end scenarios
+Suite Setup Setup Suite
+Test Setup Setup
+Test Teardown Teardown
+Suite Teardown Teardown Suite
+Library Collections
+Library String
+Library OperatingSystem
+Library XML
+Library RequestsLibrary
+Library ../../libraries/DependencyLibrary.py
+Resource ../../libraries/vgc.robot
+Resource ../../libraries/voltctl.robot
+Resource ../../libraries/voltha.robot
+Resource ../../libraries/utils_vgc.robot
+Resource ../../libraries/k8s.robot
+Resource ../../variables/variables.robot
+Resource ../../libraries/power_switch.robot
+
+
+*** Variables ***
+${POD_NAME} bbsim-kind-dt
+${KUBERNETES_CONF} ${KUBERNETES_CONFIGS_DIR}/${POD_NAME}.conf
+${KUBERNETES_CONFIGS_DIR} ~/pod-configs/kubernetes-configs
+#${KUBERNETES_CONFIGS_DIR} ${KUBERNETES_CONFIGS_DIR}/${POD_NAME}.conf
+#${KUBERNETES_YAML} ${KUBERNETES_CONFIGS_DIR}/${POD_NAME}.yml
+${KUBERNETES_YAML} /test/repos/voltha-system-tests/tests/data/bbsim-kind-dt-vgc.yaml
+${HELM_CHARTS_DIR} ~/helm-charts
+${VOLTHA_POD_NUM} 8
+${NAMESPACE} voltha
+${INFRA_NAMESPACE} default
+# For below variable value, using deployment name as using grep for
+# parsing radius pod name, we can also use full radius pod name
+${RESTART_POD_NAME} radius
+${timeout} 60s
+${of_id} 0
+${logical_id} 0
+${uprate} 0
+${dnrate} 0
+${has_dataplane} True
+${teardown_device} True
+${scripts} ../../scripts
+# flag to reboot OLT through Power Switch
+${power_cycle_olt} False
+
+# For dataplane bandwidth testing
+${upper_margin_pct} 105 # Allow 5% over the limit
+${lower_margin_pct} 90 # Allow 8% under the limit
+${udp_rate_multiplier} 1.10 # Send UDP at bw profile limit * rate_multiplier
+${udp_packet_bytes} 1470 # UDP payload in bytes
+
+# Per-test logging on failure is turned off by default; set this variable to enable
+${container_log_dir} ${None}
+
+# logging flag to enable Collect Logs, can be passed via the command line too
+# example: -v logging:False
+${logging} True
+
+# Flag specific to Soak Jobs
+${SOAK_TEST} False
+${bbsim_port} 50060
+
+*** Test Cases ***
+Sanity E2E Test for OLT/ONU on POD for DT
+ [Documentation] Validates E2E Ping Connectivity and object states for the given scenario:
+ ... Validate successful DHCP/E2E ping (no EAPOL and DHCP flows) for the tech profile that is used
+ ... Traffic sent with same vlan from different RGs,
+ ... should reach the NNI port on the OLT with the expected double tagged vlan ids
+ ... Inner vlans from the RG should not change
+ [Tags] sanityDt soak
+ [Setup] Start Logging SanityTestDt
+# [Teardown] Run Keywords Run Keyword If ${logging} Collect Logs
+# ... AND Stop Logging SanityTestDt
+ Setup ${SOAK_TEST}
+ Run Keyword If ${has_dataplane} Clean Up Linux
+ Perform Sanity Test DT
+
+Test Subscriber Delete and Add for DT
+ [Documentation] Validates E2E Ping Connectivity and object states for the given scenario:
+ ... Assuming that all the ONUs are DHCP/pingable (i.e. assuming sanityDt test was executed)
+ ... Delete a subscriber and validate that the pings do not succeed and state is purged
+ ... Disable and Enable the ONU (This is to replicate the existing DT behaviour)
+ ... Re-add the subscriber, and validate that the flows are present and pings are successful
+ [Tags] functionalDt SubAddDeleteDt soak
+ [Setup] Run Keywords Start Logging SubAddDeleteDt
+ ... AND Run Keyword If ${has_dataplane} Set Non-Critical Tag for XGSPON Tech
+ [Teardown] Run Keywords Run Keyword If ${logging} Collect Logs
+ ... AND Stop Logging SubAddDeleteDt
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${of_id}= Get ofID From OLT List ${src['olt']}
+ ${nni_port}= Wait Until Keyword Succeeds ${timeout} 2s Get NNI Port in VGC ${of_id}
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ ${olt_device_id}= Get OLTDeviceID From OLT List ${src['olt']}
+ ${num_of_olt_onus}= Get Num of Onus From OLT SN ${src['olt']}
+ ${onu_port}= Wait Until Keyword Succeeds ${timeout} 2s Get ONU Port in VGC ${src['onu']}
+ ... ${of_id} ${src['uni_id']}
+ # Remove Subscriber Access
+ Delete Request VGC services/${of_id}/${onu_port}
+ Run Keyword If ${has_dataplane} Run Keyword And Continue On Failure
+ ... Wait Until Keyword Succeeds ${timeout} 2s
+ ... Check Ping False ${dst['dp_iface_ip_qinq']} ${src['dp_iface_name']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+
+ # Number of Access Flows on VGC equals 4 * the Number of Active ONUs (2 for each downstream and upstream)
+ ${vgc_flows_count}= Evaluate 4 * ( ${num_of_olt_onus} - 1 )
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Subscriber Access Flows Added Count DT ${VGC_SSH_IP} ${VGC_SSH_PORT}
+ ... ${of_id} ${vgc_flows_count}
+ # Verify VOLTHA flows for OLT equals twice the number of ONUS (minus ONU under test) + 1 for LLDP
+ ${olt_flows}= Evaluate 2 * ( ${num_of_olt_onus} - 1 )
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s Validate OLT Flows
+ ... ${olt_flows} ${olt_device_id}
+ # Verify VOLTHA flows for ONU under test is Zero
+ Run Keyword Wait Until Keyword Succeeds ${timeout} 5s Validate Device Flows
+ ... ${onu_device_id} 0
+ # Disable and Re-Enable the ONU (To replicate DT current workflow)
+ # TODO: Delete and Auto-Discovery Add of ONU (not yet supported)
+ Disable Device ${onu_device_id}
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate Device DISABLED UNKNOWN
+ ... REACHABLE ${src['onu']}
+ Enable Device ${onu_device_id}
+ Wait Until Keyword Succeeds 360s 5s
+ ... Validate Device ENABLED ACTIVE
+ ... REACHABLE ${src['onu']}
+ # Add Subscriber Access
+ Post Request VGC services/${of_id}/${onu_port}
+ # Verify subscriber access flows are added for the ONU port
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Subscriber Access Flows Added for ONU DT in VGC ${VGC_SSH_IP} ${VGC_SSH_PORT} ${of_id}
+ ... ${onu_port} ${nni_port} ${src['s_tag']}
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate Device ENABLED ACTIVE
+ ... REACHABLE ${src['onu']} onu=True onu_reason=omci-flows-pushed
+ # Workaround for issue seen in VOL-4489. Keep this workaround until VOL-4489 is fixed.
+ Run Keyword If ${has_dataplane} Reboot XGSPON ONU ${src['olt']} ${src['onu']} omci-flows-pushed
+ # Workaround ends here for issue seen in VOL-4489.
+ Run Keyword If ${has_dataplane} Run Keyword And Continue On Failure
+ ... Wait Until Keyword Succeeds ${timeout} 2s
+ ... Check Ping True ${dst['dp_iface_ip_qinq']} ${src['dp_iface_name']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ END
+ # Verify flows for all OLTs
+ Run Keyword Wait Until Keyword Succeeds ${timeout} 5s Validate All OLT Flows
+
+Test Disable and Enable ONU for DT
+ [Documentation] Validates E2E Ping Connectivity and object states for the given scenario:
+ ... Assuming that all the ONUs are DHCP/pingable (i.e. assuming sanityDt test was executed)
+ ... Perform disable on the ONUs and validate that the pings do not succeed
+ ... Perform enable on the ONUs and validate that the pings are successful
+ [Tags] functionalDt DisableEnableONUDt soak
+ [Setup] Run Keywords Start Logging DisableEnableONUDt
+ ... AND Run Keyword If ${has_dataplane} Set Non-Critical Tag for XGSPON Tech
+ [Teardown] Run Keywords Run Keyword If ${logging} Collect Logs
+ ... AND Stop Logging DisableEnableONUDt
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${of_id}= Get ofID From OLT List ${src['olt']}
+ ${onu_port}= Wait Until Keyword Succeeds ${timeout} 2s Get ONU Port in VGC ${src['onu']}
+ ... ${of_id} ${src['uni_id']}
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ Disable Device ${onu_device_id}
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate Device DISABLED UNKNOWN
+ ... REACHABLE ${src['onu']} onu=True onu_reason=omci-admin-lock
+ Wait Until Keyword Succeeds ${timeout} 2s
+ ... Verify UNI Port Is Disabled ${VGC_SSH_IP} ${VGC_SSH_PORT} ${src['onu']} ${src['uni_id']}
+ # TODO: Yet to Verify on the GPON based Physical POD (VOL-2652)
+ Run Keyword If ${has_dataplane} Run Keyword And Continue On Failure
+ ... Wait Until Keyword Succeeds ${timeout} 2s
+ ... Check Ping False ${dst['dp_iface_ip_qinq']} ${src['dp_iface_name']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ Sleep 5s
+ Enable Device ${onu_device_id}
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds 360s 5s
+ ... Validate Device ENABLED ACTIVE
+ ... REACHABLE ${src['onu']} onu=True onu_reason=onu-reenabled
+ Wait Until Keyword Succeeds ${timeout} 2s
+ ... Verify UNI Port Is Enabled ${src['onu']} ${src['uni_id']}
+ # Workaround for issue seen in VOL-4489. Keep this workaround until VOL-4489 is fixed.
+ Run Keyword If ${has_dataplane} Reboot XGSPON ONU ${src['olt']} ${src['onu']} omci-flows-pushed
+ # Workaround ends here for issue seen in VOL-4489.
+ Run Keyword If ${has_dataplane} Run Keyword And Continue On Failure
+ ... Wait Until Keyword Succeeds ${timeout} 2s
+ ... Check Ping True ${dst['dp_iface_ip_qinq']} ${src['dp_iface_name']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ END
+
+Test Disable and Delete OLT for DT
+ [Documentation] Validates E2E Ping Connectivity and object states for the given scenario:
+ ... Assuming that all the ONUs are DHCP/pingable (i.e. assuming sanityDt test was executed)
+ ... Perform disable on the OLT and validate ONUs state and that the pings do not succeed
+ ... Perform delete on the OLT, Re-do Setup (Recreate the OLT) and Perform Sanity Test DT
+ [Tags] functionalDt DisableDeleteOLTDt soak
+ [Setup] Start Logging DisableDeleteOLTDt
+ [Teardown] Run Keywords Run Keyword If ${logging} Collect Logs
+ ... AND Stop Logging DisableDeleteOLTDt
+ # Disable and Validate OLT Device
+ FOR ${I} IN RANGE 0 ${olt_count}
+ ${olt_serial_number}= Get From Dictionary ${olt_ids}[${I}] sn
+ ${olt_device_id}= Get OLTDeviceID From OLT List ${olt_serial_number}
+ Disable Device ${olt_device_id}
+ ${of_id}= Get ofID From OLT List ${olt_serial_number}
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate OLT Device DISABLED UNKNOWN REACHABLE
+ ... ${olt_serial_number}
+ ${num_onus}= Set Variable ${list_olts}[${I}][onucount]
+ # Validate ONUs
+ Run Keyword Wait Until Keyword Succeeds ${timeout} 5s Validate ONUs After OLT Disable
+ ... ${num_onus} ${olt_serial_number}
+ # Verify VGC Flows
+ # Number of Access Flows on VGC equals 4 * the Number of Active ONUs (2 for each downstream and upstream)
+ ${vgc_flows_count}= Evaluate 4 * ${num_onus}
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Subscriber Access Flows Added Count DT ${VGC_SSH_IP} ${VGC_SSH_PORT}
+ ... ${of_id} ${vgc_flows_count}
+ # Verify VOLTHA Flows
+ # Number of per OLT Flows equals Twice the Number of Active ONUs (each for downstream and upstream) + 1 for LLDP
+ ${olt_flows}= Evaluate 2 * ${num_onus}
+ # Number of per ONU Flows equals 2 (one each for downstream and upstream)
+ ${onu_flows}= Set Variable 2
+ Run Keyword Wait Until Keyword Succeeds ${timeout} 5s Validate OLT Flows
+ ... ${olt_flows} ${olt_device_id}
+ ${List_ONU_Serial} Create List
+ Set Suite Variable ${List_ONU_Serial}
+ Build ONU SN List ${List_ONU_Serial} ${olt_serial_number} ${num_onus}
+ Log ${List_ONU_Serial}
+ Run Keyword Wait Until Keyword Succeeds ${timeout} 5s Validate ONU Flows
+ ... ${List_ONU_Serial} ${onu_flows}
+ # Delete OLT and Validate Empty Device List
+ Delete Device ${olt_device_id}
+ # Check that the OLT and the ONUs are actually removed from the system
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s Validate Device Removed
+ ... ${olt_serial_number}
+ Run Keyword and Continue On Failure Validate all ONUS for OLT Removed ${num_all_onus} ${hosts}
+ ... ${olt_serial_number} ${timeout}
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Device Flows Removed ${VGC_SSH_IP} ${VGC_SSH_PORT} ${of_id}
+ END
+ # Re-do Setup (Recreate the OLT) and Perform Sanity Test DT
+ Run Keyword Setup ${SOAK_TEST}
+ Run Keyword If ${has_dataplane} Clean Up Linux
+ Perform Sanity Test DT
+
+Test Disable and Enable OLT for DT
+ [Documentation] Validates E2E Ping Connectivity and object states for the given scenario:
+ ... Assuming that all the ONUs are DHCP/pingable (i.e. assuming sanityDt test was executed)
+ ... Perform disable on the OLT and validate that the pings do not succeed
+ ... Perform enable on the OLT and validate that the pings are successful
+ [Tags] functionalDt DisableEnableOLTDt soak
+ [Setup] Start Logging DisableEnableOLTDt
+ [Teardown] Run Keywords Run Keyword If ${logging} Collect Logs
+ ... AND Stop Logging DisableEnableOLTDt
+ # Disable and Validate OLT Device
+ FOR ${I} IN RANGE 0 ${olt_count}
+ ${olt_serial_number}= Get From Dictionary ${olt_ids}[${I}] sn
+ ${olt_device_id}= Get OLTDeviceID From OLT List ${olt_serial_number}
+ ${rc} ${output}= Run and Return Rc and Output
+ ... ${VOLTCTL_CONFIG}; voltctl device disable ${olt_device_id}
+ Should Be Equal As Integers ${rc} 0
+ Wait Until Keyword Succeeds ${timeout} 5s Validate OLT Device DISABLED UNKNOWN REACHABLE
+ ... ${olt_serial_number}
+ END
+ # Validate ONUs
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${of_id}= Get ofID From OLT List ${src['olt']}
+ ${onu_port}= Wait Until Keyword Succeeds ${timeout} 2s
+ ... Get ONU Port in VGC ${src['onu']} ${of_id} ${src['uni_id']}
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ Wait Until Keyword Succeeds ${timeout} 2s
+ ... Verify UNI Port Is Disabled ${VGC_SSH_IP} ${VGC_SSH_PORT} ${src['onu']} ${src['uni_id']}
+ Run Keyword If ${has_dataplane} Run Keyword And Continue On Failure
+ ... Wait Until Keyword Succeeds ${timeout} 2s
+ ... Check Ping False ${dst['dp_iface_ip_qinq']} ${src['dp_iface_name']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ # Remove Subscriber Access (To replicate DT workflow)
+ ${onu_port_name}= Catenate SEPARATOR=- ${src['onu']} ${src['uni_id']}
+ Wait Until Keyword Succeeds ${timeout} 2s
+ ... Delete Request VGC services/${onu_port_name}
+ # Delete ONU Device (To replicate DT workflow)
+ Delete Device ${onu_device_id}
+ END
+ Sleep 5s
+ # Enable the OLT back and check ONU, OLT status are back to "ACTIVE"
+ FOR ${I} IN RANGE 0 ${olt_count}
+ ${olt_serial_number}= Get From Dictionary ${olt_ids}[${I}] sn
+ ${olt_device_id}= Get OLTDeviceID From OLT List ${olt_serial_number}
+ Enable Device ${olt_device_id}
+ Wait Until Keyword Succeeds ${timeout} 5s Validate OLT Device ENABLED ACTIVE REACHABLE
+ ... ${olt_serial_number}
+ #TODO: Update for PON_OLT ETHERNET_NNI
+ #Wait Until Keyword Succeeds ${timeout} 5s Validate OLT Port Types
+ #... PON_OLT ETHERNET_NNI
+ END
+ # Waiting extra time for the ONUs to come up
+ Sleep 60s
+ Run Keyword If ${has_dataplane} Clean Up Linux
+ Perform Sanity Test DT
+
+Test Delete and ReAdd OLT for DT
+ [Documentation] Validates E2E Ping Connectivity and object states for the given scenario:
+ ... Assuming that all the ONUs are DHCP/pingable (i.e. assuming sanityDt test was executed)
+ ... Disable and Delete the OLT
+ ... Create/Enable the same OLT again
+ ... Validate DHCP/E2E pings succeed for all the ONUs connected to the OLT
+ [Tags] functionalDt DeleteReAddOLTDt soak
+ [Setup] Start Logging DeleteReAddOLTDt
+ [Teardown] Run Keywords Run Keyword If ${logging} Collect Logs
+ ... AND Stop Logging DeleteReAddOLTDt
+ FOR ${I} IN RANGE 0 ${olt_count}
+ ${olt_serial_number}= Get From Dictionary ${olt_ids}[${I}] sn
+ ${of_id}= Get ofID From OLT List ${olt_serial_number}
+ Delete Device and Verify ${olt_serial_number}
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Device Flows Removed ${VGC_SSH_IP} ${VGC_SSH_PORT} ${of_id}
+ END
+ # Recreate the OLTs
+ Setup ${SOAK_TEST}
+ Run Keyword If ${has_dataplane} Clean Up Linux
+ Perform Sanity Test DT
+
+Test Disable ONUs and OLT Then Delete ONUs and OLT for DT
+ [Documentation] On deployed POD, disable the ONU, disable the OLT and then delete ONU and OLT.
+ ... This TC is to confirm that ONU removal is not impacting OLT
+ ... Devices will be removed during the execution of this TC
+ ... so calling setup at the end to add the devices back to avoid the confusion.
+ [Tags] functionalDt DisableDeleteONUOLTDt
+ [Setup] Run Keywords Start Logging DisableDeleteONUOLTDt
+ ... AND Run Keyword If ${has_dataplane} Set Non-Critical Tag for XGSPON Tech
+ [Teardown] Run Keywords Run Keyword If ${logging} Collect Logs
+ ... AND Stop Logging DisableDeleteONUOLTDt
+ @{onu_reason}= Create List initial-mib-downloaded omci-flows-pushed
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate Device ENABLED ACTIVE
+ ... REACHABLE ${src['onu']} onu=True onu_reason=${onu_reason}
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate OLT Device ENABLED ACTIVE
+ ... REACHABLE ${src['olt']}
+ Disable Device ${onu_device_id}
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate Device DISABLED UNKNOWN
+ ... REACHABLE ${src['onu']} onu=false
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate OLT Device ENABLED ACTIVE
+ ... REACHABLE ${src['olt']}
+ END
+ # Disable all OLTs
+ FOR ${I} IN RANGE 0 ${olt_count}
+ ${olt_serial_number}= Get From Dictionary ${olt_ids}[${I}] sn
+ ${olt_device_id}= Get OLTDeviceID From OLT List ${olt_serial_number}
+ ${rc} ${output}= Run and Return Rc and Output
+ ... ${VOLTCTL_CONFIG}; voltctl device disable ${olt_device_id}
+ Should Be Equal As Integers ${rc} 0
+ Wait Until Keyword Succeeds ${timeout} 5s Validate OLT Device DISABLED UNKNOWN REACHABLE
+ ... ${olt_serial_number}
+ END
+ # Validate ONUs after OLT disable
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate Device DISABLED DISCOVERED
+ ... UNREACHABLE ${src['onu']} onu=false
+ Delete Device ${onu_device_id}
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate OLT Device DISABLED UNKNOWN
+ ... REACHABLE ${src['olt']}
+ END
+ # Delete all OLTs
+ Delete All Devices and Verify
+
+ #Delete Device ${olt_device_id}
+ #TODO: Fix the following assertion
+ #Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s Test Empty Device List
+ #Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ #... Verify Device Flows Removed ${VGC_SSH_IP} ${VGC_SSH_PORT} ${of_id}
+
+ # Re-do Setup (Recreate the OLT) and Perform Sanity Test DT
+ Run Keyword Setup
+ Run Keyword If ${has_dataplane} Clean Up Linux
+ Perform Sanity Test DT
+
+Test Disable and Enable OLT PON Port for DT
+ [Documentation] Validates E2E Ping Connectivity and object states for the given scenario:
+ ... Assuming that all the ONUs are DHCP/pingable (i.e. assuming sanityDt test was executed)
+ ... Perform disable on the OLT PON Port and validate that the pings do not succeed
+ ... Perform enable on the OLT PON Port and validate that the pings are successful
+ [Tags] functionalDt DisableEnableOltPonPortDt VOL-2577 soak
+ [Setup] Run Keywords Start Logging DisableEnableOltPonPortDt
+ ... AND Run Keyword If ${has_dataplane} Set Non-Critical Tag for XGSPON Tech
+ [Teardown] Run Keywords Run Keyword If ${logging} Collect Logs
+ ... AND Stop Logging DisableEnableOltPonPortDt
+ FOR ${I} IN RANGE 0 ${olt_count}
+ ${olt_serial_number}= Get From Dictionary ${olt_ids}[${I}] sn
+ Disable Enable PON Port Per OLT DT ${olt_serial_number}
+ END
+
+Test ONU Delete and Auto-Discovery for DT
+ [Documentation] Tests the voltctl delete and Auto-Discovery of the ONU
+ [Tags] functionalDt VOL-3098 ONUAutoDiscoveryDt
+ [Setup] Start Logging ONUAutoDiscoveryDt
+ [Teardown] Run Keywords Run Keyword If ${logging} Collect Logs
+ ... AND Stop Logging ONUAutoDiscoveryDt
+ Clear All Devices Then Create New Device
+ # Performing Sanity Test to make sure subscribers are all AUTH+DHCP and pingable
+ Run Keyword If ${has_dataplane} Clean Up Linux
+ Perform Sanity Test DT
+ FOR ${I} IN RANGE 0 ${num_all_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${of_id}= Get ofID From OLT List ${src['olt']}
+ ${onu_port}= Wait Until Keyword Succeeds ${timeout} 2s
+ ... Get ONU Port in VGC ${src['onu']} ${of_id}
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ ${nni_port}= Wait Until Keyword Succeeds ${timeout} 2s Get NNI Port in VGC ${of_id}
+ # Remove Subscriber
+ Delete Request VGC services/${of_id}/${onu_port}
+ # Additional sleep to let subscriber delete process
+ Sleep 10s
+ # Delete ONU and Verify Ping Fails
+ Delete Device ${onu_device_id}
+ Run Keyword If ${has_dataplane} Verify ping is successful except for given device
+ ... ${num_all_onus} ${src['onu']}
+ # Verify that no pending flows exist for the ONU port
+ Wait Until Keyword Succeeds ${timeout} 2s
+ ... Verify No Pending Flows For ONU ${VGC_SSH_IP} ${VGC_SSH_PORT} ${onu_port}
+ # ONU Auto-Discovery
+ ${onu_port}= Wait Until Keyword Succeeds ${timeout} 2s
+ ... Get ONU Port in VGC ${src['onu']} ${of_id} ${src['uni_id']}
+ # Check ONU port is Enabled in VGC
+ Wait Until Keyword Succeeds ${timeout} 2s
+ ... Verify UNI Port Is Enabled ${src['onu']} ${src['uni_id']}
+ ${onu_device_id}= Get Device ID From SN ${src['onu']}
+ Run Keyword If ${has_dataplane} Clean Up Linux ${onu_device_id}
+ # Re-Add Subscriber
+ Add Subscriber Details ${of_id} ${onu_port}
+ #Post Request VGC services/${of_id}/${onu_port}
+ # Verify ONU state in voltha
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Validate Device ENABLED ACTIVE REACHABLE
+ ... ${src['onu']} onu=True onu_reason=omci-flows-pushed
+ # Verify that no pending flows exist for the ONU port
+ Wait Until Keyword Succeeds ${timeout} 2s
+ ... Verify No Pending Flows For ONU ${VGC_SSH_IP} ${VGC_SSH_PORT} ${onu_port}
+ # Verify subscriber access flows are added for the ONU port
+ Run Keyword And Continue On Failure Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Subscriber Access Flows Added For ONU DT in VGC ${VGC_SSH_IP} ${VGC_SSH_PORT} ${of_id}
+ ... ${onu_port} ${nni_port} ${src['s_tag']}
+ # Verify Meters in VGC
+ Wait Until Keyword Succeeds ${timeout} 5s
+ ... Verify Meters in VGC Ietf ${VGC_SSH_IP} ${VGC_SSH_PORT} ${of_id} ${onu_port}
+ Run Keyword If ${has_dataplane} Validate DHCP and Ping True
+ ... True ${src['dp_iface_name']} ${src['s_tag']} ${src['c_tag']} ${dst['dp_iface_ip_qinq']}
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ ... ${dst['dp_iface_name']} ${dst['ip']} ${dst['user']} ${dst['pass']} ${dst['container_type']}
+ ... ${dst['container_name']}
+ END
+ # Verify flows for all OLTs
+ Wait Until Keyword Succeeds ${timeout} 5s Validate All OLT Flows
+
+*** Keywords ***
+Setup Suite
+ [Documentation] Set up the test suite
+ Common Test Suite Setup
+ #Restore all ONUs
+ #Run Keyword If ${has_dataplane} RestoreONUs ${num_all_onus}
+ #power_switch.robot needs it to support different vendor's power switch
+ ${switch_type}= Get Variable Value ${web_power_switch.type}
+ Run Keyword If "${switch_type}"!="" Set Global Variable ${powerswitch_type} ${switch_type}
+
+Clear All Devices Then Create New Device
+ [Documentation] Remove any devices from VOLTHA and VGC
+ # Remove all devices from voltha and nos
+ Delete All Devices and Verify
+ # Execute normal test Setup Keyword
+ Setup
+