1 # Copyright (c) 2016 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 = ("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 = {"address": [{"ip": ip_addr, "netmask": network}, ]}
517 elif isinstance(network, int) and (0 < network < 33):
518 address = {"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 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
560 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
561 return InterfaceKeywords._set_interface_properties(
562 node, interface, path, neighbor)
565 def remove_all_ipv4_neighbors(node, interface):
566 """Remove all IPv4 neighbours.
568 :param node: Honeycomb node.
569 :param interface: The name of interface.
572 :returns: Content of response.
576 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
578 return InterfaceKeywords._set_interface_properties(
579 node, interface, path, None)
582 def configure_interface_ipv6(node, interface, param, value):
583 """Configure IPv6 parameters of interface
585 :param node: Honeycomb node.
586 :param interface: The name of interface.
587 :param param: Parameter to configure (set, change, remove)
588 :param value: The value of parameter. If None, the parameter will be
594 :returns: Content of response.
596 :raises HoneycombError: If the parameter is not valid.
599 if param in InterfaceKeywords.IPV6_PARAMS:
600 path = ("interfaces", ("interface", "name", interface),
601 "ietf-ip:ipv6", param)
602 elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
603 path = ("interfaces", ("interface", "name", interface),
604 "ietf-ip:ipv6", "autoconf", param)
606 raise HoneycombError("The parameter {0} is invalid.".format(param))
608 return InterfaceKeywords._set_interface_properties(
609 node, interface, path, value)
612 def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
613 """Add the first IPv6 address.
615 If there are any other addresses configured, they will be removed.
617 :param node: Honeycomb node.
618 :param interface: The name of interface.
619 :param ip_addr: IPv6 address to be set.
620 :param prefix_len: Prefix length.
624 :type prefix_len: str
625 :returns: Content of response.
629 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
630 address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
631 return InterfaceKeywords._set_interface_properties(
632 node, interface, path, address)
635 def add_ipv6_address(node, interface, ip_addr, prefix_len):
638 :param node: Honeycomb node.
639 :param interface: The name of interface.
640 :param ip_addr: IPv6 address to be set.
641 :param prefix_len: Prefix length.
645 :type prefix_len: str
646 :returns: Content of response.
650 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
652 address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
653 return InterfaceKeywords._set_interface_properties(
654 node, interface, path, address)
657 def remove_all_ipv6_addresses(node, interface):
658 """Remove all IPv6 addresses from interface.
660 :param node: Honeycomb node.
661 :param interface: The name of interface.
664 :returns: Content of response.
668 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
670 return InterfaceKeywords._set_interface_properties(
671 node, interface, path, None)
674 def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
675 """Add the IPv6 neighbour.
677 :param node: Honeycomb node.
678 :param interface: The name of interface.
679 :param ip_addr: IPv6 address of neighbour to be set.
680 :param link_layer_address: Link layer address.
684 :type link_layer_address: str
685 :returns: Content of response.
689 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
691 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
692 return InterfaceKeywords._set_interface_properties(
693 node, interface, path, neighbor)
696 def remove_all_ipv6_neighbors(node, interface):
697 """Remove all IPv6 neighbours.
699 :param node: Honeycomb node.
700 :param interface: The name of interface.
703 :returns: Content of response.
707 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
709 return InterfaceKeywords._set_interface_properties(
710 node, interface, path, None)
713 def configure_interface_ethernet(node, interface, param, value):
714 """Configure the ethernet parameters of interface.
716 :param node: Honeycomb node.
717 :param interface: The name of interface.
718 :param param: Parameter to configure (set, change, remove)
719 :param value: The value of parameter. If None, the parameter will be
725 :returns: Content of response.
727 :raises HoneycombError: If the parameter is not valid.
730 if param not in InterfaceKeywords.ETH_PARAMS:
731 raise HoneycombError("The parameter {0} is invalid.".format(param))
732 path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
734 return InterfaceKeywords._set_interface_properties(
735 node, interface, path, value)
738 def configure_interface_routing(node, interface, param, value):
739 """Configure the routing parameters of interface.
741 :param node: Honeycomb node.
742 :param interface: The name of interface.
743 :param param: Parameter to configure (set, change, remove)
744 :param value: The value of parameter. If None, the parameter will be
750 :returns: Content of response.
752 :raises HoneycombError: If the parameter is not valid.
755 if param not in InterfaceKeywords.ROUTING_PARAMS:
756 raise HoneycombError("The parameter {0} is invalid.".format(param))
758 path = ("interfaces", ("interface", "name", interface), "v3po:routing",
760 return InterfaceKeywords._set_interface_properties(
761 node, interface, path, value)
764 def create_vxlan_interface(node, interface, **kwargs):
765 """Create a new VxLAN interface.
767 :param node: Honeycomb node.
768 :param interface: The name of interface.
769 :param kwargs: Parameters and their values. The accepted parameters are
770 defined in InterfaceKeywords.VXLAN_PARAMS.
774 :returns: Content of response.
776 :raises HoneycombError: If the parameter is not valid.
781 "type": "v3po:vxlan-tunnel",
784 for param, value in kwargs.items():
785 if param not in InterfaceKeywords.VXLAN_PARAMS:
786 raise HoneycombError("The parameter {0} is invalid.".
788 new_vx_lan["v3po:vxlan"][param] = value
790 path = ("interfaces", "interface")
791 vx_lan_structure = [new_vx_lan, ]
792 return InterfaceKeywords._set_interface_properties(
793 node, interface, path, vx_lan_structure)
796 def delete_interface(node, interface):
797 """Delete an interface.
799 :param node: Honeycomb node.
800 :param interface: The name of interface.
803 :returns: Content of response.
805 :raises HoneycombError: If it is not possible to get information about
806 interfaces or it is not possible to delete the interface.
809 path = ("interfaces", ("interface", "name", interface))
811 status_code, resp = HcUtil.\
812 get_honeycomb_data(node, "config_vpp_interfaces")
813 if status_code != HTTPCodes.OK:
814 raise HoneycombError(
815 "Not possible to get configuration information about the "
816 "interfaces. Status code: {0}.".format(status_code))
818 new_data = HcUtil.remove_item(resp, path)
819 status_code, resp = HcUtil.\
820 put_honeycomb_data(node, "config_vpp_interfaces", new_data)
821 if status_code != HTTPCodes.OK:
822 raise HoneycombError("Not possible to remove interface {0}. "
824 format(interface, status_code))
828 def configure_interface_vxlan(node, interface, **kwargs):
829 """Configure VxLAN on the interface.
831 The keyword configures VxLAN parameters on the given interface. The type
832 of interface must be set to "v3po:vxlan-tunnel".
833 The new VxLAN parameters overwrite the current configuration. If a
834 parameter in new configuration is missing, it is removed from VxLAN
836 If the dictionary kwargs is empty, VxLAN configuration is removed.
838 :param node: Honeycomb node.
839 :param interface: The name of interface.
840 :param kwargs: Parameters and their values. The accepted parameters are
841 defined in InterfaceKeywords.VXLAN_PARAMS.
845 :returns: Content of response.
847 :raises HoneycombError: If the parameter is not valid.
850 vx_lan_structure = dict()
851 for param, value in kwargs.items():
852 if param not in InterfaceKeywords.VXLAN_PARAMS:
853 raise HoneycombError("The parameter {0} is invalid.".
855 vx_lan_structure[param] = value
857 path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
858 return InterfaceKeywords._set_interface_properties(
859 node, interface, path, vx_lan_structure)
862 def configure_interface_l2(node, interface, param, value):
863 """Configure the L2 parameters of interface.
865 :param node: Honeycomb node.
866 :param interface: The name of interface.
867 :param param: Parameter to configure (set, change, remove)
868 :param value: The value of parameter. If None, the parameter will be
874 :returns: Content of response.
876 :raises HoneycombError: If the parameter is not valid.
879 if param not in InterfaceKeywords.L2_PARAMS:
880 raise HoneycombError("The parameter {0} is invalid.".format(param))
881 path = ("interfaces", ("interface", "name", interface), "v3po:l2",
883 return InterfaceKeywords._set_interface_properties(
884 node, interface, path, value)
887 def create_tap_interface(node, interface, **kwargs):
888 """Create a new TAP interface.
890 :param node: Honeycomb node.
891 :param interface: The name of interface.
892 :param kwargs: Parameters and their values. The accepted parameters are
893 defined in InterfaceKeywords.TAP_PARAMS.
897 :returns: Content of response.
899 :raises HoneycombError: If the parameter is not valid.
907 for param, value in kwargs.items():
908 if param not in InterfaceKeywords.TAP_PARAMS:
909 raise HoneycombError("The parameter {0} is invalid.".
911 new_tap["v3po:tap"][param] = value
913 path = ("interfaces", "interface")
914 new_tap_structure = [new_tap, ]
915 return InterfaceKeywords._set_interface_properties(
916 node, interface, path, new_tap_structure)
919 def configure_interface_tap(node, interface, **kwargs):
920 """Configure TAP on the interface.
922 The keyword configures TAP parameters on the given interface. The type
923 of interface must be set to "v3po:tap".
924 The new TAP parameters overwrite the current configuration. If a
925 parameter in new configuration is missing, it is removed from TAP
927 If the dictionary kwargs is empty, TAP configuration is removed.
929 :param node: Honeycomb node.
930 :param interface: The name of interface.
931 :param kwargs: Parameters and their values. The accepted parameters are
932 defined in InterfaceKeywords.TAP_PARAMS.
936 :returns: Content of response.
938 :raises HoneycombError: If the parameter is not valid.
941 tap_structure = dict()
942 for param, value in kwargs.items():
943 if param not in InterfaceKeywords.TAP_PARAMS:
944 raise HoneycombError("The parameter {0} is invalid.".
946 tap_structure[param] = value
948 path = ("interfaces", ("interface", "name", interface), "v3po:tap")
949 return InterfaceKeywords._set_interface_properties(
950 node, interface, path, tap_structure)
953 def configure_interface_vhost_user(node, interface, **kwargs):
954 """Configure vhost-user on the interface.
956 The keyword configures vhost-user parameters on the given interface.
957 The type of interface must be set to "v3po:vhost-user".
958 The new vhost-user parameters overwrite the current configuration. If a
959 parameter in new configuration is missing, it is removed from vhost-user
961 If the dictionary kwargs is empty, vhost-user configuration is removed.
963 :param node: Honeycomb node.
964 :param interface: The name of interface.
965 :param kwargs: Parameters and their values. The accepted parameters are
966 defined in InterfaceKeywords.VHOST_USER_PARAMS.
970 :returns: Content of response.
972 :raises HoneycombError: If the parameter is not valid.
975 vhost_structure = dict()
976 for param, value in kwargs.items():
977 if param not in InterfaceKeywords.VHOST_USER_PARAMS:
978 raise HoneycombError("The parameter {0} is invalid.".
980 vhost_structure[param] = value
982 path = ("interfaces", ("interface", "name", interface),
984 return InterfaceKeywords._set_interface_properties(
985 node, interface, path, vhost_structure)
988 def create_vhost_user_interface(node, interface, **kwargs):
989 """Create a new vhost-user interface.
991 :param node: Honeycomb node.
992 :param interface: The name of interface.
993 :param kwargs: Parameters and their values. The accepted parameters are
994 defined in InterfaceKeywords.VHOST_USER_PARAMS.
998 :returns: Content of response.
1000 :raises HoneycombError: If the parameter is not valid.
1005 "type": "v3po:vhost-user",
1006 "v3po:vhost-user": {}
1008 for param, value in kwargs.items():
1009 if param not in InterfaceKeywords.VHOST_USER_PARAMS:
1010 raise HoneycombError("The parameter {0} is invalid.".
1012 new_vhost["v3po:vhost-user"][param] = value
1014 path = ("interfaces", "interface")
1015 new_vhost_structure = [new_vhost, ]
1016 return InterfaceKeywords._set_interface_properties(
1017 node, interface, path, new_vhost_structure)
1020 def create_sub_interface(node, super_interface, match, tags=None, **kwargs):
1021 """Create a new sub-interface.
1023 :param node: Honeycomb node.
1024 :param super_interface: Super interface.
1025 :param match: Match type. The valid values are defined in
1026 InterfaceKeywords.SUB_IF_MATCH.
1027 :param tags: List of tags.
1028 :param kwargs: Parameters and their values. The accepted parameters are
1029 defined in InterfaceKeywords.SUB_IF_PARAMS.
1031 :type super_interface: str
1035 :returns: Content of response.
1037 :raises HoneycombError: If the parameter is not valid.
1038 :raises KeyError: If the parameter 'match' is invalid.
1047 {"vlan-tagged": {"match-exact-tags": "false"}},
1048 "vlan-tagged-exact-match":
1049 {"vlan-tagged": {"match-exact-tags": "true"}}
1052 new_sub_interface = {
1058 for param, value in kwargs.items():
1059 if param in InterfaceKeywords.SUB_IF_PARAMS:
1060 new_sub_interface[param] = value
1062 raise HoneycombError("The parameter {0} is invalid.".
1065 new_sub_interface["match"] = match_type[match]
1067 raise HoneycombError("The value '{0}' of parameter 'match' is "
1068 "invalid.".format(match))
1071 new_sub_interface["tags"]["tag"].extend(tags)
1073 path = ("interfaces",
1074 ("interface", "name", super_interface),
1075 "vpp-vlan:sub-interfaces",
1077 new_sub_interface_structure = [new_sub_interface, ]
1078 return InterfaceKeywords._set_interface_properties(
1079 node, super_interface, path, new_sub_interface_structure)
1082 def get_sub_interface_oper_data(node, super_interface, identifier):
1083 """Retrieves sub-interface operational data using Honeycomb API.
1085 :param node: Honeycomb node.
1086 :param super_interface: Super interface.
1087 :param identifier: The ID of sub-interface.
1089 :type super_interface: str
1090 :type identifier: int
1091 :returns: Sub-interface operational data.
1093 :raises HoneycombError: If there is no sub-interface with the given ID.
1096 if_data = InterfaceKeywords.get_interface_oper_data(node,
1098 for sub_if in if_data["vpp-vlan:sub-interfaces"]["sub-interface"]:
1099 if str(sub_if["identifier"]) == str(identifier):
1102 raise HoneycombError("The interface {0} does not have sub-interface "
1103 "with ID {1}".format(super_interface, identifier))
1106 def remove_all_sub_interfaces(node, super_interface):
1107 """Remove all sub-interfaces from the given interface.
1109 :param node: Honeycomb node.
1110 :param super_interface: Super interface.
1112 :type super_interface: str
1113 :returns: Content of response.
1117 path = ("interfaces",
1118 ("interface", "name", super_interface),
1119 "vpp-vlan:sub-interfaces")
1121 return InterfaceKeywords._set_interface_properties(
1122 node, super_interface, path, {})
1125 def set_sub_interface_state(node, super_interface, identifier, state):
1126 """Set the administrative state of sub-interface.
1128 :param node: Honeycomb node.
1129 :param super_interface: Super interface.
1130 :param identifier: The ID of sub-interface.
1131 :param state: Required sub-interface state - up or down.
1133 :type super_interface: str
1134 :type identifier: int
1136 :returns: Content of response.
1140 intf_state = {"up": "true",
1143 path = ("interfaces",
1144 ("interface", "name", super_interface),
1145 "vpp-vlan:sub-interfaces",
1146 ("sub-interface", "identifier", int(identifier)),
1149 return InterfaceKeywords._set_interface_properties(
1150 node, super_interface, path, intf_state[state])
1153 def add_bridge_domain_to_sub_interface(node, super_interface, identifier,
1155 """Add a sub-interface to a bridge domain and set its parameters.
1157 :param node: Honeycomb node.
1158 :param super_interface: Super interface.
1159 :param identifier: The ID of sub-interface.
1160 :param config: Bridge domain configuration.
1162 :type super_interface: str
1163 :type identifier: int
1165 :returns: Content of response.
1169 path = ("interfaces",
1170 ("interface", "name", super_interface),
1171 "vpp-vlan:sub-interfaces",
1172 ("sub-interface", "identifier", int(identifier)),
1175 return InterfaceKeywords._set_interface_properties(
1176 node, super_interface, path, config)
1179 def get_bd_data_from_sub_interface(node, super_interface, identifier):
1180 """Get the operational data about the bridge domain from sub-interface.
1182 :param node: Honeycomb node.
1183 :param super_interface: Super interface.
1184 :param identifier: The ID of sub-interface.
1186 :type super_interface: str
1187 :type identifier: int
1188 :returns: Operational data about the bridge domain.
1190 :raises HoneycombError: If there is no sub-interface with the given ID.
1194 bd_data = InterfaceKeywords.get_sub_interface_oper_data(
1195 node, super_interface, identifier)["l2"]
1198 raise HoneycombError("The operational data does not contain "
1199 "information about a bridge domain.")
1202 def configure_tag_rewrite(node, super_interface, identifier, config):
1203 """Add / change / disable vlan tag rewrite on a sub-interface.
1205 :param node: Honeycomb node.
1206 :param super_interface: Super interface.
1207 :param identifier: The ID of sub-interface.
1208 :param config: Rewrite tag configuration.
1210 :type super_interface: str
1211 :type identifier: int
1213 :returns: Content of response.
1217 path = ("interfaces",
1218 ("interface", "name", super_interface),
1219 "vpp-vlan:sub-interfaces",
1220 ("sub-interface", "identifier", int(identifier)),
1224 return InterfaceKeywords._set_interface_properties(
1225 node, super_interface, path, config)
1228 def get_tag_rewrite_oper_data(node, super_interface, identifier):
1229 """Get the operational data about tag rewrite.
1231 :param node: Honeycomb node.
1232 :param super_interface: Super interface.
1233 :param identifier: The ID of sub-interface.
1235 :type super_interface: str
1236 :type identifier: int
1237 :returns: Operational data about tag rewrite.
1239 :raises HoneycombError: If there is no sub-interface with the given ID.
1243 tag_rewrite = InterfaceKeywords.get_sub_interface_oper_data(
1244 node, super_interface, identifier)["l2"]["rewrite"]
1247 raise HoneycombError("The operational data does not contain "
1248 "information about the tag-rewrite.")
1251 def add_ipv4_address_to_sub_interface(node, super_interface, identifier,
1253 """Add an ipv4 address to the specified sub-interface, with the provided
1254 netmask or network prefix length. Any existing ipv4 addresses on the
1255 sub-interface will be replaced.
1257 :param node: Honeycomb node.
1258 :param super_interface: Super interface.
1259 :param identifier: The ID of sub-interface.
1260 :param ip_addr: IPv4 address to be set.
1261 :param network: Network mask or network prefix length.
1263 :type super_interface: str
1264 :type identifier: int
1266 :type network: str or int
1267 :returns: Content of response.
1269 :raises HoneycombError: If the provided netmask or prefix is not valid.
1272 path = ("interfaces",
1273 ("interface", "name", super_interface),
1274 "vpp-vlan:sub-interfaces",
1275 ("sub-interface", "identifier", int(identifier)),
1278 if isinstance(network, basestring):
1279 address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
1281 elif isinstance(network, int) and 0 < network < 33:
1282 address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
1285 raise HoneycombError("{0} is not a valid netmask or prefix length."
1288 return InterfaceKeywords._set_interface_properties(
1289 node, super_interface, path, address)
1292 def remove_all_ipv4_addresses_from_sub_interface(node, super_interface,
1294 """Remove all ipv4 addresses from the specified sub-interface.
1296 :param node: Honeycomb node.
1297 :param super_interface: Super interface.
1298 :param identifier: The ID of sub-interface.
1300 :type super_interface: str
1301 :type identifier: int
1302 :returns: Content of response.
1306 path = ("interfaces",
1307 ("interface", "name", super_interface),
1308 "vpp-vlan:sub-interfaces",
1309 ("sub-interface", "identifier", int(identifier)),
1312 return InterfaceKeywords._set_interface_properties(
1313 node, super_interface, path, None)
1316 def compare_data_structures(data, ref, _path=''):
1317 """Checks if data obtained from UUT is as expected. If it is not,
1318 proceeds down the list/dictionary tree and finds the point of mismatch.
1320 :param data: Data to be checked.
1321 :param ref: Referential data used for comparison.
1322 :param _path: Used in recursive calls, stores the path taken down
1328 :raises HoneycombError: If the data structures do not match in some way,
1329 or if they are not in deserialized JSON format.
1335 elif isinstance(data, dict) and isinstance(ref, dict):
1338 raise HoneycombError(
1339 "Key {key} is not present in path {path}. Keys in path:"
1340 "{data_keys}".format(
1343 data_keys=data.keys()))
1345 if data[key] != ref[key]:
1346 if isinstance(data[key], list) \
1347 or isinstance(data[key], dict):
1348 InterfaceKeywords.compare_data_structures(
1349 data[key], ref[key],
1350 _path + '[{0}]'.format(key))
1352 raise HoneycombError(
1353 "Data mismatch, key {key} in path {path} has value"
1354 " {data}, but should be {ref}".format(
1360 elif isinstance(data, list) and isinstance(ref, list):
1362 if item not in data:
1363 if isinstance(item, dict):
1364 InterfaceKeywords.compare_data_structures(
1366 _path + '[{0}]'.format(ref.index(item)))
1368 raise HoneycombError(
1369 "Data mismatch, list item {index} in path {path}"
1370 " has value {data}, but should be {ref}".format(
1371 index=ref.index(item),
1377 raise HoneycombError(
1378 "Unexpected data type {data_type} in path {path}, reference"
1379 " type is {ref_type}. Must be list or dictionary.".format(
1380 data_type=type(data),
1385 def compare_interface_lists(list1, list2):
1386 """Compare provided lists of interfaces by name.
1388 :param list1: List of interfaces.
1389 :param list2: List of interfaces.
1392 :raises HoneycombError: If an interface exists in only one of the lists.
1395 ignore = ["vx_tunnel0", "vxlan_gpe_tunnel0"]
1396 # these have no equivalent in config data and no effect on VPP
1398 names1 = [x['name'] for x in list1]
1399 names2 = [x['name'] for x in list2]
1402 if name not in names2 and name not in ignore:
1403 raise HoneycombError("Interface {0} not present in list {1}"
1404 .format(name, list2))
1406 if name not in names1 and name not in ignore:
1407 raise HoneycombError("Interface {0} not present in list {1}"
1408 .format(name, list1))
1411 def create_vxlan_gpe_interface(node, interface, **kwargs):
1412 """Create a new VxLAN GPE interface.
1414 :param node: Honeycomb node.
1415 :param interface: The name of interface to be created.
1416 :param kwargs: Parameters and their values. The accepted parameters are
1417 defined in InterfaceKeywords.VXLAN_GPE_PARAMS.
1419 :type interface: str
1421 :returns: Content of response.
1423 :raises HoneycombError: If a parameter in kwargs is not valid.
1428 "type": "v3po:vxlan-gpe-tunnel",
1429 "v3po:vxlan-gpe": {}
1431 for param, value in kwargs.items():
1432 if param in InterfaceKeywords.INTF_PARAMS:
1433 new_vxlan_gpe[param] = value
1434 elif param in InterfaceKeywords.VXLAN_GPE_PARAMS:
1435 new_vxlan_gpe["v3po:vxlan-gpe"][param] = value
1437 raise HoneycombError("The parameter {0} is invalid.".
1439 path = ("interfaces", "interface")
1440 vxlan_gpe_structure = [new_vxlan_gpe, ]
1441 return InterfaceKeywords._set_interface_properties(
1442 node, interface, path, vxlan_gpe_structure)
1445 def enable_acl_on_interface(node, interface, table_name):
1446 """Enable ACL on the given interface.
1448 :param node: Honeycomb node.
1449 :param interface: The interface where the ACL will be enabled.
1450 :param table_name: Name of the classify table.
1452 :type interface: str
1453 :type table_name: str
1454 :returns: Content of response.
1456 :raises HoneycombError: If the configuration of interface is not
1460 interface = interface.replace("/", "%2F")
1466 "classify-table": table_name
1469 "classify-table": table_name
1475 path = "/interface/" + interface + "/v3po:acl"
1476 status_code, resp = HcUtil.\
1477 put_honeycomb_data(node, "config_vpp_interfaces", data, path,
1478 data_representation=DataRepresentation.JSON)
1479 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1480 raise HoneycombError(
1481 "The configuration of interface '{0}' was not successful. "
1482 "Status code: {1}.".format(interface, status_code))
1486 def disable_acl_on_interface(node, interface):
1487 """Disable ACL on the given interface.
1489 :param node: Honeycomb node.
1490 :param interface: The interface where the ACL will be disabled.
1492 :type interface: str
1493 :returns: Content of response.
1495 :raises HoneycombError: If the configuration of interface is not
1499 interface = interface.replace("/", "%2F")
1501 path = "/interface/" + interface + "/v3po:acl"
1503 status_code, resp = HcUtil.\
1504 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1506 if status_code != HTTPCodes.OK:
1507 raise HoneycombError(
1508 "The configuration of interface '{0}' was not successful. "
1509 "Status code: {1}.".format(interface, status_code))
1513 def create_pbb_sub_interface(node, intf, params):
1514 """Creates a PBB sub-interface on the given interface and sets its
1517 :param node: Honeycomb node.
1518 :param intf: The interface where PBB sub-interface will be configured.
1519 :param params: Configuration parameters of the sub-interface to be
1524 :returns: Content of response.
1526 :raises HoneycombError: If the configuration of sub-interface is not
1530 interface = intf.replace("/", "%2F")
1531 path = "/interface/{0}/pbb-rewrite/".format(interface)
1532 status_code, resp = HcUtil. \
1533 put_honeycomb_data(node, "config_vpp_interfaces", params, path,
1534 data_representation=DataRepresentation.JSON)
1535 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1536 raise HoneycombError(
1537 "The configuration of PBB sub-interface '{0}' was not "
1538 "successful. Status code: {1}.".format(intf, status_code))
1542 def delete_pbb_sub_interface(node, intf):
1543 """Deletes the given PBB sub-interface.
1545 :param node: Honeycomb node.
1546 :param intf: The interface where PBB sub-interface will be deleted.
1549 :returns: Content of response.
1551 :raises HoneycombError: If the removal of sub-interface is not
1555 interface = intf.replace("/", "%2F")
1556 path = "/interface/{0}/pbb-rewrite".format(interface)
1558 status_code, resp = HcUtil. \
1559 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1560 if status_code != HTTPCodes.OK:
1561 raise HoneycombError(
1562 "The removal of pbb sub-interface '{0}' was not successful. "
1563 "Status code: {1}.".format(intf, status_code))
1567 def get_pbb_sub_interface_oper_data(node, intf, sub_if_id):
1568 """Retrieves PBB sub-interface operational data from Honeycomb.
1570 :param node: Honeycomb node.
1571 :param intf: The interface where PBB sub-interface is located.
1572 :param sub_if_id: ID of the PBB sub-interface.
1575 :type sub_if_id: str or int
1576 :returns: PBB sub-interface operational data.
1578 :raises HoneycombError: If the removal of sub-interface is not
1582 raise NotImplementedError
1585 def check_disabled_interface(node, interface):
1586 """Retrieves list of disabled interface indices from Honeycomb,
1587 and matches with the provided interface by index.
1589 :param node: Honeycomb node.
1590 :param interface: Index number of an interface on the node.
1592 :type interface: int
1593 :returns: True if the interface exists in disabled interfaces.
1595 :raises HoneycombError: If the interface is not present
1596 in retrieved list of disabled interfaces.
1598 data = InterfaceKeywords.get_disabled_interfaces_oper_data(node)
1599 # decrement by one = conversion from HC if-index to VPP sw_if_index
1603 if item["index"] == interface:
1605 raise HoneycombError("Interface index {0} not present in list"
1606 " of disabled interfaces.".format(interface))
1609 def configure_interface_span(node, dst_interface, *src_interfaces):
1610 """Configure SPAN port mirroring on the specified interfaces. If no
1611 source interface is provided, SPAN will be disabled.
1613 :param node: Honeycomb node.
1614 :param dst_interface: Interface to mirror packets to.
1615 :param src_interfaces: List of interfaces to mirror packets from.
1617 :type dst_interface: str
1618 :type src_interfaces: list of str
1619 :returns: Content of response.
1621 :raises HoneycombError: If SPAN could not be configured.
1624 interface = dst_interface.replace("/", "%2F")
1625 path = "/interface/" + interface + "/span"
1627 if not src_interfaces:
1628 status_code, _ = HcUtil.delete_honeycomb_data(
1629 node, "config_vpp_interfaces", path)
1633 "mirrored-interfaces": {
1634 "mirrored-interface": src_interfaces
1639 status_code, _ = HcUtil.put_honeycomb_data(
1640 node, "config_vpp_interfaces", data, path)
1642 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1643 raise HoneycombError(
1644 "Configuring SPAN failed. Status code:{0}".format(status_code))
1647 def add_interface_local0_to_topology(node):
1648 """Use Topology methods to add interface "local0" to working topology,
1649 if not already present.
1651 :param node: DUT node.
1655 if Topology.get_interface_by_sw_index(node, 0) is None:
1656 local0_key = Topology.add_new_port(node, "localzero")
1657 Topology.update_interface_sw_if_index(node, local0_key, 0)
1658 Topology.update_interface_name(node, local0_key, "local0")