HC Test: Fix intermittent failures of HC startup
[csit.git] / resources / libraries / python / honeycomb / HcAPIKwInterfaces.py
index f317d06..09c9ae9 100644 (file)
@@ -252,7 +252,7 @@ class InterfaceKeywords(object):
         return InterfaceKeywords._configure_interface(node, interface, new_data)
 
     @staticmethod
         return InterfaceKeywords._configure_interface(node, interface, new_data)
 
     @staticmethod
-    def set_interface_state(node, interface, state="up"):
+    def honeycomb_set_interface_state(node, interface, state="up"):
         """Set VPP interface state.
 
         The keyword changes the administration state of interface to up or down
         """Set VPP interface state.
 
         The keyword changes the administration state of interface to up or down
@@ -310,7 +310,8 @@ class InterfaceKeywords(object):
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
-        return InterfaceKeywords.set_interface_state(node, interface, "up")
+        return InterfaceKeywords.honeycomb_set_interface_state(
+            node, interface, "up")
 
     @staticmethod
     def set_interface_down(node, interface):
 
     @staticmethod
     def set_interface_down(node, interface):
@@ -324,7 +325,8 @@ class InterfaceKeywords(object):
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
-        return InterfaceKeywords.set_interface_state(node, interface, "down")
+        return InterfaceKeywords.honeycomb_set_interface_state(
+            node, interface, "down")
 
     @staticmethod
     def add_bridge_domain_to_interface(node, interface, bd_name,
 
     @staticmethod
     def add_bridge_domain_to_interface(node, interface, bd_name,
@@ -483,22 +485,32 @@ class InterfaceKeywords(object):
         :type network: str or int
         :returns: Content of response.
         :rtype: bytearray
         :type network: str or int
         :returns: Content of response.
         :rtype: bytearray
-        :raises HoneycombError: If the provided netmask or prefix is not valid.
+        :raises ValueError: If the provided netmask or prefix is not valid.
+        :raises HoneycombError: If the operation fails.
         """
 
         """
 
-        interface = Topology.convert_interface_reference(
-            node, interface, "name")
+        interface = InterfaceKeywords.handle_interface_reference(
+            node, interface)
 
 
-        path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
+        path = "/interface/{0}/ietf-ip:ipv4".format(interface)
         if isinstance(network, basestring):
         if isinstance(network, basestring):
-            address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
+            data = {
+                "ietf-ip:ipv4": {
+                    "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}, ]}
+            data = {
+                "ietf-ip:ipv4": {
+                    "address": [{"ip": ip_addr, "prefix-length": network}, ]}}
         else:
         else:
-            raise HoneycombError("Value {0} is not a valid netmask or network "
-                                 "prefix length.".format(network))
-        return InterfaceKeywords._set_interface_properties(
-            node, interface, path, address)
+            raise ValueError("Value {0} is not a valid netmask or network "
+                             "prefix length.".format(network))
+        status_code, _ = HcUtil.put_honeycomb_data(
+            node, "config_vpp_interfaces", data, path)
+
+        if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
+            raise HoneycombError(
+                "Configuring IPv4 address failed. "
+                "Status code:{0}".format(status_code))
 
     @staticmethod
     def add_ipv4_address(node, interface, ip_addr, network):
 
     @staticmethod
     def add_ipv4_address(node, interface, ip_addr, network):
@@ -544,6 +556,9 @@ class InterfaceKeywords(object):
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
+        interface = Topology.convert_interface_reference(
+            node, interface, "name")
+
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
                 "address")
         return InterfaceKeywords._set_interface_properties(
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
                 "address")
         return InterfaceKeywords._set_interface_properties(
@@ -586,6 +601,9 @@ class InterfaceKeywords(object):
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
+        interface = Topology.convert_interface_reference(
+            node, interface, "name")
+
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
                 "neighbor")
         return InterfaceKeywords._set_interface_properties(
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
                 "neighbor")
         return InterfaceKeywords._set_interface_properties(
@@ -684,6 +702,9 @@ class InterfaceKeywords(object):
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
+        interface = Topology.convert_interface_reference(
+            node, interface, "name")
+
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
                 "address")
         return InterfaceKeywords._set_interface_properties(
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
                 "address")
         return InterfaceKeywords._set_interface_properties(
@@ -726,6 +747,9 @@ class InterfaceKeywords(object):
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
+        interface = Topology.convert_interface_reference(
+            node, interface, "name")
+
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
                 "neighbor")
         return InterfaceKeywords._set_interface_properties(
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
                 "neighbor")
         return InterfaceKeywords._set_interface_properties(
@@ -786,7 +810,7 @@ class InterfaceKeywords(object):
             node, interface, path, value)
 
     @staticmethod
             node, interface, path, value)
 
     @staticmethod
-    def create_vxlan_interface(node, interface, **kwargs):
+    def honeycomb_create_vxlan_interface(node, interface, **kwargs):
         """Create a new VxLAN interface.
 
         :param node: Honeycomb node.
         """Create a new VxLAN interface.
 
         :param node: Honeycomb node.
@@ -850,7 +874,7 @@ class InterfaceKeywords(object):
         return resp
 
     @staticmethod
         return resp
 
     @staticmethod
-    def configure_interface_vxlan(node, interface, **kwargs):
+    def honeycomb_configure_interface_vxlan(node, interface, **kwargs):
         """Configure VxLAN on the interface.
 
         The keyword configures VxLAN parameters on the given interface. The type
         """Configure VxLAN on the interface.
 
         The keyword configures VxLAN parameters on the given interface. The type
@@ -1042,7 +1066,8 @@ class InterfaceKeywords(object):
             node, interface, path, new_vhost_structure)
 
     @staticmethod
             node, interface, path, new_vhost_structure)
 
     @staticmethod
