Add Honeycomb persistence tests
[csit.git] / resources / libraries / python / honeycomb / HcAPIKwInterfaces.py
index 8f6819e..e8cbc78 100644 (file)
@@ -25,6 +25,8 @@ 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.
 
@@ -33,7 +35,7 @@ class InterfaceKeywords(object):
     """
 
     INTF_PARAMS = ("name", "description", "type", "enabled",
     """
 
     INTF_PARAMS = ("name", "description", "type", "enabled",
-                   "link-up-down-trap-enable")
+                   "link-up-down-trap-enable", "v3po:l2")
     IPV4_PARAMS = ("enabled", "forwarding", "mtu")
     IPV6_PARAMS = ("enabled", "forwarding", "mtu", "dup-addr-detect-transmits")
     IPV6_AUTOCONF_PARAMS = ("create-global-addresses",
     IPV4_PARAMS = ("enabled", "forwarding", "mtu")
     IPV6_PARAMS = ("enabled", "forwarding", "mtu", "dup-addr-detect-transmits")
     IPV6_AUTOCONF_PARAMS = ("create-global-addresses",
@@ -45,6 +47,22 @@ class InterfaceKeywords(object):
     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")
+    L2_REWRITE_TAG_PARAMS = ("rewrite-operation",
+                             "first-pushed",
+                             "tag1",
+                             "tag2")
+    TAP_PARAMS = ("tap-name", "mac", "device-instance")
+    VHOST_USER_PARAMS = ("socket", "role")
+    SUB_INTF_PARAMS = ("super-interface",
+                       "identifier",
+                       "vlan-type",
+                       "number-of-tags",
+                       "outer-id",
+                       "inner-id",
+                       "match-any-outer-id",
+                       "match-any-inner-id",
+                       "exact-match",
+                       "default-subif")
 
     def __init__(self):
         pass
 
     def __init__(self):
         pass
@@ -331,7 +349,7 @@ class InterfaceKeywords(object):
             node, interface, path, value)
 
     @staticmethod
             node, interface, path, value)
 
     @staticmethod
-    def add_first_ipv4_address(node, interface, ip_addr, netmask):
+    def add_first_ipv4_address(node, interface, ip_addr, network):
         """Add the first IPv4 address.
 
         If there are any other addresses configured, they will be removed.
         """Add the first IPv4 address.
 
         If there are any other addresses configured, they will be removed.
@@ -339,39 +357,51 @@ class InterfaceKeywords(object):
         :param node: Honeycomb node.
         :param interface: The name of interface.
         :param ip_addr: IPv4 address to be set.
         :param node: Honeycomb node.
         :param interface: The name of interface.
         :param ip_addr: IPv4 address to be set.
-        :param netmask: Netmask.
+        :param network: Netmask or length of network prefix.
         :type node: dict
         :type interface: str
         :type ip_addr: str
         :type node: dict
         :type interface: str
         :type ip_addr: str
-        :type netmask: str
+        :type network: str or int
         :return: Content of response.
         :rtype: bytearray
         """
 
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
         :return: Content of response.
         :rtype: bytearray
         """
 
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
-        address = {"address": [{"ip": ip_addr, "netmask": netmask}, ]}
+        if isinstance(network, basestring):
+            address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
+        elif isinstance(network, int) and (0 < network < 33):
+            address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
+        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)
 
     @staticmethod
         return InterfaceKeywords._set_interface_properties(
             node, interface, path, address)
 
     @staticmethod
-    def add_ipv4_address(node, interface, ip_addr, netmask):
+    def add_ipv4_address(node, interface, ip_addr, network):
         """Add IPv4 address.
 
         :param node: Honeycomb node.
         :param interface: The name of interface.
         :param ip_addr: IPv4 address to be set.
         """Add IPv4 address.
 
         :param node: Honeycomb node.
         :param interface: The name of interface.
         :param ip_addr: IPv4 address to be set.
-        :param netmask: Netmask.
+        :param network: Netmask or length of network prefix.
         :type node: dict
         :type interface: str
         :type ip_addr: str
         :type node: dict
         :type interface: str
         :type ip_addr: str
-        :type netmask: str
+        :type network: str or int
         :return: Content of response.
         :rtype: bytearray
         """
 
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
                 "address")
         :return: Content of response.
         :rtype: bytearray
         """
 
         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
                 "address")
-        address = [{"ip": ip_addr, "prefix-length": netmask}, ]
+        if isinstance(network, basestring):
+            address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
+        elif isinstance(network, int) and (0 < network < 33):
+            address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
+        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)
 
         return InterfaceKeywords._set_interface_properties(
             node, interface, path, address)
 
@@ -662,30 +692,102 @@ class InterfaceKeywords(object):
             node, interface, path, value)
 
     @staticmethod
             node, interface, path, value)
 
     @staticmethod
