1 # Copyright (c) 2017 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 """Keywords to manipulate interface configuration using Honeycomb REST API.
16 The keywords make possible to put and get configuration data and to get
19 from robot.api import logger
21 from resources.libraries.python.topology import Topology
22 from resources.libraries.python.HTTPRequest import HTTPCodes
23 from resources.libraries.python.honeycomb.HoneycombSetup import HoneycombError
24 from resources.libraries.python.honeycomb.HoneycombUtil \
25 import DataRepresentation
26 from resources.libraries.python.honeycomb.HoneycombUtil \
27 import HoneycombUtil as HcUtil
30 class InterfaceKeywords(object):
31 """Keywords for Interface manipulation.
33 Implements keywords which get configuration and operational data about
34 vpp interfaces and set the interface's parameters using Honeycomb REST API.
37 INTF_PARAMS = ("name", "description", "type", "enabled",
38 "link-up-down-trap-enable", "v3po:l2", "v3po:vxlan-gpe",
39 "vpp-vlan:sub-interfaces")
40 IPV4_PARAMS = ("enabled", "forwarding", "mtu")
41 IPV6_PARAMS = ("enabled", "forwarding", "mtu", "dup-addr-detect-transmits")
42 IPV6_AUTOCONF_PARAMS = ("create-global-addresses",
43 "create-temporary-addresses",
44 "temporary-valid-lifetime",
45 "temporary-preferred-lifetime")
46 ETH_PARAMS = ("mtu", )
47 ROUTING_PARAMS = ("ipv4-vrf-id", "ipv6-vrf-id")
48 VXLAN_PARAMS = ("src", "dst", "vni", "encap-vrf-id")
49 L2_PARAMS = ("bridge-domain", "split-horizon-group",
50 "bridged-virtual-interface")
51 TAP_PARAMS = ("tap-name", "mac", "device-instance")
52 VHOST_USER_PARAMS = ("socket", "role")
53 SUB_IF_PARAMS = ("identifier",
56 SUB_IF_MATCH = ("default",
59 "vlan-tagged-exact-match")
60 BD_PARAMS = ("bridge-domain",
61 "split-horizon-group",
62 "bridged-virtual-interface")
63 VXLAN_GPE_PARAMS = ("local",
74 def _configure_interface(node, interface, data,
75 data_representation=DataRepresentation.JSON):
76 """Send interface configuration data and check the response.
78 :param node: Honeycomb node.
79 :param interface: The name of interface.
80 :param data: Configuration data to be sent in PUT request.
81 :param data_representation: How the data is represented.
85 :type data_representation: DataRepresentation
86 :returns: Content of response.
88 :raises HoneycombError: If the status code in response on PUT is not
92 status_code, resp = HcUtil.\
93 put_honeycomb_data(node, "config_vpp_interfaces", data,
94 data_representation=data_representation)
95 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
97 "The configuration of interface '{0}' was not successful. "
98 "Status code: {1}.".format(interface, status_code))
102 def get_all_interfaces_cfg_data(node):
103 """Get configuration data about all interfaces from Honeycomb.
105 :param node: Honeycomb node.
107 :returns: Configuration data about all interfaces from Honeycomb.
109 :raises HoneycombError: If it is not possible to get configuration data.
112 status_code, resp = HcUtil.\
113 get_honeycomb_data(node, "config_vpp_interfaces")
114 if status_code != HTTPCodes.OK:
115 raise HoneycombError(
116 "Not possible to get configuration information about the "
117 "interfaces. Status code: {0}.".format(status_code))
119 return resp["interfaces"]["interface"]
121 except (KeyError, TypeError):
125 def get_interface_cfg_data(node, interface):
126 """Get configuration data about the given interface from Honeycomb.
128 :param node: Honeycomb node.
129 :param interface: The name of interface.
132 :returns: Configuration data about the given interface from Honeycomb.
136 intfs = InterfaceKeywords.get_all_interfaces_cfg_data(node)
138 if intf["name"] == interface:
143 def get_all_interfaces_oper_data(node):
144 """Get operational data about all interfaces from Honeycomb.
146 :param node: Honeycomb node.
148 :returns: Operational data about all interfaces from Honeycomb.
150 :raises HoneycombError: If it is not possible to get operational data.
153 status_code, resp = HcUtil.\
154 get_honeycomb_data(node, "oper_vpp_interfaces")
155 if status_code != HTTPCodes.OK:
156 raise HoneycombError(
157 "Not possible to get operational information about the "
158 "interfaces. Status code: {0}.".format(status_code))
160 return resp["interfaces-state"]["interface"]
162 except (KeyError, TypeError):
166 def get_disabled_interfaces_oper_data(node):
167 """Get operational data about all disabled interfaces from Honeycomb.
169 :param node: Honeycomb node.
171 :returns: Operational data about disabled interfaces.
173 :raises HoneycombError: If it is not possible to get operational data.
176 status_code, resp = HcUtil. \
177 get_honeycomb_data(node, "oper_disabled_interfaces")
178 if status_code == HTTPCodes.NOT_FOUND:
179 raise HoneycombError(
180 "No disabled interfaces present on node."
182 if status_code != HTTPCodes.OK:
183 raise HoneycombError(
184 "Not possible to get operational information about the "
185 "interfaces. Status code: {0}.".format(status_code))
187 return resp["disabled-interfaces"]["disabled-interface-index"]
189 except (KeyError, TypeError):
193 def get_interface_oper_data(node, interface):
194 """Get operational data about the given interface from Honeycomb.
196 :param node: Honeycomb node.
197 :param interface: The name of interface.
200 :returns: Operational data about the given interface from Honeycomb.
205 interface = Topology.convert_interface_reference(
206 node, interface, "name")
208 if isinstance(interface, basestring):
209 # Probably name of a custom interface (TAP, VxLAN, Vhost, ...)
214 intfs = InterfaceKeywords.get_all_interfaces_oper_data(node)
216 if intf["name"] == interface:
221 def _set_interface_properties(node, interface, path, new_value=None):
222 """Set interface properties.
224 This method reads interface configuration data, creates, changes or
225 removes the requested data and puts it back to Honeycomb.
227 :param node: Honeycomb node.
228 :param interface: The name of interface.
229 :param path: Path to data we want to change / create / remove.
230 :param new_value: The new value to be set. If None, the item will be
235 :type new_value: str, dict or list
236 :returns: Content of response.
238 :raises HoneycombError: If it is not possible to get or set the data.
241 status_code, resp = HcUtil.\
242 get_honeycomb_data(node, "config_vpp_interfaces")
243 if status_code != HTTPCodes.OK:
244 raise HoneycombError(
245 "Not possible to get configuration information about the "
246 "interfaces. Status code: {0}.".format(status_code))
249 new_data = HcUtil.set_item_value(resp, path, new_value)
251 new_data = HcUtil.remove_item(resp, path)
252 return InterfaceKeywords._configure_interface(node, interface, new_data)
255 def honeycomb_set_interface_state(node, interface, state="up"):
256 """Set VPP interface state.
258 The keyword changes the administration state of interface to up or down
259 depending on the parameter "state".
261 :param node: Honeycomb node.
262 :param interface: Interface name, key, link name or sw_if_index.
263 :param state: The requested state, only "up" and "down" are valid
268 :returns: Content of response.
270 :raises KeyError: If the argument "state" is nor "up" or "down".
271 :raises HoneycombError: If the interface is not present on the node.
274 intf_state = {"up": "true",
277 interface = Topology.convert_interface_reference(
278 node, interface, "name")
280 intf = interface.replace("/", "%2F")
281 path = "/interface/{0}".format(intf)
283 status_code, resp = HcUtil.\
284 get_honeycomb_data(node, "config_vpp_interfaces", path)
285 if status_code != HTTPCodes.OK:
286 raise HoneycombError(
287 "Not possible to get configuration information about the "
288 "interfaces. Status code: {0}.".format(status_code))
290 resp["interface"][0]["enabled"] = intf_state[state.lower()]
292 status_code, resp = HcUtil. \
293 put_honeycomb_data(node, "config_vpp_interfaces", resp, path,
294 data_representation=DataRepresentation.JSON)
295 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
296 raise HoneycombError(
297 "The configuration of interface '{0}' was not successful. "
298 "Status code: {1}.".format(interface, status_code))
302 def set_interface_up(node, interface):
303 """Set the administration state of VPP interface to up.
305 :param node: Honeycomb node.
306 :param interface: The name of interface.
309 :returns: Content of response
313 return InterfaceKeywords.honeycomb_set_interface_state(
314 node, interface, "up")
317 def set_interface_down(node, interface):
318 """Set the administration state of VPP interface to down.
320 :param node: Honeycomb node.
321 :param interface: The name of interface.
324 :returns: Content of response.
328 return InterfaceKeywords.honeycomb_set_interface_state(
329 node, interface, "down")
332 def add_bridge_domain_to_interface(node, interface, bd_name,
333 split_horizon_group=None, bvi=None):
334 """Add a new bridge domain to an interface and set its parameters.
336 :param node: Honeycomb node.
337 :param interface: Interface name, key, link name or sw_if_index.
338 :param bd_name: Bridge domain name.
339 :param split_horizon_group: Split-horizon group name.
340 :param bvi: The bridged virtual interface.
344 :type split_horizon_group: str
346 :returns: Content of response.
348 :raises HoneycombError: If the interface is not present on the node.
351 interface = Topology.convert_interface_reference(
352 node, interface, "name")
354 v3po_l2 = {"bridge-domain": str(bd_name)}
355 if split_horizon_group:
356 v3po_l2["split-horizon-group"] = str(split_horizon_group)
358 v3po_l2["bridged-virtual-interface"] = str(bvi)
360 path = ("interfaces", ("interface", "name", str(interface)), "v3po:l2")
362 return InterfaceKeywords._set_interface_properties(
363 node, interface, path, v3po_l2)
366 def remove_bridge_domain_from_interface(node, interface):
367 """Remove bridge domain assignment from interface.
369 :param node: Honeycomb node.
370 :param interface: Interface name, key, link name or sw_if_index.
372 :type interface: str or int
374 :raises HoneycombError: If the operation fails.
377 interface = Topology.convert_interface_reference(
378 node, interface, "name")
380 intf = interface.replace("/", "%2F")
382 path = "/interface/{0}/v3po:l2".format(intf)
384 status_code, response = HcUtil.delete_honeycomb_data(
385 node, "config_vpp_interfaces", path)
387 if status_code != HTTPCodes.OK:
388 if '"error-tag":"data-missing"' in response:
389 logger.debug("Data does not exist in path.")
391 raise HoneycombError(
392 "Could not remove bridge domain assignment from interface "
393 "'{0}'. Status code: {1}.".format(interface, status_code))
396 def get_bd_oper_data_from_interface(node, interface):
397 """Returns operational data about bridge domain settings in the
400 :param node: Honeycomb node.
401 :param interface: The name of interface.
404 :returns: Operational data about bridge domain settings in the
409 if_data = InterfaceKeywords.get_interface_oper_data(node, interface)
413 return if_data["v3po:l2"]
419 def configure_interface_base(node, interface, param, value):
420 """Configure the base parameters of interface.
422 :param node: Honeycomb node.
423 :param interface: The name of interface.
424 :param param: Parameter to configure (set, change, remove)
425 :param value: The value of parameter. If None, the parameter will be
431 :returns: Content of response.
433 :raises HoneycombError: If the parameter is not valid.
436 if param not in InterfaceKeywords.INTF_PARAMS:
437 raise HoneycombError("The parameter {0} is invalid.".format(param))
439 path = ("interfaces", ("interface", "name", interface), param)
440 return InterfaceKeywords._set_interface_properties(
441 node, interface, path, value)
444 def configure_interface_ipv4(node, interface, param, value):
445 """Configure IPv4 parameters of interface.
447 :param node: Honeycomb node.
448 :param interface: The name of interface.
449 :param param: Parameter to configure (set, change, remove)
450 :param value: The value of parameter. If None, the parameter will be
456 :returns: Content of response.
458 :raises HoneycombError: If the parameter is not valid.
461 interface = Topology.convert_interface_reference(
462 node, interface, "name")
464 if param not in InterfaceKeywords.IPV4_PARAMS:
465 raise HoneycombError("The parameter {0} is invalid.".format(param))
467 path = ("interfaces", ("interface", "name", interface),
468 "ietf-ip:ipv4", param)
469 return InterfaceKeywords._set_interface_properties(
470 node, interface, path, value)
473 def add_first_ipv4_address(node, interface, ip_addr, network):
474 """Add the first IPv4 address.
476 If there are any other addresses configured, they will be removed.
478 :param node: Honeycomb node.
479 :param interface: The name of interface.
480 :param ip_addr: IPv4 address to be set.
481 :param network: Netmask or length of network prefix.
485 :type network: str or int
486 :returns: Content of response.
488 :raises ValueError: If the provided netmask or prefix is not valid.
489 :raises HoneycombError: If the operation fails.
492 interface = InterfaceKeywords.handle_interface_reference(
495 path = "/interface/{0}/ietf-ip:ipv4".format(interface)
496 if isinstance(network, basestring):
499 "address": [{"ip": ip_addr, "netmask": network}, ]}}
500 elif isinstance(network, int) and (0 < network < 33):
503 "address": [{"ip": ip_addr, "prefix-length": network}, ]}}
505 raise ValueError("Value {0} is not a valid netmask or network "
506 "prefix length.".format(network))
507 status_code, _ = HcUtil.put_honeycomb_data(
508 node, "config_vpp_interfaces", data, path)
510 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
511 raise HoneycombError(
512 "Configuring IPv4 address failed. "
513 "Status code:{0}".format(status_code))
516 def add_ipv4_address(node, interface, ip_addr, network):
519 :param node: Honeycomb node.
520 :param interface: The name of interface.
521 :param ip_addr: IPv4 address to be set.
522 :param network: Netmask or length of network prefix.
526 :type network: str or int
527 :returns: Content of response.
529 :raises HoneycombError: If the provided netmask or prefix is not valid.
532 interface = Topology.convert_interface_reference(
533 node, interface, "name")
535 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
537 if isinstance(network, basestring):
538 address = [{"ip": ip_addr, "netmask": network}]
539 elif isinstance(network, int) and (0 < network < 33):
540 address = [{"ip": ip_addr, "prefix-length": network}]
542 raise HoneycombError("Value {0} is not a valid netmask or network "
543 "prefix length.".format(network))
544 return InterfaceKeywords._set_interface_properties(
545 node, interface, path, address)
548 def remove_all_ipv4_addresses(node, interface):
549 """Remove all IPv4 addresses from interface.
551 :param node: Honeycomb node.
552 :param interface: The name of interface.
555 :returns: Content of response.
559 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
561 return InterfaceKeywords._set_interface_properties(
562 node, interface, path, None)
565 def add_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
566 """Add the IPv4 neighbour.
568 :param node: Honeycomb node.
569 :param interface: The name of interface.
570 :param ip_addr: IPv4 address of neighbour to be set.
571 :param link_layer_address: Link layer address.
575 :type link_layer_address: str
576 :returns: Content of response.
580 interface = Topology.convert_interface_reference(
581 node, interface, "name")
583 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
585 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
586 return InterfaceKeywords._set_interface_properties(
587 node, interface, path, neighbor)
590 def remove_all_ipv4_neighbors(node, interface):
591 """Remove all IPv4 neighbours.
593 :param node: Honeycomb node.
594 :param interface: The name of interface.
597 :returns: Content of response.
601 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
603 return InterfaceKeywords._set_interface_properties(
604 node, interface, path, None)
607 def configure_interface_ipv6(node, interface, param, value):
608 """Configure IPv6 parameters of interface
610 :param node: Honeycomb node.
611 :param interface: The name of interface.
612 :param param: Parameter to configure (set, change, remove)
613 :param value: The value of parameter. If None, the parameter will be
619 :returns: Content of response.
621 :raises HoneycombError: If the parameter is not valid.
624 if param in InterfaceKeywords.IPV6_PARAMS:
625 path = ("interfaces", ("interface", "name", interface),
626 "ietf-ip:ipv6", param)
627 elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
628 path = ("interfaces", ("interface", "name", interface),
629 "ietf-ip:ipv6", "autoconf", param)
631 raise HoneycombError("The parameter {0} is invalid.".format(param))
633 return InterfaceKeywords._set_interface_properties(
634 node, interface, path, value)
637 def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
638 """Add the first IPv6 address.
640 If there are any other addresses configured, they will be removed.
642 :param node: Honeycomb node.
643 :param interface: The name of interface.
644 :param ip_addr: IPv6 address to be set.
645 :param prefix_len: Prefix length.
649 :type prefix_len: str
650 :returns: Content of response.
654 interface = Topology.convert_interface_reference(
655 node, interface, "name")
657 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
658 address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
659 return InterfaceKeywords._set_interface_properties(
660 node, interface, path, address)
663 def add_ipv6_address(node, interface, ip_addr, prefix_len):
666 :param node: Honeycomb node.
667 :param interface: The name of interface.
668 :param ip_addr: IPv6 address to be set.
669 :param prefix_len: Prefix length.
673 :type prefix_len: str
674 :returns: Content of response.
678 interface = Topology.convert_interface_reference(
679 node, interface, "name")
681 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
683 address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
684 return InterfaceKeywords._set_interface_properties(
685 node, interface, path, address)
688 def remove_all_ipv6_addresses(node, interface):
689 """Remove all IPv6 addresses from interface.
691 :param node: Honeycomb node.
692 :param interface: The name of interface.
695 :returns: Content of response.
699 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
701 return InterfaceKeywords._set_interface_properties(
702 node, interface, path, None)
705 def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
706 """Add the IPv6 neighbour.
708 :param node: Honeycomb node.
709 :param interface: The name of interface.
710 :param ip_addr: IPv6 address of neighbour to be set.
711 :param link_layer_address: Link layer address.
715 :type link_layer_address: str
716 :returns: Content of response.
720 interface = Topology.convert_interface_reference(
721 node, interface, "name")
723 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
725 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
726 return InterfaceKeywords._set_interface_properties(
727 node, interface, path, neighbor)
730 def remove_all_ipv6_neighbors(node, interface):
731 """Remove all IPv6 neighbours.
733 :param node: Honeycomb node.
734 :param interface: The name of interface.
737 :returns: Content of response.
741 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
743 return InterfaceKeywords._set_interface_properties(
744 node, interface, path, None)
747 def configure_interface_ethernet(node, interface, param, value):
748 """Configure the ethernet parameters of interface.
750 :param node: Honeycomb node.
751 :param interface: The name of interface.
752 :param param: Parameter to configure (set, change, remove)
753 :param value: The value of parameter. If None, the parameter will be
759 :returns: Content of response.
761 :raises HoneycombError: If the parameter is not valid.
764 if param not in InterfaceKeywords.ETH_PARAMS:
765 raise HoneycombError("The parameter {0} is invalid.".format(param))
766 path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
768 return InterfaceKeywords._set_interface_properties(
769 node, interface, path, value)
772 def configure_interface_routing(node, interface, param, value):
773 """Configure the routing parameters of interface.
775 :param node: Honeycomb node.
776 :param interface: The name of interface.
777 :param param: Parameter to configure (set, change, remove)
778 :param value: The value of parameter. If None, the parameter will be
784 :returns: Content of response.
786 :raises HoneycombError: If the parameter is not valid.
789 interface = Topology.convert_interface_reference(
790 node, interface, "name")
792 if param not in InterfaceKeywords.ROUTING_PARAMS:
793 raise HoneycombError("The parameter {0} is invalid.".format(param))
795 path = ("interfaces", ("interface", "name", interface), "v3po:routing",
797 return InterfaceKeywords._set_interface_properties(
798 node, interface, path, value)
801 def honeycomb_create_vxlan_interface(node, interface, **kwargs):
802 """Create a new VxLAN interface.
804 :param node: Honeycomb node.
805 :param interface: The name of interface.
806 :param kwargs: Parameters and their values. The accepted parameters are
807 defined in InterfaceKeywords.VXLAN_PARAMS.
811 :returns: Content of response.
813 :raises HoneycombError: If the parameter is not valid.
818 "type": "v3po:vxlan-tunnel",
821 for param, value in kwargs.items():
822 if param not in InterfaceKeywords.VXLAN_PARAMS:
823 raise HoneycombError("The parameter {0} is invalid.".
825 new_vx_lan["v3po:vxlan"][param] = value
827 path = ("interfaces", "interface")
828 vx_lan_structure = [new_vx_lan, ]
829 return InterfaceKeywords._set_interface_properties(
830 node, interface, path, vx_lan_structure)
833 def delete_interface(node, interface):
834 """Delete an interface.
836 :param node: Honeycomb node.
837 :param interface: The name of interface.
840 :returns: Content of response.
842 :raises HoneycombError: If it is not possible to get information about
843 interfaces or it is not possible to delete the interface.
846 path = ("interfaces", ("interface", "name", interface))
848 status_code, resp = HcUtil.\
849 get_honeycomb_data(node, "config_vpp_interfaces")
850 if status_code != HTTPCodes.OK:
851 raise HoneycombError(
852 "Not possible to get configuration information about the "
853 "interfaces. Status code: {0}.".format(status_code))
855 new_data = HcUtil.remove_item(resp, path)
856 status_code, resp = HcUtil.\
857 put_honeycomb_data(node, "config_vpp_interfaces", new_data)
858 if status_code != HTTPCodes.OK:
859 raise HoneycombError("Not possible to remove interface {0}. "
861 format(interface, status_code))
865 def honeycomb_configure_interface_vxlan(node, interface, **kwargs):
866 """Configure VxLAN on the interface.
868 The keyword configures VxLAN parameters on the given interface. The type
869 of interface must be set to "v3po:vxlan-tunnel".
870 The new VxLAN parameters overwrite the current configuration. If a
871 parameter in new configuration is missing, it is removed from VxLAN
873 If the dictionary kwargs is empty, VxLAN configuration is removed.
875 :param node: Honeycomb node.
876 :param interface: The name of interface.
877 :param kwargs: Parameters and their values. The accepted parameters are
878 defined in InterfaceKeywords.VXLAN_PARAMS.
882 :returns: Content of response.
884 :raises HoneycombError: If the parameter is not valid.
887 vx_lan_structure = dict()
888 for param, value in kwargs.items():
889 if param not in InterfaceKeywords.VXLAN_PARAMS:
890 raise HoneycombError("The parameter {0} is invalid.".
892 vx_lan_structure[param] = value
894 path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
895 return InterfaceKeywords._set_interface_properties(
896 node, interface, path, vx_lan_structure)
899 def configure_interface_l2(node, interface, param, value):
900 """Configure the L2 parameters of interface.
902 :param node: Honeycomb node.
903 :param interface: The name of interface.
904 :param param: Parameter to configure (set, change, remove)
905 :param value: The value of parameter. If None, the parameter will be
911 :returns: Content of response.
913 :raises HoneycombError: If the parameter is not valid.
916 if param not in InterfaceKeywords.L2_PARAMS:
917 raise HoneycombError("The parameter {0} is invalid.".format(param))
918 path = ("interfaces", ("interface", "name", interface), "v3po:l2",
920 return InterfaceKeywords._set_interface_properties(
921 node, interface, path, value)
924 def create_tap_interface(node, interface, **kwargs):
925 """Create a new TAP interface.
927 :param node: Honeycomb node.
928 :param interface: The name of interface.
929 :param kwargs: Parameters and their values. The accepted parameters are
930 defined in InterfaceKeywords.TAP_PARAMS.
934 :returns: Content of response.
936 :raises HoneycombError: If the parameter is not valid.
944 for param, value in kwargs.items():
945 if param not in InterfaceKeywords.TAP_PARAMS:
946 raise HoneycombError("The parameter {0} is invalid.".
948 new_tap["v3po:tap"][param] = value
950 path = ("interfaces", "interface")
951 new_tap_structure = [new_tap, ]
952 return InterfaceKeywords._set_interface_properties(
953 node, interface, path, new_tap_structure)
956 def configure_interface_tap(node, interface, **kwargs):
957 """Configure TAP on the interface.
959 The keyword configures TAP parameters on the given interface. The type
960 of interface must be set to "v3po:tap".
961 The new TAP parameters overwrite the current configuration. If a
962 parameter in new configuration is missing, it is removed from TAP
964 If the dictionary kwargs is empty, TAP configuration is removed.
966 :param node: Honeycomb node.
967 :param interface: The name of interface.
968 :param kwargs: Parameters and their values. The accepted parameters are
969 defined in InterfaceKeywords.TAP_PARAMS.
973 :returns: Content of response.
975 :raises HoneycombError: If the parameter is not valid.
978 tap_structure = dict()
979 for param, value in kwargs.items():
980 if param not in InterfaceKeywords.TAP_PARAMS:
981 raise HoneycombError("The parameter {0} is invalid.".
983 tap_structure[param] = value
985 path = ("interfaces", ("interface", "name", interface), "v3po:tap")
986 return InterfaceKeywords._set_interface_properties(
987 node, interface, path, tap_structure)
990 def configure_interface_vhost_user(node, interface, **kwargs):
991 """Configure vhost-user on the interface.
993 The keyword configures vhost-user parameters on the given interface.
994 The type of interface must be set to "v3po:vhost-user".
995 The new vhost-user parameters overwrite the current configuration. If a
996 parameter in new configuration is missing, it is removed from vhost-user
998 If the dictionary kwargs is empty, vhost-user configuration is removed.
1000 :param node: Honeycomb node.
1001 :param interface: The name of interface.
1002 :param kwargs: Parameters and their values. The accepted parameters are
1003 defined in InterfaceKeywords.VHOST_USER_PARAMS.
1005 :type interface: str
1007 :returns: Content of response.
1009 :raises HoneycombError: If the parameter is not valid.
1012 vhost_structure = dict()
1013 for param, value in kwargs.items():
1014 if param not in InterfaceKeywords.VHOST_USER_PARAMS:
1015 raise HoneycombError("The parameter {0} is invalid.".
1017 vhost_structure[param] = value
1019 path = ("interfaces", ("interface", "name", interface),
1021 return InterfaceKeywords._set_interface_properties(
1022 node, interface, path, vhost_structure)
1025 def create_vhost_user_interface(node, interface, **kwargs):
1026 """Create a new vhost-user interface.
1028 :param node: Honeycomb node.
1029 :param interface: The name of interface.
1030 :param kwargs: Parameters and their values. The accepted parameters are
1031 defined in InterfaceKeywords.VHOST_USER_PARAMS.
1033 :type interface: str
1035 :returns: Content of response.
1037 :raises HoneycombError: If the parameter is not valid.
1042 "type": "v3po:vhost-user",
1043 "v3po:vhost-user": {}
1045 for param, value in kwargs.items():
1046 if param not in InterfaceKeywords.VHOST_USER_PARAMS:
1047 raise HoneycombError("The parameter {0} is invalid.".
1049 new_vhost["v3po:vhost-user"][param] = value
1051 path = ("interfaces", "interface")
1052 new_vhost_structure = [new_vhost, ]
1053 return InterfaceKeywords._set_interface_properties(
1054 node, interface, path, new_vhost_structure)
1057 def honeycomb_create_sub_interface(node, super_interface, match, tags=None,
1059 """Create a new sub-interface.
1061 :param node: Honeycomb node.
1062 :param super_interface: Super interface.
1063 :param match: Match type. The valid values are defined in
1064 InterfaceKeywords.SUB_IF_MATCH.
1065 :param tags: List of tags.
1066 :param kwargs: Parameters and their values. The accepted parameters are
1067 defined in InterfaceKeywords.SUB_IF_PARAMS.
1069 :type super_interface: str
1073 :returns: Content of response.
1075 :raises HoneycombError: If the parameter is not valid.
1076 :raises KeyError: If the parameter 'match' is invalid.
1085 {"vlan-tagged": {"match-exact-tags": "false"}},
1086 "vlan-tagged-exact-match":
1087 {"vlan-tagged": {"match-exact-tags": "true"}}
1090 new_sub_interface = {
1096 for param, value in kwargs.items():
1097 if param in InterfaceKeywords.SUB_IF_PARAMS:
1098 new_sub_interface[param] = value
1100 raise HoneycombError("The parameter {0} is invalid.".
1103 new_sub_interface["match"] = match_type[match]
1105 raise HoneycombError("The value '{0}' of parameter 'match' is "
1106 "invalid.".format(match))
1109 new_sub_interface["tags"]["tag"].extend(tags)
1111 path = ("interfaces",
1112 ("interface", "name", super_interface),
1113 "vpp-vlan:sub-interfaces",
1115 new_sub_interface_structure = [new_sub_interface, ]
1116 return InterfaceKeywords._set_interface_properties(
1117 node, super_interface, path, new_sub_interface_structure)
1120 def get_sub_interface_oper_data(node, super_interface, identifier):
1121 """Retrieves sub-interface operational data using Honeycomb API.
1123 :param node: Honeycomb node.
1124 :param super_interface: Super interface.
1125 :param identifier: The ID of sub-interface.
1127 :type super_interface: str
1128 :type identifier: int
1129 :returns: Sub-interface operational data.
1131 :raises HoneycombError: If there is no sub-interface with the given ID.
1134 if_data = InterfaceKeywords.get_interface_oper_data(node,
1136 for sub_if in if_data["vpp-vlan:sub-interfaces"]["sub-interface"]:
1137 if str(sub_if["identifier"]) == str(identifier):
1140 raise HoneycombError("The interface {0} does not have sub-interface "
1141 "with ID {1}".format(super_interface, identifier))
1144 def remove_all_sub_interfaces(node, super_interface):
1145 """Remove all sub-interfaces from the given interface.
1147 :param node: Honeycomb node.
1148 :param super_interface: Super interface.
1150 :type super_interface: str
1151 :returns: Content of response.
1155 path = ("interfaces",
1156 ("interface", "name", super_interface),
1157 "vpp-vlan:sub-interfaces")
1159 return InterfaceKeywords._set_interface_properties(
1160 node, super_interface, path, {})
1163 def set_sub_interface_state(node, super_interface, identifier, state):
1164 """Set the administrative state of sub-interface.
1166 :param node: Honeycomb node.
1167 :param super_interface: Super interface.
1168 :param identifier: The ID of sub-interface.
1169 :param state: Required sub-interface state - up or down.
1171 :type super_interface: str
1172 :type identifier: int
1174 :returns: Content of response.
1178 super_interface = Topology.convert_interface_reference(
1179 node, super_interface, "name")
1181 intf_state = {"up": "true",
1184 path = ("interfaces",
1185 ("interface", "name", super_interface),
1186 "vpp-vlan:sub-interfaces",
1187 ("sub-interface", "identifier", int(identifier)),
1190 return InterfaceKeywords._set_interface_properties(
1191 node, super_interface, path, intf_state[state])
1194 def add_bridge_domain_to_sub_interface(node, super_interface, identifier,
1196 """Add a sub-interface to a bridge domain and set its parameters.
1198 :param node: Honeycomb node.
1199 :param super_interface: Super interface.
1200 :param identifier: The ID of sub-interface.
1201 :param config: Bridge domain configuration.
1203 :type super_interface: str
1204 :type identifier: int
1206 :returns: Content of response.
1210 path = ("interfaces",
1211 ("interface", "name", super_interface),
1212 "vpp-vlan:sub-interfaces",
1213 ("sub-interface", "identifier", int(identifier)),
1216 return InterfaceKeywords._set_interface_properties(
1217 node, super_interface, path, config)
1220 def get_bd_data_from_sub_interface(node, super_interface, identifier):
1221 """Get the operational data about the bridge domain from sub-interface.
1223 :param node: Honeycomb node.
1224 :param super_interface: Super interface.
1225 :param identifier: The ID of sub-interface.
1227 :type super_interface: str
1228 :type identifier: int
1229 :returns: Operational data about the bridge domain.
1231 :raises HoneycombError: If there is no sub-interface with the given ID.
1235 bd_data = InterfaceKeywords.get_sub_interface_oper_data(
1236 node, super_interface, identifier)["l2"]
1239 raise HoneycombError("The operational data does not contain "
1240 "information about a bridge domain.")
1243 def configure_tag_rewrite(node, super_interface, identifier, config):
1244 """Add / change / disable vlan tag rewrite on a sub-interface.
1246 :param node: Honeycomb node.
1247 :param super_interface: Super interface.
1248 :param identifier: The ID of sub-interface.
1249 :param config: Rewrite tag configuration.
1251 :type super_interface: str
1252 :type identifier: int
1254 :returns: Content of response.
1258 path = ("interfaces",
1259 ("interface", "name", super_interface),
1260 "vpp-vlan:sub-interfaces",
1261 ("sub-interface", "identifier", int(identifier)),
1265 return InterfaceKeywords._set_interface_properties(
1266 node, super_interface, path, config)
1269 def get_tag_rewrite_oper_data(node, super_interface, identifier):
1270 """Get the operational data about tag rewrite.
1272 :param node: Honeycomb node.
1273 :param super_interface: Super interface.
1274 :param identifier: The ID of sub-interface.
1276 :type super_interface: str
1277 :type identifier: int
1278 :returns: Operational data about tag rewrite.
1280 :raises HoneycombError: If there is no sub-interface with the given ID.
1284 tag_rewrite = InterfaceKeywords.get_sub_interface_oper_data(
1285 node, super_interface, identifier)["l2"]["rewrite"]
1288 raise HoneycombError("The operational data does not contain "
1289 "information about the tag-rewrite.")
1292 def add_ip_address_to_sub_interface(node, super_interface, identifier,
1293 ip_addr, network, ip_version):
1294 """Add an ipv4 address to the specified sub-interface, with the provided
1295 netmask or network prefix length. Any existing ipv4 addresses on the
1296 sub-interface will be replaced.
1298 :param node: Honeycomb node.
1299 :param super_interface: Super interface.
1300 :param identifier: The ID of sub-interface.
1301 :param ip_addr: IPv4 address to be set.
1302 :param network: Network mask or network prefix length.
1303 :param ip_version: ipv4 or ipv6
1305 :type super_interface: str
1306 :type identifier: int
1308 :type network: str or int
1309 :type ip_version: string
1310 :returns: Content of response.
1312 :raises HoneycombError: If the provided netmask or prefix is not valid.
1315 path = ("interfaces",
1316 ("interface", "name", super_interface),
1317 "vpp-vlan:sub-interfaces",
1318 ("sub-interface", "identifier", int(identifier)),
1321 if isinstance(network, basestring) and ip_version.lower() == "ipv4":
1322 address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
1324 elif isinstance(network, int) and 0 < network < 33:
1325 address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
1328 raise HoneycombError("{0} is not a valid netmask or prefix length."
1331 return InterfaceKeywords._set_interface_properties(
1332 node, super_interface, path, address)
1335 def remove_all_ip_addresses_from_sub_interface(node, super_interface,
1336 identifier, ip_version):
1337 """Remove all ipv4 addresses from the specified sub-interface.
1339 :param node: Honeycomb node.
1340 :param super_interface: Super interface.
1341 :param identifier: The ID of sub-interface.
1342 :param ip_version: ipv4 or ipv6
1344 :type super_interface: str
1345 :type identifier: int
1346 :type ip_version: string
1347 :returns: Content of response.
1351 path = ("interfaces",
1352 ("interface", "name", super_interface),
1353 "vpp-vlan:sub-interfaces",
1354 ("sub-interface", "identifier", int(identifier)),
1355 str(ip_version), "address")
1357 return InterfaceKeywords._set_interface_properties(
1358 node, super_interface, path, None)
1361 def compare_data_structures(data, ref, _path=''):
1362 """Checks if data obtained from UUT is as expected. If it is not,
1363 proceeds down the list/dictionary tree and finds the point of mismatch.
1365 :param data: Data to be checked.
1366 :param ref: Referential data used for comparison.
1367 :param _path: Used in recursive calls, stores the path taken down
1373 :raises HoneycombError: If the data structures do not match in some way,
1374 or if they are not in deserialized JSON format.
1380 elif isinstance(data, dict) and isinstance(ref, dict):
1383 raise HoneycombError(
1384 "Key {key} is not present in path {path}. Keys in path:"
1385 "{data_keys}".format(
1388 data_keys=data.keys()))
1390 if data[key] != ref[key]:
1391 if isinstance(data[key], list) \
1392 or isinstance(data[key], dict):
1393 InterfaceKeywords.compare_data_structures(
1394 data[key], ref[key],
1395 _path + '[{0}]'.format(key))
1397 raise HoneycombError(
1398 "Data mismatch, key {key} in path {path} has value"
1399 " {data}, but should be {ref}".format(
1405 elif isinstance(data, list) and isinstance(ref, list):
1407 if item not in data:
1408 if isinstance(item, dict):
1409 InterfaceKeywords.compare_data_structures(
1411 _path + '[{0}]'.format(ref.index(item)))
1413 raise HoneycombError(
1414 "Data mismatch, list item {index} in path {path}"
1415 " has value {data}, but should be {ref}".format(
1416 index=ref.index(item),
1422 raise HoneycombError(
1423 "Unexpected data type {data_type} in path {path}, reference"
1424 " type is {ref_type}. Must be list or dictionary.".format(
1425 data_type=type(data),
1430 def compare_interface_lists(list1, list2):
1431 """Compare provided lists of interfaces by name.
1433 :param list1: List of interfaces.
1434 :param list2: List of interfaces.
1437 :raises HoneycombError: If an interface exists in only one of the lists.
1440 ignore = ["vx_tunnel0", "vxlan_gpe_tunnel0"]
1441 # these have no equivalent in config data and no effect on VPP
1443 names1 = [x['name'] for x in list1]
1444 names2 = [x['name'] for x in list2]
1447 if name not in names2 and name not in ignore:
1448 raise HoneycombError("Interface {0} not present in list {1}"
1449 .format(name, list2))
1451 if name not in names1 and name not in ignore:
1452 raise HoneycombError("Interface {0} not present in list {1}"
1453 .format(name, list1))
1456 def create_vxlan_gpe_interface(node, interface, **kwargs):
1457 """Create a new VxLAN GPE interface.
1459 :param node: Honeycomb node.
1460 :param interface: The name of interface to be created.
1461 :param kwargs: Parameters and their values. The accepted parameters are
1462 defined in InterfaceKeywords.VXLAN_GPE_PARAMS.
1464 :type interface: str
1466 :returns: Content of response.
1468 :raises HoneycombError: If a parameter in kwargs is not valid.
1473 "type": "v3po:vxlan-gpe-tunnel",
1474 "v3po:vxlan-gpe": {}
1476 for param, value in kwargs.items():
1477 if param in InterfaceKeywords.INTF_PARAMS:
1478 new_vxlan_gpe[param] = value
1479 elif param in InterfaceKeywords.VXLAN_GPE_PARAMS:
1480 new_vxlan_gpe["v3po:vxlan-gpe"][param] = value
1482 raise HoneycombError("The parameter {0} is invalid.".
1484 path = ("interfaces", "interface")
1485 vxlan_gpe_structure = [new_vxlan_gpe, ]
1486 return InterfaceKeywords._set_interface_properties(
1487 node, interface, path, vxlan_gpe_structure)
1490 def enable_acl_on_interface(node, interface, table_name):
1491 """Enable ACL on the given interface.
1493 :param node: Honeycomb node.
1494 :param interface: The interface where the ACL will be enabled.
1495 :param table_name: Name of the classify table.
1497 :type interface: str
1498 :type table_name: str
1499 :returns: Content of response.
1501 :raises HoneycombError: If the configuration of interface is not
1505 interface = interface.replace("/", "%2F")
1508 "vpp-interface-acl:acl": {
1511 "classify-table": table_name
1514 "classify-table": table_name
1520 path = "/interface/" + interface + "/vpp-interface-acl:acl"
1521 status_code, resp = HcUtil.\
1522 put_honeycomb_data(node, "config_vpp_interfaces", data, path,
1523 data_representation=DataRepresentation.JSON)
1524 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1525 raise HoneycombError(
1526 "The configuration of interface '{0}' was not successful. "
1527 "Status code: {1}.".format(interface, status_code))
1531 def enable_policer_on_interface(node, interface, table_name):
1532 """Enable Policer on the given interface.
1534 :param node: Honeycomb node.
1535 :param interface: The interface where policer will be enabled.
1536 :param table_name: Name of the classify table.
1538 :type interface: str
1539 :type table_name: str
1540 :returns: Content of response.
1542 :raises HoneycombError: If the configuration of interface is not
1545 interface = Topology.convert_interface_reference(
1546 node, interface, "name")
1547 interface = interface.replace("/", "%2F")
1550 "interface-policer:policer": {
1551 "ip4-table": table_name
1555 path = "/interface/" + interface + "/interface-policer:policer"
1556 status_code, resp = HcUtil.\
1557 put_honeycomb_data(node, "config_vpp_interfaces", data, path,
1558 data_representation=DataRepresentation.JSON)
1559 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1560 raise HoneycombError(
1561 "The configuration of interface '{0}' was not successful. "
1562 "Status code: {1}.".format(interface, status_code))
1566 def disable_policer_on_interface(node, interface):
1567 """Disable Policer on the given interface.
1569 :param node: Honeycomb node.
1570 :param interface: The interface where policer will be disabled.
1572 :type interface: str
1573 :returns: Content of response.
1575 :raises HoneycombError: If the configuration of interface is not
1578 interface = Topology.convert_interface_reference(
1579 node, interface, "name")
1580 interface = interface.replace("/", "%2F")
1582 path = "/interface/" + interface + "/interface-policer:policer"
1583 status_code, resp = HcUtil.\
1584 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1585 if status_code != HTTPCodes.OK:
1586 raise HoneycombError(
1587 "The configuration of interface '{0}' was not successful. "
1588 "Status code: {1}.".format(interface, status_code))
1592 def disable_acl_on_interface(node, interface):
1593 """Disable ACL on the given interface.
1595 :param node: Honeycomb node.
1596 :param interface: The interface where the ACL will be disabled.
1598 :type interface: str
1599 :returns: Content of response.
1601 :raises HoneycombError: If the configuration of interface is not
1605 interface = interface.replace("/", "%2F")
1607 path = "/interface/" + interface + "/vpp-interface-acl:acl"
1609 status_code, resp = HcUtil.\
1610 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1612 if status_code != HTTPCodes.OK:
1613 raise HoneycombError(
1614 "The configuration of interface '{0}' was not successful. "
1615 "Status code: {1}.".format(interface, status_code))
1619 def create_pbb_sub_interface(node, intf, params):
1620 """Creates a PBB sub-interface on the given interface and sets its
1623 :param node: Honeycomb node.
1624 :param intf: The interface where PBB sub-interface will be configured.
1625 :param params: Configuration parameters of the sub-interface to be
1630 :returns: Content of response.
1632 :raises HoneycombError: If the configuration of sub-interface is not
1636 interface = intf.replace("/", "%2F")
1637 path = "/interface/{0}/pbb-rewrite".format(interface)
1638 status_code, resp = HcUtil. \
1639 put_honeycomb_data(node, "config_vpp_interfaces", params, path,
1640 data_representation=DataRepresentation.JSON)
1641 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1642 raise HoneycombError(
1643 "The configuration of PBB sub-interface '{0}' was not "
1644 "successful. Status code: {1}.".format(intf, status_code))
1648 def delete_pbb_sub_interface(node, intf):
1649 """Deletes the given PBB sub-interface.
1651 :param node: Honeycomb node.
1652 :param intf: The interface where PBB sub-interface will be deleted.
1655 :returns: Content of response.
1657 :raises HoneycombError: If the removal of sub-interface is not
1661 interface = intf.replace("/", "%2F")
1662 path = "/interface/{0}/pbb-rewrite".format(interface)
1664 status_code, resp = HcUtil. \
1665 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1666 if status_code != HTTPCodes.OK:
1667 raise HoneycombError(
1668 "The removal of pbb sub-interface '{0}' was not successful. "
1669 "Status code: {1}.".format(intf, status_code))
1673 def get_pbb_sub_interface_oper_data(node, intf, sub_if_id):
1674 """Retrieves PBB sub-interface operational data from Honeycomb.
1676 :param node: Honeycomb node.
1677 :param intf: The interface where PBB sub-interface is located.
1678 :param sub_if_id: ID of the PBB sub-interface.
1681 :type sub_if_id: str or int
1682 :returns: PBB sub-interface operational data.
1684 :raises HoneycombError: If the removal of sub-interface is not
1688 raise NotImplementedError
1691 def check_disabled_interface(node, interface):
1692 """Retrieves list of disabled interface indices from Honeycomb,
1693 and matches with the provided interface by index.
1695 :param node: Honeycomb node.
1696 :param interface: Index number of an interface on the node.
1698 :type interface: int
1699 :returns: True if the interface exists in disabled interfaces.
1701 :raises HoneycombError: If the interface is not present
1702 in retrieved list of disabled interfaces.
1704 data = InterfaceKeywords.get_disabled_interfaces_oper_data(node)
1705 # decrement by one = conversion from HC if-index to VPP sw_if_index
1709 if item["index"] == interface:
1711 raise HoneycombError("Interface index {0} not present in list"
1712 " of disabled interfaces.".format(interface))
1715 def configure_interface_span(node, dst_interface, src_interfaces=None):
1716 """Configure SPAN port mirroring on the specified interfaces. If no
1717 source interface is provided, SPAN will be disabled.
1719 :param node: Honeycomb node.
1720 :param dst_interface: Interface to mirror packets to.
1721 :param src_interfaces: List of interfaces to mirror packets from.
1723 :type dst_interface: str or int
1724 :type src_interfaces: list of dict
1725 :returns: Content of response.
1727 :raises HoneycombError: If SPAN could not be configured.
1730 interface = Topology.convert_interface_reference(
1731 node, dst_interface, "name")
1732 interface = interface.replace("/", "%2F")
1733 path = "/interface/" + interface + "/span"
1735 if not src_interfaces:
1736 status_code, _ = HcUtil.delete_honeycomb_data(
1737 node, "config_vpp_interfaces", path)
1739 for src_interface in src_interfaces:
1740 src_interface["iface-ref"] = Topology.\
1741 convert_interface_reference(
1742 node, src_interface["iface-ref"], "name")
1745 "mirrored-interfaces": {
1746 "mirrored-interface": src_interfaces
1751 status_code, _ = HcUtil.put_honeycomb_data(
1752 node, "config_vpp_interfaces", data, path)
1754 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1755 raise HoneycombError(
1756 "Configuring SPAN failed. Status code:{0}".format(status_code))
1759 def configure_sub_interface_span(node, super_interface, dst_interface_index,
1760 src_interfaces=None):
1761 """Configure SPAN port mirroring on the specified sub-interface. If no
1762 source interface is provided, SPAN will be disabled.
1764 Note: Does not support source sub-interfaces, only destination.
1766 :param node: Honeycomb node.
1767 :param super_interface: Name, link name or sw_if_index
1768 of the destination interface's super-interface.
1769 :param dst_interface_index: Index of sub-interface to mirror packets to.
1770 :param src_interfaces: List of interfaces to mirror packets from.
1772 :type super_interface: str or int
1773 :type dst_interface_index: int
1774 :type src_interfaces: list of dict
1775 :returns: Content of response.
1777 :raises HoneycombError: If SPAN could not be configured.
1780 super_interface = Topology.convert_interface_reference(
1781 node, super_interface, "name")
1782 super_interface = super_interface.replace("/", "%2F")
1784 path = "/interface/{0}/vpp-vlan:sub-interfaces/sub-interface/{1}/span"\
1785 .format(super_interface, dst_interface_index)
1787 if not src_interfaces:
1788 status_code, _ = HcUtil.delete_honeycomb_data(
1789 node, "config_vpp_interfaces", path)
1791 for src_interface in src_interfaces:
1792 src_interface["iface-ref"] = Topology. \
1793 convert_interface_reference(
1794 node, src_interface["iface-ref"], "name")
1797 "mirrored-interfaces": {
1798 "mirrored-interface": src_interfaces
1803 status_code, _ = HcUtil.put_honeycomb_data(
1804 node, "config_vpp_interfaces", data, path)
1806 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1807 raise HoneycombError(
1808 "Configuring SPAN failed. Status code:{0}".format(status_code))
1811 def add_interface_local0_to_topology(node):
1812 """Use Topology methods to add interface "local0" to working topology,
1813 if not already present.
1815 :param node: DUT node.
1819 if Topology.get_interface_by_sw_index(node, 0) is None:
1820 local0_key = Topology.add_new_port(node, "localzero")
1821 Topology.update_interface_sw_if_index(node, local0_key, 0)
1822 Topology.update_interface_name(node, local0_key, "local0")
1825 def configure_interface_unnumbered(node, interface, interface_src=None):
1826 """Configure the specified interface as unnumbered. The interface
1827 borrows IP address from the specified source interface. If not source
1828 interface is provided, unnumbered configuration will be removed.
1830 :param node: Honeycomb node.
1831 :param interface: Name, link name or sw_if_index of an interface.
1832 :param interface_src: Name of source interface.
1834 :type interface: str or int
1835 :type interface_src: str
1836 :raises HoneycombError: If the configuration fails.
1839 interface = InterfaceKeywords.handle_interface_reference(
1842 path = "/interface/{0}/unnumbered-interfaces:unnumbered"\
1848 "use": interface_src
1851 status_code, _ = HcUtil.put_honeycomb_data(
1852 node, "config_vpp_interfaces", data, path)
1854 status_code, _ = HcUtil.delete_honeycomb_data(
1855 node, "config_vpp_interfaces", path)
1857 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1858 raise HoneycombError(
1859 "Configuring unnumbered interface failed. "
1860 "Status code:{0}".format(status_code))
1863 def handle_interface_reference(node, interface):
1864 """Convert any interface reference to interface name used by Honeycomb.
1866 :param node: Honeycomb node.
1867 :param interface: Name, link name or sw_if_index of an interface,
1868 name of a custom interface or name of a sub-interface.
1869 :type node: Honeycomb node.
1870 :type interface: str or int
1871 :returns: Name of interface that can be used in Honeycomb requests.
1876 interface = Topology.convert_interface_reference(
1877 node, interface, "name")
1878 interface = interface.replace("/", "%2F")
1879 except RuntimeError:
1880 # interface is not in topology
1881 if "." in interface:
1882 # Assume it's the name of a sub-interface
1883 interface, index = interface.split(".")
1884 interface = interface.replace("/", "%2F")
1885 interface = "{0}/vpp-vlan:sub-interfaces/sub-interface/{1}".\
1886 format(interface, index)
1888 # Assume it's the name of a custom interface (pbb, vxlan, etc.)
1889 interface = interface.replace("/", "%2F")