CSIT-457: Address Honeycomb test failures
[csit.git] / resources / libraries / python / honeycomb / HcAPIKwInterfaces.py
index fdb9b90..559f64e 100644 (file)
@@ -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 \
@@ -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))
@@ -222,7 +224,7 @@ 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
@@ -237,6 +239,9 @@ class InterfaceKeywords(object):
         intf_state = {"up": "true",
                       "down": "false"}
 
+        interface = Topology.convert_interface_reference(
+            node, interface, "name")
+
         intf = interface.replace("/", "%2F")
         path = "/interface/{0}".format(intf)
 
@@ -252,7 +257,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))
@@ -292,7 +297,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.
@@ -306,6 +311,9 @@ class InterfaceKeywords(object):
         :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)
@@ -317,6 +325,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
@@ -367,7 +405,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.
@@ -383,6 +421,9 @@ class InterfaceKeywords(object):
         :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))
 
@@ -410,6 +451,9 @@ class InterfaceKeywords(object):
         :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}, ]}
@@ -438,6 +482,9 @@ class InterfaceKeywords(object):
         :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):
@@ -1241,15 +1288,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.
         """
@@ -1261,10 +1312,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))
@@ -1352,11 +1406,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
+                    }
                 }
             }
         }
@@ -1365,7 +1421,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))
@@ -1424,7 +1480,7 @@ class InterfaceKeywords(object):
         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))