X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2Fhoneycomb%2FHcAPIKwInterfaces.py;h=3271413d1c856284cd90c2678d41407ad7f2bfce;hb=fa74b0cda008687827c255c1f2a51c5c44300870;hp=4feb22e90ade2ac526704ce2e0676e9b0d1ce9bb;hpb=d5e00c67d229e6f6fd9461755423cee800a1635e;p=csit.git diff --git a/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py b/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py index 4feb22e90a..3271413d1c 100644 --- a/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py +++ b/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py @@ -16,7 +16,9 @@ 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 from resources.libraries.python.honeycomb.HoneycombUtil \ @@ -83,7 +85,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 +94,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 +106,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 +131,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 +147,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 +164,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 +199,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 +225,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. """ @@ -222,13 +251,13 @@ class InterfaceKeywords(object): depending on the parameter "state". :param node: Honeycomb node. - :param interface: The name of interface. + :param interface: Interface name, key, link name or sw_if_index. :param state: The requested state, only "up" and "down" are valid values. :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. @@ -237,9 +266,29 @@ class InterfaceKeywords(object): intf_state = {"up": "true", "down": "false"} - path = ("interfaces", ("interface", "name", str(interface)), "enabled") - return InterfaceKeywords._set_interface_properties( - node, interface, path, intf_state[state.lower()]) + interface = Topology.convert_interface_reference( + node, interface, "name") + + intf = interface.replace("/", "%2F") + path = "/interface/{0}".format(intf) + + status_code, resp = HcUtil.\ + get_honeycomb_data(node, "config_vpp_interfaces", path) + if status_code != HTTPCodes.OK: + raise HoneycombError( + "Not possible to get configuration information about the " + "interfaces. Status code: {0}.".format(status_code)) + + resp["interface"][0]["enabled"] = intf_state[state.lower()] + + status_code, resp = HcUtil. \ + put_honeycomb_data(node, "config_vpp_interfaces", resp, path, + data_representation=DataRepresentation.JSON) + 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)) + return resp @staticmethod def set_interface_up(node, interface): @@ -249,7 +298,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 """ @@ -263,7 +312,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 """ @@ -275,7 +324,7 @@ class InterfaceKeywords(object): """Add a new bridge domain to an interface and set its parameters. :param node: Honeycomb node. - :param interface: The name of interface. + :param interface: Interface name, key, link name or sw_if_index. :param bd_name: Bridge domain name. :param split_horizon_group: Split-horizon group name. :param bvi: The bridged virtual interface. @@ -284,11 +333,14 @@ 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. """ + interface = Topology.convert_interface_reference( + node, interface, "name") + v3po_l2 = {"bridge-domain": str(bd_name)} if split_horizon_group: v3po_l2["split-horizon-group"] = str(split_horizon_group) @@ -300,6 +352,36 @@ class InterfaceKeywords(object): return InterfaceKeywords._set_interface_properties( node, interface, path, v3po_l2) + @staticmethod + def remove_bridge_domain_from_interface(node, interface): + """Remove bridge domain assignment from interface. + + :param node: Honeycomb node. + :param interface: Interface name, key, link name or sw_if_index. + :type node: dict + :type interface: str or int + + :raises HoneycombError: If the operation fails. + """ + + interface = Topology.convert_interface_reference( + node, interface, "name") + + intf = interface.replace("/", "%2F") + + path = "/interface/{0}/v3po:l2".format(intf) + + status_code, response = HcUtil.delete_honeycomb_data( + node, "config_vpp_interfaces", path) + + if status_code != HTTPCodes.OK: + 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): """Returns operational data about bridge domain settings in the @@ -307,9 +389,9 @@ class InterfaceKeywords(object): :param node: Honeycomb node. :param interface: The name of interface. - :type interface: str :type node: dict - :return: Operational data about bridge domain settings in the + :type interface: str + :returns: Operational data about bridge domain settings in the interface. :rtype: dict """ @@ -336,7 +418,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. """ @@ -350,7 +432,7 @@ class InterfaceKeywords(object): @staticmethod def configure_interface_ipv4(node, interface, param, value): - """Configure IPv4 parameters of interface + """Configure IPv4 parameters of interface. :param node: Honeycomb node. :param interface: The name of interface. @@ -361,11 +443,14 @@ 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. """ + interface = Topology.convert_interface_reference( + node, interface, "name") + if param not in InterfaceKeywords.IPV4_PARAMS: raise HoneycombError("The parameter {0} is invalid.".format(param)) @@ -388,11 +473,14 @@ 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. """ + interface = Topology.convert_interface_reference( + node, interface, "name") + path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4") if isinstance(network, basestring): address = {"address": [{"ip": ip_addr, "netmask": network}, ]} @@ -416,11 +504,14 @@ 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. """ + interface = Topology.convert_interface_reference( + node, interface, "name") + path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4", "address") if isinstance(network, basestring): @@ -441,7 +532,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 """ @@ -462,7 +553,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 """ @@ -480,7 +571,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 """ @@ -502,7 +593,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. """ @@ -533,7 +624,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 """ @@ -554,7 +645,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 """ @@ -572,7 +663,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 """ @@ -593,7 +684,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 """ @@ -611,7 +702,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 """ @@ -633,7 +724,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. """ @@ -658,7 +749,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. """ @@ -682,7 +773,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. """ @@ -711,7 +802,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. @@ -753,7 +844,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. """ @@ -782,7 +873,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. """ @@ -805,7 +896,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. """ @@ -844,7 +935,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. """ @@ -878,7 +969,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. """ @@ -906,7 +997,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. """ @@ -943,7 +1034,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. @@ -999,7 +1090,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. """ @@ -1021,7 +1112,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 """ @@ -1044,7 +1135,7 @@ class InterfaceKeywords(object): :type super_interface: str :type identifier: int :type state: str - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -1073,7 +1164,7 @@ class InterfaceKeywords(object): :type super_interface: str :type identifier: int :type config: dict - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -1096,7 +1187,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. """ @@ -1121,7 +1212,7 @@ class InterfaceKeywords(object): :type super_interface: str :type identifier: int :type config: dict - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -1145,7 +1236,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. """ @@ -1175,7 +1266,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. """ @@ -1200,7 +1291,7 @@ class InterfaceKeywords(object): node, super_interface, path, address) @staticmethod - def remove_all_ipv4_addresses_from_sub_interface(node, super_interface, + def remove_all_ipv4_addresses_from_sub_interface(node, super_interface, # pylint: disable=invalid-name identifier): """Remove all ipv4 addresses from the specified sub-interface. @@ -1210,7 +1301,7 @@ class InterfaceKeywords(object): :type node: dict :type super_interface: str :type identifier: int - :return: Content of response. + :returns: Content of response. :rtype: bytearray """ @@ -1224,27 +1315,43 @@ class InterfaceKeywords(object): node, super_interface, path, None) @staticmethod - def compare_data_structures(data, ref): + 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. """ + errors = "" + for key, item in ref.items(): + if key in ignore: + continue try: if data[key] != item: - raise HoneycombError("The 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: - raise HoneycombError("The parameter '{0}' is not present in " - "operational data".format(key)) + errors += ("\nThe parameter '{0}' is not present in " + "operational data".format(key)) + + if errors: + raise HoneycombError(errors) @staticmethod def compare_interface_lists(list1, list2): @@ -1283,7 +1390,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. """ @@ -1305,3 +1412,167 @@ class InterfaceKeywords(object): vxlan_gpe_structure = [new_vxlan_gpe, ] return InterfaceKeywords._set_interface_properties( node, interface, path, vxlan_gpe_structure) + + @staticmethod + def enable_acl_on_interface(node, interface, table_name): + """Enable ACL on the given interface. + + :param node: Honeycomb node. + :param interface: The interface where the ACL will be enabled. + :param table_name: Name of the classify table. + :type node: dict + :type interface: str + :type table_name: str + :returns: Content of response. + :rtype: bytearray + :raises HoneycombError: If the configuration of interface is not + successful. + """ + + interface = interface.replace("/", "%2F") + + data = { + "v3po:acl": { + "ingress": { + "ip4-acl": { + "classify-table": table_name + }, + "l2-acl": { + "classify-table": table_name + } + } + } + } + + path = "/interface/" + interface + "/v3po:acl" + status_code, resp = HcUtil.\ + put_honeycomb_data(node, "config_vpp_interfaces", data, path, + data_representation=DataRepresentation.JSON) + 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)) + return resp + + @staticmethod + def disable_acl_on_interface(node, interface): + """Disable ACL on the given interface. + + :param node: Honeycomb node. + :param interface: The interface where the ACL will be disabled. + :type node: dict + :type interface: str + :returns: Content of response. + :rtype: bytearray + :raises HoneycombError: If the configuration of interface is not + successful. + """ + + interface = interface.replace("/", "%2F") + + path = "/interface/" + interface + "/v3po:acl" + + status_code, resp = HcUtil.\ + delete_honeycomb_data(node, "config_vpp_interfaces", path) + + if status_code != HTTPCodes.OK: + raise HoneycombError( + "The configuration of interface '{0}' was not successful. " + "Status code: {1}.".format(interface, status_code)) + return resp + + @staticmethod + 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 params: Configuration parameters of the sub-interface to be + created. + :type node: dict + :type intf: str + :type params: dict + :returns: Content of response. + :rtype: bytearray + :raises HoneycombError: If the configuration of sub-interface is not + successful. + """ + + interface = intf.replace("/", "%2F") + 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 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): + """Deletes the given PBB sub-interface. + + :param node: Honeycomb node. + :param intf: The interface where PBB sub-interface will be deleted. + :type node: dict + :type intf: str + :returns: Content of response. + :rtype: bytearray + :raises HoneycombError: If the removal of sub-interface is not + successful. + """ + + interface = intf.replace("/", "%2F") + path = "/interface/{0}/pbb-rewrite".format(interface) + + status_code, resp = HcUtil. \ + delete_honeycomb_data(node, "config_vpp_interfaces", path) + if status_code != HTTPCodes.OK: + raise HoneycombError( + "The removal of pbb sub-interface '{0}' was not successful. " + "Status code: {1}.".format(intf, status_code)) + return resp + + @staticmethod + def get_pbb_sub_interface_oper_data(node, intf, sub_if_id): + """Retrieves PBB sub-interface operational data from Honeycomb. + + :param node: Honeycomb node. + :param intf: The interface where PBB sub-interface is located. + :param sub_if_id: ID of the PBB sub-interface. + :type node: dict + :type intf: str + :type sub_if_id: str or int + :returns: PBB sub-interface operational data. + :rtype: dict + :raises HoneycombError: If the removal of sub-interface is not + successful. + """ + + 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))