HC Test: SPAN Port Mirroring Suite
[csit.git] / resources / libraries / python / honeycomb / HcAPIKwInterfaces.py
index 83267b5..19ce8f2 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2016 Cisco and/or its affiliates.
+# Copyright (c) 2017 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:
 # 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:
@@ -16,6 +16,8 @@
 The keywords make possible to put and get configuration data and to get
 operational data.
 """
 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.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
 
 
     import HoneycombUtil as HcUtil
 
 
-# pylint: disable=too-many-public-methods
-# pylint: disable=too-many-lines
 class InterfaceKeywords(object):
     """Keywords for Interface manipulation.
 
 class InterfaceKeywords(object):
     """Keywords for Interface manipulation.
 
@@ -44,7 +44,7 @@ class InterfaceKeywords(object):
                             "temporary-valid-lifetime",
                             "temporary-preferred-lifetime")
     ETH_PARAMS = ("mtu", )
                             "temporary-valid-lifetime",
                             "temporary-preferred-lifetime")
     ETH_PARAMS = ("mtu", )
-    ROUTING_PARAMS = ("vrf-id", )
+    ROUTING_PARAMS = ("ipv4-vrf-id", "ipv6-vrf-id")
     VXLAN_PARAMS = ("src", "dst", "vni", "encap-vrf-id")
     L2_PARAMS = ("bridge-domain", "split-horizon-group",
                  "bridged-virtual-interface")
     VXLAN_PARAMS = ("src", "dst", "vni", "encap-vrf-id")
     L2_PARAMS = ("bridge-domain", "split-horizon-group",
                  "bridged-virtual-interface")
@@ -83,7 +83,7 @@ class InterfaceKeywords(object):
         :type interface: str
         :type data: dict
         :type data_representation: DataRepresentation
         :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.
         :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)
         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))
             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
 
         :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.
         """
         :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
         :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
         """
 
         :rtype: dict
         """
 
@@ -145,7 +145,7 @@ class InterfaceKeywords(object):
 
         :param node: Honeycomb node.
         :type node: 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.
         """
         :rtype: list
         :raises HoneycombError: If it is not possible to get operational data.
         """
@@ -162,6 +162,33 @@ class InterfaceKeywords(object):
         except (KeyError, TypeError):
             return []
 
         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.
     @staticmethod
     def get_interface_oper_data(node, interface):
         """Get operational data about the given interface from Honeycomb.
@@ -170,10 +197,20 @@ class InterfaceKeywords(object):
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
         :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
         """
 
         :rtype: dict
         """
 
+        try:
+            interface = Topology.convert_interface_reference(
+                node, interface, "name")
+        except RuntimeError:
+            if isinstance(interface, basestring):
+                # Probably name of a custom interface (TAP, VxLAN, Vhost, ...)
+                pass
+            else:
+                raise
+
         intfs = InterfaceKeywords.get_all_interfaces_oper_data(node)
         for intf in intfs:
             if intf["name"] == interface:
         intfs = InterfaceKeywords.get_all_interfaces_oper_data(node)
         for intf in intfs:
             if intf["name"] == interface:
@@ -196,7 +233,7 @@ class InterfaceKeywords(object):
         :type interface: str
         :type path: tuple
         :type new_value: str, dict or list
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If it is not possible to get or set the data.
         """
@@ -228,7 +265,7 @@ class InterfaceKeywords(object):
         :type node: dict
         :type interface: str
         :type state: str
         :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.
         :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 +292,7 @@ class InterfaceKeywords(object):
         status_code, resp = HcUtil. \
             put_honeycomb_data(node, "config_vpp_interfaces", resp, path,
                                data_representation=DataRepresentation.JSON)
         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))
             raise HoneycombError(
                 "The configuration of interface '{0}' was not successful. "
                 "Status code: {1}.".format(interface, status_code))
