1 # Copyright (c) 2018 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
373 :raises HoneycombError: If the operation fails.
376 interface = Topology.convert_interface_reference(
377 node, interface, "name")
379 intf = interface.replace("/", "%2F")
381 path = "/interface/{0}/v3po:l2".format(intf)
383 status_code, response = HcUtil.delete_honeycomb_data(
384 node, "config_vpp_interfaces", path)
386 if status_code != HTTPCodes.OK:
387 if '"error-tag":"data-missing"' in response:
388 logger.debug("Data does not exist in path.")
390 raise HoneycombError(
391 "Could not remove bridge domain assignment from interface "
392 "'{0}'. Status code: {1}.".format(interface, status_code))
395 def get_bd_oper_data_from_interface(node, interface):
396 """Returns operational data about bridge domain settings in the
399 :param node: Honeycomb node.
400 :param interface: The name of interface.
403 :returns: Operational data about bridge domain settings in the
408 if_data = InterfaceKeywords.get_interface_oper_data(node, interface)
412 return if_data["v3po:l2"]
418 def configure_interface_base(node, interface, param, value):
419 """Configure the base parameters of interface.
421 :param node: Honeycomb node.
422 :param interface: The name of interface.
423 :param param: Parameter to configure (set, change, remove)
424 :param value: The value of parameter. If None, the parameter will be
430 :returns: Content of response.
432 :raises HoneycombError: If the parameter is not valid.
435 if param not in InterfaceKeywords.INTF_PARAMS:
436 raise HoneycombError("The parameter {0} is invalid.".format(param))
438 path = ("interfaces", ("interface", "name", interface), param)
439 return InterfaceKeywords._set_interface_properties(
440 node, interface, path, value)
443 def configure_interface_ipv4(node, interface, param, value):
444 """Configure IPv4 parameters of interface.
446 :param node: Honeycomb node.
447 :param interface: The name of interface.
448 :param param: Parameter to configure (set, change, remove)
449 :param value: The value of parameter. If None, the parameter will be
455 :returns: Content of response.
457 :raises HoneycombError: If the parameter is not valid.
460 interface = Topology.convert_interface_reference(
461 node, interface, "name")
463 if param not in InterfaceKeywords.IPV4_PARAMS:
464 raise HoneycombError("The parameter {0} is invalid.".format(param))
466 path = ("interfaces", ("interface", "name", interface),
467 "ietf-ip:ipv4", param)
468 return InterfaceKeywords._set_interface_properties(
469 node, interface, path, value)
472 def add_first_ipv4_address(node, interface, ip_addr, network):
473 """Add the first IPv4 address.
475 If there are any other addresses configured, they will be removed.
477 :param node: Honeycomb node.
478 :param interface: The name of interface.
479 :param ip_addr: IPv4 address to be set.
480 :param network: Netmask or length of network prefix.
484 :type network: str or int
485 :returns: Content of response.
487 :raises ValueError: If the provided netmask or prefix is not valid.
488 :raises HoneycombError: If the operation fails.
491 interface = InterfaceKeywords.handle_interface_reference(
494 path = "/interface/{0}/ietf-ip:ipv4".format(interface)
495 if isinstance(network, basestring):
498 "address": [{"ip": ip_addr, "netmask": network}, ]}}
499 elif isinstance(network, int) and (0 < network < 33):
502 "address": [{"ip": ip_addr, "prefix-length": network}, ]}}
504 raise ValueError("Value {0} is not a valid netmask or network "
505 "prefix length.".format(network))
506 status_code, _ = HcUtil.put_honeycomb_data(
507 node, "config_vpp_interfaces", data, path)
509 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
510 raise HoneycombError(
511 "Configuring IPv4 address failed. "
512 "Status code:{0}".format(status_code))
515 def add_ipv4_address(node, interface, ip_addr, network):
518 :param node: Honeycomb node.
519 :param interface: The name of interface.
520 :param ip_addr: IPv4 address to be set.
521 :param network: Netmask or length of network prefix.
525 :type network: str or int
526 :returns: Content of response.
528 :raises HoneycombError: If the provided netmask or prefix is not valid.
531 interface = Topology.convert_interface_reference(
532 node, interface, "name")
534 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
536 if isinstance(network, basestring):
537 address = [{"ip": ip_addr, "netmask": network}]
538 elif isinstance(network, int) and (0 < network < 33):
539 address = [{"ip": ip_addr, "prefix-length": network}]
541 raise HoneycombError("Value {0} is not a valid netmask or network "
542 "prefix length.".format(network))
543 return InterfaceKeywords._set_interface_properties(
544 node, interface, path, address)
547 def remove_all_ipv4_addresses(node, interface):
548 """Remove all IPv4 addresses from interface.
550 :param node: Honeycomb node.
551 :param interface: The name of interface.
554 :returns: Content of response.
558 interface = Topology.convert_interface_reference(
559 node, interface, "name")
561 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
563 return InterfaceKeywords._set_interface_properties(
564 node, interface, path, None)
567 def add_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
568 """Add the IPv4 neighbour.
570 :param node: Honeycomb node.
571 :param interface: The name of interface.
572 :param ip_addr: IPv4 address of neighbour to be set.
573 :param link_layer_address: Link layer address.
577 :type link_layer_address: str
578 :returns: Content of response.
582 interface = Topology.convert_interface_reference(
583 node, interface, "name")
585 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
587 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
588 return InterfaceKeywords._set_interface_properties(
589 node, interface, path, neighbor)
592 def remove_all_ipv4_neighbors(node, interface):
593 """Remove all IPv4 neighbours.
595 :param node: Honeycomb node.
596 :param interface: The name of interface.
599 :returns: Content of response.
603 interface = Topology.convert_interface_reference(
604 node, interface, "name")
606 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
608 return InterfaceKeywords._set_interface_properties(
609 node, interface, path, None)
612 def configure_interface_ipv6(node, interface, param, value):
613 """Configure IPv6 parameters of interface
615 :param node: Honeycomb node.
616 :param interface: The name of interface.
617 :param param: Parameter to configure (set, change, remove)
618 :param value: The value of parameter. If None, the parameter will be
624 :returns: Content of response.
626 :raises HoneycombError: If the parameter is not valid.
629 if param in InterfaceKeywords.IPV6_PARAMS:
630 path = ("interfaces", ("interface", "name", interface),
631 "ietf-ip:ipv6", param)
632 elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
633 path = ("interfaces", ("interface", "name", interface),
634 "ietf-ip:ipv6", "autoconf", param)
636 raise HoneycombError("The parameter {0} is invalid.".format(param))
638 return InterfaceKeywords._set_interface_properties(
639 node, interface, path, value)
642 def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
643 """Add the first IPv6 address.
645 If there are any other addresses configured, they will be removed.
647 :param node: Honeycomb node.
648 :param interface: The name of interface.
649 :param ip_addr: IPv6 address to be set.
650 :param prefix_len: Prefix length.
654 :type prefix_len: str
655 :returns: Content of response.
659 interface = Topology.convert_interface_reference(
660 node, interface, "name")
662 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
663 address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
664 return InterfaceKeywords._set_interface_properties(
665 node, interface, path, address)
668 def add_ipv6_address(node, interface, ip_addr, prefix_len):
671 :param node: Honeycomb node.
672 :param interface: The name of interface.
673 :param ip_addr: IPv6 address to be set.
674 :param prefix_len: Prefix length.
678 :type prefix_len: str
679 :returns: Content of response.
683 interface = Topology.convert_interface_reference(
684 node, interface, "name")
686 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
688 address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
689 return InterfaceKeywords._set_interface_properties(
690 node, interface, path, address)
693 def remove_all_ipv6_addresses(node, interface):
694 """Remove all IPv6 addresses from interface.
696 :param node: Honeycomb node.
697 :param interface: The name of interface.
700 :returns: Content of response.
704 interface = Topology.convert_interface_reference(
705 node, interface, "name")
707 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
709 return InterfaceKeywords._set_interface_properties(
710 node, interface, path, None)
713 def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
714 """Add the IPv6 neighbour.
716 :param node: Honeycomb node.
717 :param interface: The name of interface.
718 :param ip_addr: IPv6 address of neighbour to be set.
719 :param link_layer_address: Link layer address.
723 :type link_layer_address: str
724 :returns: Content of response.
728 interface = Topology.convert_interface_reference(
729 node, interface, "name")
731 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
733 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
734 return InterfaceKeywords._set_interface_properties(
735 node, interface, path, neighbor)
738 def remove_all_ipv6_neighbors(node, interface):
739 """Remove all IPv6 neighbours.
741 :param node: Honeycomb node.
742 :param interface: The name of interface.
745 :returns: Content of response.
749 interface = Topology.convert_interface_reference(
750 node, interface, "name")
752 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
754 return InterfaceKeywords._set_interface_properties(
755 node, interface, path, None)
758 def configure_interface_ethernet(node, interface, param, value):
759 """Configure the ethernet parameters of interface.
761 :param node: Honeycomb node.
762 :param interface: The name of interface.
763 :param param: Parameter to configure (set, change, remove)
764 :param value: The value of parameter. If None, the parameter will be
770 :returns: Content of response.
772 :raises HoneycombError: If the parameter is not valid.
775 if param not in InterfaceKeywords.ETH_PARAMS:
776 raise HoneycombError("The parameter {0} is invalid.".format(param))
777 path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
779 return InterfaceKeywords._set_interface_properties(
780 node, interface, path, value)
783 def configure_interface_routing(node, interface, param, value):
784 """Configure the routing parameters of interface.
786 :param node: Honeycomb node.
787 :param interface: The name of interface.
788 :param param: Parameter to configure (set, change, remove)
789 :param value: The value of parameter. If None, the parameter will be
795 :returns: Content of response.
797 :raises HoneycombError: If the parameter is not valid.
800 interface = Topology.convert_interface_reference(
801 node, interface, "name")
803 if param not in InterfaceKeywords.ROUTING_PARAMS:
804 raise HoneycombError("The parameter {0} is invalid.".format(param))
806 path = ("interfaces", ("interface", "name", interface), "v3po:routing",
808 return InterfaceKeywords._set_interface_properties(
809 node, interface, path, value)
812 def honeycomb_create_vxlan_interface(node, interface, **kwargs):
813 """Create a new VxLAN interface.
815 :param node: Honeycomb node.
816 :param interface: The name of interface.
817 :param kwargs: Parameters and their values. The accepted parameters are
818 defined in InterfaceKeywords.VXLAN_PARAMS.
822 :returns: Content of response.
824 :raises HoneycombError: If the parameter is not valid.
829 "type": "v3po:vxlan-tunnel",
832 for param, value in kwargs.items():
833 if param not in InterfaceKeywords.VXLAN_PARAMS:
834 raise HoneycombError("The parameter {0} is invalid.".
836 new_vx_lan["v3po:vxlan"][param] = value
838 path = ("interfaces", "interface")
839 vx_lan_structure = [new_vx_lan, ]
840 return InterfaceKeywords._set_interface_properties(
841 node, interface, path, vx_lan_structure)
844 def delete_interface(node, interface):
845 """Delete an interface.
847 :param node: Honeycomb node.
848 :param interface: The name of interface.
851 :returns: Content of response.
853 :raises HoneycombError: If it is not possible to get information about
854 interfaces or it is not possible to delete the interface.
857 path = ("interfaces", ("interface", "name", interface))
859 status_code, resp = HcUtil.\
860 get_honeycomb_data(node, "config_vpp_interfaces")
861 if status_code != HTTPCodes.OK:
862 raise HoneycombError(
863 "Not possible to get configuration information about the "
864 "interfaces. Status code: {0}.".format(status_code))
866 new_data = HcUtil.remove_item(resp, path)
867 status_code, resp = HcUtil.\
868 put_honeycomb_data(node, "config_vpp_interfaces", new_data)
869 if status_code != HTTPCodes.OK:
870 raise HoneycombError("Not possible to remove interface {0}. "
872 format(interface, status_code))
876 def honeycomb_configure_interface_vxlan(node, interface, **kwargs):
877 """Configure VxLAN on the interface.
879 The keyword configures VxLAN parameters on the given interface. The type
880 of interface must be set to "v3po:vxlan-tunnel".
881 The new VxLAN parameters overwrite the current configuration. If a
882 parameter in new configuration is missing, it is removed from VxLAN
884 If the dictionary kwargs is empty, VxLAN configuration is removed.
886 :param node: Honeycomb node.
887 :param interface: The name of interface.
888 :param kwargs: Parameters and their values. The accepted parameters are
889 defined in InterfaceKeywords.VXLAN_PARAMS.
893 :returns: Content of response.
895 :raises HoneycombError: If the parameter is not valid.
898 vx_lan_structure = dict()
899 for param, value in kwargs.items():
900 if param not in InterfaceKeywords.VXLAN_PARAMS:
901 raise HoneycombError("The parameter {0} is invalid.".
903 vx_lan_structure[param] = value
905 path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
906 return InterfaceKeywords._set_interface_properties(
907 node, interface, path, vx_lan_structure)
910 def configure_interface_l2(node, interface, param, value):
911 """Configure the L2 parameters of interface.
913 :param node: Honeycomb node.
914 :param interface: The name of interface.
915 :param param: Parameter to configure (set, change, remove)
916 :param value: The value of parameter. If None, the parameter will be
922 :returns: Content of response.
924 :raises HoneycombError: If the parameter is not valid.
927 if param not in InterfaceKeywords.L2_PARAMS:
928 raise HoneycombError("The parameter {0} is invalid.".format(param))
929 path = ("interfaces", ("interface", "name", interface), "v3po:l2",
931 return InterfaceKeywords._set_interface_properties(
932 node, interface, path, value)
935 def create_tap_interface(node, interface, **kwargs):
936 """Create a new TAP interface.
938 :param node: Honeycomb node.
939 :param interface: The name of interface.
940 :param kwargs: Parameters and their values. The accepted parameters are
941 defined in InterfaceKeywords.TAP_PARAMS.
945 :returns: Content of response.
947 :raises HoneycombError: If the parameter is not valid.
955 for param, value in kwargs.items():
956 if param not in InterfaceKeywords.TAP_PARAMS:
957 raise HoneycombError("The parameter {0} is invalid.".
959 new_tap["v3po:tap"][param] = value
961 path = ("interfaces", "interface")
962 new_tap_structure = [new_tap, ]
963 return InterfaceKeywords._set_interface_properties(
964 node, interface, path, new_tap_structure)
967 def configure_interface_tap(node, interface, **kwargs):
968 """Configure TAP on the interface.
970 The keyword configures TAP parameters on the given interface. The type
971 of interface must be set to "v3po:tap".
972 The new TAP parameters overwrite the current configuration. If a
973 parameter in new configuration is missing, it is removed from TAP
975 If the dictionary kwargs is empty, TAP configuration is removed.
977 :param node: Honeycomb node.
978 :param interface: The name of interface.
979 :param kwargs: Parameters and their values. The accepted parameters are
980 defined in InterfaceKeywords.TAP_PARAMS.
984 :returns: Content of response.
986 :raises HoneycombError: If the parameter is not valid.
989 tap_structure = dict()
990 for param, value in kwargs.items():
991 if param not in InterfaceKeywords.TAP_PARAMS:
992 raise HoneycombError("The parameter {0} is invalid.".
994 tap_structure[param] = value
996 path = ("interfaces", ("interface", "name", interface), "v3po:tap")
997 return InterfaceKeywords._set_interface_properties(
998 node, interface, path, tap_structure)
1001 def configure_interface_vhost_user(node, interface, **kwargs):
1002 """Configure vhost-user on the interface.
1004 The keyword configures vhost-user parameters on the given interface.
1005 The type of interface must be set to "v3po:vhost-user".
1006 The new vhost-user parameters overwrite the current configuration. If a
1007 parameter in new configuration is missing, it is removed from vhost-user
1009 If the dictionary kwargs is empty, vhost-user configuration is removed.
1011 :param node: Honeycomb node.
1012 :param interface: The name of interface.
1013 :param kwargs: Parameters and their values. The accepted parameters are
1014 defined in InterfaceKeywords.VHOST_USER_PARAMS.
1016 :type interface: str
1018 :returns: Content of response.
1020 :raises HoneycombError: If the parameter is not valid.
1023 vhost_structure = dict()
1024 for param, value in kwargs.items():
1025 if param not in InterfaceKeywords.VHOST_USER_PARAMS:
1026 raise HoneycombError("The parameter {0} is invalid.".
1028 vhost_structure[param] = value
1030 path = ("interfaces", ("interface", "name", interface),
1032 return InterfaceKeywords._set_interface_properties(
1033 node, interface, path, vhost_structure)
1036 def create_vhost_user_interface(node, interface, **kwargs):
1037 """Create a new vhost-user interface.
1039 :param node: Honeycomb node.
1040 :param interface: The name of interface.
1041 :param kwargs: Parameters and their values. The accepted parameters are
1042 defined in InterfaceKeywords.VHOST_USER_PARAMS.
1044 :type interface: str
1046 :returns: Content of response.
1048 :raises HoneycombError: If the parameter is not valid.
1053 "type": "v3po:vhost-user",
1054 "v3po:vhost-user": {}
1056 for param, value in kwargs.items():
1057 if param not in InterfaceKeywords.VHOST_USER_PARAMS:
1058 raise HoneycombError("The parameter {0} is invalid.".
1060 new_vhost["v3po:vhost-user"][param] = value
1062 path = ("interfaces", "interface")
1063 new_vhost_structure = [new_vhost, ]
1064 return InterfaceKeywords._set_interface_properties(
1065 node, interface, path, new_vhost_structure)
1068 def honeycomb_create_sub_interface(node, super_interface, match, tags=None,
1070 """Create a new sub-interface.
1072 :param node: Honeycomb node.
1073 :param super_interface: Super interface.
1074 :param match: Match type. The valid values are defined in
1075 InterfaceKeywords.SUB_IF_MATCH.
1076 :param tags: List of tags.
1077 :param kwargs: Parameters and their values. The accepted parameters are
1078 defined in InterfaceKeywords.SUB_IF_PARAMS.
1080 :type super_interface: str
1084 :returns: Content of response.
1086 :raises HoneycombError: If the parameter is not valid.
1087 :raises KeyError: If the parameter 'match' is invalid.
1090 super_interface = Topology.convert_interface_reference(
1091 node, super_interface, "name")
1099 {"vlan-tagged": {"match-exact-tags": "false"}},
1100 "vlan-tagged-exact-match":
1101 {"vlan-tagged": {"match-exact-tags": "true"}}
1104 new_sub_interface = {
1110 for param, value in kwargs.items():
1111 if param in InterfaceKeywords.SUB_IF_PARAMS:
1112 new_sub_interface[param] = value
1114 raise HoneycombError("The parameter {0} is invalid.".
1117 new_sub_interface["match"] = match_type[match]
1119 raise HoneycombError("The value '{0}' of parameter 'match' is "
1120 "invalid.".format(match))
1123 new_sub_interface["tags"]["tag"].extend(tags)
1125 path = ("interfaces",
1126 ("interface", "name", super_interface),
1127 "vpp-vlan:sub-interfaces",
1129 new_sub_interface_structure = [new_sub_interface, ]
1130 return InterfaceKeywords._set_interface_properties(
1131 node, super_interface, path, new_sub_interface_structure)
1134 def get_sub_interface_oper_data(node, super_interface, identifier):
1135 """Retrieves sub-interface operational data using Honeycomb API.
1137 :param node: Honeycomb node.
1138 :param super_interface: Super interface.
1139 :param identifier: The ID of sub-interface.
1141 :type super_interface: str
1142 :type identifier: int
1143 :returns: Sub-interface operational data.
1145 :raises HoneycombError: If there is no sub-interface with the given ID.
1148 if_data = InterfaceKeywords.get_interface_oper_data(node,
1150 for sub_if in if_data["vpp-vlan:sub-interfaces"]["sub-interface"]:
1151 if str(sub_if["identifier"]) == str(identifier):
1154 raise HoneycombError("The interface {0} does not have sub-interface "
1155 "with ID {1}".format(super_interface, identifier))
1158 def remove_all_sub_interfaces(node, super_interface):
1159 """Remove all sub-interfaces from the given interface.
1161 :param node: Honeycomb node.
1162 :param super_interface: Super interface.
1164 :type super_interface: str
1165 :returns: Content of response.
1169 path = ("interfaces",
1170 ("interface", "name", super_interface),
1171 "vpp-vlan:sub-interfaces")
1173 return InterfaceKeywords._set_interface_properties(
1174 node, super_interface, path, {})
1177 def set_sub_interface_state(node, super_interface, identifier, state):
1178 """Set the administrative state of sub-interface.
1180 :param node: Honeycomb node.
1181 :param super_interface: Super interface.
1182 :param identifier: The ID of sub-interface.
1183 :param state: Required sub-interface state - up or down.
1185 :type super_interface: str
1186 :type identifier: int
1188 :returns: Content of response.
1192 super_interface = Topology.convert_interface_reference(
1193 node, super_interface, "name")
1195 intf_state = {"up": "true",
1198 path = ("interfaces",
1199 ("interface", "name", super_interface),
1200 "vpp-vlan:sub-interfaces",
1201 ("sub-interface", "identifier", int(identifier)),
1204 return InterfaceKeywords._set_interface_properties(
1205 node, super_interface, path, intf_state[state])
1208 def add_bridge_domain_to_sub_interface(node, super_interface, identifier,
1210 """Add a sub-interface to a bridge domain and set its parameters.
1212 :param node: Honeycomb node.
1213 :param super_interface: Super interface.
1214 :param identifier: The ID of sub-interface.
1215 :param config: Bridge domain configuration.
1217 :type super_interface: str
1218 :type identifier: int
1220 :returns: Content of response.
1224 path = ("interfaces",
1225 ("interface", "name", super_interface),
1226 "vpp-vlan:sub-interfaces",
1227 ("sub-interface", "identifier", int(identifier)),
1230 return InterfaceKeywords._set_interface_properties(
1231 node, super_interface, path, config)
1234 def get_bd_data_from_sub_interface(node, super_interface, identifier):
1235 """Get the operational data about the bridge domain from sub-interface.
1237 :param node: Honeycomb node.
1238 :param super_interface: Super interface.
1239 :param identifier: The ID of sub-interface.
1241 :type super_interface: str
1242 :type identifier: int
1243 :returns: Operational data about the bridge domain.
1245 :raises HoneycombError: If there is no sub-interface with the given ID.
1249 bd_data = InterfaceKeywords.get_sub_interface_oper_data(
1250 node, super_interface, identifier)["l2"]
1253 raise HoneycombError("The operational data does not contain "
1254 "information about a bridge domain.")
1257 def configure_tag_rewrite(node, super_interface, identifier, config):
1258 """Add / change / disable vlan tag rewrite on a sub-interface.
1260 :param node: Honeycomb node.
1261 :param super_interface: Super interface.
1262 :param identifier: The ID of sub-interface.
1263 :param config: Rewrite tag configuration.
1265 :type super_interface: str
1266 :type identifier: int
1268 :returns: Content of response.
1272 path = ("interfaces",
1273 ("interface", "name", super_interface),
1274 "vpp-vlan:sub-interfaces",
1275 ("sub-interface", "identifier", int(identifier)),
1279 return InterfaceKeywords._set_interface_properties(
1280 node, super_interface, path, config)
1283 def get_tag_rewrite_oper_data(node, super_interface, identifier):
1284 """Get the operational data about tag rewrite.
1286 :param node: Honeycomb node.
1287 :param super_interface: Super interface.
1288 :param identifier: The ID of sub-interface.
1290 :type super_interface: str
1291 :type identifier: int
1292 :returns: Operational data about tag rewrite.
1294 :raises HoneycombError: If there is no sub-interface with the given ID.
1298 tag_rewrite = InterfaceKeywords.get_sub_interface_oper_data(
1299 node, super_interface, identifier)["l2"]["rewrite"]
1302 raise HoneycombError("The operational data does not contain "
1303 "information about the tag-rewrite.")
1306 def add_ip_address_to_sub_interface(node, super_interface, identifier,
1307 ip_addr, network, ip_version):
1308 """Add an ipv4 address to the specified sub-interface, with the provided
1309 netmask or network prefix length. Any existing ipv4 addresses on the
1310 sub-interface will be replaced.
1312 :param node: Honeycomb node.
1313 :param super_interface: Super interface.
1314 :param identifier: The ID of sub-interface.
1315 :param ip_addr: IPv4 address to be set.
1316 :param network: Network mask or network prefix length.
1317 :param ip_version: ipv4 or ipv6
1319 :type super_interface: str
1320 :type identifier: int
1322 :type network: str or int
1323 :type ip_version: string
1324 :returns: Content of response.
1326 :raises HoneycombError: If the provided netmask or prefix is not valid.
1329 path = ("interfaces",
1330 ("interface", "name", super_interface),
1331 "vpp-vlan:sub-interfaces",
1332 ("sub-interface", "identifier", int(identifier)),
1335 if isinstance(network, basestring) and ip_version.lower() == "ipv4":
1336 address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
1338 elif isinstance(network, int) and 0 < network < 33:
1339 address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
1342 raise HoneycombError("{0} is not a valid netmask or prefix length."
1345 return InterfaceKeywords._set_interface_properties(
1346 node, super_interface, path, address)
1349 def remove_all_ip_addresses_from_sub_interface(node, super_interface,
1350 identifier, ip_version):
1351 """Remove all ipv4 addresses from the specified sub-interface.
1353 :param node: Honeycomb node.
1354 :param super_interface: Super interface.
1355 :param identifier: The ID of sub-interface.
1356 :param ip_version: ipv4 or ipv6
1358 :type super_interface: str
1359 :type identifier: int
1360 :type ip_version: string
1361 :returns: Content of response.
1365 path = ("interfaces",
1366 ("interface", "name", super_interface),
1367 "vpp-vlan:sub-interfaces",
1368 ("sub-interface", "identifier", int(identifier)),
1369 str(ip_version), "address")
1371 return InterfaceKeywords._set_interface_properties(
1372 node, super_interface, path, None)
1375 def compare_data_structures(data, ref, _path=''):
1376 """Checks if data obtained from UUT is as expected. If it is not,
1377 proceeds down the list/dictionary tree and finds the point of mismatch.
1379 :param data: Data to be checked.
1380 :param ref: Referential data used for comparison.
1381 :param _path: Used in recursive calls, stores the path taken down
1387 :raises HoneycombError: If the data structures do not match in some way,
1388 or if they are not in deserialized JSON format.
1394 elif isinstance(data, dict) and isinstance(ref, dict):
1397 raise HoneycombError(
1398 "Key {key} is not present in path {path}. Keys in path:"
1399 "{data_keys}".format(
1402 data_keys=data.keys()))
1404 if data[key] != ref[key]:
1405 if isinstance(data[key], list) \
1406 or isinstance(data[key], dict):
1407 InterfaceKeywords.compare_data_structures(
1408 data[key], ref[key],
1409 _path + '[{0}]'.format(key))
1411 raise HoneycombError(
1412 "Data mismatch, key {key} in path {path} has value"
1413 " {data}, but should be {ref}".format(
1419 elif isinstance(data, list) and isinstance(ref, list):
1421 if item not in data:
1422 if isinstance(item, dict):
1423 InterfaceKeywords.compare_data_structures(
1425 _path + '[{0}]'.format(ref.index(item)))
1427 raise HoneycombError(
1428 "Data mismatch, list item {index} in path {path}"
1429 " has value {data}, but should be {ref}".format(
1430 index=ref.index(item),
1436 raise HoneycombError(
1437 "Unexpected data type {data_type} in path {path}, reference"
1438 " type is {ref_type}. Must be list or dictionary.".format(
1439 data_type=type(data),
1444 def compare_interface_lists(list1, list2):
1445 """Compare provided lists of interfaces by name.
1447 :param list1: List of interfaces.
1448 :param list2: List of interfaces.
1451 :raises HoneycombError: If an interface exists in only one of the lists.
1454 ignore = ["vx_tunnel0", "vxlan_gpe_tunnel0"]
1455 # these have no equivalent in config data and no effect on VPP
1457 names1 = [x['name'] for x in list1]
1458 names2 = [x['name'] for x in list2]
1461 if name not in names2 and name not in ignore:
1462 raise HoneycombError("Interface {0} not present in list {1}"
1463 .format(name, list2))
1465 if name not in names1 and name not in ignore:
1466 raise HoneycombError("Interface {0} not present in list {1}"
1467 .format(name, list1))
1470 def create_vxlan_gpe_interface(node, interface, **kwargs):
1471 """Create a new VxLAN GPE interface.
1473 :param node: Honeycomb node.
1474 :param interface: The name of interface to be created.
1475 :param kwargs: Parameters and their values. The accepted parameters are
1476 defined in InterfaceKeywords.VXLAN_GPE_PARAMS.
1478 :type interface: str
1480 :returns: Content of response.
1482 :raises HoneycombError: If a parameter in kwargs is not valid.
1487 "type": "v3po:vxlan-gpe-tunnel",
1488 "v3po:vxlan-gpe": {}
1490 for param, value in kwargs.items():
1491 if param in InterfaceKeywords.INTF_PARAMS:
1492 new_vxlan_gpe[param] = value
1493 elif param in InterfaceKeywords.VXLAN_GPE_PARAMS:
1494 new_vxlan_gpe["v3po:vxlan-gpe"][param] = value
1496 raise HoneycombError("The parameter {0} is invalid.".
1498 path = ("interfaces", "interface")
1499 vxlan_gpe_structure = [new_vxlan_gpe, ]
1500 return InterfaceKeywords._set_interface_properties(
1501 node, interface, path, vxlan_gpe_structure)
1504 def enable_acl_on_interface(node, interface, table_name):
1505 """Enable ACL on the given interface.
1507 :param node: Honeycomb node.
1508 :param interface: The interface where the ACL will be enabled.
1509 :param table_name: Name of the classify table.
1511 :type interface: str
1512 :type table_name: str
1513 :returns: Content of response.
1515 :raises HoneycombError: If the configuration of interface is not
1519 interface = interface.replace("/", "%2F")
1522 "vpp-interface-acl:acl": {
1525 "classify-table": table_name
1528 "classify-table": table_name
1534 path = "/interface/" + interface + "/vpp-interface-acl:acl"
1535 status_code, resp = HcUtil.\
1536 put_honeycomb_data(node, "config_vpp_interfaces", data, path,
1537 data_representation=DataRepresentation.JSON)
1538 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1539 raise HoneycombError(
1540 "The configuration of interface '{0}' was not successful. "
1541 "Status code: {1}.".format(interface, status_code))
1545 def enable_policer_on_interface(node, interface, table_name):
1546 """Enable Policer on the given interface.
1548 :param node: Honeycomb node.
1549 :param interface: The interface where policer will be enabled.
1550 :param table_name: Name of the classify table.
1552 :type interface: str
1553 :type table_name: str
1554 :returns: Content of response.
1556 :raises HoneycombError: If the configuration of interface is not
1559 interface = Topology.convert_interface_reference(
1560 node, interface, "name")
1561 interface = interface.replace("/", "%2F")
1564 "interface-policer:policer": {
1565 "ip4-table": table_name
1569 path = "/interface/" + interface + "/interface-policer:policer"
1570 status_code, resp = HcUtil.\
1571 put_honeycomb_data(node, "config_vpp_interfaces", data, path,
1572 data_representation=DataRepresentation.JSON)
1573 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1574 raise HoneycombError(
1575 "The configuration of interface '{0}' was not successful. "
1576 "Status code: {1}.".format(interface, status_code))
1580 def disable_policer_on_interface(node, interface):
1581 """Disable Policer on the given interface.
1583 :param node: Honeycomb node.
1584 :param interface: The interface where policer will be disabled.
1586 :type interface: str
1587 :returns: Content of response.
1589 :raises HoneycombError: If the configuration of interface is not
1592 interface = Topology.convert_interface_reference(
1593 node, interface, "name")
1594 interface = interface.replace("/", "%2F")
1596 path = "/interface/" + interface + "/interface-policer:policer"
1597 status_code, resp = HcUtil.\
1598 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1599 if status_code != HTTPCodes.OK:
1600 raise HoneycombError(
1601 "The configuration of interface '{0}' was not successful. "
1602 "Status code: {1}.".format(interface, status_code))
1606 def disable_acl_on_interface(node, interface):
1607 """Disable ACL on the given interface.
1609 :param node: Honeycomb node.
1610 :param interface: The interface where the ACL will be disabled.
1612 :type interface: str
1613 :returns: Content of response.
1615 :raises HoneycombError: If the configuration of interface is not
1619 interface = interface.replace("/", "%2F")
1621 path = "/interface/" + interface + "/vpp-interface-acl:acl"
1623 status_code, resp = HcUtil.\
1624 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1626 if status_code != HTTPCodes.OK:
1627 raise HoneycombError(
1628 "The configuration of interface '{0}' was not successful. "
1629 "Status code: {1}.".format(interface, status_code))
1633 def create_pbb_sub_interface(node, intf, params):
1634 """Creates a PBB sub-interface on the given interface and sets its
1637 :param node: Honeycomb node.
1638 :param intf: The interface where PBB sub-interface will be configured.
1639 :param params: Configuration parameters of the sub-interface to be
1644 :returns: Content of response.
1646 :raises HoneycombError: If the configuration of sub-interface is not
1650 interface = intf.replace("/", "%2F")
1651 path = "/interface/{0}/pbb-rewrite".format(interface)
1652 status_code, resp = HcUtil. \
1653 put_honeycomb_data(node, "config_vpp_interfaces", params, path,
1654 data_representation=DataRepresentation.JSON)
1655 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1656 raise HoneycombError(
1657 "The configuration of PBB sub-interface '{0}' was not "
1658 "successful. Status code: {1}.".format(intf, status_code))
1662 def delete_pbb_sub_interface(node, intf):
1663 """Deletes the given PBB sub-interface.
1665 :param node: Honeycomb node.
1666 :param intf: The interface where PBB sub-interface will be deleted.
1669 :returns: Content of response.
1671 :raises HoneycombError: If the removal of sub-interface is not
1675 interface = intf.replace("/", "%2F")
1676 path = "/interface/{0}/pbb-rewrite".format(interface)
1678 status_code, resp = HcUtil. \
1679 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1680 if status_code != HTTPCodes.OK:
1681 raise HoneycombError(
1682 "The removal of pbb sub-interface '{0}' was not successful. "
1683 "Status code: {1}.".format(intf, status_code))
1687 def get_pbb_sub_interface_oper_data(node, intf, sub_if_id):
1688 """Retrieves PBB sub-interface operational data from Honeycomb.
1690 :param node: Honeycomb node.
1691 :param intf: The interface where PBB sub-interface is located.
1692 :param sub_if_id: ID of the PBB sub-interface.
1695 :type sub_if_id: str or int
1696 :returns: PBB sub-interface operational data.
1698 :raises HoneycombError: If the removal of sub-interface is not
1702 raise NotImplementedError
1705 def check_disabled_interface(node, interface):
1706 """Retrieves list of disabled interface indices from Honeycomb,
1707 and matches with the provided interface by index.
1709 :param node: Honeycomb node.
1710 :param interface: Index number of an interface on the node.
1712 :type interface: int
1713 :returns: True if the interface exists in disabled interfaces.
1715 :raises HoneycombError: If the interface is not present
1716 in retrieved list of disabled interfaces.
1718 data = InterfaceKeywords.get_disabled_interfaces_oper_data(node)
1719 # decrement by one = conversion from HC if-index to VPP sw_if_index
1723 if item["index"] == interface:
1725 raise HoneycombError("Interface index {0} not present in list"
1726 " of disabled interfaces.".format(interface))
1729 def configure_interface_span(node, dst_interface, src_interfaces=None):
1730 """Configure SPAN port mirroring on the specified interfaces. If no
1731 source interface is provided, SPAN will be disabled.
1733 :param node: Honeycomb node.
1734 :param dst_interface: Interface to mirror packets to.
1735 :param src_interfaces: List of interfaces to mirror packets from.
1737 :type dst_interface: str or int
1738 :type src_interfaces: list of dict
1739 :returns: Content of response.
1741 :raises HoneycombError: If SPAN could not be configured.
1744 interface = Topology.convert_interface_reference(
1745 node, dst_interface, "name")
1746 interface = interface.replace("/", "%2F")
1747 path = "/interface/" + interface + "/span"
1749 if not src_interfaces:
1750 status_code, _ = HcUtil.delete_honeycomb_data(
1751 node, "config_vpp_interfaces", path)
1753 for src_interface in src_interfaces:
1754 src_interface["iface-ref"] = Topology.\
1755 convert_interface_reference(
1756 node, src_interface["iface-ref"], "name")
1759 "mirrored-interfaces": {
1760 "mirrored-interface": src_interfaces
1765 status_code, _ = HcUtil.put_honeycomb_data(
1766 node, "config_vpp_interfaces", data, path)
1768 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1769 raise HoneycombError(
1770 "Configuring SPAN failed. Status code:{0}".format(status_code))
1773 def configure_sub_interface_span(node, super_interface, dst_interface_index,
1774 src_interfaces=None):
1775 """Configure SPAN port mirroring on the specified sub-interface. If no
1776 source interface is provided, SPAN will be disabled.
1778 Note: Does not support source sub-interfaces, only destination.
1780 :param node: Honeycomb node.
1781 :param super_interface: Name, link name or sw_if_index
1782 of the destination interface's super-interface.
1783 :param dst_interface_index: Index of sub-interface to mirror packets to.
1784 :param src_interfaces: List of interfaces to mirror packets from.
1786 :type super_interface: str or int
1787 :type dst_interface_index: int
1788 :type src_interfaces: list of dict
1789 :returns: Content of response.
1791 :raises HoneycombError: If SPAN could not be configured.
1794 super_interface = Topology.convert_interface_reference(
1795 node, super_interface, "name")
1796 super_interface = super_interface.replace("/", "%2F")
1798 path = "/interface/{0}/vpp-vlan:sub-interfaces/sub-interface/{1}/span"\
1799 .format(super_interface, dst_interface_index)
1801 if not src_interfaces:
1802 status_code, _ = HcUtil.delete_honeycomb_data(
1803 node, "config_vpp_interfaces", path)
1805 for src_interface in src_interfaces:
1806 src_interface["iface-ref"] = Topology. \
1807 convert_interface_reference(
1808 node, src_interface["iface-ref"], "name")
1811 "mirrored-interfaces": {
1812 "mirrored-interface": src_interfaces
1817 status_code, _ = HcUtil.put_honeycomb_data(
1818 node, "config_vpp_interfaces", data, path)
1820 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1821 raise HoneycombError(
1822 "Configuring SPAN failed. Status code:{0}".format(status_code))
1825 def add_interface_local0_to_topology(node):
1826 """Use Topology methods to add interface "local0" to working topology,
1827 if not already present.
1829 :param node: DUT node.
1833 if Topology.get_interface_by_sw_index(node, 0) is None:
1834 local0_key = Topology.add_new_port(node, "localzero")
1835 Topology.update_interface_sw_if_index(node, local0_key, 0)
1836 Topology.update_interface_name(node, local0_key, "local0")
1839 def configure_interface_unnumbered(node, interface, interface_src=None):
1840 """Configure the specified interface as unnumbered. The interface
1841 borrows IP address from the specified source interface. If not source
1842 interface is provided, unnumbered configuration will be removed.
1844 :param node: Honeycomb node.
1845 :param interface: Name, link name or sw_if_index of an interface.
1846 :param interface_src: Name of source interface.
1848 :type interface: str or int
1849 :type interface_src: str
1850 :raises HoneycombError: If the configuration fails.
1853 interface = InterfaceKeywords.handle_interface_reference(
1856 path = "/interface/{0}/unnumbered-interfaces:unnumbered"\
1862 "use": interface_src
1865 status_code, _ = HcUtil.put_honeycomb_data(
1866 node, "config_vpp_interfaces", data, path)
1868 status_code, _ = HcUtil.delete_honeycomb_data(
1869 node, "config_vpp_interfaces", path)
1871 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1872 raise HoneycombError(
1873 "Configuring unnumbered interface failed. "
1874 "Status code:{0}".format(status_code))
1877 def handle_interface_reference(node, interface):
1878 """Convert any interface reference to interface name used by Honeycomb.
1880 :param node: Honeycomb node.
1881 :param interface: Name, link name or sw_if_index of an interface,
1882 name of a custom interface or name of a sub-interface.
1883 :type node: Honeycomb node.
1884 :type interface: str or int
1885 :returns: Name of interface that can be used in Honeycomb requests.
1890 interface = Topology.convert_interface_reference(
1891 node, interface, "name")
1892 interface = interface.replace("/", "%2F")
1893 except RuntimeError:
1894 # interface is not in topology
1895 if "." in interface:
1896 # Assume it's the name of a sub-interface
1897 interface, index = interface.split(".")
1898 interface = interface.replace("/", "%2F")
1899 interface = "{0}/vpp-vlan:sub-interfaces/sub-interface/{1}".\
1900 format(interface, index)
1902 # Assume it's the name of a custom interface (pbb, vxlan, etc.)
1903 interface = interface.replace("/", "%2F")