aboutsummaryrefslogtreecommitdiffstats
path: root/resources
diff options
context:
space:
mode:
Diffstat (limited to 'resources')
-rw-r--r--resources/libraries/python/InterfaceSetup.py182
-rw-r--r--resources/libraries/python/InterfaceUtil.py237
-rw-r--r--resources/libraries/python/TGSetup.py4
-rw-r--r--resources/libraries/python/VatConfigGenerator.py58
-rw-r--r--resources/libraries/python/VatJsonUtil.py102
-rw-r--r--resources/libraries/python/topology.py176
-rw-r--r--resources/libraries/robot/default.robot5
-rw-r--r--resources/libraries/robot/vxlan.robot4
8 files changed, 345 insertions, 423 deletions
diff --git a/resources/libraries/python/InterfaceSetup.py b/resources/libraries/python/InterfaceSetup.py
deleted file mode 100644
index 946c8fc8fd..0000000000
--- a/resources/libraries/python/InterfaceSetup.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# 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.
-
-"""Interface setup library."""
-
-from ssh import SSH
-from robot.api.deco import keyword
-from resources.libraries.python.VatExecutor import VatExecutor
-
-
-class InterfaceSetup(object):
- """Interface setup utilities."""
-
- __UDEV_IF_RULES_FILE = '/etc/udev/rules.d/10-network.rules'
-
- @staticmethod
- def tg_set_interface_driver(node, pci_addr, driver):
- """Set interface driver on the TG node.
-
- :param node: Node to set interface driver on (must be TG node).
- :param pci_addr: PCI address of the interface.
- :param driver: Driver name.
- :type node: dict
- :type pci_addr: str
- :type driver: str
- """
- old_driver = InterfaceSetup.tg_get_interface_driver(node, pci_addr)
- if old_driver == driver:
- return
-
- ssh = SSH()
- ssh.connect(node)
-
- # Unbind from current driver
- if old_driver is not None:
- cmd = 'sh -c "echo {0} > /sys/bus/pci/drivers/{1}/unbind"'.format(
- pci_addr, old_driver)
- (ret_code, _, _) = ssh.exec_command_sudo(cmd)
- if int(ret_code) != 0:
- raise Exception("'{0}' failed on '{1}'".format(cmd,
- node['host']))
-
- # Bind to the new driver
- cmd = 'sh -c "echo {0} > /sys/bus/pci/drivers/{1}/bind"'.format(
- pci_addr, driver)
- (ret_code, _, _) = ssh.exec_command_sudo(cmd)
- if int(ret_code) != 0:
- raise Exception("'{0}' failed on '{1}'".format(cmd, node['host']))
-
- @staticmethod
- def tg_get_interface_driver(node, pci_addr):
- """Get interface driver from the TG node.
-
- :param node: Node to get interface driver on (must be TG node).
- :param pci_addr: PCI address of the interface.
- :type node: dict
- :type pci_addr: str
- :return: Interface driver or None if not found.
- :rtype: str
-
- .. note::
- # lspci -vmmks 0000:00:05.0
- Slot: 00:05.0
- Class: Ethernet controller
- Vendor: Red Hat, Inc
- Device: Virtio network device
- SVendor: Red Hat, Inc
- SDevice: Device 0001
- PhySlot: 5
- Driver: virtio-pci
- """
- ssh = SSH()
- ssh.connect(node)
-
- cmd = 'lspci -vmmks {0}'.format(pci_addr)
-
- (ret_code, stdout, _) = ssh.exec_command(cmd)
- if int(ret_code) != 0:
- raise Exception("'{0}' failed on '{1}'".format(cmd, node['host']))
-
- for line in stdout.splitlines():
- if len(line) == 0:
- continue
- (name, value) = line.split("\t", 1)
- if name == 'Driver:':
- return value
-
- return None
-
- @staticmethod
- def tg_set_interfaces_udev_rules(node):
- """Set udev rules for interfaces.
-
- Create udev rules file in /etc/udev/rules.d where are rules for each
- interface used by TG node, based on MAC interface has specific name.
- So after unbind and bind again to kernel driver interface has same
- name as before. This must be called after TG has set name for each
- port in topology dictionary.
- udev rule example
- SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="52:54:00:e1:8a:0f",
- NAME="eth1"
-
- :param node: Node to set udev rules on (must be TG node).
- :type node: dict
- """
- ssh = SSH()
- ssh.connect(node)
-
- cmd = 'rm -f {0}'.format(InterfaceSetup.__UDEV_IF_RULES_FILE)
- (ret_code, _, _) = ssh.exec_command_sudo(cmd)
- if int(ret_code) != 0:
- raise Exception("'{0}' failed on '{1}'".format(cmd, node['host']))
-
- for if_k, if_v in node['interfaces'].items():
- if if_k == 'mgmt':
- continue
- rule = 'SUBSYSTEM==\\"net\\", ACTION==\\"add\\", ATTR{address}' + \
- '==\\"' + if_v['mac_address'] + '\\", NAME=\\"' + \
- if_v['name'] + '\\"'
- cmd = 'sh -c "echo \'{0}\' >> {1}"'.format(
- rule, InterfaceSetup.__UDEV_IF_RULES_FILE)
- (ret_code, _, _) = ssh.exec_command_sudo(cmd)
- if int(ret_code) != 0:
- raise Exception("'{0}' failed on '{1}'".format(cmd,
- node['host']))
-
- cmd = '/etc/init.d/udev restart'
- ssh.exec_command_sudo(cmd)
-
- @staticmethod
- def tg_set_interfaces_default_driver(node):
- """Set interfaces default driver specified in topology yaml file.
-
- :param node: Node to setup interfaces driver on (must be TG node).
- :type node: dict
- """
- for if_k, if_v in node['interfaces'].items():
- if if_k == 'mgmt':
- continue
- InterfaceSetup.tg_set_interface_driver(node, if_v['pci_address'],
- if_v['driver'])
-
- @staticmethod
- def create_vxlan_interface(node, vni, source_ip, destination_ip):
- """Create VXLAN interface and return index of created interface
-
- Executes "vxlan_add_del_tunnel src {src} dst {dst} vni {vni}" VAT
- command on the node.
-
- :param node: Node where to create VXLAN interface
- :param vni: VXLAN Network Identifier
- :param source_ip: Source IP of a VXLAN Tunnel End Point
- :param destination_ip: Destination IP of a VXLAN Tunnel End Point
- :type node: dict
- :type vni: int
- :type source_ip: str
- :type destination_ip: str
- :return: SW IF INDEX of created interface
- :rtype: int
- """
-
- output = VatExecutor.cmd_from_template(node, "vxlan_create.vat",
- src=source_ip,
- dst=destination_ip,
- vni=vni)
- output = output[0]
-
- if output["retval"] == 0:
- return output["sw_if_index"]
- else:
- raise RuntimeError('Unable to create VXLAN interface on node {}'.\
- format(node))
diff --git a/resources/libraries/python/InterfaceUtil.py b/resources/libraries/python/InterfaceUtil.py
index 25503c08df..4631ccce7a 100644
--- a/resources/libraries/python/InterfaceUtil.py
+++ b/resources/libraries/python/InterfaceUtil.py
@@ -14,15 +14,22 @@
"""Interface util library"""
from time import time, sleep
+
from robot.api import logger
+
+from resources.libraries.python.ssh import SSH
from resources.libraries.python.ssh import exec_cmd_no_error
from resources.libraries.python.topology import NodeType, Topology
from resources.libraries.python.VatExecutor import VatExecutor, VatTerminal
+from resources.libraries.python.VatJsonUtil import VatJsonUtil
+from resources.libraries.python.parsers.JsonParser import JsonParser
class InterfaceUtil(object):
"""General utilities for managing interfaces"""
+ __UDEV_IF_RULES_FILE = '/etc/udev/rules.d/10-network.rules'
+
@staticmethod
def set_interface_state(node, interface, state):
"""Set interface state on a node.
@@ -191,3 +198,233 @@ class InterfaceUtil(object):
return data_if
return data
+
+ @staticmethod
+ def tg_set_interface_driver(node, pci_addr, driver):
+ """Set interface driver on the TG node.
+
+ :param node: Node to set interface driver on (must be TG node).
+ :param pci_addr: PCI address of the interface.
+ :param driver: Driver name.
+ :type node: dict
+ :type pci_addr: str
+ :type driver: str
+ """
+ old_driver = InterfaceUtil.tg_get_interface_driver(node, pci_addr)
+ if old_driver == driver:
+ return
+
+ ssh = SSH()
+ ssh.connect(node)
+
+ # Unbind from current driver
+ if old_driver is not None:
+ cmd = 'sh -c "echo {0} > /sys/bus/pci/drivers/{1}/unbind"'.format(
+ pci_addr, old_driver)
+ (ret_code, _, _) = ssh.exec_command_sudo(cmd)
+ if int(ret_code) != 0:
+ raise Exception("'{0}' failed on '{1}'".format(cmd,
+ node['host']))
+
+ # Bind to the new driver
+ cmd = 'sh -c "echo {0} > /sys/bus/pci/drivers/{1}/bind"'.format(
+ pci_addr, driver)
+ (ret_code, _, _) = ssh.exec_command_sudo(cmd)
+ if int(ret_code) != 0:
+ raise Exception("'{0}' failed on '{1}'".format(cmd, node['host']))
+
+ @staticmethod
+ def tg_get_interface_driver(node, pci_addr):
+ """Get interface driver from the TG node.
+
+ :param node: Node to get interface driver on (must be TG node).
+ :param pci_addr: PCI address of the interface.
+ :type node: dict
+ :type pci_addr: str
+ :return: Interface driver or None if not found.
+ :rtype: str
+
+ .. note::
+ # lspci -vmmks 0000:00:05.0
+ Slot: 00:05.0
+ Class: Ethernet controller
+ Vendor: Red Hat, Inc
+ Device: Virtio network device
+ SVendor: Red Hat, Inc
+ SDevice: Device 0001
+ PhySlot: 5
+ Driver: virtio-pci
+ """
+ ssh = SSH()
+ ssh.connect(node)
+
+ cmd = 'lspci -vmmks {0}'.format(pci_addr)
+
+ (ret_code, stdout, _) = ssh.exec_command(cmd)
+ if int(ret_code) != 0:
+ raise Exception("'{0}' failed on '{1}'".format(cmd, node['host']))
+
+ for line in stdout.splitlines():
+ if len(line) == 0:
+ continue
+ (name, value) = line.split("\t", 1)
+ if name == 'Driver:':
+ return value
+
+ return None
+
+ @staticmethod
+ def tg_set_interfaces_udev_rules(node):
+ """Set udev rules for interfaces.
+
+ Create udev rules file in /etc/udev/rules.d where are rules for each
+ interface used by TG node, based on MAC interface has specific name.
+ So after unbind and bind again to kernel driver interface has same
+ name as before. This must be called after TG has set name for each
+ port in topology dictionary.
+ udev rule example
+ SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="52:54:00:e1:8a:0f",
+ NAME="eth1"
+
+ :param node: Node to set udev rules on (must be TG node).
+ :type node: dict
+ """
+ ssh = SSH()
+ ssh.connect(node)
+
+ cmd = 'rm -f {0}'.format(InterfaceUtil.__UDEV_IF_RULES_FILE)
+ (ret_code, _, _) = ssh.exec_command_sudo(cmd)
+ if int(ret_code) != 0:
+ raise Exception("'{0}' failed on '{1}'".format(cmd, node['host']))
+
+ for interface in node['interfaces'].values():
+ rule = 'SUBSYSTEM==\\"net\\", ACTION==\\"add\\", ATTR{address}' + \
+ '==\\"' + interface['mac_address'] + '\\", NAME=\\"' + \
+ interface['name'] + '\\"'
+ cmd = 'sh -c "echo \'{0}\' >> {1}"'.format(
+ rule, InterfaceUtil.__UDEV_IF_RULES_FILE)
+ (ret_code, _, _) = ssh.exec_command_sudo(cmd)
+ if int(ret_code) != 0:
+ raise Exception("'{0}' failed on '{1}'".format(cmd,
+ node['host']))
+
+ cmd = '/etc/init.d/udev restart'
+ ssh.exec_command_sudo(cmd)
+
+ @staticmethod
+ def tg_set_interfaces_default_driver(node):
+ """Set interfaces default driver specified in topology yaml file.
+
+ :param node: Node to setup interfaces driver on (must be TG node).
+ :type node: dict
+ """
+ for interface in node['interfaces'].values():
+ InterfaceUtil.tg_set_interface_driver(node,
+ interface['pci_address'],
+ interface['driver'])
+
+ @staticmethod
+ def update_vpp_interface_data_on_node(node):
+ """Update vpp generated interface data for a given node in DICT__nodes
+
+ Updates interface names, software if index numbers and any other details
+ generated specifically by vpp that are unknown before testcase run.
+ It does this by dumping interface list to JSON output from all
+ devices using vpp_api_test, and pairing known information from topology
+ (mac address/pci address of interface) to state from VPP.
+
+ :param node: Node selected from DICT__nodes
+ :type node: dict
+ """
+ vat_executor = VatExecutor()
+ vat_executor.execute_script_json_out("dump_interfaces.vat", node)
+ interface_dump_json = vat_executor.get_script_stdout()
+ VatJsonUtil.update_vpp_interface_data_from_json(node,
+ interface_dump_json)
+
+ @staticmethod
+ def update_tg_interface_data_on_node(node):
+ """Update interface name for TG/linux node in DICT__nodes.
+
+ :param node: Node selected from DICT__nodes.
+ :type node: dict
+
+ .. note::
+ # for dev in `ls /sys/class/net/`;
+ > do echo "\"`cat /sys/class/net/$dev/address`\": \"$dev\""; done
+ "52:54:00:9f:82:63": "eth0"
+ "52:54:00:77:ae:a9": "eth1"
+ "52:54:00:e1:8a:0f": "eth2"
+ "00:00:00:00:00:00": "lo"
+
+ .. todo:: parse lshw -json instead
+ """
+ # First setup interface driver specified in yaml file
+ InterfaceUtil.tg_set_interfaces_default_driver(node)
+
+ # Get interface names
+ ssh = SSH()
+ ssh.connect(node)
+
+ cmd = ('for dev in `ls /sys/class/net/`; do echo "\\"`cat '
+ '/sys/class/net/$dev/address`\\": \\"$dev\\""; done;')
+
+ (ret_code, stdout, _) = ssh.exec_command(cmd)
+ if int(ret_code) != 0:
+ raise Exception('Get interface name and MAC failed')
+ tmp = "{" + stdout.rstrip().replace('\n', ',') + "}"
+ interfaces = JsonParser().parse_data(tmp)
+ for interface in node['interfaces'].values():
+ name = interfaces.get(interface['mac_address'])
+ if name is None:
+ continue
+ interface['name'] = name
+
+ # Set udev rules for interfaces
+ InterfaceUtil.tg_set_interfaces_udev_rules(node)
+
+ @staticmethod
+ def update_all_interface_data_on_all_nodes(nodes):
+ """Update interface names on all nodes in DICT__nodes.
+
+ This method updates the topology dictionary by querying interface lists
+ of all nodes mentioned in the topology dictionary.
+
+ :param nodes: Nodes in the topology.
+ :type nodes: dict
+ """
+ for node_data in nodes.values():
+ if node_data['type'] == NodeType.DUT:
+ InterfaceUtil.update_vpp_interface_data_on_node(node_data)
+ elif node_data['type'] == NodeType.TG:
+ InterfaceUtil.update_tg_interface_data_on_node(node_data)
+
+ @staticmethod
+ def create_vxlan_interface(node, vni, source_ip, destination_ip):
+ """Create VXLAN interface and return sw if index of created interface.
+
+ Executes "vxlan_add_del_tunnel src {src} dst {dst} vni {vni}" VAT
+ command on the node.
+
+ :param node: Node where to create VXLAN interface.
+ :param vni: VXLAN Network Identifier.
+ :param source_ip: Source IP of a VXLAN Tunnel End Point.
+ :param destination_ip: Destination IP of a VXLAN Tunnel End Point.
+ :type node: dict
+ :type vni: int
+ :type source_ip: str
+ :type destination_ip: str
+ :return: SW IF INDEX of created interface.
+ :rtype: int
+ """
+ output = VatExecutor.cmd_from_template(node, "vxlan_create.vat",
+ src=source_ip,
+ dst=destination_ip,
+ vni=vni)
+ output = output[0]
+
+ if output["retval"] == 0:
+ return output["sw_if_index"]
+ else:
+ raise RuntimeError('Unable to create VXLAN interface on node {}'
+ .format(node))
diff --git a/resources/libraries/python/TGSetup.py b/resources/libraries/python/TGSetup.py
index 3e372e9464..05c8b1d177 100644
--- a/resources/libraries/python/TGSetup.py
+++ b/resources/libraries/python/TGSetup.py
@@ -14,7 +14,7 @@
"""TG Setup library."""
from topology import NodeType
-from InterfaceSetup import InterfaceSetup
+from InterfaceUtil import InterfaceUtil
class TGSetup(object):
@@ -29,4 +29,4 @@ class TGSetup(object):
"""
for node in nodes.values():
if node['type'] == NodeType.TG:
- InterfaceSetup.tg_set_interfaces_default_driver(node)
+ InterfaceUtil.tg_set_interfaces_default_driver(node)
diff --git a/resources/libraries/python/VatConfigGenerator.py b/resources/libraries/python/VatConfigGenerator.py
deleted file mode 100644
index 98be9d3448..0000000000
--- a/resources/libraries/python/VatConfigGenerator.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# 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.
-
-"""Can be used to generate VAT scripts from VAT template files."""
-
-from robot.api import logger
-
-
-class VatConfigGenerator(object):
- """Generates VAT configuration scripts from VAT script template files.
- """
- def __init__(self):
- pass
-
- @staticmethod
- def generate_vat_config_file(template_file, env_var_dict, out_file):
- """ Write VAT configuration script to out file.
-
- Generates VAT configuration script from template using
- dictionary containing environment variables
- :param template_file: file that contains the VAT script template
- :param env_var_dict: python dictionary that maps test
- environment variables
- """
-
- template_data = open(template_file).read()
- logger.trace("Loaded template file: \n '{0}'".format(template_data))
- generated_config = template_data.format(**env_var_dict)
- logger.trace("Generated script file: \n '{0}'".format(generated_config))
- with open(out_file, 'w') as work_file:
- work_file.write(generated_config)
-
- @staticmethod
- def generate_vat_config_string(template_file, env_var_dict):
- """ Return wat config string generated from template.
-
- Generates VAT configuration script from template using
- dictionary containing environment variables
- :param template_file: file that contains the VAT script template
- :param env_var_dict: python dictionary that maps test
- environment variables
- """
-
- template_data = open(template_file).read()
- logger.trace("Loaded template file: \n '{0}'".format(template_data))
- generated_config = template_data.format(**env_var_dict)
- logger.trace("Generated script file: \n '{0}'".format(generated_config))
- return generated_config
diff --git a/resources/libraries/python/VatJsonUtil.py b/resources/libraries/python/VatJsonUtil.py
new file mode 100644
index 0000000000..36c50533fc
--- /dev/null
+++ b/resources/libraries/python/VatJsonUtil.py
@@ -0,0 +1,102 @@
+# 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.
+
+"""Utilities to work with JSON data format from VAT."""
+
+from robot.api import logger
+
+from resources.libraries.python.parsers.JsonParser import JsonParser
+
+
+class VatJsonUtil(object):
+ """Utilities to work with JSON data format from VAT."""
+
+ @staticmethod
+ def _convert_mac_to_number_list(mac_address):
+ """Convert MAC address string to list of decimal numbers.
+
+ Converts a ":" separated MAC address to decimal number list as used
+ in JSON interface dump.
+
+ :param mac_address: MAC address.
+ :type mac_address: str
+ :return: List representation of MAC address.
+ :rtype: list
+ """
+ list_mac = []
+ for num in mac_address.split(":"):
+ list_mac.append(int(num, 16))
+ return list_mac
+
+ @staticmethod
+ def get_vpp_interface_by_mac(interfaces_list, mac_address):
+ """Return interface dictionary from interface_list by MAC address.
+
+ Extracts interface dictionary from all of the interfaces in interfaces
+ list parsed from json according to mac_address of the interface.
+
+ :param interfaces_list: Interfaces parsed from JSON.
+ :param mac_address: MAC address of interface we are looking for.
+ :type interfaces_list: dict
+ :type mac_address: str
+ :return: Interface from JSON.
+ :rtype: dict
+ """
+ interface_dict = {}
+ list_mac_address = VatJsonUtil._convert_mac_to_number_list(mac_address)
+ logger.trace("MAC address {0} converted to list {1}."
+ .format(mac_address, list_mac_address))
+ for interface in interfaces_list:
+ # TODO: create vat json integrity checking and move there
+ if "l2_address" not in interface:
+ raise KeyError(
+ "key l2_address not found in interface dict."
+ "Probably input list is not parsed from correct VAT "
+ "json output.")
+ if "l2_address_length" not in interface:
+ raise KeyError(
+ "key l2_address_length not found in interface "
+ "dict. Probably input list is not parsed from correct "
+ "VAT json output.")
+ mac_from_json = interface["l2_address"][:6]
+ if mac_from_json == list_mac_address:
+ if interface["l2_address_length"] != 6:
+ raise ValueError("l2_address_length value is not 6.")
+ interface_dict = interface
+ break
+ return interface_dict
+
+ @staticmethod
+ def update_vpp_interface_data_from_json(node, interface_dump_json):
+ """Update vpp node data in node__DICT from json interface dump.
+
+ This method updates vpp interface names and sw if indexes according to
+ interface MAC addresses found in interface_dump_json.
+
+ :param node: Node dictionary.
+ :param interface_dump_json: JSON output from dump_interface_list VAT
+ command.
+ :type node: dict
+ :type interface_dump_json: str
+ """
+ interface_list = JsonParser().parse_data(interface_dump_json)
+ for ifc in node['interfaces'].values():
+ if_mac = ifc['mac_address']
+ interface_dict = VatJsonUtil.get_vpp_interface_by_mac(
+ interface_list, if_mac)
+ if not interface_dict:
+ raise Exception('Interface {0} not found by MAC {1}'
+ .format(ifc, if_mac))
+ ifc['name'] = interface_dict["interface_name"]
+ ifc['vpp_sw_index'] = interface_dict["sw_if_index"]
+ ifc['mtu'] = interface_dict["mtu"]
diff --git a/resources/libraries/python/topology.py b/resources/libraries/python/topology.py
index 7a27173d40..d04d584623 100644
--- a/resources/libraries/python/topology.py
+++ b/resources/libraries/python/topology.py
@@ -13,10 +13,6 @@
"""Defines nodes and topology structure."""
-from resources.libraries.python.parsers.JsonParser import JsonParser
-from resources.libraries.python.VatExecutor import VatExecutor
-from resources.libraries.python.ssh import SSH
-from resources.libraries.python.InterfaceSetup import InterfaceSetup
from robot.api import logger
from robot.libraries.BuiltIn import BuiltIn
from robot.api.deco import keyword
@@ -137,8 +133,6 @@ class Topology(object):
This method returns the interface names asociated with given links
for a given node.
- The resulting dictionary can be then used to with VatConfigGenerator
- to generate a VAT script with proper interface names.
:param link_names: list of names of the link that a interface is
connected to.
:param node: the node topology directory
@@ -169,176 +163,6 @@ class Topology(object):
return self._get_interface_by_key_value(node, "vpp_sw_index", sw_index)
@staticmethod
- def convert_mac_to_number_list(mac_address):
- """Convert mac address string to list of decimal numbers.
-
- Converts a : separated mac address to decimal number list as used
- in json interface dump.
- :param mac_address: string mac address
- :return: list representation of mac address
- """
-
- list_mac = []
- for num in mac_address.split(":"):
- list_mac.append(int(num, 16))
- return list_mac
-
- def _extract_vpp_interface_by_mac(self, interfaces_list, mac_address):
- """Return interface dictionary from interface_list by mac address.
-
- Extracts interface dictionary from all of the interfaces in interfaces
- list parsed from json according to mac_address of the interface
- :param interfaces_list: dictionary of all interfaces parsed from json
- :param mac_address: string mac address of interface we are looking for
- :return: interface dictionary from json
- """
-
- interface_dict = {}
- list_mac_address = self.convert_mac_to_number_list(mac_address)
- logger.trace(str(list_mac_address))
- for interface in interfaces_list:
- # TODO: create vat json integrity checking and move there
- if "l2_address" not in interface:
- raise KeyError(
- "key l2_address not found in interface dict."
- "Probably input list is not parsed from correct VAT "
- "json output.")
- if "l2_address_length" not in interface:
- raise KeyError(
- "key l2_address_length not found in interface "
- "dict. Probably input list is not parsed from correct "
- "VAT json output.")
- mac_from_json = interface["l2_address"][:6]
- if mac_from_json == list_mac_address:
- if interface["l2_address_length"] != 6:
- raise ValueError("l2_address_length value is not 6.")
- interface_dict = interface
- break
- return interface_dict
-
- def vpp_interface_name_from_json_by_mac(self, json_data, mac_address):
- """Return vpp interface name string from VAT interface dump json output
-
- Extracts the name given to an interface by VPP.
- These interface names differ from what you would see if you
- used the ipconfig or similar command.
- Required json data can be obtained by calling :
- VatExecutor.execute_script_json_out("dump_interfaces.vat", node)
- :param json_data: string json data from sw_interface_dump VAT command
- :param mac_address: string containing mac address of interface
- whose vpp name we wish to discover.
- :return: string vpp interface name
- """
-
- interfaces_list = JsonParser().parse_data(json_data)
- # TODO: checking if json data is parsed correctly
- interface_dict = self._extract_vpp_interface_by_mac(interfaces_list,
- mac_address)
- interface_name = interface_dict["interface_name"]
- return interface_name
-
- def _update_node_interface_data_from_json(self, node, interface_dump_json):
- """Update node vpp data in node__DICT from json interface dump.
-
- This method updates vpp interface names and sw indexexs according to
- interface mac addresses found in interface_dump_json
- :param node: node dictionary
- :param interface_dump_json: json output from dump_interface_list VAT
- command
- """
-
- interface_list = JsonParser().parse_data(interface_dump_json)
- for ifc in node['interfaces'].values():
- if 'link' not in ifc:
- continue
- if_mac = ifc['mac_address']
- interface_dict = self._extract_vpp_interface_by_mac(interface_list,
- if_mac)
- if not interface_dict:
- raise Exception('Interface {0} not found by MAC {1}'.
- format(ifc, if_mac))
- ifc['name'] = interface_dict["interface_name"]
- ifc['vpp_sw_index'] = interface_dict["sw_if_index"]
- ifc['mtu'] = interface_dict["mtu"]
-
- def update_vpp_interface_data_on_node(self, node):
- """Update vpp generated interface data for a given node in DICT__nodes
-
- Updates interface names, software index numbers and any other details
- generated specifically by vpp that are unknown before testcase run.
- :param node: Node selected from DICT__nodes
- """
-
- vat_executor = VatExecutor()
- vat_executor.execute_script_json_out("dump_interfaces.vat", node)
- interface_dump_json = vat_executor.get_script_stdout()
- self._update_node_interface_data_from_json(node,
- interface_dump_json)
-
- @staticmethod
- def update_tg_interface_data_on_node(node):
- """Update interface name for TG/linux node in DICT__nodes
-
- :param node: Node selected from DICT__nodes.
- :type node: dict
-
- .. note::
- # for dev in `ls /sys/class/net/`;
- > do echo "\"`cat /sys/class/net/$dev/address`\": \"$dev\""; done
- "52:54:00:9f:82:63": "eth0"
- "52:54:00:77:ae:a9": "eth1"
- "52:54:00:e1:8a:0f": "eth2"
- "00:00:00:00:00:00": "lo"
-
- .. todo:: parse lshw -json instead
- """
- # First setup interface driver specified in yaml file
- InterfaceSetup.tg_set_interfaces_default_driver(node)
-
- # Get interface names
- ssh = SSH()
- ssh.connect(node)
-
- cmd = 'for dev in `ls /sys/class/net/`; do echo "\\"`cat ' \
- '/sys/class/net/$dev/address`\\": \\"$dev\\""; done;'
-
- (ret_code, stdout, _) = ssh.exec_command(cmd)
- if int(ret_code) != 0:
- raise Exception('Get interface name and MAC failed')
- tmp = "{" + stdout.rstrip().replace('\n', ',') + "}"
- interfaces = JsonParser().parse_data(tmp)
- for if_k, if_v in node['interfaces'].items():
- if if_k == 'mgmt':
- continue
- name = interfaces.get(if_v['mac_address'])
- if name is None:
- continue
- if_v['name'] = name
-
- # Set udev rules for interfaces
- InterfaceSetup.tg_set_interfaces_udev_rules(node)
-
- def update_all_interface_data_on_all_nodes(self, nodes):
- """Update interface names on all nodes in DICT__nodes
-
- :param nodes: Nodes in the topology.
- :type nodes: dict
-
- This method updates the topology dictionary by querying interface lists
- of all nodes mentioned in the topology dictionary.
- It does this by dumping interface list to json output from all devices
- using vpp_api_test, and pairing known information from topology
- (mac address/pci address of interface) to state from VPP.
- For TG/linux nodes add interface name only.
- """
-
- for node_data in nodes.values():
- if node_data['type'] == NodeType.DUT:
- self.update_vpp_interface_data_on_node(node_data)
- elif node_data['type'] == NodeType.TG:
- self.update_tg_interface_data_on_node(node_data)
-
- @staticmethod
def get_interface_sw_index(node, interface):
"""Get VPP sw_index for the interface.
diff --git a/resources/libraries/robot/default.robot b/resources/libraries/robot/default.robot
index d085825a04..dae515423b 100644
--- a/resources/libraries/robot/default.robot
+++ b/resources/libraries/robot/default.robot
@@ -13,8 +13,9 @@
*** Settings ***
| Variables | resources/libraries/python/topology.py
-| Library | resources/libraries/python/DUTSetup.py
-| Library | resources/libraries/python/TGSetup.py
+| Library | resources.libraries.python.topology.Topology
+| Library | resources.libraries.python.DUTSetup
+| Library | resources.libraries.python.TGSetup
| Library | Collections
*** Keywords ***
diff --git a/resources/libraries/robot/vxlan.robot b/resources/libraries/robot/vxlan.robot
index e855f2499d..1f3b141470 100644
--- a/resources/libraries/robot/vxlan.robot
+++ b/resources/libraries/robot/vxlan.robot
@@ -14,15 +14,13 @@
*** Settings ***
| Library | Collections
| Resource | resources/libraries/robot/default.robot
+| Resource | resources/libraries/robot/interfaces.robot
| Resource | resources/libraries/robot/bridge_domain.robot
| Resource | resources/libraries/robot/l2_xconnect.robot
| Library | resources.libraries.python.L2Util
| Library | resources.libraries.python.IPUtil
| Library | resources.libraries.python.IPv4Util
| Library | resources.libraries.python.IPv4Setup
-| Library | resources.libraries.python.InterfaceSetup
-| Library | resources.libraries.python.InterfaceUtil
-| Library | resources.libraries.python.topology.Topology
| Library | resources.libraries.python.NodePath