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 interface = Topology.convert_interface_reference(
560 node, interface, "name")
562 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
564 return InterfaceKeywords._set_interface_properties(
565 node, interface, path, None)
568 def add_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
569 """Add the IPv4 neighbour.
571 :param node: Honeycomb node.
572 :param interface: The name of interface.
573 :param ip_addr: IPv4 address of neighbour to be set.
574 :param link_layer_address: Link layer address.
578 :type link_layer_address: str
579 :returns: Content of response.
583 interface = Topology.convert_interface_reference(
584 node, interface, "name")
586 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
588 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
589 return InterfaceKeywords._set_interface_properties(
590 node, interface, path, neighbor)
593 def remove_all_ipv4_neighbors(node, interface):
594 """Remove all IPv4 neighbours.
596 :param node: Honeycomb node.
597 :param interface: The name of interface.
600 :returns: Content of response.
604 interface = Topology.convert_interface_reference(
605 node, interface, "name")
607 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
609 return InterfaceKeywords._set_interface_properties(
610 node, interface, path, None)
613 def configure_interface_ipv6(node, interface, param, value):
614 """Configure IPv6 parameters of interface
616 :param node: Honeycomb node.
617 :param interface: The name of interface.
618 :param param: Parameter to configure (set, change, remove)
619 :param value: The value of parameter. If None, the parameter will be
625 :returns: Content of response.
627 :raises HoneycombError: If the parameter is not valid.
630 if param in InterfaceKeywords.IPV6_PARAMS:
631 path = ("interfaces", ("interface", "name", interface),
632 "ietf-ip:ipv6", param)
633 elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
634 path = ("interfaces", ("interface", "name", interface),
635 "ietf-ip:ipv6", "autoconf", param)
637 raise HoneycombError("The parameter {0} is invalid.".format(param))
639 return InterfaceKeywords._set_interface_properties(
640 node, interface, path, value)
643 def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
644 """Add the first IPv6 address.
646 If there are any other addresses configured, they will be removed.
648 :param node: Honeycomb node.
649 :param interface: The name of interface.
650 :param ip_addr: IPv6 address to be set.
651 :param prefix_len: Prefix length.
655 :type prefix_len: str
656 :returns: Content of response.
660 interface = Topology.convert_interface_reference(
661 node, interface, "name")
663 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
664 address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
665 return InterfaceKeywords._set_interface_properties(
666 node, interface, path, address)
669 def add_ipv6_address(node, interface, ip_addr, prefix_len):
672 :param node: Honeycomb node.
673 :param interface: The name of interface.
674 :param ip_addr: IPv6 address to be set.
675 :param prefix_len: Prefix length.
679 :type prefix_len: str
680 :returns: Content of response.
684 interface = Topology.convert_interface_reference(
685 node, interface, "name")
687 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
689 address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
690 return InterfaceKeywords._set_interface_properties(
691 node, interface, path, address)
694 def remove_all_ipv6_addresses(node, interface):
695 """Remove all IPv6 addresses from interface.
697 :param node: Honeycomb node.
698 :param interface: The name of interface.
701 :returns: Content of response.
705 interface = Topology.convert_interface_reference(
706 node, interface, "name")
708 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
710 return InterfaceKeywords._set_interface_properties(
711 node, interface, path, None)
714 def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
715 """Add the IPv6 neighbour.
717 :param node: Honeycomb node.
718 :param interface: The name of interface.
719 :param ip_addr: IPv6 address of neighbour to be set.
720 :param link_layer_address: Link layer address.
724 :type link_layer_address: str
725 :returns: Content of response.
729 interface = Topology.convert_interface_reference(
730 node, interface, "name")
732 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
734 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
735 return InterfaceKeywords._set_interface_properties(
736 node, interface, path, neighbor)
739 def remove_all_ipv6_neighbors(node, interface):
740 """Remove all IPv6 neighbours.
742 :param node: Honeycomb node.
743 :param interface: The name of interface.
746 :returns: Content of response.
750 interface = Topology.convert_interface_reference(
751 node, interface, "name")
753 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
755 return InterfaceKeywords._set_interface_properties(
756 node, interface, path, None)
759 def configure_interface_ethernet(node, interface, param, value):
760 """Configure the ethernet parameters of interface.
762 :param node: Honeycomb node.
763 :param interface: The name of interface.
764 :param param: Parameter to configure (set, change, remove)
765 :param value: The value of parameter. If None, the parameter will be
771 :returns: Content of response.
773 :raises HoneycombError: If the parameter is not valid.
776 if param not in InterfaceKeywords.ETH_PARAMS:
777 raise HoneycombError("The parameter {0} is invalid.".format(param))
778 path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
780 return InterfaceKeywords._set_interface_properties(
781 node, interface, path, value)
784 def configure_interface_routing(node, interface, param, value):
785 """Configure the routing parameters of interface.
787 :param node: Honeycomb node.
788 :param interface: The name of interface.
789 :param param: Parameter to configure (set, change, remove)
790 :param value: The value of parameter. If None, the parameter will be
796 :returns: Content of response.
798 :raises HoneycombError: If the parameter is not valid.
801 interface = Topology.convert_interface_reference(
802 node, interface, "name")
804 if param not in InterfaceKeywords.ROUTING_PARAMS:
805 raise HoneycombError("The parameter {0} is invalid.".format(param))
807 path = ("interfaces", ("interface", "name", interface), "v3po:routing",
809 return InterfaceKeywords._set_interface_properties(
810 node, interface, path, value)
813 def honeycomb_create_vxlan_interface(node, interface, **kwargs):
814 """Create a new VxLAN interface.
816 :param node: Honeycomb node.
817 :param interface: The name of interface.
818 :param kwargs: Parameters and their values. The accepted parameters are
819 defined in InterfaceKeywords.VXLAN_PARAMS.
823 :returns: Content of response.
825 :raises HoneycombError: If the parameter is not valid.
830 "type": "v3po:vxlan-tunnel",
833 for param, value in kwargs.items():
834 if param not in InterfaceKeywords.VXLAN_PARAMS:
835 raise HoneycombError("The parameter {0} is invalid.".
837 new_vx_lan["v3po:vxlan"][param] = value
839 path = ("interfaces", "interface")
840 vx_lan_structure = [new_vx_lan, ]
841 return InterfaceKeywords._set_interface_properties(
842 node, interface, path, vx_lan_structure)
845 def delete_interface(node, interface):
846 """Delete an interface.
848 :param node: Honeycomb node.
849 :param interface: The name of interface.
852 :returns: Content of response.
854 :raises HoneycombError: If it is not possible to get information about
855 interfaces or it is not possible to delete the interface.
858 path = ("interfaces", ("interface", "name", interface))
860 status_code, resp = HcUtil.\
861 get_honeycomb_data(node, "config_vpp_interfaces")
862 if status_code != HTTPCodes.OK:
863 raise HoneycombError(
864 "Not possible to get configuration information about the "
865 "interfaces. Status code: {0}.".format(status_code))
867 new_data = HcUtil.remove_item(resp, path)
868 status_code, resp = HcUtil.\
869 put_honeycomb_data(node, "config_vpp_interfaces", new_data)
870 if status_code != HTTPCodes.OK:
871 raise HoneycombError("Not possible to remove interface {0}. "
873 format(interface, status_code))
877 def honeycomb_configure_interface_vxlan(node, interface, **kwargs):
878 """Configure VxLAN on the interface.
880 The keyword configures VxLAN parameters on the given interface. The type
881 of interface must be set to "v3po:vxlan-tunnel".
882 The new VxLAN parameters overwrite the current configuration. If a
883 parameter in new configuration is missing, it is removed from VxLAN
885 If the dictionary kwargs is empty, VxLAN configuration is removed.
887 :param node: Honeycomb node.
888 :param interface: The name of interface.
889 :param kwargs: Parameters and their values. The accepted parameters are
890 defined in InterfaceKeywords.VXLAN_PARAMS.
894 :returns: Content of response.
896 :raises HoneycombError: If the parameter is not valid.
899 vx_lan_structure = dict()
900 for param, value in kwargs.items():
901 if param not in InterfaceKeywords.VXLAN_PARAMS:
902 raise HoneycombError("The parameter {0} is invalid.".
904 vx_lan_structure[param] = value
906 path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
907 return InterfaceKeywords._set_interface_properties(
908 node, interface, path, vx_lan_structure)
911 def configure_interface_l2(node, interface, param, value):
912 """Configure the L2 parameters of interface.
914 :param node: Honeycomb node.
915 :param interface: The name of interface.
916 :param param: Parameter to configure (set, change, remove)
917 :param value: The value of parameter. If None, the parameter will be
923 :returns: Content of response.
925 :raises HoneycombError: If the parameter is not valid.
928 if param not in InterfaceKeywords.L2_PARAMS:
929 raise HoneycombError("The parameter {0} is invalid.".format(param))
930 path = ("interfaces", ("interface", "name", interface), "v3po:l2",
932 return InterfaceKeywords._set_interface_properties(
933 node, interface, path, value)
936 def create_tap_interface(node, interface, **kwargs):
937 """Create a new TAP interface.
939 :param node: Honeycomb node.
940 :param interface: The name of interface.
941 :param kwargs: Parameters and their values. The accepted parameters are
942 defined in InterfaceKeywords.TAP_PARAMS.
946 :returns: Content of response.
948 :raises HoneycombError: If the parameter is not valid.
956 for param, value in kwargs.items():
957 if param not in InterfaceKeywords.TAP_PARAMS:
958 raise HoneycombError("The parameter {0} is invalid.".
960 new_tap["v3po:tap"][param] = value
962 path = ("interfaces", "interface")
963 new_tap_structure = [new_tap, ]
964 return InterfaceKeywords._set_interface_properties(
965 node, interface, path, new_tap_structure)
968 def configure_interface_tap(node, interface, **kwargs):
969 """Configure TAP on the interface.
971 The keyword configures TAP parameters on the given interface. The type
972 of interface must be set to "v3po:tap".
973 The new TAP parameters overwrite the current configuration. If a
974 parameter in new configuration is missing, it is removed from TAP
976 If the dictionary kwargs is empty, TAP configuration is removed.
978 :param node: Honeycomb node.
979 :param interface: The name of interface.
980 :param kwargs: Parameters and their values. The accepted parameters are
981 defined in InterfaceKeywords.TAP_PARAMS.
985 :returns: Content of response.
987 :raises HoneycombError: If the parameter is not valid.
990 tap_structure = dict()
991 for param, value in kwargs.items():
992 if param not in InterfaceKeywords.TAP_PARAMS:
993 raise HoneycombError("The parameter {0} is invalid.".
995 tap_structure[param] = value
997 path = ("interfaces", ("interface", "name", interface), "v3po:tap")
998 return InterfaceKeywords._set_interface_properties(
999 node, interface, path, tap_structure)
1002 def configure_interface_vhost_user(node, interface, **kwargs):
1003 """Configure vhost-user on the interface.
1005 The keyword configures vhost-user parameters on the given interface.
1006 The type of interface must be set to "v3po:vhost-user".
1007 The new vhost-user parameters overwrite the current configuration. If a
1008 parameter in new configuration is missing, it is removed from vhost-user
1010 If the dictionary kwargs is empty, vhost-user configuration is removed.
1012 :param node: Honeycomb node.
1013 :param interface: The name of interface.
1014 :param kwargs: Parameters and their values. The accepted parameters are
1015 defined in InterfaceKeywords.VHOST_USER_PARAMS.
1017 :type interface: str
1019 :returns: Content of response.
1021 :raises HoneycombError: If the parameter is not valid.
1024 vhost_structure = dict()
1025 for param, value in kwargs.items():
1026 if param not in InterfaceKeywords.VHOST_USER_PARAMS:
1027 raise HoneycombError("The parameter {0} is invalid.".
1029 vhost_structure[param] = value
1031 path = ("interfaces", ("interface", "name", interface),
1033 return InterfaceKeywords._set_interface_properties(
1034 node, interface, path, vhost_structure)
1037 def create_vhost_user_interface(node, interface, **kwargs):
1038 """Create a new vhost-user interface.
1040 :param node: Honeycomb node.
1041 :param interface: The name of interface.
1042 :param kwargs: Parameters and their values. The accepted parameters are
1043 defined in InterfaceKeywords.VHOST_USER_PARAMS.
1045 :type interface: str
1047 :returns: Content of response.
1049 :raises HoneycombError: If the parameter is not valid.
1054 "type": "v3po:vhost-user",
1055 "v3po:vhost-user": {}
1057 for param, value in kwargs.items():
1058 if param not in InterfaceKeywords.VHOST_USER_PARAMS:
1059 raise HoneycombError("The parameter {0} is invalid.".
1061 new_vhost["v3po:vhost-user"][param] = value
1063 path = ("interfaces", "interface")
1064 new_vhost_structure = [new_vhost, ]
1065 return InterfaceKeywords._set_interface_properties(
1066 node, interface, path, new_vhost_structure)
1069 def honeycomb_create_sub_interface(node, super_interface, match, tags=None,
1071 """Create a new sub-interface.
1073 :param node: Honeycomb node.
1074 :param super_interface: Super interface.
1075 :param match: Match type. The valid values are defined in
1076 InterfaceKeywords.SUB_IF_MATCH.
1077 :param tags: List of tags.
1078 :param kwargs: Parameters and their values. The accepted parameters are
1079 defined in InterfaceKeywords.SUB_IF_PARAMS.
1081 :type super_interface: str
1085 :returns: Content of response.
1087 :raises HoneycombError: If the parameter is not valid.
1088 :raises KeyError: If the parameter 'match' is invalid.
1091 super_interface = Topology.convert_interface_reference(
1092 node, super_interface, "name")
1100 {"vlan-tagged": {"match-exact-tags": "false"}},
1101 "vlan-tagged-exact-match":
1102 {"vlan-tagged": {"match-exact-tags": "true"}}
1105 new_sub_interface = {
1111 for param, value in kwargs.items():
1112 if param in InterfaceKeywords.SUB_IF_PARAMS:
1113 new_sub_interface[param] = value
1115 raise HoneycombError("The parameter {0} is invalid.".
1118 new_sub_interface["match"] = match_type[match]
1120 raise HoneycombError("The value '{0}' of parameter 'match' is "
1121 "invalid.".format(match))
1124 new_sub_interface["tags"]["tag"].extend(tags)
1126 path = ("interfaces",
1127 ("interface", "name", super_interface),
1128 "vpp-vlan:sub-interfaces",
1130 new_sub_interface_structure = [new_sub_interface, ]
1131 return InterfaceKeywords._set_interface_properties(
1132 node, super_interface, path, new_sub_interface_structure)
1135 def get_sub_interface_oper_data(node, super_interface, identifier):
1136 """Retrieves sub-interface operational data using Honeycomb API.
1138 :param node: Honeycomb node.
1139 :param super_interface: Super interface.
1140 :param identifier: The ID of sub-interface.
1142 :type super_interface: str
1143 :type identifier: int
1144 :returns: Sub-interface operational data.
1146 :raises HoneycombError: If there is no sub-interface with the given ID.
1149 if_data = InterfaceKeywords.get_interface_oper_data(node,
1151 for sub_if in if_data["vpp-vlan:sub-interfaces"]["sub-interface"]:
1152 if str(sub_if["identifier"]) == str(identifier):
1155 raise HoneycombError("The interface {0} does not have sub-interface "
1156 "with ID {1}".format(super_interface, identifier))
1159 def remove_all_sub_interfaces(node, super_interface):
1160 """Remove all sub-interfaces from the given interface.
1162 :param node: Honeycomb node.
1163 :param super_interface: Super interface.
1165 :type super_interface: str
1166 :returns: Content of response.
1170 path = ("interfaces",
1171 ("interface", "name", super_interface),
1172 "vpp-vlan:sub-interfaces")
1174 return InterfaceKeywords._set_interface_properties(
1175 node, super_interface, path, {})
1178 def set_sub_interface_state(node, super_interface, identifier, state):
1179 """Set the administrative state of sub-interface.
1181 :param node: Honeycomb node.
1182 :param super_interface: Super interface.
1183 :param identifier: The ID of sub-interface.
1184 :param state: Required sub-interface state - up or down.
1186 :type super_interface: str
1187 :type identifier: int
1189 :returns: Content of response.
1193 super_interface = Topology.convert_interface_reference(
1194 node, super_interface, "name")
1196 intf_state = {"up": "true",
1199 path = ("interfaces",
1200 ("interface", "name", super_interface),
1201 "vpp-vlan:sub-interfaces",
1202 ("sub-interface", "identifier", int(identifier)),
1205 return InterfaceKeywords._set_interface_properties(
1206 node, super_interface, path, intf_state[state])
1209 def add_bridge_domain_to_sub_interface(node, super_interface, identifier,
1211 """Add a sub-interface to a bridge domain and set its parameters.
1213 :param node: Honeycomb node.
1214 :param super_interface: Super interface.
1215 :param identifier: The ID of sub-interface.
1216 :param config: Bridge domain configuration.
1218 :type super_interface: str
1219 :type identifier: int
1221 :returns: Content of response.
1225 path = ("interfaces",
1226 ("interface", "name", super_interface),
1227 "vpp-vlan:sub-interfaces",
1228 ("sub-interface", "identifier", int(identifier)),
1231 return InterfaceKeywords._set_interface_properties(
1232 node, super_interface, path, config)
1235 def get_bd_data_from_sub_interface(node, super_interface, identifier):
1236 """Get the operational data about the bridge domain from sub-interface.
1238 :param node: Honeycomb node.
1239 :param super_interface: Super interface.
1240 :param identifier: The ID of sub-interface.
1242 :type super_interface: str
1243 :type identifier: int
1244 :returns: Operational data about the bridge domain.
1246 :raises HoneycombError: If there is no sub-interface with the given ID.
1250 bd_data = InterfaceKeywords.get_sub_interface_oper_data(
1251 node, super_interface, identifier)["l2"]
1254 raise HoneycombError("The operational data does not contain "
1255 "information about a bridge domain.")
1258 def configure_tag_rewrite(node, super_interface, identifier, config):
1259 """Add / change / disable vlan tag rewrite on a sub-interface.
1261 :param node: Honeycomb node.
1262 :param super_interface: Super interface.
1263 :param identifier: The ID of sub-interface.
1264 :param config: Rewrite tag configuration.
1266 :type super_interface: str
1267 :type identifier: int
1269 :returns: Content of response.
1273 path = ("interfaces",
1274 ("interface", "name", super_interface),
1275 "vpp-vlan:sub-interfaces",
1276 ("sub-interface", "identifier", int(identifier)),
1280 return InterfaceKeywords._set_interface_properties(
1281 node, super_interface, path, config)
1284 def get_tag_rewrite_oper_data(node, super_interface, identifier):
1285 """Get the operational data about tag rewrite.
1287 :param node: Honeycomb node.
1288 :param super_interface: Super interface.
1289 :param identifier: The ID of sub-interface.
1291 :type super_interface: str
1292 :type identifier: int
1293 :returns: Operational data about tag rewrite.
1295 :raises HoneycombError: If there is no sub-interface with the given ID.
1299 tag_rewrite = InterfaceKeywords.get_sub_interface_oper_data(
1300 node, super_interface, identifier)["l2"]["rewrite"]
1303 raise HoneycombError("The operational data does not contain "
1304 "information about the tag-rewrite.")
1307 def add_ip_address_to_sub_interface(node, super_interface, identifier,
1308 ip_addr, network, ip_version):
1309 """Add an ipv4 address to the specified sub-interface, with the provided
1310 netmask or network prefix length. Any existing ipv4 addresses on the
1311 sub-interface will be replaced.
1313 :param node: Honeycomb node.
1314 :param super_interface: Super interface.
1315 :param identifier: The ID of sub-interface.
1316 :param ip_addr: IPv4 address to be set.
1317 :param network: Network mask or network prefix length.
1318 :param ip_version: ipv4 or ipv6
1320 :type super_interface: str
1321 :type identifier: int
1323 :type network: str or int
1324 :type ip_version: string
1325 :returns: Content of response.
1327 :raises HoneycombError: If the provided netmask or prefix is not valid.
1330 path = ("interfaces",
1331 ("interface", "name", super_interface),
1332 "vpp-vlan:sub-interfaces",
1333 ("sub-interface", "identifier", int(identifier)),
1336 if isinstance(network, basestring) and ip_version.lower() == "ipv4":
1337 address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
1339 elif isinstance(network, int) and 0 < network < 33:
1340 address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
1343 raise HoneycombError("{0} is not a valid netmask or prefix length."
1346 return InterfaceKeywords._set_interface_properties(
1347 node, super_interface, path, address)
1350 def remove_all_ip_addresses_from_sub_interface(node, super_interface,
1351 identifier, ip_version):
1352 """Remove all ipv4 addresses from the specified sub-interface.
1354 :param node: Honeycomb node.
1355 :param super_interface: Super interface.
1356 :param identifier: The ID of sub-interface.
1357 :param ip_version: ipv4 or ipv6
1359 :type super_interface: str
1360 :type identifier: int
1361 :type ip_version: string
1362 :returns: Content of response.
1366 path = ("interfaces",
1367 ("interface", "name", super_interface),
1368 "vpp-vlan:sub-interfaces",
1369 ("sub-interface", "identifier", int(identifier)),
1370 str(ip_version), "address")
1372 return InterfaceKeywords._set_interface_properties(
1373 node, super_interface, path, None)
1376 def compare_data_structures(data, ref, _path=''):
1377 """Checks if data obtained from UUT is as expected. If it is not,
1378 proceeds down the list/dictionary tree and finds the point of mismatch.
1380 :param data: Data to be checked.
1381 :param ref: Referential data used for comparison.
1382 :param _path: Used in recursive calls, stores the path taken down
1388 :raises HoneycombError: If the data structures do not match in some way,
1389 or if they are not in deserialized JSON format.
1395 elif isinstance(data, dict) and isinstance(ref, dict):
1398 raise HoneycombError(
1399 "Key {key} is not present in path {path}. Keys in path:"
1400 "{data_keys}".format(
1403 data_keys=data.keys()))
1405 if data[key] != ref[key]:
1406 if isinstance(data[key], list) \
1407 or isinstance(data[key], dict):
1408 InterfaceKeywords.compare_data_structures(
1409 data[key], ref[key],
1410 _path + '[{0}]'.format(key))
1412 raise HoneycombError(
1413 "Data mismatch, key {key} in path {path} has value"
1414 " {data}, but should be {ref}".format(
1420 elif isinstance(data, list) and isinstance(ref, list):
1422 if item not in data:
1423 if isinstance(item, dict):
1424 InterfaceKeywords.compare_data_structures(
1426 _path + '[{0}]'.format(ref.index(item)))
1428 raise HoneycombError(
1429 "Data mismatch, list item {index} in path {path}"
1430 " has value {data}, but should be {ref}".format(
1431 index=ref.index(item),
1437 raise HoneycombError(
1438 "Unexpected data type {data_type} in path {path}, reference"
1439 " type is {ref_type}. Must be list or dictionary.".format(
1440 data_type=type(data),
1445 def compare_interface_lists(list1, list2):
1446 """Compare provided lists of interfaces by name.
1448 :param list1: List of interfaces.
1449 :param list2: List of interfaces.
1452 :raises HoneycombError: If an interface exists in only one of the lists.
1455 ignore = ["vx_tunnel0", "vxlan_gpe_tunnel0"]
1456 # these have no equivalent in config data and no effect on VPP
1458 names1 = [x['name'] for x in list1]
1459 names2 = [x['name'] for x in list2]
1462 if name not in names2 and name not in ignore:
1463 raise HoneycombError("Interface {0} not present in list {1}"
1464 .format(name, list2))
1466 if name not in names1 and name not in ignore:
1467 raise HoneycombError("Interface {0} not present in list {1}"
1468 .format(name, list1))
1471 def create_vxlan_gpe_interface(node, interface, **kwargs):
1472 """Create a new VxLAN GPE interface.
1474 :param node: Honeycomb node.
1475 :param interface: The name of interface to be created.
1476 :param kwargs: Parameters and their values. The accepted parameters are
1477 defined in InterfaceKeywords.VXLAN_GPE_PARAMS.
1479 :type interface: str
1481 :returns: Content of response.
1483 :raises HoneycombError: If a parameter in kwargs is not valid.
1488 "type": "v3po:vxlan-gpe-tunnel",
1489 "v3po:vxlan-gpe": {}
1491 for param, value in kwargs.items():
1492 if param in InterfaceKeywords.INTF_PARAMS:
1493 new_vxlan_gpe[param] = value
1494 elif param in InterfaceKeywords.VXLAN_GPE_PARAMS:
1495 new_vxlan_gpe["v3po:vxlan-gpe"][param] = value
1497 raise HoneycombError("The parameter {0} is invalid.".
1499 path = ("interfaces", "interface")
1500 vxlan_gpe_structure = [new_vxlan_gpe, ]
1501 return InterfaceKeywords._set_interface_properties(
1502 node, interface, path, vxlan_gpe_structure)
1505 def enable_acl_on_interface(node, interface, table_name):
1506 """Enable ACL on the given interface.
1508 :param node: Honeycomb node.
1509 :param interface: The interface where the ACL will be enabled.
1510 :param table_name: Name of the classify table.
1512 :type interface: str
1513 :type table_name: str
1514 :returns: Content of response.
1516 :raises HoneycombError: If the configuration of interface is not
1520 interface = interface.replace("/", "%2F")
1523 "vpp-interface-acl:acl": {
1526 "classify-table": table_name
1529 "classify-table": table_name
1535 path = "/interface/" + interface + "/vpp-interface-acl:acl"
1536 status_code, resp = HcUtil.\
1537 put_honeycomb_data(node, "config_vpp_interfaces", data, path,
1538 data_representation=DataRepresentation.JSON)
1539 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1540 raise HoneycombError(
1541 "The configuration of interface '{0}' was not successful. "
1542 "Status code: {1}.".format(interface, status_code))
1546 def enable_policer_on_interface(node, interface, table_name):
1547 """Enable Policer on the given interface.
1549 :param node: Honeycomb node.
1550 :param interface: The interface where policer will be enabled.
1551 :param table_name: Name of the classify table.
1553 :type interface: str
1554 :type table_name: str
1555 :returns: Content of response.
1557 :raises HoneycombError: If the configuration of interface is not
1560 interface = Topology.convert_interface_reference(
1561 node, interface, "name")
1562 interface = interface.replace("/", "%2F")
1565 "interface-policer:policer": {
1566 "ip4-table": table_name
1570 path = "/interface/" + interface + "/interface-policer:policer"
1571 status_code, resp = HcUtil.\
1572 put_honeycomb_data(node, "config_vpp_interfaces", data, path,
1573 data_representation=DataRepresentation.JSON)
1574 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1575 raise HoneycombError(
1576 "The configuration of interface '{0}' was not successful. "
1577 "Status code: {1}.".format(interface, status_code))
1581 def disable_policer_on_interface(node, interface):
1582 """Disable Policer on the given interface.
1584 :param node: Honeycomb node.
1585 :param interface: The interface where policer will be disabled.
1587 :type interface: str
1588 :returns: Content of response.
1590 :raises HoneycombError: If the configuration of interface is not
1593 interface = Topology.convert_interface_reference(
1594 node, interface, "name")
1595 interface = interface.replace("/", "%2F")
1597 path = "/interface/" + interface + "/interface-policer:policer"
1598 status_code, resp = HcUtil.\
1599 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1600 if status_code != HTTPCodes.OK:
1601 raise HoneycombError(
1602 "The configuration of interface '{0}' was not successful. "
1603 "Status code: {1}.".format(interface, status_code))
1607 def disable_acl_on_interface(node, interface):
1608 """Disable ACL on the given interface.
1610 :param node: Honeycomb node.
1611 :param interface: The interface where the ACL will be disabled.
1613 :type interface: str
1614 :returns: Content of response.
1616 :raises HoneycombError: If the configuration of interface is not
1620 interface = interface.replace("/", "%2F")
1622 path = "/interface/" + interface + "/vpp-interface-acl:acl"
1624 status_code, resp = HcUtil.\
1625 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1627 if status_code != HTTPCodes.OK:
1628 raise HoneycombError(
1629 "The configuration of interface '{0}' was not successful. "
1630 "Status code: {1}.".format(interface, status_code))
1634 def create_pbb_sub_interface(node, intf, params):
1635 """Creates a PBB sub-interface on the given interface and sets its
1638 :param node: Honeycomb node.
1639 :param intf: The interface where PBB sub-interface will be configured.
1640 :param params: Configuration parameters of the sub-interface to be
1645 :returns: Content of response.
1647 :raises HoneycombError: If the configuration of sub-interface is not
1651 interface = intf.replace("/", "%2F")
1652 path = "/interface/{0}/pbb-rewrite".format(interface)
1653 status_code, resp = HcUtil. \
1654 put_honeycomb_data(node, "config_vpp_interfaces", params, path,
1655 data_representation=DataRepresentation.JSON)
1656 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1657 raise HoneycombError(
1658 "The configuration of PBB sub-interface '{0}' was not "
1659 "successful. Status code: {1}.".format(intf, status_code))
1663 def delete_pbb_sub_interface(node, intf):
1664 """Deletes the given PBB sub-interface.
1666 :param node: Honeycomb node.
1667 :param intf: The interface where PBB sub-interface will be deleted.
1670 :returns: Content of response.
1672 :raises HoneycombError: If the removal of sub-interface is not
1676 interface = intf.replace("/", "%2F")
1677 path = "/interface/{0}/pbb-rewrite".format(interface)
1679 status_code, resp = HcUtil. \
1680 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1681 if status_code != HTTPCodes.OK:
1682 raise HoneycombError(
1683 "The removal of pbb sub-interface '{0}' was not successful. "
1684 "Status code: {1}.".format(intf, status_code))
1688 def get_pbb_sub_interface_oper_data(node, intf, sub_if_id):
1689 """Retrieves PBB sub-interface operational data from Honeycomb.
1691 :param node: Honeycomb node.
1692 :param intf: The interface where PBB sub-interface is located.
1693 :param sub_if_id: ID of the PBB sub-interface.
1696 :type sub_if_id: str or int
1697 :returns: PBB sub-interface operational data.
1699 :raises HoneycombError: If the removal of sub-interface is not
1703 raise NotImplementedError
1706 def check_disabled_interface(node, interface):
1707 """Retrieves list of disabled interface indices from Honeycomb,
1708 and matches with the provided interface by index.
1710 :param node: Honeycomb node.
1711 :param interface: Index number of an interface on the node.
1713 :type interface: int
1714 :returns: True if the interface exists in disabled interfaces.
1716 :raises HoneycombError: If the interface is not present
1717 in retrieved list of disabled interfaces.
1719 data = InterfaceKeywords.get_disabled_interfaces_oper_data(node)
1720 # decrement by one = conversion from HC if-index to VPP sw_if_index
1724 if item["index"] == interface:
1726 raise HoneycombError("Interface index {0} not present in list"
1727 " of disabled interfaces.".format(interface))
1730 def configure_interface_span(node, dst_interface, src_interfaces=None):
1731 """Configure SPAN port mirroring on the specified interfaces. If no
1732 source interface is provided, SPAN will be disabled.
1734 :param node: Honeycomb node.
1735 :param dst_interface: Interface to mirror packets to.
1736 :param src_interfaces: List of interfaces to mirror packets from.
1738 :type dst_interface: str or int
1739 :type src_interfaces: list of dict
1740 :returns: Content of response.
1742 :raises HoneycombError: If SPAN could not be configured.
1745 interface = Topology.convert_interface_reference(
1746 node, dst_interface, "name")
1747 interface = interface.replace("/", "%2F")
1748 path = "/interface/" + interface + "/span"
1750 if not src_interfaces:
1751 status_code, _ = HcUtil.delete_honeycomb_data(
1752 node, "config_vpp_interfaces", path)
1754 for src_interface in src_interfaces:
1755 src_interface["iface-ref"] = Topology.\
1756 convert_interface_reference(
1757 node, src_interface["iface-ref"], "name")
1760 "mirrored-interfaces": {
1761 "mirrored-interface": src_interfaces
1766 status_code, _ = HcUtil.put_honeycomb_data(
1767 node, "config_vpp_interfaces", data, path)
1769 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1770 raise HoneycombError(
1771 "Configuring SPAN failed. Status code:{0}".format(status_code))
1774 def configure_sub_interface_span(node, super_interface, dst_interface_index,
1775 src_interfaces=None):
1776 """Configure SPAN port mirroring on the specified sub-interface. If no
1777 source interface is provided, SPAN will be disabled.
1779 Note: Does not support source sub-interfaces, only destination.
1781 :param node: Honeycomb node.
1782 :param super_interface: Name, link name or sw_if_index
1783 of the destination interface's super-interface.
1784 :param dst_interface_index: Index of sub-interface to mirror packets to.
1785 :param src_interfaces: List of interfaces to mirror packets from.
1787 :type super_interface: str or int
1788 :type dst_interface_index: int
1789 :type src_interfaces: list of dict
1790 :returns: Content of response.
1792 :raises HoneycombError: If SPAN could not be configured.
1795 super_interface = Topology.convert_interface_reference(
1796 node, super_interface, "name")
1797 super_interface = super_interface.replace("/", "%2F")
1799 path = "/interface/{0}/vpp-vlan:sub-interfaces/sub-interface/{1}/span"\
1800 .format(super_interface, dst_interface_index)
1802 if not src_interfaces:
1803 status_code, _ = HcUtil.delete_honeycomb_data(
1804 node, "config_vpp_interfaces", path)
1806 for src_interface in src_interfaces:
1807 src_interface["iface-ref"] = Topology. \
1808 convert_interface_reference(
1809 node, src_interface["iface-ref"], "name")
1812 "mirrored-interfaces": {
1813 "mirrored-interface": src_interfaces
1818 status_code, _ = HcUtil.put_honeycomb_data(
1819 node, "config_vpp_interfaces", data, path)
1821 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1822 raise HoneycombError(
1823 "Configuring SPAN failed. Status code:{0}".format(status_code))
1826 def add_interface_local0_to_topology(node):
1827 """Use Topology methods to add interface "local0" to working topology,
1828 if not already present.
1830 :param node: DUT node.
1834 if Topology.get_interface_by_sw_index(node, 0) is None:
1835 local0_key = Topology.add_new_port(node, "localzero")
1836 Topology.update_interface_sw_if_index(node, local0_key, 0)
1837 Topology.update_interface_name(node, local0_key, "local0")
1840 def configure_interface_unnumbered(node, interface, interface_src=None):
1841 """Configure the specified interface as unnumbered. The interface
1842 borrows IP address from the specified source interface. If not source
1843 interface is provided, unnumbered configuration will be removed.
1845 :param node: Honeycomb node.
1846 :param interface: Name, link name or sw_if_index of an interface.
1847 :param interface_src: Name of source interface.
1849 :type interface: str or int
1850 :type interface_src: str
1851 :raises HoneycombError: If the configuration fails.
1854 interface = InterfaceKeywords.handle_interface_reference(
1857 path = "/interface/{0}/unnumbered-interfaces:unnumbered"\
1863 "use": interface_src
1866 status_code, _ = HcUtil.put_honeycomb_data(
1867 node, "config_vpp_interfaces", data, path)
1869 status_code, _ = HcUtil.delete_honeycomb_data(
1870 node, "config_vpp_interfaces", path)
1872 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1873 raise HoneycombError(
1874 "Configuring unnumbered interface failed. "
1875 "Status code:{0}".format(status_code))
1878 def handle_interface_reference(node, interface):
1879 """Convert any interface reference to interface name used by Honeycomb.
1881 :param node: Honeycomb node.
1882 :param interface: Name, link name or sw_if_index of an interface,
1883 name of a custom interface or name of a sub-interface.
1884 :type node: Honeycomb node.
1885 :type interface: str or int
1886 :returns: Name of interface that can be used in Honeycomb requests.
1891 interface = Topology.convert_interface_reference(
1892 node, interface, "name")
1893 interface = interface.replace("/", "%2F")
1894 except RuntimeError:
1895 # interface is not in topology
1896 if "." in interface:
1897 # Assume it's the name of a sub-interface
1898 interface, index = interface.split(".")
1899 interface = interface.replace("/", "%2F")
1900 interface = "{0}/vpp-vlan:sub-interfaces/sub-interface/{1}".\
1901 format(interface, index)
1903 # Assume it's the name of a custom interface (pbb, vxlan, etc.)
1904 interface = interface.replace("/", "%2F")