X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2Fhoneycomb%2FHcAPIKwInterfaces.py;h=5658eea1463cbc52449315a6f726e6febd5451d3;hp=83267b5e55166234881e1c02d0b302c33d34eb0a;hb=cf561a6e3d4c4fbd78ab6c9d0a9aa817bb3300fc;hpb=233683de57527f477bf7e8d042a5f3d1f08c7744 diff --git a/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py b/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py index 83267b5e55..5658eea146 100644 --- a/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py +++ b/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py @@ -16,6 +16,8 @@ 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 @@ -25,8 +27,6 @@ from resources.libraries.python.honeycomb.HoneycombUtil \ import HoneycombUtil as HcUtil -# pylint: disable=too-many-public-methods -# pylint: disable=too-many-lines class InterfaceKeywords(object): """Keywords for Interface manipulation. @@ -83,7 +83,7 @@ class InterfaceKeywords(object): :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. @@ -92,7 +92,7 @@ class InterfaceKeywords(object): status_code, resp = HcUtil.\ put_honeycomb_data(node, "config_vpp_interfaces", data, data_representation=data_representation) - if status_code != HTTPCodes.OK: + if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED): raise HoneycombError( "The configuration of interface '{0}' was not successful. " "Status code: {1}.".format(interface, status_code)) @@ -104,7 +104,7 @@ class InterfaceKeywords(object): :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. """ @@ -129,7 +129,7 @@ class InterfaceKeywords(object): :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 """ @@ -145,7 +145,7 @@ class InterfaceKeywords(object): :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. """ @@ -162,6 +162,33 @@ class InterfaceKeywords(object): 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. @@ -170,7 +197,7 @@ class InterfaceKeywords(object): :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 """ @@ -196,7 +223,7 @@ class InterfaceKeywords(object): :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. """ @@ -228,7 +255,7 @@ class InterfaceKeywords(object): :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. @@ -255,7 +282,7 @@ class InterfaceKeywords(object): status_code, resp = HcUtil. \ put_honeycomb_data(node, "config_vpp_interfaces", resp, path, data_representation=DataRepresentation.JSON) - if status_code != HTTPCodes.OK: + if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED): raise HoneycombError( "The configuration of interface '{0}' was not successful. " "Status code: {1}.".format(interface, status_code)) @@ -269,7 +296,7 @@ class InterfaceKeywords(object): :param interface: The name of interface. :type node: dict :type interface: str - :return: Content of response + :returns: Content of response :rtype: bytearray """ @@ -283,7 +310,7 @@ class InterfaceKeywords(object): :param interface: The name of interface. :type node: dict :type interface: str - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -304,7 +331,7 @@ class InterfaceKeywords(object): :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. """ @@ -342,13 +369,16 @@ class InterfaceKeywords(object): 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): @@ -359,7 +389,7 @@ class InterfaceKeywords(object): :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 """ @@ -386,7 +416,7 @@ class InterfaceKeywords(object): :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. """ @@ -411,7 +441,7 @@ class InterfaceKeywords(object): :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. """ @@ -441,7 +471,7 @@ class InterfaceKeywords(object): :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. """ @@ -472,7 +502,7 @@ class InterfaceKeywords(object): :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. """ @@ -500,7 +530,7 @@ class InterfaceKeywords(object): :param interface: The name of interface. :type node: dict :type interface: str - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -521,7 +551,7 @@ class InterfaceKeywords(object): :type interface: str :type ip_addr: str :type link_layer_address: str - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -539,7 +569,7 @@ class InterfaceKeywords(object): :param interface: The name of interface. :type node: dict :type interface: str - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -561,7 +591,7 @@ class InterfaceKeywords(object): :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. """ @@ -592,7 +622,7 @@ class InterfaceKeywords(object): :type interface: str :type ip_addr: str :type prefix_len: str - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -613,7 +643,7 @@ class InterfaceKeywords(object): :type interface: str :type ip_addr: str :type prefix_len: str - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -631,7 +661,7 @@ class InterfaceKeywords(object): :param interface: The name of interface. :type node: dict :type interface: str - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -652,7 +682,7 @@ class InterfaceKeywords(object): :type interface: str :type ip_addr: str :type link_layer_address: str - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -670,7 +700,7 @@ class InterfaceKeywords(object): :param interface: The name of interface. :type node: dict :type interface: str - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -692,7 +722,7 @@ class InterfaceKeywords(object): :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. """ @@ -717,7 +747,7 @@ class InterfaceKeywords(object): :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. """ @@ -741,7 +771,7 @@ class InterfaceKeywords(object): :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. """ @@ -770,7 +800,7 @@ class InterfaceKeywords(object): :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. @@ -812,7 +842,7 @@ class InterfaceKeywords(object): :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. """ @@ -841,7 +871,7 @@ class InterfaceKeywords(object): :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. """ @@ -864,7 +894,7 @@ class InterfaceKeywords(object): :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. """ @@ -903,7 +933,7 @@ class InterfaceKeywords(object): :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. """ @@ -937,7 +967,7 @@ class InterfaceKeywords(object): :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. """ @@ -965,7 +995,7 @@ class InterfaceKeywords(object): :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. """ @@ -1002,7 +1032,7 @@ class InterfaceKeywords(object): :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. @@ -1058,7 +1088,7 @@ class InterfaceKeywords(object): :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. """ @@ -1080,7 +1110,7 @@ class InterfaceKeywords(object): :param super_interface: Super interface. :type node: dict :type super_interface: str - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -1103,7 +1133,7 @@ class InterfaceKeywords(object): :type super_interface: str :type identifier: int :type state: str - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -1132,7 +1162,7 @@ class InterfaceKeywords(object): :type super_interface: str :type identifier: int :type config: dict - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -1155,7 +1185,7 @@ class InterfaceKeywords(object): :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. """ @@ -1180,7 +1210,7 @@ class InterfaceKeywords(object): :type super_interface: str :type identifier: int :type config: dict - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -1204,7 +1234,7 @@ class InterfaceKeywords(object): :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. """ @@ -1234,7 +1264,7 @@ class InterfaceKeywords(object): :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. """ @@ -1259,7 +1289,7 @@ class InterfaceKeywords(object): 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. @@ -1269,7 +1299,7 @@ class InterfaceKeywords(object): :type node: dict :type super_interface: str :type identifier: int - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -1283,15 +1313,19 @@ class InterfaceKeywords(object): node, super_interface, path, None) @staticmethod - def compare_data_structures(data, ref, ignore=()): + def compare_data_structures(data, ref, ignore=(), list_order=True): """Checks if data obtained from UUT is as expected. :param data: Data to be checked. :param ref: Referential data used for comparison. :param ignore: Dictionary keys to be ignored. + :param list_order: Whether to consider the order of list items\ + in comparison. :type data: dict :type ref: dict :type ignore: iterable + :type list_order: bool + :raises HoneycombError: If a parameter from referential data is not present in operational data or if it has different value. """ @@ -1303,10 +1337,13 @@ class InterfaceKeywords(object): 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])) + if not list_order and sorted(data[key]) == sorted(item): + pass + else: + 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)) @@ -1351,7 +1388,7 @@ class InterfaceKeywords(object): :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. """ @@ -1384,7 +1421,7 @@ class InterfaceKeywords(object): :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. @@ -1394,11 +1431,13 @@ class InterfaceKeywords(object): 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 + } } } } @@ -1407,7 +1446,7 @@ class InterfaceKeywords(object): status_code, resp = HcUtil.\ put_honeycomb_data(node, "config_vpp_interfaces", data, path, data_representation=DataRepresentation.JSON) - if status_code != HTTPCodes.OK: + if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED): raise HoneycombError( "The configuration of interface '{0}' was not successful. " "Status code: {1}.".format(interface, status_code)) @@ -1421,7 +1460,7 @@ class InterfaceKeywords(object): :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. @@ -1441,56 +1480,50 @@ class InterfaceKeywords(object): 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) - if status_code != HTTPCodes.OK: + if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED): raise HoneycombError( "The configuration of PBB sub-interface '{0}' was not " "successful. Status code: {1}.".format(intf, status_code)) 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) @@ -1510,11 +1543,86 @@ class InterfaceKeywords(object): :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")