-    def configure_interface_vxlan(node, interface, param, value):
-        """Configure the VxLAN parameters of interface.
+    def create_vxlan_interface(node, interface, **kwargs):
+        """Create a new VxLAN interface.
 
         :param node: Honeycomb node.
         :param interface: The name of interface.
 
         :param node: Honeycomb node.
         :param interface: The name of interface.
-        :param param: Parameter to configure (set, change, remove)
-        :param value: The value of parameter. If None, the parameter will be
-        removed.
+        :param kwargs: Parameters and their values. The accepted parameters are
+        defined in InterfaceKeywords.VXLAN_PARAMS.
         :type node: dict
         :type interface: str
         :type node: dict
         :type interface: str
-        :type param: str
-        :type value: str
+        :type kwargs: dict
         :return: Content of response.
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
 
         :return: Content of response.
         :rtype: bytearray
         :raises HoneycombError: If the parameter is not valid.
         """
 
-        if param not in InterfaceKeywords.VXLAN_PARAMS:
-            raise HoneycombError("The parameter {0} is invalid.".format(param))
+        new_vx_lan = {
+            "name": interface,
+            "type": "v3po:vxlan-tunnel",
+            "v3po:vxlan": {}
+        }
+        for param, value in kwargs.items():
+            if param not in InterfaceKeywords.VXLAN_PARAMS:
+                raise HoneycombError("The parameter {0} is invalid.".
+                                     format(param))
+            new_vx_lan["v3po:vxlan"][param] = value
+
+        path = ("interfaces", "interface")
+        vx_lan_structure = [new_vx_lan, ]
+        return InterfaceKeywords._set_interface_properties(
+            node, interface, path, vx_lan_structure)
 
 
-        path = ("interfaces", ("interface", "name", interface), "v3po:vxlan",
-                param)
+    @staticmethod
+    def delete_interface(node, interface):
+        """Delete an interface.
+
+        :param node: Honeycomb node.
+        :param interface: The name of interface.
+        :type node: dict
+        :type interface: str
+        :return: 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.
+        """
+
+        path = ("interfaces", ("interface", "name", interface))
+
+        status_code, resp = HcUtil.\
+            get_honeycomb_data(node, "config_vpp_interfaces")
+        if status_code != HTTPCodes.OK:
+            raise HoneycombError(
+                "Not possible to get configuration information about the "
+                "interfaces. Status code: {0}.".format(status_code))
+
+        new_data = HcUtil.remove_item(resp, path)
+        status_code, resp = HcUtil.\
+            put_honeycomb_data(node, "config_vpp_interfaces", new_data)
+        if status_code != HTTPCodes.OK:
+            raise HoneycombError("Not possible to remove interface {0}. "
+                                 "Status code: {1}.".
+                                 format(interface, status_code))
+        return resp
+
+    @staticmethod
+    def configure_interface_vxlan(node, interface, **kwargs):
+        """Configure VxLAN on the interface.
+
+        The keyword configures VxLAN parameters on the given interface. The type
+        of interface must be set to "v3po:vxlan-tunnel".
+        The new VxLAN parameters overwrite the current configuration. If a
+        parameter in new configuration is missing, it is removed from VxLAN
+        configuration.
+        If the dictionary kwargs is empty, VxLAN configuration is removed.
+
+        :param node: Honeycomb node.
+        :param interface: The name of interface.
+        :param kwargs: Parameters and their values. The accepted parameters are
+        defined in InterfaceKeywords.VXLAN_PARAMS.
+        :type node: dict
+        :type interface: str
+        :type kwargs: dict
+        :return: Content of response.
+        :rtype: bytearray
+        :raises HoneycombError: If the parameter is not valid.
+        """
+
+        vx_lan_structure = dict()
+        for param, value in kwargs.items():
+            if param not in InterfaceKeywords.VXLAN_PARAMS:
+                raise HoneycombError("The parameter {0} is invalid.".
+                                     format(param))
+            vx_lan_structure[param] = value
+
+        path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
         return InterfaceKeywords._set_interface_properties(
         return InterfaceKeywords._set_interface_properties(
-            node, interface, path, value)
+            node, interface, path, vx_lan_structure)
 
     @staticmethod
     def configure_interface_l2(node, interface, param, value):
 
     @staticmethod
     def configure_interface_l2(node, interface, param, value):
@@ -711,3 +813,263 @@ class InterfaceKeywords(object):
                 param)
         return InterfaceKeywords._set_interface_properties(
             node, interface, path, value)
                 param)
         return InterfaceKeywords._set_interface_properties(
             node, interface, path, value)
+
+    @staticmethod
+    def create_tap_interface(node, interface, **kwargs):
+        """Create a new TAP interface.
+
+        :param node: Honeycomb node.
+        :param interface: The name of interface.
+        :param kwargs: Parameters and their values. The accepted parameters are
+        defined in InterfaceKeywords.TAP_PARAMS.
+        :type node: dict
+        :type interface: str
+        :type kwargs: dict
+        :return: Content of response.
+        :rtype: bytearray
+        :raises HoneycombError: If the parameter is not valid.
+        """
+
+        new_tap = {
+            "name": interface,
+            "type": "v3po:tap",
+            "v3po:tap": {}
+        }
+        for param, value in kwargs.items():
+            if param not in InterfaceKeywords.TAP_PARAMS:
+                raise HoneycombError("The parameter {0} is invalid.".
+                                     format(param))
+            new_tap["v3po:tap"][param] = value
+
+        path = ("interfaces", "interface")
+        new_tap_structure = [new_tap, ]
+        return InterfaceKeywords._set_interface_properties(
+            node, interface, path, new_tap_structure)
+
+    @staticmethod
+    def configure_interface_tap(node, interface, **kwargs):
+        """Configure TAP on the interface.
+
+        The keyword configures TAP parameters on the given interface. The type
+        of interface must be set to "v3po:tap".
+        The new TAP parameters overwrite the current configuration. If a
+        parameter in new configuration is missing, it is removed from TAP
+        configuration.
+        If the dictionary kwargs is empty, TAP configuration is removed.
+
+        :param node: Honeycomb node.
+        :param interface: The name of interface.
+        :param kwargs: Parameters and their values. The accepted parameters are
+        defined in InterfaceKeywords.TAP_PARAMS.
+        :type node: dict
+        :type interface: str
+        :type kwargs: dict
+        :return: Content of response.
+        :rtype: bytearray
+        :raises HoneycombError: If the parameter is not valid.
+        """
+
+        tap_structure = dict()
+        for param, value in kwargs.items():
+            if param not in InterfaceKeywords.TAP_PARAMS:
+                raise HoneycombError("The parameter {0} is invalid.".
+                                     format(param))
+            tap_structure[param] = value
+
+        path = ("interfaces", ("interface", "name", interface), "v3po:tap")
+        return InterfaceKeywords._set_interface_properties(
+            node, interface, path, tap_structure)
+
+    @staticmethod
+    def configure_interface_vhost_user(node, interface, **kwargs):
+        """Configure vhost-user on the interface.
+
+        The keyword configures vhost-user parameters on the given interface.
+        The type of interface must be set to "v3po:vhost-user".
+        The new vhost-user parameters overwrite the current configuration. If a
+        parameter in new configuration is missing, it is removed from vhost-user
+        configuration.
+        If the dictionary kwargs is empty, vhost-user configuration is removed.
+
+        :param node: Honeycomb node.
+        :param interface: The name of interface.
+        :param kwargs: Parameters and their values. The accepted parameters are
+        defined in InterfaceKeywords.VHOST_USER_PARAMS.
+        :type node: dict
+        :type interface: str
+        :type kwargs: dict
+        :return: Content of response.
+        :rtype: bytearray
+        :raises HoneycombError: If the parameter is not valid.
+        """
+
+        vhost_structure = dict()
+        for param, value in kwargs.items():
+            if param not in InterfaceKeywords.VHOST_USER_PARAMS:
+                raise HoneycombError("The parameter {0} is invalid.".
+                                     format(param))
+            vhost_structure[param] = value
+
+        path = ("interfaces", ("interface", "name", interface),
+                "v3po:vhost-user")
+        return InterfaceKeywords._set_interface_properties(
+            node, interface, path, vhost_structure)
+
+    @staticmethod
+    def create_vhost_user_interface(node, interface, **kwargs):
+        """Create a new vhost-user interface.
+
+        :param node: Honeycomb node.
+        :param interface: The name of interface.
+        :param kwargs: Parameters and their values. The accepted parameters are
+        defined in InterfaceKeywords.VHOST_USER_PARAMS.
+        :type node: dict
+        :type interface: str
+        :type kwargs: dict
+        :return: Content of response.
+        :rtype: bytearray
+        :raises HoneycombError: If the parameter is not valid.
+        """
+
+        new_vhost = {
+            "name": interface,
+            "type": "v3po:vhost-user",
+            "v3po:vhost-user": {}
+        }
+        for param, value in kwargs.items():
+            if param not in InterfaceKeywords.VHOST_USER_PARAMS:
+                raise HoneycombError("The parameter {0} is invalid.".
+                                     format(param))
+            new_vhost["v3po:vhost-user"][param] = value
+
+        path = ("interfaces", "interface")
+        new_vhost_structure = [new_vhost, ]
+        return InterfaceKeywords._set_interface_properties(
+            node, interface, path, new_vhost_structure)
+
+    @staticmethod
+    def create_sub_interface(node, super_interface, identifier, **kwargs):
+        """Create a new sub-interface.
+
+        :param node: Honeycomb node.
+        :param super_interface: The name of super interface.
+        :param identifier: sub-interface identifier.
+        :param kwargs: Parameters and their values. The accepted parameters are
+        defined in InterfaceKeywords.SUB_INTF_PARAMS.
+        :type node: dict
+        :type super_interface: str
+        :type identifier: int
+        :type kwargs: dict
+        :return: Content of response.
+        :rtype: bytearray
+        :raises HoneycombError: If the parameter is not valid.
+        """
+
+        # These parameters are empty types (in JSON represented as empty
+        # dictionary) but ODL internally represents them as Booleans. If the
+        # value is an empty dictionary, it is True, if the parameter is
+        # missing, it is False.
+        empty_types = ("match-any-outer-id",
+                       "match-any-inner-id",
+                       "exact-match",
+                       "default-subif")
+
+        sub_interface_name = "{0}.{1}".format(super_interface, str(identifier))
+        new_sub_interface = {
+            "name": sub_interface_name,
+            "type": "v3po:sub-interface",
+            "enabled": "false",
+            "sub-interface": {
+                "super-interface": super_interface,
+                "identifier": identifier
+            }
+        }
+        for param, value in kwargs.items():
+            if param in InterfaceKeywords.INTF_PARAMS:
+                new_sub_interface[param] = value
+            elif param in InterfaceKeywords.SUB_INTF_PARAMS:
+                if param in empty_types:
+                    if value:
+                        new_sub_interface["sub-interface"][param] = dict()
+                else:
+                    new_sub_interface["sub-interface"][param] = value
+            else:
+                raise HoneycombError("The parameter {0} is invalid.".
+                                     format(param))
+
+        path = ("interfaces", "interface")
+        new_sub_interface_structure = [new_sub_interface, ]
+        return InterfaceKeywords._set_interface_properties(
+            node, sub_interface_name, path, new_sub_interface_structure)
+
+    @staticmethod
+    def add_vlan_tag_rewrite_to_sub_interface(node, sub_interface, **kwargs):
+        """Add vlan tag rewrite to a sub-interface.
+
+        :param node: Honeycomb node.
+        :param sub_interface: The name of sub-interface.
+        :param kwargs: Parameters and their values. The accepted parameters are
+        defined in InterfaceKeywords.L2_REWRITE_TAG_PARAMS.
+        :type node: dict
+        :type sub_interface: str
+        :type kwargs: dict
+        :return: Content of response.
+        :rtype: bytearray
+        :raises HoneycombError: If the parameter is not valid.
+        """
+
+        new_rewrite = dict()
+        for param, value in kwargs.items():
+            if param in InterfaceKeywords.L2_REWRITE_TAG_PARAMS:
+                new_rewrite[param] = value
+            else:
+                raise HoneycombError("The parameter {0} is invalid.".
+                                     format(param))
+
+        path = ("interfaces", ("interface", "name", sub_interface), "v3po:l2",
+                "vlan-tag-rewrite")
+        return InterfaceKeywords._set_interface_properties(
+            node, sub_interface, path, new_rewrite)
+
+    @staticmethod
+    def remove_vlan_tag_rewrite_from_sub_interface(node, sub_interface):
+        """Remove vlan tag rewrite from a sub-interface.
+
+        :param node: Honeycomb node.
+        :param sub_interface: The name of sub-interface.
+        :type node: dict
+        :type sub_interface: str
+        :rtype: bytearray
+        :raises HoneycombError: If the parameter is not valid.
+        """
+
+        path = ("interfaces", ("interface", "name", sub_interface), "v3po:l2",
+                "vlan-tag-rewrite")
+        return InterfaceKeywords._set_interface_properties(
+            node, sub_interface, path, None)
+
+    @staticmethod
+    def compare_interface_lists(list1, list2):
+        """Compare provided lists of interfaces by name.
+
+        :param list1: List of interfaces.
+        :param list2: List of interfaces.
+        :type list1: list
+        :type list2: list
+        :raises HoneycombError: If an interface exists in only one of the lists.
+        """
+
+        ignore = ["vx_tunnel0", "vxlan_gpe_tunnel0"]
+        # these have no equivalent in config data and no effect on VPP
+
+        names1 = [x['name'] for x in list1]
+        names2 = [x['name'] for x in list2]
+
+        for name in names1:
+            if name not in names2 and name not in ignore:
+                raise HoneycombError("Interface {0} not present in list {1}"
+                                     .format(name, list2))
+        for name in names2:
+            if name not in names1 and name not in ignore:
+                raise HoneycombError("Interface {0} not present in list {1}"
+                                     .format(name, list1))