@@ -269,7 +306,7 @@ class InterfaceKeywords(object):
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
-        :return: Content of response
+        :returns: Content of response
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
@@ -283,7 +320,7 @@ class InterfaceKeywords(object):
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
-        :return: Content of response.
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
@@ -304,7 +341,7 @@ class InterfaceKeywords(object):
         :type bd_name: str
         :type split_horizon_group: str
         :type bvi: str
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the interface is not present on the node.
         """
@@ -342,13 +379,16 @@ class InterfaceKeywords(object):
 
         path = "/interface/{0}/v3po:l2".format(intf)
 
 
         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:
             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):
 
     @staticmethod
     def get_bd_oper_data_from_interface(node, interface):
@@ -359,7 +399,7 @@ class InterfaceKeywords(object):
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
         :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
         """
         interface.
         :rtype: dict
         """
@@ -386,7 +426,7 @@ class InterfaceKeywords(object):
         :type interface: str
         :type param: str
         :type value: str
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
@@ -411,7 +451,7 @@ class InterfaceKeywords(object):
         :type interface: str
         :type param: str
         :type value: str
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
@@ -441,7 +481,7 @@ class InterfaceKeywords(object):
         :type interface: str
         :type ip_addr: str
         :type network: str or int
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the provided netmask or prefix is not valid.
         """
@@ -472,7 +512,7 @@ class InterfaceKeywords(object):
         :type interface: str
         :type ip_addr: str
         :type network: str or int
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the provided netmask or prefix is not valid.
         """
@@ -483,9 +523,9 @@ class InterfaceKeywords(object):
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
                 "address")
         if isinstance(network, basestring):
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
                 "address")
         if isinstance(network, basestring):
-            address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
+            address = [{"ip": ip_addr, "netmask": network}]
         elif isinstance(network, int) and (0 < network < 33):
         elif isinstance(network, int) and (0 < network < 33):
-            address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
+            address = [{"ip": ip_addr, "prefix-length": network}]
         else:
             raise HoneycombError("Value {0} is not a valid netmask or network "
                                  "prefix length.".format(network))
         else:
             raise HoneycombError("Value {0} is not a valid netmask or network "
                                  "prefix length.".format(network))
@@ -500,7 +540,7 @@ class InterfaceKeywords(object):
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
-        :return: Content of response.
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
@@ -521,10 +561,13 @@ class InterfaceKeywords(object):
         :type interface: str
         :type ip_addr: str
         :type link_layer_address: str
         :type interface: str
         :type ip_addr: str
         :type link_layer_address: str
-        :return: Content of response.
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
+        interface = Topology.convert_interface_reference(
+            node, interface, "name")
+
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
                 "neighbor")
         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
                 "neighbor")
         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
@@ -539,7 +582,7 @@ class InterfaceKeywords(object):
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
-        :return: Content of response.
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
@@ -561,7 +604,7 @@ class InterfaceKeywords(object):
         :type interface: str
         :type param: str
         :type value: str
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
@@ -592,10 +635,13 @@ class InterfaceKeywords(object):
         :type interface: str
         :type ip_addr: str
         :type prefix_len: str
         :type interface: str
         :type ip_addr: str
         :type prefix_len: str
-        :return: Content of response.
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
+        interface = Topology.convert_interface_reference(
+            node, interface, "name")
+
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
         address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
         return InterfaceKeywords._set_interface_properties(
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
         address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
         return InterfaceKeywords._set_interface_properties(
@@ -613,10 +659,13 @@ class InterfaceKeywords(object):
         :type interface: str
         :type ip_addr: str
         :type prefix_len: str
         :type interface: str
         :type ip_addr: str
         :type prefix_len: str
-        :return: Content of response.
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
+        interface = Topology.convert_interface_reference(
+            node, interface, "name")
+
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
                 "address")
         address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
                 "address")
         address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
@@ -631,7 +680,7 @@ class InterfaceKeywords(object):
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
-        :return: Content of response.
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
@@ -652,10 +701,13 @@ class InterfaceKeywords(object):
         :type interface: str
         :type ip_addr: str
         :type link_layer_address: str
         :type interface: str
         :type ip_addr: str
         :type link_layer_address: str
-        :return: Content of response.
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
+        interface = Topology.convert_interface_reference(
+            node, interface, "name")
+
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
                 "neighbor")
         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
                 "neighbor")
         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
@@ -670,7 +722,7 @@ class InterfaceKeywords(object):
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
-        :return: Content of response.
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
@@ -692,7 +744,7 @@ class InterfaceKeywords(object):
         :type interface: str
         :type param: str
         :type value: str
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
@@ -717,11 +769,14 @@ class InterfaceKeywords(object):
         :type interface: str
         :type param: str
         :type value: str
         :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.
         """
 
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
 