-    def create_sub_interface(node, super_interface, match, tags=None, **kwargs):
+    def honeycomb_create_sub_interface(node, super_interface, match, tags=None,
+                                       **kwargs):
         """Create a new sub-interface.
 
         :param node: Honeycomb node.
         """Create a new sub-interface.
 
         :param node: Honeycomb node.
@@ -1063,6 +1088,9 @@ class InterfaceKeywords(object):
         :raises KeyError: If the parameter 'match' is invalid.
         """
 
         :raises KeyError: If the parameter 'match' is invalid.
         """
 
+        super_interface = Topology.convert_interface_reference(
+            node, super_interface, "name")
+
         match_type = {
             "default":
                 {"default": {}},
         match_type = {
             "default":
                 {"default": {}},
@@ -1162,6 +1190,9 @@ class InterfaceKeywords(object):
         :rtype: bytearray
         """
 
         :rtype: bytearray
         """
 
+        super_interface = Topology.convert_interface_reference(
+            node, super_interface, "name")
+
         intf_state = {"up": "true",
                       "down": "false"}
 
         intf_state = {"up": "true",
                       "down": "false"}
 
@@ -1511,6 +1542,67 @@ class InterfaceKeywords(object):
                 "Status code: {1}.".format(interface, status_code))
         return resp
 
                 "Status code: {1}.".format(interface, status_code))
         return resp
 
+    @staticmethod
+    def enable_policer_on_interface(node, interface, table_name):
+        """Enable Policer on the given interface.
+
+        :param node: Honeycomb node.
+        :param interface: The interface where policer 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 = Topology.convert_interface_reference(
+            node, interface, "name")
+        interface = interface.replace("/", "%2F")
+
+        data = {
+            "interface-policer:policer": {
+                "ip4-table": table_name
+                }
+            }
+
+        path = "/interface/" + interface + "/interface-policer:policer"
+        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_policer_on_interface(node, interface):
+        """Disable Policer on the given interface.
+
+        :param node: Honeycomb node.
+        :param interface: The interface where policer 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 = Topology.convert_interface_reference(
+            node, interface, "name")
+        interface = interface.replace("/", "%2F")
+
+        path = "/interface/" + interface + "/interface-policer:policer"
+        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 disable_acl_on_interface(node, interface):
         """Disable ACL on the given interface.
     @staticmethod
     def disable_acl_on_interface(node, interface):
         """Disable ACL on the given interface.
@@ -1635,7 +1727,7 @@ class InterfaceKeywords(object):
                              " of disabled interfaces.".format(interface))
 
     @staticmethod
                              " of disabled interfaces.".format(interface))
 
     @staticmethod
