+
+Wait For Routes To Propogate
+ [Arguments] ${networks} ${subnets}
+ [Documentation] Check propagated routes
+ Get ControlNode Connection
+ : FOR ${INDEX} IN RANGE 0 1
+ \ ${net_id}= Get Net Id @{networks}[${INDEX}]
+ \ ${is_ipv6}= Get Regexp Matches @{subnets}[${INDEX}] ${IP6_REGEX}
+ \ ${length}= Get Length ${is_ipv6}
+ \ ${cmd}= Set Variable If ${length} == 0 ip route ip -6 route
+ \ ${output}= Write Commands Until Expected Prompt sudo ip netns exec qdhcp-${net_id} ${cmd} ]>
+ \ Should Contain ${output} @{subnets}[${INDEX}]
+
+Neutron Cleanup
+ [Arguments] ${vms}=@{EMPTY} ${networks}=@{EMPTY} ${subnets}=@{EMPTY} ${ports}=@{EMPTY} ${sgs}=@{EMPTY}
+ : FOR ${vm} IN @{vms}
+ \ BuiltIn.Run Keyword And Ignore Error Delete Vm Instance ${vm}
+ : FOR ${port} IN @{ports}
+ \ BuiltIn.Run Keyword And Ignore Error Delete Port ${port}
+ : FOR ${subnet} IN @{subnets}
+ \ BuiltIn.Run Keyword And Ignore Error Delete SubNet ${subnet}
+ : FOR ${network} IN @{networks}
+ \ BuiltIn.Run Keyword And Ignore Error Delete Network ${network}
+ : FOR ${sg} IN @{sgs}
+ \ BuiltIn.Run Keyword And Ignore Error Delete SecurityGroup ${sg}
+
+OpenStack List All
+ [Documentation] Get a list of different OpenStack resources that might be in use.
+ @{modules} = BuiltIn.Create List server port network subnet security group
+ ... security group rule
+ Run Keyword If "${ODL_ENABLE_L3_FWD}"=="yes" Append To List ${modules} floating ip router
+ : FOR ${module} IN @{modules}
+ \ OpenStack CLI openstack ${module} list
+
+OpenStack CLI Get List
+ [Arguments] ${cmd}
+ [Documentation] Return a json list from the output of an OpenStack command.
+ @{list} = BuiltIn.Create List
+ ${json} = OpenStack CLI ${cmd}
+ @{list} = RequestsLibrary.To Json ${json}
+ BuiltIn.Log ${list}
+ [Return] @{list}
+
+OpenStack CLI
+ [Arguments] ${cmd} ${log_output}=True
+ [Documentation] Run the given OpenStack ${cmd}.
+ ${rc} ${output} = OperatingSystem.Run And Return Rc And Output ${cmd}
+ Run Keyword If "${log_output}"=="True" BuiltIn.Log ${output}
+ Should Be True '${rc}' == '0'
+ [Return] ${output}
+
+OpenStack Cleanup All
+ [Documentation] Cleanup all Openstack resources with best effort. The keyword will query for all resources
+ ... in use and then attempt to delete them. Errors are ignored to allow the cleanup to continue.
+ @{fips} = Run Keyword If "${ODL_ENABLE_L3_FWD}"=="yes" OpenStack CLI Get List openstack floating ip list -f json
+ ... ELSE Create List @{EMPTY}
+ : FOR ${fip} IN @{fips}
+ \ BuiltIn.Run Keyword And Ignore Error Delete Floating IP ${fip['ID']}
+ @{vms} = OpenStack CLI Get List openstack server list -f json
+ : FOR ${vm} IN @{vms}
+ \ BuiltIn.Run Keyword And Ignore Error Delete Vm Instance ${vm['ID']}
+ @{routers} = Run Keyword If "${ODL_ENABLE_L3_FWD}"=="yes" OpenStack CLI Get List openstack router list -f json
+ ... ELSE Create List @{EMPTY}
+ : FOR ${router} IN @{routers}
+ \ BuiltIn.Run Keyword And Ignore Error Cleanup Router ${router['ID']}
+ @{ports} = OpenStack CLI Get List openstack port list -f json
+ : FOR ${port} IN @{ports}
+ \ BuiltIn.Run Keyword And Ignore Error Delete Port ${port['ID']}
+ @{networks} = OpenStack CLI Get List openstack network list -f json
+ : FOR ${network} IN @{networks}
+ \ BuiltIn.Run Keyword And Ignore Error Delete Subnet ${network['Subnets']}
+ \ BuiltIn.Run Keyword And Ignore Error Delete Network ${network['ID']}
+ @{security_groups} = OpenStack CLI Get List openstack security group list -f json
+ : FOR ${security_group} IN @{security_groups}
+ \ BuiltIn.Run Keyword If "${security_group['Name']}" != "default" BuiltIn.Run Keyword And Ignore Error Delete SecurityGroup ${security_group['ID']}
+ OpenStack List All
+
+Cleanup Router
+ [Arguments] ${id}
+ [Documentation] Delete a router, but first remove any interfaces or gateways so that the delete will be successful.
+ @{ports} = OpenStack CLI Get List openstack port list --router ${id} -f json --long
+ : FOR ${port} IN @{ports}
+ \ ${subnet_id} = Get Match ${port['Fixed IP Addresses']} [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} 0
+ \ BuiltIn.Run Keyword If "${port['Device Owner']}" == "network:router_gateway" BuiltIn.Run Keyword And Ignore Error Remove Gateway ${id}
+ \ BuiltIn.Run Keyword If "${port['Device Owner']}" == "network:router_interface" BuiltIn.Run Keyword And Ignore Error Remove Interface ${id} ${subnet_id}
+ BuiltIn.Run Keyword And Ignore Error Delete Router ${id}
+
+OpenStack Suite Setup
+ [Documentation] Wrapper teardown keyword that can be used in any suite running in an openstack environement
+ SetupUtils.Setup_Utils_For_Setup_And_Teardown
+ @{tcpdump_port_6653_conn_ids} = OpenStackOperations.Start Packet Capture On Nodes tcpdump_port_6653 port 6653 ${OS_CONTROL_NODE_IP} ${OS_COMPUTE_1_IP} ${OS_COMPUTE_2_IP}
+ BuiltIn.Set Suite Variable @{tcpdump_port_6653_conn_ids}
+ Run Keyword If "${PRE_CLEAN_OPENSTACK_ALL}"=="True" OpenStack Cleanup All
+ DevstackUtils.Devstack Suite Setup
+ Add OVS Logging On All OpenStack Nodes
+
+OpenStack Suite Teardown
+ [Documentation] Wrapper teardown keyword that can be used in any suite running in an openstack environement
+ ... to clean up all openstack resources. For example, all instances, networks, ports, etc will be listed and
+ ... and deleted. As other global cleanup tasks are needed, they can be added here and the suites will all
+ ... benefit automatically.
+ OpenStack Cleanup All
+ OpenStackOperations.Stop Packet Capture On Nodes ${tcpdump_port_6653_conn_ids}
+ SSHLibrary.Close All Connections
+
+Copy DHCP Files From Control Node
+ [Documentation] Copy the current DHCP files to the robot vm. The keyword must be called
+ ... after the subnet(s) are created and before the subnet(s) are deleted.
+ ${suite_} = BuiltIn.Evaluate """${SUITE_NAME}""".replace(" ","_").replace("/","_").replace(".","_")
+ ${dstdir} = Set Variable /tmp/qdhcp/${suite_}
+ OperatingSystem.Create Directory ${dstdir}
+ Get ControlNode Connection
+ BuiltIn.Run Keyword And Ignore Error SSHLibrary.Get Directory /opt/stack/data/neutron/dhcp ${dstdir} recursive=True
+
+Is Feature Installed
+ [Arguments] ${features}=none
+ : FOR ${feature} IN @{features}
+ \ ${status} ${output} Run Keyword And Ignore Error Builtin.Should Contain ${CONTROLLERFEATURES} ${feature}
+ \ Return From Keyword If "${status}" == "PASS" True
+ [Return] False
+
+Add OVS Logging On All OpenStack Nodes
+ [Documentation] Add higher levels of OVS logging to all the OpenStack nodes
+ Run Keyword If 0 < ${NUM_OS_SYSTEM} OVSDB.Add OVS Logging ${OS_CNTL_CONN_ID}
+ Run Keyword If 1 < ${NUM_OS_SYSTEM} OVSDB.Add OVS Logging ${OS_CMP1_CONN_ID}
+ Run Keyword If 2 < ${NUM_OS_SYSTEM} OVSDB.Add OVS Logging ${OS_CMP2_CONN_ID}
+
+Reset OVS Logging On All OpenStack Nodes
+ [Documentation] Reset the OVS logging to all the OpenStack nodes
+ Run Keyword If 0 < ${NUM_OS_SYSTEM} OVSDB.Reset OVS Logging ${OS_CNTL_CONN_ID}
+ Run Keyword If 1 < ${NUM_OS_SYSTEM} OVSDB.Reset OVS Logging ${OS_CMP1_CONN_ID}
+ Run Keyword If 2 < ${NUM_OS_SYSTEM} OVSDB.Reset OVS Logging ${OS_CMP2_CONN_ID}
+
+Start Packet Capture On Nodes
+ [Arguments] ${tag} ${filter} @{ips}
+ [Documentation] Wrapper keyword around the TcpDump packet capture that is catered to the Openstack setup.
+ ... The caller must pass the three arguments with a variable number of ips at the end,
+ ... but ${EMPTY} can be used for the tag and filter.
+ ${suite_} = BuiltIn.Evaluate """${SUITE_NAME}""".replace(" ","_").replace("/","_").replace(".","_")
+ ${tag_} = BuiltIn.Catenate SEPARATOR=__ ${tag} ${suite_}
+ @{conn_ids} = Tcpdump.Start Packet Capture on Nodes tag=${tag_} filter=${filter} ips=${ips}
+ [Return] @{conn_ids}
+
+Stop Packet Capture On Nodes
+ [Arguments] ${conn_ids}=@{EMPTY}
+ Tcpdump.Stop Packet Capture on Nodes ${conn_ids}