+        interface = Topology.convert_interface_reference(
+            node, interface, "name")
+
         if param not in InterfaceKeywords.ROUTING_PARAMS:
             raise HoneycombError("The parameter {0} is invalid.".format(param))
 
         if param not in InterfaceKeywords.ROUTING_PARAMS:
             raise HoneycombError("The parameter {0} is invalid.".format(param))
 
@@ -741,7 +796,7 @@ class InterfaceKeywords(object):
         :type node: dict
         :type interface: str
         :type kwargs: dict
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
@@ -770,7 +825,7 @@ class InterfaceKeywords(object):
         :param interface: The name of interface.
         :type node: dict
         :type interface: str
         :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.
         :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 +867,7 @@ class InterfaceKeywords(object):
         :type node: dict
         :type interface: str
         :type kwargs: dict
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
@@ -841,7 +896,7 @@ class InterfaceKeywords(object):
         :type interface: str
         :type param: str
         :type value: str
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
@@ -864,7 +919,7 @@ class InterfaceKeywords(object):
         :type node: dict
         :type interface: str
         :type kwargs: dict
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
@@ -903,7 +958,7 @@ class InterfaceKeywords(object):
         :type node: dict
         :type interface: str
         :type kwargs: dict
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
@@ -937,7 +992,7 @@ class InterfaceKeywords(object):
         :type node: dict
         :type interface: str
         :type kwargs: dict
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
@@ -965,7 +1020,7 @@ class InterfaceKeywords(object):
         :type node: dict
         :type interface: str
         :type kwargs: dict
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
@@ -1002,7 +1057,7 @@ class InterfaceKeywords(object):
         :type match: str
         :type tags: list
         :type kwargs: dict
         :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.
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         :raises KeyError: If the parameter 'match' is invalid.
@@ -1058,7 +1113,7 @@ class InterfaceKeywords(object):
         :type node: dict
         :type super_interface: str
         :type identifier: int
         :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.
         """
         :rtype: dict
         :raises HoneycombError: If there is no sub-interface with the given ID.
         """
@@ -1080,7 +1135,7 @@ class InterfaceKeywords(object):
         :param super_interface: Super interface.
         :type node: dict
         :type super_interface: str
         :param super_interface: Super interface.
         :type node: dict
         :type super_interface: str
-        :return: Content of response.
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
@@ -1103,7 +1158,7 @@ class InterfaceKeywords(object):
         :type super_interface: str
         :type identifier: int
         :type state: str
         :type super_interface: str
         :type identifier: int
         :type state: str
-        :return: Content of response.
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
@@ -1113,7 +1168,7 @@ class InterfaceKeywords(object):
         path = ("interfaces",
                 ("interface", "name", super_interface),
                 "vpp-vlan:sub-interfaces",
         path = ("interfaces",
                 ("interface", "name", super_interface),
                 "vpp-vlan:sub-interfaces",
-                ("sub-interface", "identifier", identifier),
+                ("sub-interface", "identifier", int(identifier)),
                 "enabled")
 
         return InterfaceKeywords._set_interface_properties(
                 "enabled")
 
         return InterfaceKeywords._set_interface_properties(
@@ -1132,7 +1187,7 @@ class InterfaceKeywords(object):
         :type super_interface: str
         :type identifier: int
         :type config: dict
         :type super_interface: str
         :type identifier: int
         :type config: dict
-        :return: Content of response.
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
@@ -1155,7 +1210,7 @@ class InterfaceKeywords(object):
         :type node: dict
         :type super_interface: str
         :type identifier: int
         :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.
         """
         :rtype: dict
         :raises HoneycombError: If there is no sub-interface with the given ID.
         """
@@ -1180,7 +1235,7 @@ class InterfaceKeywords(object):
         :type super_interface: str
         :type identifier: int
         :type config: dict
         :type super_interface: str
         :type identifier: int
         :type config: dict
-        :return: Content of response.
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
@@ -1204,7 +1259,7 @@ class InterfaceKeywords(object):
         :type node: dict
         :type super_interface: str
         :type identifier: int
         :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.
         """
         :rtype: dict
         :raises HoneycombError: If there is no sub-interface with the given ID.
         """
@@ -1218,8 +1273,8 @@ class InterfaceKeywords(object):
                                  "information about the tag-rewrite.")
 
     @staticmethod
                                  "information about the tag-rewrite.")
 
     @staticmethod
