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.
204 intfs = InterfaceKeywords.get_all_interfaces_oper_data(node)
206 if intf["name"] == interface:
211 def _set_interface_properties(node, interface, path, new_value=None):
212 """Set interface properties.
214 This method reads interface configuration data, creates, changes or
215 removes the requested data and puts it back to Honeycomb.
217 :param node: Honeycomb node.
218 :param interface: The name of interface.
219 :param path: Path to data we want to change / create / remove.
220 :param new_value: The new value to be set. If None, the item will be
225 :type new_value: str, dict or list
226 :returns: Content of response.
228 :raises HoneycombError: If it is not possible to get or set the data.
231 status_code, resp = HcUtil.\
232 get_honeycomb_data(node, "config_vpp_interfaces")
233 if status_code != HTTPCodes.OK:
234 raise HoneycombError(
235 "Not possible to get configuration information about the "
236 "interfaces. Status code: {0}.".format(status_code))
239 new_data = HcUtil.set_item_value(resp, path, new_value)
241 new_data = HcUtil.remove_item(resp, path)
242 return InterfaceKeywords._configure_interface(node, interface, new_data)
245 def set_interface_state(node, interface, state="up"):
246 """Set VPP interface state.
248 The keyword changes the administration state of interface to up or down
249 depending on the parameter "state".
251 :param node: Honeycomb node.
252 :param interface: Interface name, key, link name or sw_if_index.
253 :param state: The requested state, only "up" and "down" are valid
258 :returns: Content of response.
260 :raises KeyError: If the argument "state" is nor "up" or "down".
261 :raises HoneycombError: If the interface is not present on the node.
264 intf_state = {"up": "true",
267 interface = Topology.convert_interface_reference(
268 node, interface, "name")
270 intf = interface.replace("/", "%2F")
271 path = "/interface/{0}".format(intf)
273 status_code, resp = HcUtil.\
274 get_honeycomb_data(node, "config_vpp_interfaces", path)
275 if status_code != HTTPCodes.OK:
276 raise HoneycombError(
277 "Not possible to get configuration information about the "
278 "interfaces. Status code: {0}.".format(status_code))
280 resp["interface"][0]["enabled"] = intf_state[state.lower()]
282 status_code, resp = HcUtil. \
283 put_honeycomb_data(node, "config_vpp_interfaces", resp, path,
284 data_representation=DataRepresentation.JSON)
285 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
286 raise HoneycombError(
287 "The configuration of interface '{0}' was not successful. "
288 "Status code: {1}.".format(interface, status_code))
292 def set_interface_up(node, interface):
293 """Set the administration state of VPP interface to up.
295 :param node: Honeycomb node.
296 :param interface: The name of interface.
299 :returns: Content of response
303 return InterfaceKeywords.set_interface_state(node, interface, "up")
306 def set_interface_down(node, interface):
307 """Set the administration state of VPP interface to down.
309 :param node: Honeycomb node.
310 :param interface: The name of interface.
313 :returns: Content of response.
317 return InterfaceKeywords.set_interface_state(node, interface, "down")
320 def add_bridge_domain_to_interface(node, interface, bd_name,
321 split_horizon_group=None, bvi=None):
322 """Add a new bridge domain to an interface and set its parameters.
324 :param node: Honeycomb node.
325 :param interface: Interface name, key, link name or sw_if_index.
326 :param bd_name: Bridge domain name.
327 :param split_horizon_group: Split-horizon group name.
328 :param bvi: The bridged virtual interface.
332 :type split_horizon_group: str
334 :returns: Content of response.
336 :raises HoneycombError: If the interface is not present on the node.
339 interface = Topology.convert_interface_reference(
340 node, interface, "name")
342 v3po_l2 = {"bridge-domain": str(bd_name)}
343 if split_horizon_group:
344 v3po_l2["split-horizon-group"] = str(split_horizon_group)
346 v3po_l2["bridged-virtual-interface"] = str(bvi)
348 path = ("interfaces", ("interface", "name", str(interface)), "v3po:l2")
350 return InterfaceKeywords._set_interface_properties(
351 node, interface, path, v3po_l2)
354 def remove_bridge_domain_from_interface(node, interface):
355 """Remove bridge domain assignment from interface.
357 :param node: Honeycomb node.
358 :param interface: Interface name, key, link name or sw_if_index.
360 :type interface: str or int
362 :raises HoneycombError: If the operation fails.
365 interface = Topology.convert_interface_reference(
366 node, interface, "name")
368 intf = interface.replace("/", "%2F")
370 path = "/interface/{0}/v3po:l2".format(intf)
372 status_code, response = HcUtil.delete_honeycomb_data(
373 node, "config_vpp_interfaces", path)
375 if status_code != HTTPCodes.OK:
376 if '"error-tag":"data-missing"' in response:
377 logger.debug("Data does not exist in path.")
379 raise HoneycombError(
380 "Could not remove bridge domain assignment from interface "
381 "'{0}'. Status code: {1}.".format(interface, status_code))
384 def get_bd_oper_data_from_interface(node, interface):
385 """Returns operational data about bridge domain settings in the
388 :param node: Honeycomb node.
389 :param interface: The name of interface.
392 :returns: Operational data about bridge domain settings in the
397 if_data = InterfaceKeywords.get_interface_oper_data(node, interface)
401 return if_data["v3po:l2"]
407 def configure_interface_base(node, interface, param, value):
408 """Configure the base parameters of interface.
410 :param node: Honeycomb node.
411 :param interface: The name of interface.
412 :param param: Parameter to configure (set, change, remove)
413 :param value: The value of parameter. If None, the parameter will be
419 :returns: Content of response.
421 :raises HoneycombError: If the parameter is not valid.
424 if param not in InterfaceKeywords.INTF_PARAMS:
425 raise HoneycombError("The parameter {0} is invalid.".format(param))
427 path = ("interfaces", ("interface", "name", interface), param)
428 return InterfaceKeywords._set_interface_properties(
429 node, interface, path, value)
432 def configure_interface_ipv4(node, interface, param, value):
433 """Configure IPv4 parameters of interface.
435 :param node: Honeycomb node.
436 :param interface: The name of interface.
437 :param param: Parameter to configure (set, change, remove)
438 :param value: The value of parameter. If None, the parameter will be
444 :returns: Content of response.
446 :raises HoneycombError: If the parameter is not valid.
449 interface = Topology.convert_interface_reference(
450 node, interface, "name")
452 if param not in InterfaceKeywords.IPV4_PARAMS:
453 raise HoneycombError("The parameter {0} is invalid.".format(param))
455 path = ("interfaces", ("interface", "name", interface),
456 "ietf-ip:ipv4", param)
457 return InterfaceKeywords._set_interface_properties(
458 node, interface, path, value)
461 def add_first_ipv4_address(node, interface, ip_addr, network):
462 """Add the first IPv4 address.
464 If there are any other addresses configured, they will be removed.
466 :param node: Honeycomb node.
467 :param interface: The name of interface.
468 :param ip_addr: IPv4 address to be set.
469 :param network: Netmask or length of network prefix.
473 :type network: str or int
474 :returns: Content of response.
476 :raises HoneycombError: If the provided netmask or prefix is not valid.
479 interface = Topology.convert_interface_reference(
480 node, interface, "name")
482 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
483 if isinstance(network, basestring):
484 address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
485 elif isinstance(network, int) and (0 < network < 33):
486 address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
488 raise HoneycombError("Value {0} is not a valid netmask or network "
489 "prefix length.".format(network))
490 return InterfaceKeywords._set_interface_properties(
491 node, interface, path, address)
494 def add_ipv4_address(node, interface, ip_addr, network):
497 :param node: Honeycomb node.
498 :param interface: The name of interface.
499 :param ip_addr: IPv4 address to be set.
500 :param network: Netmask or length of network prefix.
504 :type network: str or int
505 :returns: Content of response.
507 :raises HoneycombError: If the provided netmask or prefix is not valid.
510 interface = Topology.convert_interface_reference(
511 node, interface, "name")
513 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
515 if isinstance(network, basestring):
516 address = [{"ip": ip_addr, "netmask": network}]
517 elif isinstance(network, int) and (0 < network < 33):
518 address = [{"ip": ip_addr, "prefix-length": network}]
520 raise HoneycombError("Value {0} is not a valid netmask or network "
521 "prefix length.".format(network))
522 return InterfaceKeywords._set_interface_properties(
523 node, interface, path, address)
526 def remove_all_ipv4_addresses(node, interface):
527 """Remove all IPv4 addresses from interface.
529 :param node: Honeycomb node.
530 :param interface: The name of interface.
533 :returns: Content of response.
537 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
539 return InterfaceKeywords._set_interface_properties(
540 node, interface, path, None)
543 def add_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
544 """Add the IPv4 neighbour.
546 :param node: Honeycomb node.
547 :param interface: The name of interface.
548 :param ip_addr: IPv4 address of neighbour to be set.
549 :param link_layer_address: Link layer address.
553 :type link_layer_address: str
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 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
564 return InterfaceKeywords._set_interface_properties(
565 node, interface, path, neighbor)
568 def remove_all_ipv4_neighbors(node, interface):
569 """Remove all IPv4 neighbours.
571 :param node: Honeycomb node.
572 :param interface: The name of interface.
575 :returns: Content of response.
579 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
581 return InterfaceKeywords._set_interface_properties(
582 node, interface, path, None)
585 def configure_interface_ipv6(node, interface, param, value):
586 """Configure IPv6 parameters of interface
588 :param node: Honeycomb node.
589 :param interface: The name of interface.
590 :param param: Parameter to configure (set, change, remove)
591 :param value: The value of parameter. If None, the parameter will be
597 :returns: Content of response.
599 :raises HoneycombError: If the parameter is not valid.
602 if param in InterfaceKeywords.IPV6_PARAMS:
603 path = ("interfaces", ("interface", "name", interface),
604 "ietf-ip:ipv6", param)
605 elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
606 path = ("interfaces", ("interface", "name", interface),
607 "ietf-ip:ipv6", "autoconf", param)
609 raise HoneycombError("The parameter {0} is invalid.".format(param))
611 return InterfaceKeywords._set_interface_properties(
612 node, interface, path, value)
615 def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
616 """Add the first IPv6 address.
618 If there are any other addresses configured, they will be removed.
620 :param node: Honeycomb node.
621 :param interface: The name of interface.
622 :param ip_addr: IPv6 address to be set.
623 :param prefix_len: Prefix length.
627 :type prefix_len: str
628 :returns: Content of response.
632 interface = Topology.convert_interface_reference(
633 node, interface, "name")
635 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
636 address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
637 return InterfaceKeywords._set_interface_properties(
638 node, interface, path, address)
641 def add_ipv6_address(node, interface, ip_addr, prefix_len):
644 :param node: Honeycomb node.
645 :param interface: The name of interface.
646 :param ip_addr: IPv6 address to be set.
647 :param prefix_len: Prefix length.
651 :type prefix_len: str
652 :returns: Content of response.
656 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
658 address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
659 return InterfaceKeywords._set_interface_properties(
660 node, interface, path, address)
663 def remove_all_ipv6_addresses(node, interface):
664 """Remove all IPv6 addresses from interface.
666 :param node: Honeycomb node.
667 :param interface: The name of interface.
670 :returns: Content of response.
674 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
676 return InterfaceKeywords._set_interface_properties(
677 node, interface, path, None)
680 def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
681 """Add the IPv6 neighbour.
683 :param node: Honeycomb node.
684 :param interface: The name of interface.
685 :param ip_addr: IPv6 address of neighbour to be set.
686 :param link_layer_address: Link layer address.
690 :type link_layer_address: str
691 :returns: Content of response.
695 interface = Topology.convert_interface_reference(
696 node, interface, "name")
698 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
700 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
701 return InterfaceKeywords._set_interface_properties(
702 node, interface, path, neighbor)
705 def remove_all_ipv6_neighbors(node, interface):
706 """Remove all IPv6 neighbours.
708 :param node: Honeycomb node.
709 :param interface: The name of interface.
712 :returns: Content of response.
716 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
718 return InterfaceKeywords._set_interface_properties(
719 node, interface, path, None)
722 def configure_interface_ethernet(node, interface, param, value):
723 """Configure the ethernet parameters of interface.
725 :param node: Honeycomb node.
726 :param interface: The name of interface.
727 :param param: Parameter to configure (set, change, remove)
728 :param value: The value of parameter. If None, the parameter will be
734 :returns: Content of response.
736 :raises HoneycombError: If the parameter is not valid.
739 if param not in InterfaceKeywords.ETH_PARAMS:
740 raise HoneycombError("The parameter {0} is invalid.".format(param))
741 path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
743 return InterfaceKeywords._set_interface_properties(
744 node, interface, path, value)
747 def configure_interface_routing(node, interface, param, value):
748 """Configure the routing parameters of interface.
750 :param node: Honeycomb node.
751 :param interface: The name of interface.
752 :param param: Parameter to configure (set, change, remove)
753 :param value: The value of parameter. If None, the parameter will be
759 :returns: Content of response.
761 :raises HoneycombError: If the parameter is not valid.
764 interface = Topology.convert_interface_reference(
765 node, interface, "name")
767 if param not in InterfaceKeywords.ROUTING_PARAMS:
768 raise HoneycombError("The parameter {0} is invalid.".format(param))
770 path = ("interfaces", ("interface", "name", interface), "v3po:routing",
772 return InterfaceKeywords._set_interface_properties(
773 node, interface, path, value)
776 def create_vxlan_interface(node, interface, **kwargs):
777 """Create a new VxLAN interface.
779 :param node: Honeycomb node.
780 :param interface: The name of interface.
781 :param kwargs: Parameters and their values. The accepted parameters are
782 defined in InterfaceKeywords.VXLAN_PARAMS.
786 :returns: Content of response.
788 :raises HoneycombError: If the parameter is not valid.
793 "type": "v3po:vxlan-tunnel",
796 for param, value in kwargs.items():
797 if param not in InterfaceKeywords.VXLAN_PARAMS:
798 raise HoneycombError("The parameter {0} is invalid.".
800 new_vx_lan["v3po:vxlan"][param] = value
802 path = ("interfaces", "interface")
803 vx_lan_structure = [new_vx_lan, ]
804 return InterfaceKeywords._set_interface_properties(
805 node, interface, path, vx_lan_structure)
808 def delete_interface(node, interface):
809 """Delete an interface.
811 :param node: Honeycomb node.
812 :param interface: The name of interface.
815 :returns: Content of response.
817 :raises HoneycombError: If it is not possible to get information about
818 interfaces or it is not possible to delete the interface.
821 path = ("interfaces", ("interface", "name", interface))
823 status_code, resp = HcUtil.\
824 get_honeycomb_data(node, "config_vpp_interfaces")
825 if status_code != HTTPCodes.OK:
826 raise HoneycombError(
827 "Not possible to get configuration information about the "
828 "interfaces. Status code: {0}.".format(status_code))
830 new_data = HcUtil.remove_item(resp, path)
831 status_code, resp = HcUtil.\
832 put_honeycomb_data(node, "config_vpp_interfaces", new_data)
833 if status_code != HTTPCodes.OK:
834 raise HoneycombError("Not possible to remove interface {0}. "
836 format(interface, status_code))
840 def configure_interface_vxlan(node, interface, **kwargs):
841 """Configure VxLAN on the interface.
843 The keyword configures VxLAN parameters on the given interface. The type
844 of interface must be set to "v3po:vxlan-tunnel".
845 The new VxLAN parameters overwrite the current configuration. If a
846 parameter in new configuration is missing, it is removed from VxLAN
848 If the dictionary kwargs is empty, VxLAN configuration is removed.
850 :param node: Honeycomb node.
851 :param interface: The name of interface.
852 :param kwargs: Parameters and their values. The accepted parameters are
853 defined in InterfaceKeywords.VXLAN_PARAMS.
857 :returns: Content of response.
859 :raises HoneycombError: If the parameter is not valid.
862 vx_lan_structure = dict()
863 for param, value in kwargs.items():
864 if param not in InterfaceKeywords.VXLAN_PARAMS:
865 raise HoneycombError("The parameter {0} is invalid.".
867 vx_lan_structure[param] = value
869 path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
870 return InterfaceKeywords._set_interface_properties(
871 node, interface, path, vx_lan_structure)
874 def configure_interface_l2(node, interface, param, value):
875 """Configure the L2 parameters of interface.
877 :param node: Honeycomb node.
878 :param interface: The name of interface.
879 :param param: Parameter to configure (set, change, remove)
880 :param value: The value of parameter. If None, the parameter will be
886 :returns: Content of response.
888 :raises HoneycombError: If the parameter is not valid.
891 if param not in InterfaceKeywords.L2_PARAMS:
892 raise HoneycombError("The parameter {0} is invalid.".format(param))
893 path = ("interfaces", ("interface", "name", interface), "v3po:l2",
895 return InterfaceKeywords._set_interface_properties(
896 node, interface, path, value)
899 def create_tap_interface(node, interface, **kwargs):
900 """Create a new TAP interface.
902 :param node: Honeycomb node.
903 :param interface: The name of interface.
904 :param kwargs: Parameters and their values. The accepted parameters are
905 defined in InterfaceKeywords.TAP_PARAMS.
909 :returns: Content of response.
911 :raises HoneycombError: If the parameter is not valid.
919 for param, value in kwargs.items():
920 if param not in InterfaceKeywords.TAP_PARAMS:
921 raise HoneycombError("The parameter {0} is invalid.".
923 new_tap["v3po:tap"][param] = value
925 path = ("interfaces", "interface")
926 new_tap_structure = [new_tap, ]
927 return InterfaceKeywords._set_interface_properties(
928 node, interface, path, new_tap_structure)
931 def configure_interface_tap(node, interface, **kwargs):
932 """Configure TAP on the interface.
934 The keyword configures TAP parameters on the given interface. The type
935 of interface must be set to "v3po:tap".
936 The new TAP parameters overwrite the current configuration. If a
937 parameter in new configuration is missing, it is removed from TAP
939 If the dictionary kwargs is empty, TAP configuration is removed.
941 :param node: Honeycomb node.
942 :param interface: The name of interface.
943 :param kwargs: Parameters and their values. The accepted parameters are
944 defined in InterfaceKeywords.TAP_PARAMS.
948 :returns: Content of response.
950 :raises HoneycombError: If the parameter is not valid.
953 tap_structure = dict()
954 for param, value in kwargs.items():
955 if param not in InterfaceKeywords.TAP_PARAMS:
956 raise HoneycombError("The parameter {0} is invalid.".
958 tap_structure[param] = value
960 path = ("interfaces", ("interface", "name", interface), "v3po:tap")
961 return InterfaceKeywords._set_interface_properties(
962 node, interface, path, tap_structure)
965 def configure_interface_vhost_user(node, interface, **kwargs):
966 """Configure vhost-user on the interface.
968 The keyword configures vhost-user parameters on the given interface.
969 The type of interface must be set to "v3po:vhost-user".
970 The new vhost-user parameters overwrite the current configuration. If a
971 parameter in new configuration is missing, it is removed from vhost-user
973 If the dictionary kwargs is empty, vhost-user configuration is removed.
975 :param node: Honeycomb node.
976 :param interface: The name of interface.
977 :param kwargs: Parameters and their values. The accepted parameters are
978 defined in InterfaceKeywords.VHOST_USER_PARAMS.
982 :returns: Content of response.
984 :raises HoneycombError: If the parameter is not valid.
987 vhost_structure = dict()
988 for param, value in kwargs.items():
989 if param not in InterfaceKeywords.VHOST_USER_PARAMS:
990 raise HoneycombError("The parameter {0} is invalid.".
992 vhost_structure[param] = value
994 path = ("interfaces", ("interface", "name", interface),
996 return InterfaceKeywords._set_interface_properties(
997 node, interface, path, vhost_structure)
1000 def create_vhost_user_interface(node, interface, **kwargs):
1001 """Create a new vhost-user interface.
1003 :param node: Honeycomb node.
1004 :param interface: The name of interface.
1005 :param kwargs: Parameters and their values. The accepted parameters are
1006 defined in InterfaceKeywords.VHOST_USER_PARAMS.
1008 :type interface: str
1010 :returns: Content of response.
1012 :raises HoneycombError: If the parameter is not valid.
1017 "type": "v3po:vhost-user",
1018 "v3po:vhost-user": {}
1020 for param, value in kwargs.items():
1021 if param not in InterfaceKeywords.VHOST_USER_PARAMS:
1022 raise HoneycombError("The parameter {0} is invalid.".
1024 new_vhost["v3po:vhost-user"][param] = value
1026 path = ("interfaces", "interface")
1027 new_vhost_structure = [new_vhost, ]
1028 return InterfaceKeywords._set_interface_properties(
1029 node, interface, path, new_vhost_structure)
1032 def create_sub_interface(node, super_interface, match, tags=None, **kwargs):
1033 """Create a new sub-interface.
1035 :param node: Honeycomb node.
1036 :param super_interface: Super interface.
1037 :param match: Match type. The valid values are defined in
1038 InterfaceKeywords.SUB_IF_MATCH.
1039 :param tags: List of tags.
1040 :param kwargs: Parameters and their values. The accepted parameters are
1041 defined in InterfaceKeywords.SUB_IF_PARAMS.
1043 :type super_interface: str
1047 :returns: Content of response.
1049 :raises HoneycombError: If the parameter is not valid.
1050 :raises KeyError: If the parameter 'match' is invalid.
1059 {"vlan-tagged": {"match-exact-tags": "false"}},
1060 "vlan-tagged-exact-match":
1061 {"vlan-tagged": {"match-exact-tags": "true"}}
1064 new_sub_interface = {
1070 for param, value in kwargs.items():
1071 if param in InterfaceKeywords.SUB_IF_PARAMS:
1072 new_sub_interface[param] = value
1074 raise HoneycombError("The parameter {0} is invalid.".
1077 new_sub_interface["match"] = match_type[match]
1079 raise HoneycombError("The value '{0}' of parameter 'match' is "
1080 "invalid.".format(match))
1083 new_sub_interface["tags"]["tag"].extend(tags)
1085 path = ("interfaces",
1086 ("interface", "name", super_interface),
1087 "vpp-vlan:sub-interfaces",
1089 new_sub_interface_structure = [new_sub_interface, ]
1090 return InterfaceKeywords._set_interface_properties(
1091 node, super_interface, path, new_sub_interface_structure)
1094 def get_sub_interface_oper_data(node, super_interface, identifier):
1095 """Retrieves sub-interface operational data using Honeycomb API.
1097 :param node: Honeycomb node.
1098 :param super_interface: Super interface.
1099 :param identifier: The ID of sub-interface.
1101 :type super_interface: str
1102 :type identifier: int
1103 :returns: Sub-interface operational data.
1105 :raises HoneycombError: If there is no sub-interface with the given ID.
1108 if_data = InterfaceKeywords.get_interface_oper_data(node,
1110 for sub_if in if_data["vpp-vlan:sub-interfaces"]["sub-interface"]:
1111 if str(sub_if["identifier"]) == str(identifier):
1114 raise HoneycombError("The interface {0} does not have sub-interface "
1115 "with ID {1}".format(super_interface, identifier))
1118 def remove_all_sub_interfaces(node, super_interface):
1119 """Remove all sub-interfaces from the given interface.
1121 :param node: Honeycomb node.
1122 :param super_interface: Super interface.
1124 :type super_interface: str
1125 :returns: Content of response.
1129 path = ("interfaces",
1130 ("interface", "name", super_interface),
1131 "vpp-vlan:sub-interfaces")
1133 return InterfaceKeywords._set_interface_properties(
1134 node, super_interface, path, {})
1137 def set_sub_interface_state(node, super_interface, identifier, state):
1138 """Set the administrative state of sub-interface.
1140 :param node: Honeycomb node.
1141 :param super_interface: Super interface.
1142 :param identifier: The ID of sub-interface.
1143 :param state: Required sub-interface state - up or down.
1145 :type super_interface: str
1146 :type identifier: int
1148 :returns: Content of response.
1152 intf_state = {"up": "true",
1155 path = ("interfaces",
1156 ("interface", "name", super_interface),
1157 "vpp-vlan:sub-interfaces",
1158 ("sub-interface", "identifier", int(identifier)),
1161 return InterfaceKeywords._set_interface_properties(
1162 node, super_interface, path, intf_state[state])
1165 def add_bridge_domain_to_sub_interface(node, super_interface, identifier,
1167 """Add a sub-interface to a bridge domain and set its parameters.
1169 :param node: Honeycomb node.
1170 :param super_interface: Super interface.
1171 :param identifier: The ID of sub-interface.
1172 :param config: Bridge domain configuration.
1174 :type super_interface: str
1175 :type identifier: int
1177 :returns: Content of response.
1181 path = ("interfaces",
1182 ("interface", "name", super_interface),
1183 "vpp-vlan:sub-interfaces",
1184 ("sub-interface", "identifier", int(identifier)),
1187 return InterfaceKeywords._set_interface_properties(
1188 node, super_interface, path, config)
1191 def get_bd_data_from_sub_interface(node, super_interface, identifier):
1192 """Get the operational data about the bridge domain from sub-interface.
1194 :param node: Honeycomb node.
1195 :param super_interface: Super interface.
1196 :param identifier: The ID of sub-interface.
1198 :type super_interface: str
1199 :type identifier: int
1200 :returns: Operational data about the bridge domain.
1202 :raises HoneycombError: If there is no sub-interface with the given ID.
1206 bd_data = InterfaceKeywords.get_sub_interface_oper_data(
1207 node, super_interface, identifier)["l2"]
1210 raise HoneycombError("The operational data does not contain "
1211 "information about a bridge domain.")
1214 def configure_tag_rewrite(node, super_interface, identifier, config):
1215 """Add / change / disable vlan tag rewrite on a sub-interface.
1217 :param node: Honeycomb node.
1218 :param super_interface: Super interface.
1219 :param identifier: The ID of sub-interface.
1220 :param config: Rewrite tag configuration.
1222 :type super_interface: str
1223 :type identifier: int
1225 :returns: Content of response.
1229 path = ("interfaces",
1230 ("interface", "name", super_interface),
1231 "vpp-vlan:sub-interfaces",
1232 ("sub-interface", "identifier", int(identifier)),
1236 return InterfaceKeywords._set_interface_properties(
1237 node, super_interface, path, config)
1240 def get_tag_rewrite_oper_data(node, super_interface, identifier):
1241 """Get the operational data about tag rewrite.
1243 :param node: Honeycomb node.
1244 :param super_interface: Super interface.
1245 :param identifier: The ID of sub-interface.
1247 :type super_interface: str
1248 :type identifier: int
1249 :returns: Operational data about tag rewrite.
1251 :raises HoneycombError: If there is no sub-interface with the given ID.
1255 tag_rewrite = InterfaceKeywords.get_sub_interface_oper_data(
1256 node, super_interface, identifier)["l2"]["rewrite"]
1259 raise HoneycombError("The operational data does not contain "
1260 "information about the tag-rewrite.")
1263 def add_ip_address_to_sub_interface(node, super_interface, identifier,
1264 ip_addr, network, ip_version):
1265 """Add an ipv4 address to the specified sub-interface, with the provided
1266 netmask or network prefix length. Any existing ipv4 addresses on the
1267 sub-interface will be replaced.
1269 :param node: Honeycomb node.
1270 :param super_interface: Super interface.
1271 :param identifier: The ID of sub-interface.
1272 :param ip_addr: IPv4 address to be set.
1273 :param network: Network mask or network prefix length.
1274 :param ip_version: ipv4 or ipv6
1276 :type super_interface: str
1277 :type identifier: int
1279 :type network: str or int
1280 :type ip_version: string
1281 :returns: Content of response.
1283 :raises HoneycombError: If the provided netmask or prefix is not valid.
1286 path = ("interfaces",
1287 ("interface", "name", super_interface),
1288 "vpp-vlan:sub-interfaces",
1289 ("sub-interface", "identifier", int(identifier)),
1292 if isinstance(network, basestring) and ip_version.lower() == "ipv4":
1293 address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
1295 elif isinstance(network, int) and 0 < network < 33:
1296 address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
1299 raise HoneycombError("{0} is not a valid netmask or prefix length."
1302 return InterfaceKeywords._set_interface_properties(
1303 node, super_interface, path, address)
1306 def remove_all_ip_addresses_from_sub_interface(node, super_interface,
1307 identifier, ip_version):
1308 """Remove all ipv4 addresses from the specified sub-interface.
1310 :param node: Honeycomb node.
1311 :param super_interface: Super interface.
1312 :param identifier: The ID of sub-interface.
1313 :param ip_version: ipv4 or ipv6
1315 :type super_interface: str
1316 :type identifier: int
1317 :type ip_version: string
1318 :returns: Content of response.
1322 path = ("interfaces",
1323 ("interface", "name", super_interface),
1324 "vpp-vlan:sub-interfaces",
1325 ("sub-interface", "identifier", int(identifier)),
1326 str(ip_version), "address")
1328 return InterfaceKeywords._set_interface_properties(
1329 node, super_interface, path, None)
1332 def compare_data_structures(data, ref, _path=''):
1333 """Checks if data obtained from UUT is as expected. If it is not,
1334 proceeds down the list/dictionary tree and finds the point of mismatch.
1336 :param data: Data to be checked.
1337 :param ref: Referential data used for comparison.
1338 :param _path: Used in recursive calls, stores the path taken down
1344 :raises HoneycombError: If the data structures do not match in some way,
1345 or if they are not in deserialized JSON format.
1351 elif isinstance(data, dict) and isinstance(ref, dict):
1354 raise HoneycombError(
1355 "Key {key} is not present in path {path}. Keys in path:"
1356 "{data_keys}".format(
1359 data_keys=data.keys()))
1361 if data[key] != ref[key]:
1362 if isinstance(data[key], list) \
1363 or isinstance(data[key], dict):
1364 InterfaceKeywords.compare_data_structures(
1365 data[key], ref[key],
1366 _path + '[{0}]'.format(key))
1368 raise HoneycombError(
1369 "Data mismatch, key {key} in path {path} has value"
1370 " {data}, but should be {ref}".format(
1376 elif isinstance(data, list) and isinstance(ref, list):
1378 if item not in data:
1379 if isinstance(item, dict):
1380 InterfaceKeywords.compare_data_structures(
1382 _path + '[{0}]'.format(ref.index(item)))
1384 raise HoneycombError(
1385 "Data mismatch, list item {index} in path {path}"
1386 " has value {data}, but should be {ref}".format(
1387 index=ref.index(item),
1393 raise HoneycombError(
1394 "Unexpected data type {data_type} in path {path}, reference"
1395 " type is {ref_type}. Must be list or dictionary.".format(
1396 data_type=type(data),
1401 def compare_interface_lists(list1, list2):
1402 """Compare provided lists of interfaces by name.
1404 :param list1: List of interfaces.
1405 :param list2: List of interfaces.
1408 :raises HoneycombError: If an interface exists in only one of the lists.
1411 ignore = ["vx_tunnel0", "vxlan_gpe_tunnel0"]
1412 # these have no equivalent in config data and no effect on VPP
1414 names1 = [x['name'] for x in list1]
1415 names2 = [x['name'] for x in list2]
1418 if name not in names2 and name not in ignore:
1419 raise HoneycombError("Interface {0} not present in list {1}"
1420 .format(name, list2))
1422 if name not in names1 and name not in ignore:
1423 raise HoneycombError("Interface {0} not present in list {1}"
1424 .format(name, list1))
1427 def create_vxlan_gpe_interface(node, interface, **kwargs):
1428 """Create a new VxLAN GPE interface.
1430 :param node: Honeycomb node.
1431 :param interface: The name of interface to be created.
1432 :param kwargs: Parameters and their values. The accepted parameters are
1433 defined in InterfaceKeywords.VXLAN_GPE_PARAMS.
1435 :type interface: str
1437 :returns: Content of response.
1439 :raises HoneycombError: If a parameter in kwargs is not valid.
1444 "type": "v3po:vxlan-gpe-tunnel",
1445 "v3po:vxlan-gpe": {}
1447 for param, value in kwargs.items():
1448 if param in InterfaceKeywords.INTF_PARAMS:
1449 new_vxlan_gpe[param] = value
1450 elif param in InterfaceKeywords.VXLAN_GPE_PARAMS:
1451 new_vxlan_gpe["v3po:vxlan-gpe"][param] = value
1453 raise HoneycombError("The parameter {0} is invalid.".
1455 path = ("interfaces", "interface")
1456 vxlan_gpe_structure = [new_vxlan_gpe, ]
1457 return InterfaceKeywords._set_interface_properties(
1458 node, interface, path, vxlan_gpe_structure)
1461 def enable_acl_on_interface(node, interface, table_name):
1462 """Enable ACL on the given interface.
1464 :param node: Honeycomb node.
1465 :param interface: The interface where the ACL will be enabled.
1466 :param table_name: Name of the classify table.
1468 :type interface: str
1469 :type table_name: str
1470 :returns: Content of response.
1472 :raises HoneycombError: If the configuration of interface is not
1476 interface = interface.replace("/", "%2F")
1482 "classify-table": table_name
1485 "classify-table": table_name
1491 path = "/interface/" + interface + "/v3po:acl"
1492 status_code, resp = HcUtil.\
1493 put_honeycomb_data(node, "config_vpp_interfaces", data, path,
1494 data_representation=DataRepresentation.JSON)
1495 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1496 raise HoneycombError(
1497 "The configuration of interface '{0}' was not successful. "
1498 "Status code: {1}.".format(interface, status_code))
1502 def disable_acl_on_interface(node, interface):
1503 """Disable ACL on the given interface.
1505 :param node: Honeycomb node.
1506 :param interface: The interface where the ACL will be disabled.
1508 :type interface: str
1509 :returns: Content of response.
1511 :raises HoneycombError: If the configuration of interface is not
1515 interface = interface.replace("/", "%2F")
1517 path = "/interface/" + interface + "/v3po:acl"
1519 status_code, resp = HcUtil.\
1520 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1522 if status_code != HTTPCodes.OK:
1523 raise HoneycombError(
1524 "The configuration of interface '{0}' was not successful. "
1525 "Status code: {1}.".format(interface, status_code))
1529 def create_pbb_sub_interface(node, intf, params):
1530 """Creates a PBB sub-interface on the given interface and sets its
1533 :param node: Honeycomb node.
1534 :param intf: The interface where PBB sub-interface will be configured.
1535 :param params: Configuration parameters of the sub-interface to be
1540 :returns: Content of response.
1542 :raises HoneycombError: If the configuration of sub-interface is not
1546 interface = intf.replace("/", "%2F")
1547 path = "/interface/{0}/pbb-rewrite/".format(interface)
1548 status_code, resp = HcUtil. \
1549 put_honeycomb_data(node, "config_vpp_interfaces", params, path,
1550 data_representation=DataRepresentation.JSON)
1551 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1552 raise HoneycombError(
1553 "The configuration of PBB sub-interface '{0}' was not "
1554 "successful. Status code: {1}.".format(intf, status_code))
1558 def delete_pbb_sub_interface(node, intf):
1559 """Deletes the given PBB sub-interface.
1561 :param node: Honeycomb node.
1562 :param intf: The interface where PBB sub-interface will be deleted.
1565 :returns: Content of response.
1567 :raises HoneycombError: If the removal of sub-interface is not
1571 interface = intf.replace("/", "%2F")
1572 path = "/interface/{0}/pbb-rewrite".format(interface)
1574 status_code, resp = HcUtil. \
1575 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1576 if status_code != HTTPCodes.OK:
1577 raise HoneycombError(
1578 "The removal of pbb sub-interface '{0}' was not successful. "
1579 "Status code: {1}.".format(intf, status_code))
1583 def get_pbb_sub_interface_oper_data(node, intf, sub_if_id):
1584 """Retrieves PBB sub-interface operational data from Honeycomb.
1586 :param node: Honeycomb node.
1587 :param intf: The interface where PBB sub-interface is located.
1588 :param sub_if_id: ID of the PBB sub-interface.
1591 :type sub_if_id: str or int
1592 :returns: PBB sub-interface operational data.
1594 :raises HoneycombError: If the removal of sub-interface is not
1598 raise NotImplementedError
1601 def check_disabled_interface(node, interface):
1602 """Retrieves list of disabled interface indices from Honeycomb,
1603 and matches with the provided interface by index.
1605 :param node: Honeycomb node.
1606 :param interface: Index number of an interface on the node.
1608 :type interface: int
1609 :returns: True if the interface exists in disabled interfaces.
1611 :raises HoneycombError: If the interface is not present
1612 in retrieved list of disabled interfaces.
1614 data = InterfaceKeywords.get_disabled_interfaces_oper_data(node)
1615 # decrement by one = conversion from HC if-index to VPP sw_if_index
1619 if item["index"] == interface:
1621 raise HoneycombError("Interface index {0} not present in list"
1622 " of disabled interfaces.".format(interface))
1625 def configure_interface_span(node, dst_interface, *src_interfaces):
1626 """Configure SPAN port mirroring on the specified interfaces. If no
1627 source interface is provided, SPAN will be disabled.
1629 :param node: Honeycomb node.
1630 :param dst_interface: Interface to mirror packets to.
1631 :param src_interfaces: List of interfaces to mirror packets from.
1633 :type dst_interface: str
1634 :type src_interfaces: list of str
1635 :returns: Content of response.
1637 :raises HoneycombError: If SPAN could not be configured.
1640 interface = dst_interface.replace("/", "%2F")
1641 path = "/interface/" + interface + "/span"
1643 if not src_interfaces:
1644 status_code, _ = HcUtil.delete_honeycomb_data(
1645 node, "config_vpp_interfaces", path)
1649 "mirrored-interfaces": {
1650 "mirrored-interface": src_interfaces
1655 status_code, _ = HcUtil.put_honeycomb_data(
1656 node, "config_vpp_interfaces", data, path)
1658 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1659 raise HoneycombError(
1660 "Configuring SPAN failed. Status code:{0}".format(status_code))
1663 def add_interface_local0_to_topology(node):
1664 """Use Topology methods to add interface "local0" to working topology,
1665 if not already present.
1667 :param node: DUT node.
1671 if Topology.get_interface_by_sw_index(node, 0) is None:
1672 local0_key = Topology.add_new_port(node, "localzero")
1673 Topology.update_interface_sw_if_index(node, local0_key, 0)
1674 Topology.update_interface_name(node, local0_key, "local0")