-    def configure_interface_span(node, dst_interface, *src_interfaces):
+    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.
 
         """Configure SPAN port mirroring on the specified interfaces. If no
          source interface is provided, SPAN will be disabled.
 
@@ -1643,30 +1735,88 @@ class InterfaceKeywords(object):
         :param dst_interface: Interface to mirror packets to.
         :param src_interfaces: List of interfaces to mirror packets from.
         :type node: dict
         :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
+        :type dst_interface: str or int
+        :type src_interfaces: list of dict
         :returns: Content of response.
         :rtype: bytearray
         :raises HoneycombError: If SPAN could not be configured.
         """
 
         :returns: Content of response.
         :rtype: bytearray
         :raises HoneycombError: If SPAN could not be configured.
         """
 
-        interface = dst_interface.replace("/", "%2F")
+        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)
         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
+                    }
+                }
+            }
 
 
-        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 configure_sub_interface_span(node, super_interface, dst_interface_index,
+                                     src_interfaces=None):
+        """Configure SPAN port mirroring on the specified sub-interface. If no
+         source interface is provided, SPAN will be disabled.
+
+        Note: Does not support source sub-interfaces, only destination.
+
+        :param node: Honeycomb node.
+        :param super_interface: Name, link name or sw_if_index
+        of the destination interface's super-interface.
+        :param dst_interface_index: Index of sub-interface to mirror packets to.
+        :param src_interfaces: List of interfaces to mirror packets from.
+        :type node: dict
+        :type super_interface: str or int
+        :type dst_interface_index: int
+        :type src_interfaces: list of dict
+        :returns: Content of response.
+        :rtype: bytearray
+        :raises HoneycombError: If SPAN could not be configured.
+        """
+
+        super_interface = Topology.convert_interface_reference(
+            node, super_interface, "name")
+        super_interface = super_interface.replace("/", "%2F")
+
+        path = "/interface/{0}/vpp-vlan:sub-interfaces/sub-interface/{1}/span"\
+            .format(super_interface, dst_interface_index)
+
+        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)
+            status_code, _ = HcUtil.put_honeycomb_data(
+                node, "config_vpp_interfaces", data, path)
 
         if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
             raise HoneycombError(
 
         if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
             raise HoneycombError(
@@ -1685,3 +1835,72 @@ class InterfaceKeywords(object):
             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")
             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")
+
+    @staticmethod
+    def configure_interface_unnumbered(node, interface, interface_src=None):
+        """Configure the specified interface as unnumbered. The interface
+        borrows IP address from the specified source interface. If not source
+        interface is provided, unnumbered configuration will be removed.
+
+        :param node: Honeycomb node.
+        :param interface: Name, link name or sw_if_index of an interface.
+        :param interface_src: Name of source interface.
+        :type node: dict
+        :type interface: str or int
+        :type interface_src: str
+        :raises HoneycombError: If the configuration fails.
+        """
+
+        interface = InterfaceKeywords.handle_interface_reference(
+            node, interface)
+
+        path = "/interface/{0}/unnumbered-interfaces:unnumbered"\
+            .format(interface)
+
+        if interface_src:
+            data = {
+                "unnumbered": {
+                    "use": interface_src
+                }
+            }
+            status_code, _ = HcUtil.put_honeycomb_data(
+                node, "config_vpp_interfaces", data, path)
+        else:
+            status_code, _ = HcUtil.delete_honeycomb_data(
+                node, "config_vpp_interfaces", path)
+
+        if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
+            raise HoneycombError(
+                "Configuring unnumbered interface failed. "
+                "Status code:{0}".format(status_code))
+
+    @staticmethod
+    def handle_interface_reference(node, interface):
+        """Convert any interface reference to interface name used by Honeycomb.
+
+        :param node: Honeycomb node.
+        :param interface: Name, link name or sw_if_index of an interface,
+        name of a custom interface or name of a sub-interface.
+        :type node: Honeycomb node.
+        :type interface: str or int
+        :returns: Name of interface that can be used in Honeycomb requests.
+        :rtype: str
+        """
+
+        try:
+            interface = Topology.convert_interface_reference(
+                node, interface, "name")
+            interface = interface.replace("/", "%2F")
+        except RuntimeError:
+            # interface is not in topology
+            if "." in interface:
+                # Assume it's the name of a sub-interface
+                interface, index = interface.split(".")
+                interface = interface.replace("/", "%2F")
+                interface = "{0}/vpp-vlan:sub-interfaces/sub-interface/{1}".\
+                    format(interface, index)
+            else:
+                # Assume it's the name of a custom interface (pbb, vxlan, etc.)
+                interface = interface.replace("/", "%2F")
+
+        return interface