-    def add_ipv4_address_to_sub_interface(node, super_interface, identifier,
-                                          ip_addr, network):
+    def add_ip_address_to_sub_interface(node, super_interface, identifier,
+                                        ip_addr, network, ip_version):
         """Add an ipv4 address to the specified sub-interface, with the provided
         netmask or network prefix length. Any existing ipv4 addresses on the
         sub-interface will be replaced.
         """Add an ipv4 address to the specified sub-interface, with the provided
         netmask or network prefix length. Any existing ipv4 addresses on the
         sub-interface will be replaced.
@@ -1229,12 +1284,14 @@ class InterfaceKeywords(object):
         :param identifier: The ID of sub-interface.
         :param ip_addr: IPv4 address to be set.
         :param network: Network mask or network prefix length.
         :param identifier: The ID of sub-interface.
         :param ip_addr: IPv4 address to be set.
         :param network: Network mask or network prefix length.
+        :param ip_version: ipv4 or ipv6
         :type node: dict
         :type super_interface: str
         :type identifier: int
         :type ip_addr: str
         :type network: str or int
         :type node: dict
         :type super_interface: str
         :type identifier: int
         :type ip_addr: str
         :type network: str or int
-        :return: Content of response.
+        :type ip_version: string
+        :returns: Content of response.
         :rtype: bytearray
         :raises HoneycombError: If the provided netmask or prefix is not valid.
         """
         :rtype: bytearray
         :raises HoneycombError: If the provided netmask or prefix is not valid.
         """
@@ -1243,9 +1300,9 @@ class InterfaceKeywords(object):
                 ("interface", "name", super_interface),
                 "vpp-vlan:sub-interfaces",
                 ("sub-interface", "identifier", int(identifier)),
                 ("interface", "name", super_interface),
                 "vpp-vlan:sub-interfaces",
                 ("sub-interface", "identifier", int(identifier)),
-                "ipv4")
+                ip_version.lower())
 
 
-        if isinstance(network, basestring):
+        if isinstance(network, basestring) and ip_version.lower() == "ipv4":
             address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
 
         elif isinstance(network, int) and 0 < network < 33:
             address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
 
         elif isinstance(network, int) and 0 < network < 33:
@@ -1259,17 +1316,19 @@ class InterfaceKeywords(object):
             node, super_interface, path, address)
 
     @staticmethod
             node, super_interface, path, address)
 
     @staticmethod
-    def remove_all_ipv4_addresses_from_sub_interface(node, super_interface, # pylint: disable=invalid-name
-                                                     identifier):
+    def remove_all_ip_addresses_from_sub_interface(node, super_interface,
+                                                   identifier, ip_version):
         """Remove all ipv4 addresses from the specified sub-interface.
 
         :param node: Honeycomb node.
         :param super_interface: Super interface.
         :param identifier: The ID of sub-interface.
         """Remove all ipv4 addresses from the specified sub-interface.
 
         :param node: Honeycomb node.
         :param super_interface: Super interface.
         :param identifier: The ID of sub-interface.
+        :param ip_version: ipv4 or ipv6
         :type node: dict
         :type super_interface: str
         :type identifier: int
         :type node: dict
         :type super_interface: str
         :type identifier: int
-        :return: Content of response.
+        :type ip_version: string
+        :returns: Content of response.
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
@@ -1277,42 +1336,79 @@ class InterfaceKeywords(object):
                 ("interface", "name", super_interface),
                 "vpp-vlan:sub-interfaces",
                 ("sub-interface", "identifier", int(identifier)),
                 ("interface", "name", super_interface),
                 "vpp-vlan:sub-interfaces",
                 ("sub-interface", "identifier", int(identifier)),
