The keywords make possible to put and get configuration data and to get
operational data.
"""
+from robot.api import logger
+
from resources.libraries.python.topology import Topology
from resources.libraries.python.HTTPRequest import HTTPCodes
from resources.libraries.python.honeycomb.HoneycombSetup import HoneycombError
import HoneycombUtil as HcUtil
-# pylint: disable=too-many-public-methods
-# pylint: disable=too-many-lines
class InterfaceKeywords(object):
"""Keywords for Interface manipulation.
:type interface: str
:type data: dict
:type data_representation: DataRepresentation
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the status code in response on PUT is not
200 = OK.
:param node: Honeycomb node.
:type node: dict
- :return: Configuration data about all interfaces from Honeycomb.
+ :returns: Configuration data about all interfaces from Honeycomb.
:rtype: list
:raises HoneycombError: If it is not possible to get configuration data.
"""
:param interface: The name of interface.
:type node: dict
:type interface: str
- :return: Configuration data about the given interface from Honeycomb.
+ :returns: Configuration data about the given interface from Honeycomb.
:rtype: dict
"""
:param node: Honeycomb node.
:type node: dict
- :return: Operational data about all interfaces from Honeycomb.
+ :returns: Operational data about all interfaces from Honeycomb.
:rtype: list
:raises HoneycombError: If it is not possible to get operational data.
"""
except (KeyError, TypeError):
return []
+ @staticmethod
+ def get_disabled_interfaces_oper_data(node):
+ """Get operational data about all disabled interfaces from Honeycomb.
+
+ :param node: Honeycomb node.
+ :type node: dict
+ :returns: Operational data about disabled interfaces.
+ :rtype: list
+ :raises HoneycombError: If it is not possible to get operational data.
+ """
+
+ status_code, resp = HcUtil. \
+ get_honeycomb_data(node, "oper_disabled_interfaces")
+ if status_code == HTTPCodes.NOT_FOUND:
+ raise HoneycombError(
+ "No disabled interfaces present on node."
+ )
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError(
+ "Not possible to get operational information about the "
+ "interfaces. Status code: {0}.".format(status_code))
+ try:
+ return resp["disabled-interfaces"]["disabled-interface-index"]
+
+ except (KeyError, TypeError):
+ return []
+
@staticmethod
def get_interface_oper_data(node, interface):
"""Get operational data about the given interface from Honeycomb.
:param interface: The name of interface.
:type node: dict
:type interface: str
- :return: Operational data about the given interface from Honeycomb.
+ :returns: Operational data about the given interface from Honeycomb.
:rtype: dict
"""
:type interface: str
:type path: tuple
:type new_value: str, dict or list
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If it is not possible to get or set the data.
"""
:type node: dict
:type interface: str
:type state: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises KeyError: If the argument "state" is nor "up" or "down".
:raises HoneycombError: If the interface is not present on the node.
:param interface: The name of interface.
:type node: dict
:type interface: str
- :return: Content of response
+ :returns: Content of response
:rtype: bytearray
"""
:param interface: The name of interface.
:type node: dict
:type interface: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
:type bd_name: str
:type split_horizon_group: str
:type bvi: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the interface is not present on the node.
"""
path = "/interface/{0}/v3po:l2".format(intf)
- status_code, _ = HcUtil.delete_honeycomb_data(
+ status_code, response = HcUtil.delete_honeycomb_data(
node, "config_vpp_interfaces", path)
if status_code != HTTPCodes.OK:
- raise HoneycombError(
- "Could not remove bridge domain assignment from interface "
- "'{0}'. Status code: {1}.".format(interface, status_code))
+ if '"error-tag":"data-missing"' in response:
+ logger.debug("Data does not exist in path.")
+ else:
+ raise HoneycombError(
+ "Could not remove bridge domain assignment from interface "
+ "'{0}'. Status code: {1}.".format(interface, status_code))
@staticmethod
def get_bd_oper_data_from_interface(node, interface):
:param interface: The name of interface.
:type node: dict
:type interface: str
- :return: Operational data about bridge domain settings in the
+ :returns: Operational data about bridge domain settings in the
interface.
:rtype: dict
"""
:type interface: str
:type param: str
:type value: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the parameter is not valid.
"""
:type interface: str
:type param: str
:type value: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the parameter is not valid.
"""
:type interface: str
:type ip_addr: str
:type network: str or int
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the provided netmask or prefix is not valid.
"""
:type interface: str
:type ip_addr: str
:type network: str or int
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the provided netmask or prefix is not valid.
"""
:param interface: The name of interface.
:type node: dict
:type interface: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
:type interface: str
:type ip_addr: str
:type link_layer_address: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
:param interface: The name of interface.
:type node: dict
:type interface: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
:type interface: str
:type param: str
:type value: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the parameter is not valid.
"""
:type interface: str
:type ip_addr: str
:type prefix_len: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
:type interface: str
:type ip_addr: str
:type prefix_len: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
:param interface: The name of interface.
:type node: dict
:type interface: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
:type interface: str
:type ip_addr: str
:type link_layer_address: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
:param interface: The name of interface.
:type node: dict
:type interface: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
:type interface: str
:type param: str
:type value: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the parameter is not valid.
"""
:type interface: str
:type param: str
:type value: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the parameter is not valid.
"""
:type node: dict
:type interface: str
:type kwargs: dict
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the parameter is not valid.
"""
:param interface: The name of interface.
:type node: dict
:type interface: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If it is not possible to get information about
interfaces or it is not possible to delete the interface.
:type node: dict
:type interface: str
:type kwargs: dict
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the parameter is not valid.
"""
:type interface: str
:type param: str
:type value: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the parameter is not valid.
"""
:type node: dict
:type interface: str
:type kwargs: dict
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the parameter is not valid.
"""
:type node: dict
:type interface: str
:type kwargs: dict
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the parameter is not valid.
"""
:type node: dict
:type interface: str
:type kwargs: dict
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the parameter is not valid.
"""
:type node: dict
:type interface: str
:type kwargs: dict
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the parameter is not valid.
"""
:type match: str
:type tags: list
:type kwargs: dict
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the parameter is not valid.
:raises KeyError: If the parameter 'match' is invalid.
:type node: dict
:type super_interface: str
:type identifier: int
- :return: Sub-interface operational data.
+ :returns: Sub-interface operational data.
:rtype: dict
:raises HoneycombError: If there is no sub-interface with the given ID.
"""
:param super_interface: Super interface.
:type node: dict
:type super_interface: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
:type super_interface: str
:type identifier: int
:type state: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
:type super_interface: str
:type identifier: int
:type config: dict
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
:type node: dict
:type super_interface: str
:type identifier: int
- :return: Operational data about the bridge domain.
+ :returns: Operational data about the bridge domain.
:rtype: dict
:raises HoneycombError: If there is no sub-interface with the given ID.
"""
:type super_interface: str
:type identifier: int
:type config: dict
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
:type node: dict
:type super_interface: str
:type identifier: int
- :return: Operational data about tag rewrite.
+ :returns: Operational data about tag rewrite.
:rtype: dict
:raises HoneycombError: If there is no sub-interface with the given ID.
"""
:type identifier: int
:type ip_addr: str
:type network: str or int
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the provided netmask or prefix is not valid.
"""
node, super_interface, path, address)
@staticmethod
- def remove_all_ipv4_addresses_from_sub_interface(node, super_interface, # pylint: disable=invalid-name
+ def remove_all_ipv4_addresses_from_sub_interface(node, super_interface,
identifier):
"""Remove all ipv4 addresses from the specified sub-interface.
:type node: dict
:type super_interface: str
:type identifier: int
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
"""
node, super_interface, path, None)
@staticmethod
- def compare_data_structures(data, ref, ignore=()):
- """Checks if data obtained from UUT is as expected.
+ def compare_data_structures(data, ref, _path=''):
+ """Checks if data obtained from UUT is as expected. If it is not,
+ proceeds down the list/dictionary tree and finds the point of mismatch.
:param data: Data to be checked.
:param ref: Referential data used for comparison.
- :param ignore: Dictionary keys to be ignored.
+ :param _path: Used in recursive calls, stores the path taken down
+ the JSON tree.
:type data: dict
:type ref: dict
- :type ignore: iterable
- :raises HoneycombError: If a parameter from referential data is not
- present in operational data or if it has different value.
- """
+ :type _path: str
- errors = ""
+ :raises HoneycombError: If the data structures do not match in some way,
+ or if they are not in deserialized JSON format.
+ """
- for key, item in ref.items():
- if key in ignore:
- continue
- try:
- if data[key] != item:
- errors += ("\nThe value of parameter '{0}' is "
- "incorrect. It should be "
- "'{1}' but it is '{2}'".
- format(key, item, data[key]))
- except KeyError:
- errors += ("\nThe parameter '{0}' is not present in "
- "operational data".format(key))
+ if data == ref:
+ return True
+
+ elif isinstance(data, dict) and isinstance(ref, dict):
+ for key in ref:
+ if key not in data:
+ raise HoneycombError(
+ "Key {key} is not present in path {path}. Keys in path:"
+ "{data_keys}".format(
+ key=key,
+ path=_path,
+ data_keys=data.keys()))
+
+ if data[key] != ref[key]:
+ if isinstance(data[key], list) \
+ or isinstance(data[key], dict):
+ InterfaceKeywords.compare_data_structures(
+ data[key], ref[key],
+ _path + '[{0}]'.format(key))
+ else:
+ raise HoneycombError(
+ "Data mismatch, key {key} in path {path} has value"
+ " {data}, but should be {ref}".format(
+ key=key,
+ path=_path,
+ data=data[key],
+ ref=ref[key]))
+
+ elif isinstance(data, list) and isinstance(ref, list):
+ for item in ref:
+ if item not in data:
+ if isinstance(item, dict):
+ InterfaceKeywords.compare_data_structures(
+ data[0], item,
+ _path + '[{0}]'.format(ref.index(item)))
+ else:
+ raise HoneycombError(
+ "Data mismatch, list item {index} in path {path}"
+ " has value {data}, but should be {ref}".format(
+ index=ref.index(item),
+ path=_path,
+ data=data[0],
+ ref=item))
- if errors:
- raise HoneycombError(errors)
+ else:
+ raise HoneycombError(
+ "Unexpected data type {data_type}, reference type is"
+ " {ref_type}. Must be list or dictionary.".format(
+ data_type=type(data),
+ ref_type=type(ref)))
@staticmethod
def compare_interface_lists(list1, list2):
:type node: dict
:type interface: str
:type kwargs: dict
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If a parameter in kwargs is not valid.
"""
:type node: dict
:type interface: str
:type table_name: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the configuration of interface is not
successful.
data = {
"v3po:acl": {
- "l2-acl": {
- "classify-table": table_name
- },
- "ip4-acl": {
- "classify-table": table_name
+ "ingress": {
+ "ip4-acl": {
+ "classify-table": table_name
+ },
+ "l2-acl": {
+ "classify-table": table_name
+ }
}
}
}
:param interface: The interface where the ACL will be disabled.
:type node: dict
:type interface: str
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the configuration of interface is not
successful.
return resp
@staticmethod
- def create_pbb_sub_interface(node, intf, sub_if_id, params):
+ def create_pbb_sub_interface(node, intf, params):
"""Creates a PBB sub-interface on the given interface and sets its
parameters.
:param node: Honeycomb node.
:param intf: The interface where PBB sub-interface will be configured.
- :param sub_if_id: Sub-interface ID.
:param params: Configuration parameters of the sub-interface to be
created.
:type node: dict
:type intf: str
- :type sub_if_id: str or int
:type params: dict
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the configuration of sub-interface is not
successful.
"""
interface = intf.replace("/", "%2F")
- path = "/interface/{0}/sub-interfaces:sub-interfaces/sub-interface/" \
- "{1}".format(interface, sub_if_id)
+ path = "/interface/{0}/pbb-rewrite/".format(interface)
status_code, resp = HcUtil. \
put_honeycomb_data(node, "config_vpp_interfaces", params, path,
data_representation=DataRepresentation.JSON)
return resp
@staticmethod
- def delete_pbb_sub_interface(node, intf, sub_if_id):
+ def delete_pbb_sub_interface(node, intf):
"""Deletes the given PBB sub-interface.
:param node: Honeycomb node.
:param intf: The interface where PBB sub-interface will be deleted.
- :param sub_if_id: ID of the PBB sub-interface to be deleted.
:type node: dict
:type intf: str
- :type sub_if_id: str or int
- :return: Content of response.
+ :returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the removal of sub-interface is not
successful.
"""
interface = intf.replace("/", "%2F")
- path = "/interface/{0}/sub-interfaces:sub-interfaces/sub-interface/" \
- "{1}".format(interface, sub_if_id)
+ path = "/interface/{0}/pbb-rewrite".format(interface)
status_code, resp = HcUtil. \
delete_honeycomb_data(node, "config_vpp_interfaces", path)
:type node: dict
:type intf: str
:type sub_if_id: str or int
- :return: PBB sub-interface operational data.
+ :returns: PBB sub-interface operational data.
:rtype: dict
:raises HoneycombError: If the removal of sub-interface is not
successful.
"""
- interface = "{0}.{1}".format(intf, sub_if_id)
- return InterfaceKeywords.get_interface_oper_data(node, interface)
+ raise NotImplementedError
+
+ @staticmethod
+ def check_disabled_interface(node, interface):
+ """Retrieves list of disabled interface indices from Honeycomb,
+ and matches with the provided interface by index.
+
+ :param node: Honeycomb node.
+ :param interface: Index number of an interface on the node.
+ :type node: dict
+ :type interface: int
+ :returns: True if the interface exists in disabled interfaces.
+ :rtype: bool
+ :raises HoneycombError: If the interface is not present
+ in retrieved list of disabled interfaces.
+ """
+ data = InterfaceKeywords.get_disabled_interfaces_oper_data(node)
+ # decrement by one = conversion from HC if-index to VPP sw_if_index
+ interface -= 1
+
+ for item in data:
+ if item["index"] == interface:
+ return True
+ raise HoneycombError("Interface index {0} not present in list"
+ " of disabled interfaces.".format(interface))
+
+ @staticmethod
+ def configure_interface_span(node, dst_interface, *src_interfaces):
+ """Configure SPAN port mirroring on the specified interfaces. If no
+ source interface is provided, SPAN will be disabled.
+
+ :param node: Honeycomb node.
+ :param dst_interface: Interface to mirror packets to.
+ :param src_interfaces: List of interfaces to mirror packets from.
+ :type node: dict
+ :type dst_interface: str
+ :type src_interfaces: list of str
+ :returns: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If SPAN could not be configured.
+ """
+
+ interface = dst_interface.replace("/", "%2F")
+ path = "/interface/" + interface + "/span"
+
+ if not src_interfaces:
+ status_code, _ = HcUtil.delete_honeycomb_data(
+ node, "config_vpp_interfaces", path)
+
+ data = {
+ "span": {
+ "mirrored-interfaces": {
+ "mirrored-interface": src_interfaces
+ }
+ }
+ }
+
+ status_code, _ = HcUtil.put_honeycomb_data(
+ node, "config_vpp_interfaces", data, path)
+
+ if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
+ raise HoneycombError(
+ "Configuring SPAN failed. Status code:{0}".format(status_code))
+
+ @staticmethod
+ def add_interface_local0_to_topology(node):
+ """Use Topology methods to add interface "local0" to working topology,
+ if not already present.
+
+ :param node: DUT node.
+ :type node: dict
+ """
+
+ if Topology.get_interface_by_sw_index(node, 0) is None:
+ local0_key = Topology.add_new_port(node, "localzero")
+ Topology.update_interface_sw_if_index(node, local0_key, 0)
+ Topology.update_interface_name(node, local0_key, "local0")