diff options
Diffstat (limited to 'resources/libraries')
-rw-r--r-- | resources/libraries/python/IPUtil.py | 68 | ||||
-rw-r--r-- | resources/libraries/python/IPv4Util.py | 26 | ||||
-rw-r--r-- | resources/libraries/python/InterfaceUtil.py | 22 | ||||
-rw-r--r-- | resources/libraries/python/L2Util.py | 29 | ||||
-rw-r--r-- | resources/libraries/python/LispSetup.py | 44 | ||||
-rw-r--r-- | resources/libraries/python/LispUtil.py | 17 | ||||
-rw-r--r-- | resources/libraries/robot/lisp/lisp_api.robot | 35 | ||||
-rw-r--r-- | resources/libraries/robot/lisp/lispgpe.robot | 118 |
8 files changed, 294 insertions, 65 deletions
diff --git a/resources/libraries/python/IPUtil.py b/resources/libraries/python/IPUtil.py index 5011708c39..ed38272645 100644 --- a/resources/libraries/python/IPUtil.py +++ b/resources/libraries/python/IPUtil.py @@ -17,7 +17,7 @@ from ipaddress import IPv4Network, ip_address from resources.libraries.python.ssh import SSH from resources.libraries.python.constants import Constants - +from resources.libraries.python.ssh import exec_cmd_no_error, exec_cmd from resources.libraries.python.topology import Topology @@ -73,6 +73,72 @@ class IPUtil(object): raise AssertionError('IP addresses are not equal: {0} != {1}'. format(ip1, ip2)) + @staticmethod + def setup_network_namespace(node, namespace_name, interface_name, + ip_address, prefix): + """Setup namespace on given node and attach interface and IP to + this namespace. Applicable also on TG node. + + :param node: Node to set namespace on. + :param namespace_name: Namespace name. + :param interface_name: Interface name. + :param ip_address: IP address of namespace's interface. + :param prefix: IP address prefix length. + :type node: dict + :type namespace_name: str + :type vhost_if: str + :type ip_address: str + :type prefix: int + """ + cmd = ('ip netns add {0}'.format(namespace_name)) + exec_cmd_no_error(node, cmd, sudo=True) + + cmd = ('ip link set dev {0} up netns {1}'.format(interface_name, + namespace_name)) + exec_cmd_no_error(node, cmd, sudo=True) + + cmd = ('ip netns exec {0} ip addr add {1}/{2} dev {3}'.format( + namespace_name, ip_address, prefix, interface_name)) + exec_cmd_no_error(node, cmd, sudo=True) + + @staticmethod + def linux_enable_forwarding(node, ip_ver='ipv4'): + """Enable forwarding on a Linux node, e.g. VM. + + :param node: Node to enable forwarding on. + :param ip_ver: IP version, 'ipv4' or 'ipv6'. + :type node: dict + :type ip_ver: str + """ + cmd = 'sysctl -w net.{0}.ip_forward=1'.format(ip_ver) + exec_cmd_no_error(node, cmd, sudo=True) + + @staticmethod + def set_linux_interface_ip(node, interface, ip, prefix, namespace=None): + """Set IP address to interface in linux. + + :param node: Node where to execute command. + :param interface: Interface in namespace. + :param ip: IP to be set on interface. + :param prefix: IP prefix. + :param namespace: Execute command in namespace. Optional + :type node: dict + :type interface: str + :type ip: str + :type prefix: int + :type namespace: str + :raises RuntimeError: IP could not be set. + """ + if namespace is not None: + cmd = 'ip netns exec {} ip addr add {}/{} dev {}'.format( + namespace, ip, prefix, interface) + else: + cmd = 'ip addr add {}/{} dev {}'.format(ip, prefix, interface) + (rc, _, stderr) = exec_cmd(node, cmd, timeout=5, sudo=True) + if rc != 0: + raise RuntimeError( + 'Could not set IP for interface, reason:{}'.format(stderr)) + def convert_ipv4_netmask_prefix(network): """Convert network mask to equivalent network prefix length or vice versa. diff --git a/resources/libraries/python/IPv4Util.py b/resources/libraries/python/IPv4Util.py index 3043f230c2..ca5a1b571f 100644 --- a/resources/libraries/python/IPv4Util.py +++ b/resources/libraries/python/IPv4Util.py @@ -218,29 +218,3 @@ class IPv4Util(object): if rc != 0: raise RuntimeError("Arp set not successful, reason:{}". format(stderr)) - - @staticmethod - def set_linux_interface_ip(node, interface, ip, prefix, namespace=None): - """Set IP address to interface in linux. - - :param node: Node where to execute command. - :param interface: Interface in namespace. - :param ip: IP to be set on interface. - :param prefix: IP prefix. - :param namespace: Execute command in namespace. Optional - :type node: dict - :type interface: str - :type ip: str - :type prefix: int - :type namespace: str - :raises RuntimeError: IP could not be set. - """ - if namespace is not None: - cmd = 'ip netns exec {} ip addr add {}/{} dev {}'.format( - namespace, ip, prefix, interface) - else: - cmd = 'ip addr add {}/{} dev {}'.format(ip, prefix, interface) - (rc, _, stderr) = exec_cmd(node, cmd, timeout=5, sudo=True) - if rc != 0: - raise RuntimeError( - 'Could not set IP for interface, reason:{}'.format(stderr)) diff --git a/resources/libraries/python/InterfaceUtil.py b/resources/libraries/python/InterfaceUtil.py index f5f1ce314e..11600a1d47 100644 --- a/resources/libraries/python/InterfaceUtil.py +++ b/resources/libraries/python/InterfaceUtil.py @@ -213,6 +213,28 @@ class InterfaceUtil(object): return data @staticmethod + def vpp_get_interface_mac(node, interface=None): + """Get MAC address for the given interface from actual interface dump. + + :param node: VPP node to get interface data from. + :param interface: Numeric index or name string of a specific interface. + :type node: dict + :type interface: int or str + :return: MAC address. + :rtype: str + """ + + if_data = InterfaceUtil.vpp_get_interface_data(node, interface) + mac_data = [str(hex(item))[2:] for item in if_data['l2_address'][:6]] + mac_data_nice = [] + for item in mac_data: + if len(item) == 1: + item = '0' + item + mac_data_nice.append(item) + mac = ":".join(mac_data_nice) + return mac + + @staticmethod def vpp_get_interface_ip_addresses(node, interface, ip_version): """Get list of IP addresses from an interface on a VPP node. diff --git a/resources/libraries/python/L2Util.py b/resources/libraries/python/L2Util.py index 566b69bf1c..a909e8611b 100644 --- a/resources/libraries/python/L2Util.py +++ b/resources/libraries/python/L2Util.py @@ -218,35 +218,6 @@ class L2Util(object): exec_cmd_no_error(node, cmd, sudo=True) @staticmethod - def setup_network_namespace(node, namespace_name, interface_name, - ip_address, prefix): - """Setup namespace on given node and attach interface and IP to - this namespace. Applicable also on TG node. - - :param node: Node to set namespace on. - :param namespace_name: Namespace name. - :param interface_name: Interface name. - :param ip_address: IP address of namespace's interface. - :param prefix: IP address prefix length. - :type node: dict - :type namespace_name: str - :type vhost_if: str - :type ip_address: str - :type prefix: int - - """ - cmd = ('ip netns add {0}'.format(namespace_name)) - exec_cmd_no_error(node, cmd, sudo=True) - - cmd = ('ip link set dev {0} up netns {1}'.format(interface_name, - namespace_name)) - exec_cmd_no_error(node, cmd, sudo=True) - - cmd = ('ip netns exec {0} ip addr add {1}/{2} dev {3}'.format( - namespace_name, ip_address, prefix, interface_name)) - exec_cmd_no_error(node, cmd, sudo=True) - - @staticmethod def linux_del_bridge(node, br_name, set_down=True): """Delete bridge from linux node. diff --git a/resources/libraries/python/LispSetup.py b/resources/libraries/python/LispSetup.py index 531510198c..ee2ae5d8a3 100644 --- a/resources/libraries/python/LispSetup.py +++ b/resources/libraries/python/LispSetup.py @@ -164,6 +164,26 @@ class LispAdjacency(object): seid_prefix=seid_prefix) +class LispGpeStatus(object): + """Clas for LISP GPE status manipulation.""" + + def __init__(self): + pass + + @staticmethod + def vpp_lisp_gpe_enable_disable(node, state): + """Change the state of LISP GPE - enable or disable. + + :param node: VPP node. + :param state: Requested state - enable or disable. + :type node: dict + :type state: str + """ + + VatExecutor.cmd_from_template(node, 'lisp/lisp_gpe_status.vat', + state=state) + + class LispGpeIface(object): """Class for Lisp gpe interface API.""" @@ -180,11 +200,31 @@ class LispGpeIface(object): :type state: str """ - VatExecutor.cmd_from_template(node, - 'lisp/lisp_gpe_iface.vat', + VatExecutor.cmd_from_template(node, 'lisp/lisp_gpe_iface.vat', state=state) +class LispGpeForwardEntry(object): + """The functionality needed for these methods is not implemented in VPP + (VAT). Bug https://jira.fd.io/browse/VPP-334 was open to cover this issue. + + TODO: Implement when VPP-334 is fixed. + """ + + def __init__(self): + pass + + @staticmethod + def add_lisp_gpe_forward_entry(node, *args): + # TODO: Implement when VPP-334 is fixed. + pass + + @staticmethod + def del_lisp_gpe_forward_entry(node, *args): + # TODO: Implement when VPP-334 is fixed. + pass + + class LispMapResolver(object): """Class for Lisp map resolver API.""" diff --git a/resources/libraries/python/LispUtil.py b/resources/libraries/python/LispUtil.py index 8a83dc4d30..c50e626b80 100644 --- a/resources/libraries/python/LispUtil.py +++ b/resources/libraries/python/LispUtil.py @@ -15,7 +15,7 @@ from resources.libraries.python.parsers.JsonParser import JsonParser from resources.libraries.python.topology import Topology -from resources.libraries.python.VatExecutor import VatExecutor +from resources.libraries.python.VatExecutor import VatExecutor, VatTerminal class LispUtil(object): @@ -40,18 +40,25 @@ class LispUtil(object): return JsonParser().parse_data(vat.get_script_stdout()) @staticmethod - def vpp_show_lisp_locator_set(node): + def vpp_show_lisp_locator_set(node, items_filter): """Get lisp locator_set from VPP node. :param node: VPP node. + :param items_filter: Filter which specifies which items should be + retrieved - local, remote, empty string = both. :type node: dict + :type items_filter: str :return: Lisp locator_set data as python list. :rtype: list """ - vat = VatExecutor() - vat.execute_script_json_out('lisp/show_lisp_locator_set.vat', node) - return JsonParser().parse_data(vat.get_script_stdout()) + try: + with VatTerminal(node) as vat: + response = vat.vat_terminal_exec_cmd_from_template( + 'lisp/show_lisp_locator_set.vat', filter=items_filter) + return response[0] + except ValueError: + return [] @staticmethod def vpp_show_lisp_eid_table(node): diff --git a/resources/libraries/robot/lisp/lisp_api.robot b/resources/libraries/robot/lisp/lisp_api.robot index 8094d08b84..4bd22bc036 100644 --- a/resources/libraries/robot/lisp/lisp_api.robot +++ b/resources/libraries/robot/lisp/lisp_api.robot @@ -16,6 +16,7 @@ | Library | resources.libraries.python.NodePath | Library | resources.libraries.python.LispSetup.LispStatus | Library | resources.libraries.python.LispSetup.LispSetup +| Library | resources.libraries.python.LispSetup.LispGpeStatus | Library | resources.libraries.python.LispUtil *** Keywords *** @@ -82,7 +83,7 @@ | | ... | \| Then Lisp locator_set is set correctly \| ${nodes['DUT1']} \| | | ... | | [Arguments] | ${dut_node} -| | ${show_locator_set}= | Vpp Show Lisp Locator Set | ${dut_node} +| | ${show_locator_set}= | Vpp Show Lisp Locator Set | ${dut_node} | local | | Lisp Locator S Should Be Equal | | ... | ${locator_set_values} | ${show_locator_set} @@ -120,7 +121,7 @@ | | ... | \| Then Lisp locator_set should be unset \| ${nodes['DUT1']} \| | | ... | | [Arguments] | ${dut_node} -| | ${show_locator_set}= | Vpp Show Lisp Locator Set | ${dut_node} +| | ${show_locator_set}= | Vpp Show Lisp Locator Set | ${dut_node} | ${EMPTY} | | Lisp Is Empty | ${show_locator_set} | Lisp locator_set data use for test reset locator_set are prepared @@ -359,3 +360,33 @@ | | [Arguments] | ${dut_node} | ${lisp_status_data} | | ${show_lisp_stat}= | Vpp Show Lisp State | ${dut_node} | | Lisp Should Be Equal | ${show_lisp_stat} | ${lisp_status_data[0]} + +| Enable Lisp Gpe +| | [Documentation] | Enable Lisp Gpe on VPP node. +| | ... +| | ... | *Arguments:* +| | ... | - dut_node - DUT node. Type: dictionary +| | ... +| | ... | *Return:* +| | ... | - No value returned +| | ... +| | ... | *Example:* +| | ... | \| Enable Lisp Gpe \| ${nodes['DUT1']} \| +| | ... +| | [Arguments] | ${dut_node} +| | Vpp Lisp Gpe Enable Disable | ${dut_node} | enable + +| Disable Lisp Gpe +| | [Documentation] | Disable Lisp Gpe on VPP node. +| | ... +| | ... | *Arguments:* +| | ... | - dut_node - DUT node. Type: dictionary +| | ... +| | ... | *Return:* +| | ... | - No value returned +| | ... +| | ... | *Example:* +| | ... | \| Disable Lisp Gpe \| ${nodes['DUT1']} \| +| | ... +| | [Arguments] | ${dut_node} +| | Vpp Lisp Gpe Enable Disable | ${dut_node} | disable diff --git a/resources/libraries/robot/lisp/lispgpe.robot b/resources/libraries/robot/lisp/lispgpe.robot new file mode 100644 index 0000000000..a5ab102652 --- /dev/null +++ b/resources/libraries/robot/lisp/lispgpe.robot @@ -0,0 +1,118 @@ +# Copyright (c) 2016 Cisco and/or its affiliates. +# 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 | LISP-gpe encapsulation suite keywords +| Library | resources.libraries.python.topology.Topology +| Resource | resources/libraries/robot/lisp/lisp_api.robot +| Library | resources.libraries.python.LispSetup.LispLocatorSet +| Library | resources.libraries.python.LispSetup.LispLocator +| Library | resources.libraries.python.LispSetup.LispLocalEid +| Library | resources.libraries.python.LispSetup.LispAdjacency +| Library | resources.libraries.python.LispSetup.LispRemoteMapping + +*** Keywords *** +| Set up LISP GPE topology +| | [Documentation] | Set up LISP GPE topology. +| | ... +| | ... | *Arguments:* +| | ... | - dut1_node - DUT1 node. Type: dictionary +| | ... | - dut1_if - DUT1 node interface. Type: string +| | ... | - dut1_int_index - DUT1 node interface index. Type: integer +| | ... | - dut2_node - DUT2 node. Type: dictionary +| | ... | - dut2_if - DUT2 node interface. Type: string +| | ... | - dut2_int_index - DUT2 node interface index. Type: integer +| | ... | - locator_set - Locator set values. Type: dictionary +| | ... | - dut1_eid - DUT1 node eid address. Type: dictionary +| | ... | - dut2_eid - DUT2 node eid address. Type: dictionary +| | ... | - dut1_static_adjacency - DUT1 static adjacency. Type: dictionary +| | ... | - dut2_static_adjacency - DUT2 static adjacency. Type: dictionary +| | ... +| | ... | *Return:* +| | ... | - No value returned +| | ... +| | ... | *Example:* +| | ... | \| Set up LISP GPE topology \| ${dut1_node} \| ${interface_name} \ +| | ... | \| None \| ${dut2_node} \| ${interface_name} \| None \ +| | ... | \| ${locator_set} \| ${dut1_eid} \| ${dut2_eid} \ +| | ... | \| ${dut1_static_adjacency} \| ${dut2_static_adjacency} \| +| | ... +| | [Arguments] +| | ... | ${dut1_node} | ${dut1_if} | ${dut1_int_index} +| | ... | ${dut2_node} | ${dut2_if} | ${dut2_int_index} +| | ... | ${locator_set} | ${dut1_eid} | ${dut2_eid} +| | ... | ${dut1_static_adjacency} | ${dut2_static_adjacency} +| | ... +# DUT1 settings: +| | ${dut1_int_index}= | Run Keyword If | ${dut1_int_index} is None +| | | ... | Get Interface Sw Index | ${dut1_node} | ${dut1_if} +| | | ... | ELSE | Set Variable | ${dut1_int_index} +| | Enable Lisp | ${dut1_node} +| | Enable Lisp GPE | ${dut1_node} +| | Vpp Add Lisp Locator Set | ${dut1_node} +| | ... | ${locator_set['locator_name']} +| | Vpp Add Lisp Locator | ${dut1_node} +| | ... | ${locator_set['locator_name']} +| | ... | ${dut1_int_index} +| | ... | ${locator_set['priority']} +| | ... | ${locator_set['weight']} +| | Vpp Add Lisp Local Eid | ${dut1_node} +| | ... | ${dut1_eid['locator_name']} +| | ... | ${dut1_eid['vni']} +| | ... | ${dut1_eid['eid']} +| | ... | ${dut1_eid['prefix']} +| | Vpp Add Lisp Remote Mapping | ${dut1_node} +| | ... | ${dut1_static_adjacency['vni']} +| | ... | ${dut1_static_adjacency['deid']} +| | ... | ${dut1_static_adjacency['prefix']} +| | ... | ${dut1_static_adjacency['seid']} +| | ... | ${dut1_static_adjacency['prefix']} +| | ... | ${dut1_static_adjacency['rloc']} +| | Vpp Add Lisp Adjacency | ${dut1_node} +| | ... | ${dut1_static_adjacency['vni']} +| | ... | ${dut1_static_adjacency['deid']} +| | ... | ${dut1_static_adjacency['prefix']} +| | ... | ${dut1_static_adjacency['seid']} +| | ... | ${dut1_static_adjacency['prefix']} +| | ... +# DUT2 settings: +| | ${dut2_int_index}= | Run Keyword If | ${dut2_int_index} is None +| | | ... | Get Interface Sw Index | ${dut2_node} | ${dut2_if} +| | | ... | ELSE | Set Variable | ${dut2_int_index} +| | Enable Lisp | ${dut2_node} +| | Enable Lisp GPE | ${dut2_node} +| | Vpp Add Lisp Locator Set | ${dut2_node} +| | ... | ${locator_set['locator_name']} +| | Vpp Add Lisp Locator | ${dut2_node} +| | ... | ${locator_set['locator_name']} +| | ... | ${dut2_int_index} +| | ... | ${locator_set['priority']} +| | ... | ${locator_set['weight']} +| | Vpp Add Lisp Local Eid | ${dut2_node} +| | ... | ${dut2_eid['locator_name']} +| | ... | ${dut2_eid['vni']} +| | ... | ${dut2_eid['eid']} +| | ... | ${dut2_eid['prefix']} +| | Vpp Add Lisp Remote Mapping | ${dut2_node} +| | ... | ${dut2_static_adjacency['vni']} +| | ... | ${dut2_static_adjacency['deid']} +| | ... | ${dut2_static_adjacency['prefix']} +| | ... | ${dut2_static_adjacency['seid']} +| | ... | ${dut2_static_adjacency['prefix']} +| | ... | ${dut2_static_adjacency['rloc']} +| | Vpp Add Lisp Adjacency | ${dut2_node} +| | ... | ${dut2_static_adjacency['vni']} +| | ... | ${dut2_static_adjacency['deid']} +| | ... | ${dut2_static_adjacency['prefix']} +| | ... | ${dut2_static_adjacency['seid']} +| | ... | ${dut2_static_adjacency['prefix']} |