-                "ipv4", "address")
+                str(ip_version), "address")
 
         return InterfaceKeywords._set_interface_properties(
             node, super_interface, path, None)
 
     @staticmethod
 
         return InterfaceKeywords._set_interface_properties(
             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 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 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
+
+        :raises HoneycombError: If the data structures do not match in some way,
+        or if they are not in deserialized JSON format.
         """
 
         """
 
-        errors = ""
+        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))
 
 
-        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 errors:
-            raise HoneycombError(errors)
+        else:
+            raise HoneycombError(
+                "Unexpected data type {data_type} in path {path}, reference"
+                " type is {ref_type}. Must be list or dictionary.".format(
+                    data_type=type(data),
+                    ref_type=type(ref),
+                    path=_path))
 
     @staticmethod
     def compare_interface_lists(list1, list2):
 
     @staticmethod
     def compare_interface_lists(list1, list2):
@@ -1351,7 +1447,7 @@ class InterfaceKeywords(object):
         :type node: dict
         :type interface: str
         :type kwargs: dict
         :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.
         """
         :rtype: bytearray
         :raises HoneycombError: If a parameter in kwargs is not valid.
         """
@@ -1384,7 +1480,7 @@ class InterfaceKeywords(object):
         :type node: dict
         :type interface: str
         :type table_name: str
         :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.
         :rtype: bytearray
         :raises HoneycombError: If the configuration of interface is not
         successful.
@@ -1393,21 +1489,23 @@ class InterfaceKeywords(object):
         interface = interface.replace("/", "%2F")
 
         data = {
         interface = interface.replace("/", "%2F")
 
         data = {
-            "v3po:acl": {
-                "l2-acl": {
-                    "classify-table": table_name
-                },
-                "ip4-acl": {
-                    "classify-table": table_name
+            "vpp-interface-acl:acl": {
+                "ingress": {
+                    "ip4-acl": {
+                        "classify-table": table_name
+                    },
+                    "l2-acl": {
+                        "classify-table": table_name
+                    }
                 }
             }
         }
 
                 }
             }
         }
 
-        path = "/interface/" + interface + "/v3po:acl"
+        path = "/interface/" + interface + "/vpp-interface-acl:acl"
         status_code, resp = HcUtil.\
             put_honeycomb_data(node, "config_vpp_interfaces", data, path,
                                data_representation=DataRepresentation.JSON)
         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))
             raise HoneycombError(
                 "The configuration of interface '{0}' was not successful. "
                 "Status code: {1}.".format(interface, status_code))
@@ -1421,7 +1519,7 @@ class InterfaceKeywords(object):
         :param interface: The interface where the ACL will be disabled.
         :type node: dict
         :type interface: str
         :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.
         :rtype: bytearray
         :raises HoneycombError: If the configuration of interface is not
         successful.
@@ -1429,7 +1527,7 @@ class InterfaceKeywords(object):
 
         interface = interface.replace("/", "%2F")
 
 
         interface = interface.replace("/", "%2F")
 
-        path = "/interface/" + interface + "/v3po:acl"
+        path = "/interface/" + interface + "/vpp-interface-acl:acl"
 
         status_code, resp = HcUtil.\
             delete_honeycomb_data(node, "config_vpp_interfaces", path)
 
         status_code, resp = HcUtil.\
             delete_honeycomb_data(node, "config_vpp_interfaces", path)
@@ -1441,56 +1539,50 @@ class InterfaceKeywords(object):
         return resp
 
     @staticmethod
         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.
         """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
         :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
         :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")
         :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)
         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
             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.
         """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 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")
         :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)
 
         status_code, resp = HcUtil. \
             delete_honeycomb_data(node, "config_vpp_interfaces", path)
@@ -1510,11 +1602,92 @@ class InterfaceKeywords(object):
         :type node: dict
         :type intf: str
         :type sub_if_id: str or int
         :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.
         """
 
         :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=None):
+        """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 dict
+        :returns: Content of response.
+        :rtype: bytearray
+        :raises HoneycombError: If SPAN could not be configured.
+        """
+
+        interface = Topology.convert_interface_reference(
+            node, dst_interface, "name")
+        interface = interface.replace("/", "%2F")
+        path = "/interface/" + interface + "/span"
+
+        if not src_interfaces:
+            status_code, _ = HcUtil.delete_honeycomb_data(
+                node, "config_vpp_interfaces", path)
+        else:
+            for src_interface in src_interfaces:
+                src_interface["iface-ref"] = Topology.\
+                    convert_interface_reference(
+                    node, src_interface["iface-ref"], "name")
+            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")