-# Copyright (c) 2017 Cisco and/or its affiliates.
+# Copyright (c) 2018 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:
"""
from robot.api import logger
-from resources.libraries.python.topology import Topology
from resources.libraries.python.HTTPRequest import HTTPCodes
from resources.libraries.python.honeycomb.HoneycombSetup import HoneycombError
from resources.libraries.python.honeycomb.HoneycombUtil \
import DataRepresentation
from resources.libraries.python.honeycomb.HoneycombUtil \
import HoneycombUtil as HcUtil
+from resources.libraries.python.topology import Topology
class InterfaceKeywords(object):
VXLAN_PARAMS = ("src", "dst", "vni", "encap-vrf-id")
L2_PARAMS = ("bridge-domain", "split-horizon-group",
"bridged-virtual-interface")
- TAP_PARAMS = ("tap-name", "mac", "device-instance")
+ TAP_PARAMS = ("id", "tx-ring-size", "rx-ring-size", "host-mac",
+ "host-interface-name", "host-namespace", "host-bridge",
+ "host-ipv4-address", "host-ipv6-address", "tag",
+ "host-ipv4-gateway", "host-ipv6-gateway", "mac")
VHOST_USER_PARAMS = ("socket", "role")
SUB_IF_PARAMS = ("identifier",
"vlan-type",
:returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the status code in response on PUT is not
- 200 = OK.
+ 200 = OK.
"""
status_code, resp = HcUtil.\
"Not possible to get operational information about the "
"interfaces. Status code: {0}.".format(status_code))
try:
- return resp["interfaces-state"]["interface"]
+ return resp["interfaces"]["interface"]
except (KeyError, TypeError):
return []
: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:
:param interface: The name of interface.
:param path: Path to data we want to change / create / remove.
:param new_value: The new value to be set. If None, the item will be
- removed.
+ removed.
:type node: dict
:type interface: str
:type path: tuple
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
:param node: Honeycomb node.
:param interface: Interface name, key, link name or sw_if_index.
:param state: The requested state, only "up" and "down" are valid
- values.
+ values.
:type node: dict
:type interface: str
:type state: str
: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):
: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,
:param interface: Interface name, key, link name or sw_if_index.
:type node: dict
:type interface: str or int
-
:raises HoneycombError: If the operation fails.
"""
:type node: dict
:type interface: str
:returns: Operational data about bridge domain settings in the
- interface.
+ interface.
:rtype: dict
"""
: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.
+ removed.
:type node: dict
:type interface: str
:type param: str
: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.
+ removed.
:type node: dict
:type interface: str
:type param: str
: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):
- 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):
- address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
+ data = {
+ "ietf-ip:ipv4": {
+ "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)
+ 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):
:rtype: bytearray
"""
+ interface = Topology.convert_interface_reference(
+ node, interface, "name")
+
path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
"address")
return InterfaceKeywords._set_interface_properties(
:rtype: bytearray
"""
+ interface = Topology.convert_interface_reference(
+ node, interface, "name")
+
path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
"neighbor")
return InterfaceKeywords._set_interface_properties(
: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.
+ removed.
:type node: dict
:type interface: str
:type param: str
: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}, ]
:rtype: bytearray
"""
+ interface = Topology.convert_interface_reference(
+ node, interface, "name")
+
path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
"address")
return InterfaceKeywords._set_interface_properties(
:rtype: bytearray
"""
+ interface = Topology.convert_interface_reference(
+ node, interface, "name")
+
path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
"neighbor")
return InterfaceKeywords._set_interface_properties(
: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.
+ removed.
:type node: dict
:type interface: str
:type param: str
: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.
+ removed.
:type node: dict
:type interface: str
:type param: str
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.
:param interface: The name of interface.
:param kwargs: Parameters and their values. The accepted parameters are
- defined in InterfaceKeywords.VXLAN_PARAMS.
+ defined in InterfaceKeywords.VXLAN_PARAMS.
:type node: dict
:type interface: str
:type kwargs: dict
: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.
+ interfaces or it is not possible to delete the interface.
"""
path = ("interfaces", ("interface", "name", interface))
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
: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.
+ defined in InterfaceKeywords.VXLAN_PARAMS.
:type node: dict
:type interface: str
:type kwargs: dict
: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.
+ removed.
:type node: dict
:type interface: str
:type param: str
: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.
+ defined in InterfaceKeywords.TAP_PARAMS.
:type node: dict
:type interface: str
:type kwargs: dict
new_tap = {
"name": interface,
- "type": "v3po:tap",
- "v3po:tap": {}
+ "type": "v3po:tap-v2",
+ "v3po:tap-v2": {}
}
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
+ raise HoneycombError(
+ "The parameter {0} is invalid.".format(param))
+ new_tap["v3po:tap-v2"][param] = value
path = ("interfaces", "interface")
new_tap_structure = [new_tap, ]
"""Configure TAP on the interface.
The keyword configures TAP parameters on the given interface. The type
- of interface must be set to "v3po:tap".
+ of interface must be set to "v3po:tap-v2".
The new TAP parameters overwrite the current configuration. If a
parameter in new configuration is missing, it is removed from TAP
configuration.
: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.
+ defined in InterfaceKeywords.TAP_PARAMS.
:type node: dict
:type interface: str
:type kwargs: dict
format(param))
tap_structure[param] = value
- path = ("interfaces", ("interface", "name", interface), "v3po:tap")
+ path = ("interfaces", ("interface", "name", interface), "v3po:tap-v2")
return InterfaceKeywords._set_interface_properties(
node, interface, path, tap_structure)
: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.
+ defined in InterfaceKeywords.VHOST_USER_PARAMS.
:type node: dict
:type interface: str
:type kwargs: dict
: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.
+ defined in InterfaceKeywords.VHOST_USER_PARAMS.
:type node: dict
:type interface: str
:type kwargs: dict
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.
:param super_interface: Super interface.
:param match: Match type. The valid values are defined in
- InterfaceKeywords.SUB_IF_MATCH.
+ InterfaceKeywords.SUB_IF_MATCH.
:param tags: List of tags.
:param kwargs: Parameters and their values. The accepted parameters are
- defined in InterfaceKeywords.SUB_IF_PARAMS.
+ defined in InterfaceKeywords.SUB_IF_PARAMS.
:type node: dict
:type super_interface: str
:type match: str
:raises KeyError: If the parameter 'match' is invalid.
"""
+ super_interface = Topology.convert_interface_reference(
+ node, super_interface, "name")
+
match_type = {
"default":
{"default": {}},
:rtype: bytearray
"""
+ super_interface = Topology.convert_interface_reference(
+ node, super_interface, "name")
+
intf_state = {"up": "true",
"down": "false"}
:param data: Data to be checked.
:param ref: Referential data used for comparison.
:param _path: Used in recursive calls, stores the path taken down
- the JSON tree.
+ the JSON tree.
:type data: dict
:type ref: dict
:type _path: str
:raises HoneycombError: If the data structures do not match in some way,
- or if they are not in deserialized JSON format.
+ or if they are not in deserialized JSON format.
"""
if data == ref:
:param node: Honeycomb node.
:param interface: The name of interface to be created.
:param kwargs: Parameters and their values. The accepted parameters are
- defined in InterfaceKeywords.VXLAN_GPE_PARAMS.
+ defined in InterfaceKeywords.VXLAN_GPE_PARAMS.
:type node: dict
:type interface: str
:type kwargs: dict
:returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the configuration of interface is not
- successful.
+ successful.
"""
interface = interface.replace("/", "%2F")
"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.
:returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the configuration of interface is not
- successful.
+ successful.
"""
interface = interface.replace("/", "%2F")
:param node: Honeycomb node.
:param intf: The interface where PBB sub-interface will be configured.
:param params: Configuration parameters of the sub-interface to be
- created.
+ created.
:type node: dict
:type intf: str
:type params: dict
:returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the configuration of sub-interface is not
- successful.
+ successful.
"""
interface = intf.replace("/", "%2F")
- path = "/interface/{0}/pbb-rewrite/".format(interface)
+ path = "/interface/{0}/pbb-rewrite".format(interface)
status_code, resp = HcUtil. \
put_honeycomb_data(node, "config_vpp_interfaces", params, path,
data_representation=DataRepresentation.JSON)
:returns: Content of response.
:rtype: bytearray
:raises HoneycombError: If the removal of sub-interface is not
- successful.
+ successful.
"""
interface = intf.replace("/", "%2F")
:returns: PBB sub-interface operational data.
:rtype: dict
:raises HoneycombError: If the removal of sub-interface is not
- successful.
+ successful.
"""
raise NotImplementedError
: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.
- """
+ 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
" 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.
: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.
"""
- 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)
+ 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(
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