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 # pylint: disable=too-many-public-methods
31 # pylint: disable=too-many-lines
32 class InterfaceKeywords(object):
33 """Keywords for Interface manipulation.
35 Implements keywords which get configuration and operational data about
36 vpp interfaces and set the interface's parameters using Honeycomb REST API.
39 INTF_PARAMS = ("name", "description", "type", "enabled",
40 "link-up-down-trap-enable", "v3po:l2", "v3po:vxlan-gpe",
41 "vpp-vlan:sub-interfaces")
42 IPV4_PARAMS = ("enabled", "forwarding", "mtu")
43 IPV6_PARAMS = ("enabled", "forwarding", "mtu", "dup-addr-detect-transmits")
44 IPV6_AUTOCONF_PARAMS = ("create-global-addresses",
45 "create-temporary-addresses",
46 "temporary-valid-lifetime",
47 "temporary-preferred-lifetime")
48 ETH_PARAMS = ("mtu", )
49 ROUTING_PARAMS = ("vrf-id", )
50 VXLAN_PARAMS = ("src", "dst", "vni", "encap-vrf-id")
51 L2_PARAMS = ("bridge-domain", "split-horizon-group",
52 "bridged-virtual-interface")
53 TAP_PARAMS = ("tap-name", "mac", "device-instance")
54 VHOST_USER_PARAMS = ("socket", "role")
55 SUB_IF_PARAMS = ("identifier",
58 SUB_IF_MATCH = ("default",
61 "vlan-tagged-exact-match")
62 BD_PARAMS = ("bridge-domain",
63 "split-horizon-group",
64 "bridged-virtual-interface")
65 VXLAN_GPE_PARAMS = ("local",
76 def _configure_interface(node, interface, data,
77 data_representation=DataRepresentation.JSON):
78 """Send interface configuration data and check the response.
80 :param node: Honeycomb node.
81 :param interface: The name of interface.
82 :param data: Configuration data to be sent in PUT request.
83 :param data_representation: How the data is represented.
87 :type data_representation: DataRepresentation
88 :return: Content of response.
90 :raises HoneycombError: If the status code in response on PUT is not
94 status_code, resp = HcUtil.\
95 put_honeycomb_data(node, "config_vpp_interfaces", data,
96 data_representation=data_representation)
97 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
99 "The configuration of interface '{0}' was not successful. "
100 "Status code: {1}.".format(interface, status_code))
104 def get_all_interfaces_cfg_data(node):
105 """Get configuration data about all interfaces from Honeycomb.
107 :param node: Honeycomb node.
109 :return: Configuration data about all interfaces from Honeycomb.
111 :raises HoneycombError: If it is not possible to get configuration data.
114 status_code, resp = HcUtil.\
115 get_honeycomb_data(node, "config_vpp_interfaces")
116 if status_code != HTTPCodes.OK:
117 raise HoneycombError(
118 "Not possible to get configuration information about the "
119 "interfaces. Status code: {0}.".format(status_code))
121 return resp["interfaces"]["interface"]
123 except (KeyError, TypeError):
127 def get_interface_cfg_data(node, interface):
128 """Get configuration data about the given interface from Honeycomb.
130 :param node: Honeycomb node.
131 :param interface: The name of interface.
134 :return: Configuration data about the given interface from Honeycomb.
138 intfs = InterfaceKeywords.get_all_interfaces_cfg_data(node)
140 if intf["name"] == interface:
145 def get_all_interfaces_oper_data(node):
146 """Get operational data about all interfaces from Honeycomb.
148 :param node: Honeycomb node.
150 :return: Operational data about all interfaces from Honeycomb.
152 :raises HoneycombError: If it is not possible to get operational data.
155 status_code, resp = HcUtil.\
156 get_honeycomb_data(node, "oper_vpp_interfaces")
157 if status_code != HTTPCodes.OK:
158 raise HoneycombError(
159 "Not possible to get operational information about the "
160 "interfaces. Status code: {0}.".format(status_code))
162 return resp["interfaces-state"]["interface"]
164 except (KeyError, TypeError):
168 def get_disabled_interfaces_oper_data(node):
169 """Get operational data about all disabled interfaces from Honeycomb.
171 :param node: Honeycomb node.
173 :return: Operational data about disabled interfaces.
175 :raises HoneycombError: If it is not possible to get operational data.
178 status_code, resp = HcUtil. \
179 get_honeycomb_data(node, "oper_disabled_interfaces")
180 if status_code == HTTPCodes.NOT_FOUND:
181 raise HoneycombError(
182 "No disabled interfaces present on node."
184 if status_code != HTTPCodes.OK:
185 raise HoneycombError(
186 "Not possible to get operational information about the "
187 "interfaces. Status code: {0}.".format(status_code))
189 return resp["disabled-interfaces"]["disabled-interface-index"]
191 except (KeyError, TypeError):
195 def get_interface_oper_data(node, interface):
196 """Get operational data about the given interface from Honeycomb.
198 :param node: Honeycomb node.
199 :param interface: The name of interface.
202 :return: Operational data about the given interface from Honeycomb.
206 intfs = InterfaceKeywords.get_all_interfaces_oper_data(node)
208 if intf["name"] == interface:
213 def _set_interface_properties(node, interface, path, new_value=None):
214 """Set interface properties.
216 This method reads interface configuration data, creates, changes or
217 removes the requested data and puts it back to Honeycomb.
219 :param node: Honeycomb node.
220 :param interface: The name of interface.
221 :param path: Path to data we want to change / create / remove.
222 :param new_value: The new value to be set. If None, the item will be
227 :type new_value: str, dict or list
228 :return: Content of response.
230 :raises HoneycombError: If it is not possible to get or set the data.
233 status_code, resp = HcUtil.\
234 get_honeycomb_data(node, "config_vpp_interfaces")
235 if status_code != HTTPCodes.OK:
236 raise HoneycombError(
237 "Not possible to get configuration information about the "
238 "interfaces. Status code: {0}.".format(status_code))
241 new_data = HcUtil.set_item_value(resp, path, new_value)
243 new_data = HcUtil.remove_item(resp, path)
244 return InterfaceKeywords._configure_interface(node, interface, new_data)
247 def set_interface_state(node, interface, state="up"):
248 """Set VPP interface state.
250 The keyword changes the administration state of interface to up or down
251 depending on the parameter "state".
253 :param node: Honeycomb node.
254 :param interface: Interface name, key, link name or sw_if_index.
255 :param state: The requested state, only "up" and "down" are valid
260 :return: Content of response.
262 :raises KeyError: If the argument "state" is nor "up" or "down".
263 :raises HoneycombError: If the interface is not present on the node.
266 intf_state = {"up": "true",
269 interface = Topology.convert_interface_reference(
270 node, interface, "name")
272 intf = interface.replace("/", "%2F")
273 path = "/interface/{0}".format(intf)
275 status_code, resp = HcUtil.\
276 get_honeycomb_data(node, "config_vpp_interfaces", path)
277 if status_code != HTTPCodes.OK:
278 raise HoneycombError(
279 "Not possible to get configuration information about the "
280 "interfaces. Status code: {0}.".format(status_code))
282 resp["interface"][0]["enabled"] = intf_state[state.lower()]
284 status_code, resp = HcUtil. \
285 put_honeycomb_data(node, "config_vpp_interfaces", resp, path,
286 data_representation=DataRepresentation.JSON)
287 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
288 raise HoneycombError(
289 "The configuration of interface '{0}' was not successful. "
290 "Status code: {1}.".format(interface, status_code))
294 def set_interface_up(node, interface):
295 """Set the administration state of VPP interface to up.
297 :param node: Honeycomb node.
298 :param interface: The name of interface.
301 :return: Content of response
305 return InterfaceKeywords.set_interface_state(node, interface, "up")
308 def set_interface_down(node, interface):
309 """Set the administration state of VPP interface to down.
311 :param node: Honeycomb node.
312 :param interface: The name of interface.
315 :return: Content of response.
319 return InterfaceKeywords.set_interface_state(node, interface, "down")
322 def add_bridge_domain_to_interface(node, interface, bd_name,
323 split_horizon_group=None, bvi=None):
324 """Add a new bridge domain to an interface and set its parameters.
326 :param node: Honeycomb node.
327 :param interface: Interface name, key, link name or sw_if_index.
328 :param bd_name: Bridge domain name.
329 :param split_horizon_group: Split-horizon group name.
330 :param bvi: The bridged virtual interface.
334 :type split_horizon_group: str
336 :return: Content of response.
338 :raises HoneycombError: If the interface is not present on the node.
341 interface = Topology.convert_interface_reference(
342 node, interface, "name")
344 v3po_l2 = {"bridge-domain": str(bd_name)}
345 if split_horizon_group:
346 v3po_l2["split-horizon-group"] = str(split_horizon_group)
348 v3po_l2["bridged-virtual-interface"] = str(bvi)
350 path = ("interfaces", ("interface", "name", str(interface)), "v3po:l2")
352 return InterfaceKeywords._set_interface_properties(
353 node, interface, path, v3po_l2)
356 def remove_bridge_domain_from_interface(node, interface):
357 """Remove bridge domain assignment from interface.
359 :param node: Honeycomb node.
360 :param interface: Interface name, key, link name or sw_if_index.
362 :type interface: str or int
364 :raises HoneycombError: If the operation fails.
367 interface = Topology.convert_interface_reference(
368 node, interface, "name")
370 intf = interface.replace("/", "%2F")
372 path = "/interface/{0}/v3po:l2".format(intf)
374 status_code, response = HcUtil.delete_honeycomb_data(
375 node, "config_vpp_interfaces", path)
377 if status_code != HTTPCodes.OK:
378 if '"error-tag":"data-missing"' in response:
379 logger.debug("Data does not exist in path.")
381 raise HoneycombError(
382 "Could not remove bridge domain assignment from interface "
383 "'{0}'. Status code: {1}.".format(interface, status_code))
386 def get_bd_oper_data_from_interface(node, interface):
387 """Returns operational data about bridge domain settings in the
390 :param node: Honeycomb node.
391 :param interface: The name of interface.
394 :return: Operational data about bridge domain settings in the
399 if_data = InterfaceKeywords.get_interface_oper_data(node, interface)
403 return if_data["v3po:l2"]
409 def configure_interface_base(node, interface, param, value):
410 """Configure the base parameters of interface.
412 :param node: Honeycomb node.
413 :param interface: The name of interface.
414 :param param: Parameter to configure (set, change, remove)
415 :param value: The value of parameter. If None, the parameter will be
421 :return: Content of response.
423 :raises HoneycombError: If the parameter is not valid.
426 if param not in InterfaceKeywords.INTF_PARAMS:
427 raise HoneycombError("The parameter {0} is invalid.".format(param))
429 path = ("interfaces", ("interface", "name", interface), param)
430 return InterfaceKeywords._set_interface_properties(
431 node, interface, path, value)
434 def configure_interface_ipv4(node, interface, param, value):
435 """Configure IPv4 parameters of interface.
437 :param node: Honeycomb node.
438 :param interface: The name of interface.
439 :param param: Parameter to configure (set, change, remove)
440 :param value: The value of parameter. If None, the parameter will be
446 :return: Content of response.
448 :raises HoneycombError: If the parameter is not valid.
451 interface = Topology.convert_interface_reference(
452 node, interface, "name")
454 if param not in InterfaceKeywords.IPV4_PARAMS:
455 raise HoneycombError("The parameter {0} is invalid.".format(param))
457 path = ("interfaces", ("interface", "name", interface),
458 "ietf-ip:ipv4", param)
459 return InterfaceKeywords._set_interface_properties(
460 node, interface, path, value)
463 def add_first_ipv4_address(node, interface, ip_addr, network):
464 """Add the first IPv4 address.
466 If there are any other addresses configured, they will be removed.
468 :param node: Honeycomb node.
469 :param interface: The name of interface.
470 :param ip_addr: IPv4 address to be set.
471 :param network: Netmask or length of network prefix.
475 :type network: str or int
476 :return: Content of response.
478 :raises HoneycombError: If the provided netmask or prefix is not valid.
481 interface = Topology.convert_interface_reference(
482 node, interface, "name")
484 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
485 if isinstance(network, basestring):
486 address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
487 elif isinstance(network, int) and (0 < network < 33):
488 address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
490 raise HoneycombError("Value {0} is not a valid netmask or network "
491 "prefix length.".format(network))
492 return InterfaceKeywords._set_interface_properties(
493 node, interface, path, address)
496 def add_ipv4_address(node, interface, ip_addr, network):
499 :param node: Honeycomb node.
500 :param interface: The name of interface.
501 :param ip_addr: IPv4 address to be set.
502 :param network: Netmask or length of network prefix.
506 :type network: str or int
507 :return: Content of response.
509 :raises HoneycombError: If the provided netmask or prefix is not valid.
512 interface = Topology.convert_interface_reference(
513 node, interface, "name")
515 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
517 if isinstance(network, basestring):
518 address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
519 elif isinstance(network, int) and (0 < network < 33):
520 address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
522 raise HoneycombError("Value {0} is not a valid netmask or network "
523 "prefix length.".format(network))
524 return InterfaceKeywords._set_interface_properties(
525 node, interface, path, address)
528 def remove_all_ipv4_addresses(node, interface):
529 """Remove all IPv4 addresses from interface.
531 :param node: Honeycomb node.
532 :param interface: The name of interface.
535 :return: Content of response.
539 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
541 return InterfaceKeywords._set_interface_properties(
542 node, interface, path, None)
545 def add_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
546 """Add the IPv4 neighbour.
548 :param node: Honeycomb node.
549 :param interface: The name of interface.
550 :param ip_addr: IPv4 address of neighbour to be set.
551 :param link_layer_address: Link layer address.
555 :type link_layer_address: str
556 :return: Content of response.
560 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
562 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
563 return InterfaceKeywords._set_interface_properties(
564 node, interface, path, neighbor)
567 def remove_all_ipv4_neighbors(node, interface):
568 """Remove all IPv4 neighbours.
570 :param node: Honeycomb node.
571 :param interface: The name of interface.
574 :return: Content of response.
578 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
580 return InterfaceKeywords._set_interface_properties(
581 node, interface, path, None)
584 def configure_interface_ipv6(node, interface, param, value):
585 """Configure IPv6 parameters of interface
587 :param node: Honeycomb node.
588 :param interface: The name of interface.
589 :param param: Parameter to configure (set, change, remove)
590 :param value: The value of parameter. If None, the parameter will be
596 :return: Content of response.
598 :raises HoneycombError: If the parameter is not valid.
601 if param in InterfaceKeywords.IPV6_PARAMS:
602 path = ("interfaces", ("interface", "name", interface),
603 "ietf-ip:ipv6", param)
604 elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
605 path = ("interfaces", ("interface", "name", interface),
606 "ietf-ip:ipv6", "autoconf", param)
608 raise HoneycombError("The parameter {0} is invalid.".format(param))
610 return InterfaceKeywords._set_interface_properties(
611 node, interface, path, value)
614 def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
615 """Add the first IPv6 address.
617 If there are any other addresses configured, they will be removed.
619 :param node: Honeycomb node.
620 :param interface: The name of interface.
621 :param ip_addr: IPv6 address to be set.
622 :param prefix_len: Prefix length.
626 :type prefix_len: str
627 :return: Content of response.
631 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
632 address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
633 return InterfaceKeywords._set_interface_properties(
634 node, interface, path, address)
637 def add_ipv6_address(node, interface, ip_addr, prefix_len):
640 :param node: Honeycomb node.
641 :param interface: The name of interface.
642 :param ip_addr: IPv6 address to be set.
643 :param prefix_len: Prefix length.
647 :type prefix_len: str
648 :return: Content of response.
652 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
654 address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
655 return InterfaceKeywords._set_interface_properties(
656 node, interface, path, address)
659 def remove_all_ipv6_addresses(node, interface):
660 """Remove all IPv6 addresses from interface.
662 :param node: Honeycomb node.
663 :param interface: The name of interface.
666 :return: Content of response.
670 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
672 return InterfaceKeywords._set_interface_properties(
673 node, interface, path, None)
676 def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
677 """Add the IPv6 neighbour.
679 :param node: Honeycomb node.
680 :param interface: The name of interface.
681 :param ip_addr: IPv6 address of neighbour to be set.
682 :param link_layer_address: Link layer address.
686 :type link_layer_address: str
687 :return: Content of response.
691 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
693 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
694 return InterfaceKeywords._set_interface_properties(
695 node, interface, path, neighbor)
698 def remove_all_ipv6_neighbors(node, interface):
699 """Remove all IPv6 neighbours.
701 :param node: Honeycomb node.
702 :param interface: The name of interface.
705 :return: Content of response.
709 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
711 return InterfaceKeywords._set_interface_properties(
712 node, interface, path, None)
715 def configure_interface_ethernet(node, interface, param, value):
716 """Configure the ethernet parameters of interface.
718 :param node: Honeycomb node.
719 :param interface: The name of interface.
720 :param param: Parameter to configure (set, change, remove)
721 :param value: The value of parameter. If None, the parameter will be
727 :return: Content of response.
729 :raises HoneycombError: If the parameter is not valid.
732 if param not in InterfaceKeywords.ETH_PARAMS:
733 raise HoneycombError("The parameter {0} is invalid.".format(param))
734 path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
736 return InterfaceKeywords._set_interface_properties(
737 node, interface, path, value)
740 def configure_interface_routing(node, interface, param, value):
741 """Configure the routing parameters of interface.
743 :param node: Honeycomb node.
744 :param interface: The name of interface.
745 :param param: Parameter to configure (set, change, remove)
746 :param value: The value of parameter. If None, the parameter will be
752 :return: Content of response.
754 :raises HoneycombError: If the parameter is not valid.
757 if param not in InterfaceKeywords.ROUTING_PARAMS:
758 raise HoneycombError("The parameter {0} is invalid.".format(param))
760 path = ("interfaces", ("interface", "name", interface), "v3po:routing",
762 return InterfaceKeywords._set_interface_properties(
763 node, interface, path, value)
766 def create_vxlan_interface(node, interface, **kwargs):
767 """Create a new VxLAN interface.
769 :param node: Honeycomb node.
770 :param interface: The name of interface.
771 :param kwargs: Parameters and their values. The accepted parameters are
772 defined in InterfaceKeywords.VXLAN_PARAMS.
776 :return: Content of response.
778 :raises HoneycombError: If the parameter is not valid.
783 "type": "v3po:vxlan-tunnel",
786 for param, value in kwargs.items():
787 if param not in InterfaceKeywords.VXLAN_PARAMS:
788 raise HoneycombError("The parameter {0} is invalid.".
790 new_vx_lan["v3po:vxlan"][param] = value
792 path = ("interfaces", "interface")
793 vx_lan_structure = [new_vx_lan, ]
794 return InterfaceKeywords._set_interface_properties(
795 node, interface, path, vx_lan_structure)
798 def delete_interface(node, interface):
799 """Delete an interface.
801 :param node: Honeycomb node.
802 :param interface: The name of interface.
805 :return: Content of response.
807 :raises HoneycombError: If it is not possible to get information about
808 interfaces or it is not possible to delete the interface.
811 path = ("interfaces", ("interface", "name", interface))
813 status_code, resp = HcUtil.\
814 get_honeycomb_data(node, "config_vpp_interfaces")
815 if status_code != HTTPCodes.OK:
816 raise HoneycombError(
817 "Not possible to get configuration information about the "
818 "interfaces. Status code: {0}.".format(status_code))
820 new_data = HcUtil.remove_item(resp, path)
821 status_code, resp = HcUtil.\
822 put_honeycomb_data(node, "config_vpp_interfaces", new_data)
823 if status_code != HTTPCodes.OK:
824 raise HoneycombError("Not possible to remove interface {0}. "
826 format(interface, status_code))
830 def configure_interface_vxlan(node, interface, **kwargs):
831 """Configure VxLAN on the interface.
833 The keyword configures VxLAN parameters on the given interface. The type
834 of interface must be set to "v3po:vxlan-tunnel".
835 The new VxLAN parameters overwrite the current configuration. If a
836 parameter in new configuration is missing, it is removed from VxLAN
838 If the dictionary kwargs is empty, VxLAN configuration is removed.
840 :param node: Honeycomb node.
841 :param interface: The name of interface.
842 :param kwargs: Parameters and their values. The accepted parameters are
843 defined in InterfaceKeywords.VXLAN_PARAMS.
847 :return: Content of response.
849 :raises HoneycombError: If the parameter is not valid.
852 vx_lan_structure = dict()
853 for param, value in kwargs.items():
854 if param not in InterfaceKeywords.VXLAN_PARAMS:
855 raise HoneycombError("The parameter {0} is invalid.".
857 vx_lan_structure[param] = value
859 path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
860 return InterfaceKeywords._set_interface_properties(
861 node, interface, path, vx_lan_structure)
864 def configure_interface_l2(node, interface, param, value):
865 """Configure the L2 parameters of interface.
867 :param node: Honeycomb node.
868 :param interface: The name of interface.
869 :param param: Parameter to configure (set, change, remove)
870 :param value: The value of parameter. If None, the parameter will be
876 :return: Content of response.
878 :raises HoneycombError: If the parameter is not valid.
881 if param not in InterfaceKeywords.L2_PARAMS:
882 raise HoneycombError("The parameter {0} is invalid.".format(param))
883 path = ("interfaces", ("interface", "name", interface), "v3po:l2",
885 return InterfaceKeywords._set_interface_properties(
886 node, interface, path, value)
889 def create_tap_interface(node, interface, **kwargs):
890 """Create a new TAP interface.
892 :param node: Honeycomb node.
893 :param interface: The name of interface.
894 :param kwargs: Parameters and their values. The accepted parameters are
895 defined in InterfaceKeywords.TAP_PARAMS.
899 :return: Content of response.
901 :raises HoneycombError: If the parameter is not valid.
909 for param, value in kwargs.items():
910 if param not in InterfaceKeywords.TAP_PARAMS:
911 raise HoneycombError("The parameter {0} is invalid.".
913 new_tap["v3po:tap"][param] = value
915 path = ("interfaces", "interface")
916 new_tap_structure = [new_tap, ]
917 return InterfaceKeywords._set_interface_properties(
918 node, interface, path, new_tap_structure)
921 def configure_interface_tap(node, interface, **kwargs):
922 """Configure TAP on the interface.
924 The keyword configures TAP parameters on the given interface. The type
925 of interface must be set to "v3po:tap".
926 The new TAP parameters overwrite the current configuration. If a
927 parameter in new configuration is missing, it is removed from TAP
929 If the dictionary kwargs is empty, TAP configuration is removed.
931 :param node: Honeycomb node.
932 :param interface: The name of interface.
933 :param kwargs: Parameters and their values. The accepted parameters are
934 defined in InterfaceKeywords.TAP_PARAMS.
938 :return: Content of response.
940 :raises HoneycombError: If the parameter is not valid.
943 tap_structure = dict()
944 for param, value in kwargs.items():
945 if param not in InterfaceKeywords.TAP_PARAMS:
946 raise HoneycombError("The parameter {0} is invalid.".
948 tap_structure[param] = value
950 path = ("interfaces", ("interface", "name", interface), "v3po:tap")
951 return InterfaceKeywords._set_interface_properties(
952 node, interface, path, tap_structure)
955 def configure_interface_vhost_user(node, interface, **kwargs):
956 """Configure vhost-user on the interface.
958 The keyword configures vhost-user parameters on the given interface.
959 The type of interface must be set to "v3po:vhost-user".
960 The new vhost-user parameters overwrite the current configuration. If a
961 parameter in new configuration is missing, it is removed from vhost-user
963 If the dictionary kwargs is empty, vhost-user configuration is removed.
965 :param node: Honeycomb node.
966 :param interface: The name of interface.
967 :param kwargs: Parameters and their values. The accepted parameters are
968 defined in InterfaceKeywords.VHOST_USER_PARAMS.
972 :return: Content of response.
974 :raises HoneycombError: If the parameter is not valid.
977 vhost_structure = dict()
978 for param, value in kwargs.items():
979 if param not in InterfaceKeywords.VHOST_USER_PARAMS:
980 raise HoneycombError("The parameter {0} is invalid.".
982 vhost_structure[param] = value
984 path = ("interfaces", ("interface", "name", interface),
986 return InterfaceKeywords._set_interface_properties(
987 node, interface, path, vhost_structure)
990 def create_vhost_user_interface(node, interface, **kwargs):
991 """Create a new vhost-user interface.
993 :param node: Honeycomb node.
994 :param interface: The name of interface.
995 :param kwargs: Parameters and their values. The accepted parameters are
996 defined in InterfaceKeywords.VHOST_USER_PARAMS.
1000 :return: Content of response.
1002 :raises HoneycombError: If the parameter is not valid.
1007 "type": "v3po:vhost-user",
1008 "v3po:vhost-user": {}
1010 for param, value in kwargs.items():
1011 if param not in InterfaceKeywords.VHOST_USER_PARAMS:
1012 raise HoneycombError("The parameter {0} is invalid.".
1014 new_vhost["v3po:vhost-user"][param] = value
1016 path = ("interfaces", "interface")
1017 new_vhost_structure = [new_vhost, ]
1018 return InterfaceKeywords._set_interface_properties(
1019 node, interface, path, new_vhost_structure)
1022 def create_sub_interface(node, super_interface, match, tags=None, **kwargs):
1023 """Create a new sub-interface.
1025 :param node: Honeycomb node.
1026 :param super_interface: Super interface.
1027 :param match: Match type. The valid values are defined in
1028 InterfaceKeywords.SUB_IF_MATCH.
1029 :param tags: List of tags.
1030 :param kwargs: Parameters and their values. The accepted parameters are
1031 defined in InterfaceKeywords.SUB_IF_PARAMS.
1033 :type super_interface: str
1037 :return: Content of response.
1039 :raises HoneycombError: If the parameter is not valid.
1040 :raises KeyError: If the parameter 'match' is invalid.
1049 {"vlan-tagged": {"match-exact-tags": "false"}},
1050 "vlan-tagged-exact-match":
1051 {"vlan-tagged": {"match-exact-tags": "true"}}
1054 new_sub_interface = {
1060 for param, value in kwargs.items():
1061 if param in InterfaceKeywords.SUB_IF_PARAMS:
1062 new_sub_interface[param] = value
1064 raise HoneycombError("The parameter {0} is invalid.".
1067 new_sub_interface["match"] = match_type[match]
1069 raise HoneycombError("The value '{0}' of parameter 'match' is "
1070 "invalid.".format(match))
1073 new_sub_interface["tags"]["tag"].extend(tags)
1075 path = ("interfaces",
1076 ("interface", "name", super_interface),
1077 "vpp-vlan:sub-interfaces",
1079 new_sub_interface_structure = [new_sub_interface, ]
1080 return InterfaceKeywords._set_interface_properties(
1081 node, super_interface, path, new_sub_interface_structure)
1084 def get_sub_interface_oper_data(node, super_interface, identifier):
1085 """Retrieves sub-interface operational data using Honeycomb API.
1087 :param node: Honeycomb node.
1088 :param super_interface: Super interface.
1089 :param identifier: The ID of sub-interface.
1091 :type super_interface: str
1092 :type identifier: int
1093 :return: Sub-interface operational data.
1095 :raises HoneycombError: If there is no sub-interface with the given ID.
1098 if_data = InterfaceKeywords.get_interface_oper_data(node,
1100 for sub_if in if_data["vpp-vlan:sub-interfaces"]["sub-interface"]:
1101 if str(sub_if["identifier"]) == str(identifier):
1104 raise HoneycombError("The interface {0} does not have sub-interface "
1105 "with ID {1}".format(super_interface, identifier))
1108 def remove_all_sub_interfaces(node, super_interface):
1109 """Remove all sub-interfaces from the given interface.
1111 :param node: Honeycomb node.
1112 :param super_interface: Super interface.
1114 :type super_interface: str
1115 :return: Content of response.
1119 path = ("interfaces",
1120 ("interface", "name", super_interface),
1121 "vpp-vlan:sub-interfaces")
1123 return InterfaceKeywords._set_interface_properties(
1124 node, super_interface, path, {})
1127 def set_sub_interface_state(node, super_interface, identifier, state):
1128 """Set the administrative state of sub-interface.
1130 :param node: Honeycomb node.
1131 :param super_interface: Super interface.
1132 :param identifier: The ID of sub-interface.
1133 :param state: Required sub-interface state - up or down.
1135 :type super_interface: str
1136 :type identifier: int
1138 :return: Content of response.
1142 intf_state = {"up": "true",
1145 path = ("interfaces",
1146 ("interface", "name", super_interface),
1147 "vpp-vlan:sub-interfaces",
1148 ("sub-interface", "identifier", identifier),
1151 return InterfaceKeywords._set_interface_properties(
1152 node, super_interface, path, intf_state[state])
1155 def add_bridge_domain_to_sub_interface(node, super_interface, identifier,
1157 """Add a sub-interface to a bridge domain and set its parameters.
1159 :param node: Honeycomb node.
1160 :param super_interface: Super interface.
1161 :param identifier: The ID of sub-interface.
1162 :param config: Bridge domain configuration.
1164 :type super_interface: str
1165 :type identifier: int
1167 :return: Content of response.
1171 path = ("interfaces",
1172 ("interface", "name", super_interface),
1173 "vpp-vlan:sub-interfaces",
1174 ("sub-interface", "identifier", int(identifier)),
1177 return InterfaceKeywords._set_interface_properties(
1178 node, super_interface, path, config)
1181 def get_bd_data_from_sub_interface(node, super_interface, identifier):
1182 """Get the operational data about the bridge domain from sub-interface.
1184 :param node: Honeycomb node.
1185 :param super_interface: Super interface.
1186 :param identifier: The ID of sub-interface.
1188 :type super_interface: str
1189 :type identifier: int
1190 :return: Operational data about the bridge domain.
1192 :raises HoneycombError: If there is no sub-interface with the given ID.
1196 bd_data = InterfaceKeywords.get_sub_interface_oper_data(
1197 node, super_interface, identifier)["l2"]
1200 raise HoneycombError("The operational data does not contain "
1201 "information about a bridge domain.")
1204 def configure_tag_rewrite(node, super_interface, identifier, config):
1205 """Add / change / disable vlan tag rewrite on a sub-interface.
1207 :param node: Honeycomb node.
1208 :param super_interface: Super interface.
1209 :param identifier: The ID of sub-interface.
1210 :param config: Rewrite tag configuration.
1212 :type super_interface: str
1213 :type identifier: int
1215 :return: Content of response.
1219 path = ("interfaces",
1220 ("interface", "name", super_interface),
1221 "vpp-vlan:sub-interfaces",
1222 ("sub-interface", "identifier", int(identifier)),
1226 return InterfaceKeywords._set_interface_properties(
1227 node, super_interface, path, config)
1230 def get_tag_rewrite_oper_data(node, super_interface, identifier):
1231 """Get the operational data about tag rewrite.
1233 :param node: Honeycomb node.
1234 :param super_interface: Super interface.
1235 :param identifier: The ID of sub-interface.
1237 :type super_interface: str
1238 :type identifier: int
1239 :return: Operational data about tag rewrite.
1241 :raises HoneycombError: If there is no sub-interface with the given ID.
1245 tag_rewrite = InterfaceKeywords.get_sub_interface_oper_data(
1246 node, super_interface, identifier)["l2"]["rewrite"]
1249 raise HoneycombError("The operational data does not contain "
1250 "information about the tag-rewrite.")
1253 def add_ipv4_address_to_sub_interface(node, super_interface, identifier,
1255 """Add an ipv4 address to the specified sub-interface, with the provided
1256 netmask or network prefix length. Any existing ipv4 addresses on the
1257 sub-interface will be replaced.
1259 :param node: Honeycomb node.
1260 :param super_interface: Super interface.
1261 :param identifier: The ID of sub-interface.
1262 :param ip_addr: IPv4 address to be set.
1263 :param network: Network mask or network prefix length.
1265 :type super_interface: str
1266 :type identifier: int
1268 :type network: str or int
1269 :return: Content of response.
1271 :raises HoneycombError: If the provided netmask or prefix is not valid.
1274 path = ("interfaces",
1275 ("interface", "name", super_interface),
1276 "vpp-vlan:sub-interfaces",
1277 ("sub-interface", "identifier", int(identifier)),
1280 if isinstance(network, basestring):
1281 address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
1283 elif isinstance(network, int) and 0 < network < 33:
1284 address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
1287 raise HoneycombError("{0} is not a valid netmask or prefix length."
1290 return InterfaceKeywords._set_interface_properties(
1291 node, super_interface, path, address)
1294 def remove_all_ipv4_addresses_from_sub_interface(node, super_interface, # pylint: disable=invalid-name
1296 """Remove all ipv4 addresses from the specified sub-interface.
1298 :param node: Honeycomb node.
1299 :param super_interface: Super interface.
1300 :param identifier: The ID of sub-interface.
1302 :type super_interface: str
1303 :type identifier: int
1304 :return: Content of response.
1308 path = ("interfaces",
1309 ("interface", "name", super_interface),
1310 "vpp-vlan:sub-interfaces",
1311 ("sub-interface", "identifier", int(identifier)),
1314 return InterfaceKeywords._set_interface_properties(
1315 node, super_interface, path, None)
1318 def compare_data_structures(data, ref, ignore=(), list_order=True):
1319 """Checks if data obtained from UUT is as expected.
1321 :param data: Data to be checked.
1322 :param ref: Referential data used for comparison.
1323 :param ignore: Dictionary keys to be ignored.
1324 :param list_order: Whether to consider the order of list items\
1328 :type ignore: iterable
1329 :type list_order: bool
1331 :raises HoneycombError: If a parameter from referential data is not
1332 present in operational data or if it has different value.
1337 for key, item in ref.items():
1341 if data[key] != item:
1342 if not list_order and sorted(data[key]) == sorted(item):
1345 errors += ("\nThe value of parameter '{0}' is "
1346 "incorrect. It should be "
1347 "'{1}' but it is '{2}'".
1348 format(key, item, data[key]))
1350 errors += ("\nThe parameter '{0}' is not present in "
1351 "operational data".format(key))
1354 raise HoneycombError(errors)
1357 def compare_interface_lists(list1, list2):
1358 """Compare provided lists of interfaces by name.
1360 :param list1: List of interfaces.
1361 :param list2: List of interfaces.
1364 :raises HoneycombError: If an interface exists in only one of the lists.
1367 ignore = ["vx_tunnel0", "vxlan_gpe_tunnel0"]
1368 # these have no equivalent in config data and no effect on VPP
1370 names1 = [x['name'] for x in list1]
1371 names2 = [x['name'] for x in list2]
1374 if name not in names2 and name not in ignore:
1375 raise HoneycombError("Interface {0} not present in list {1}"
1376 .format(name, list2))
1378 if name not in names1 and name not in ignore:
1379 raise HoneycombError("Interface {0} not present in list {1}"
1380 .format(name, list1))
1383 def create_vxlan_gpe_interface(node, interface, **kwargs):
1384 """Create a new VxLAN GPE interface.
1386 :param node: Honeycomb node.
1387 :param interface: The name of interface to be created.
1388 :param kwargs: Parameters and their values. The accepted parameters are
1389 defined in InterfaceKeywords.VXLAN_GPE_PARAMS.
1391 :type interface: str
1393 :return: Content of response.
1395 :raises HoneycombError: If a parameter in kwargs is not valid.
1400 "type": "v3po:vxlan-gpe-tunnel",
1401 "v3po:vxlan-gpe": {}
1403 for param, value in kwargs.items():
1404 if param in InterfaceKeywords.INTF_PARAMS:
1405 new_vxlan_gpe[param] = value
1406 elif param in InterfaceKeywords.VXLAN_GPE_PARAMS:
1407 new_vxlan_gpe["v3po:vxlan-gpe"][param] = value
1409 raise HoneycombError("The parameter {0} is invalid.".
1411 path = ("interfaces", "interface")
1412 vxlan_gpe_structure = [new_vxlan_gpe, ]
1413 return InterfaceKeywords._set_interface_properties(
1414 node, interface, path, vxlan_gpe_structure)
1417 def enable_acl_on_interface(node, interface, table_name):
1418 """Enable ACL on the given interface.
1420 :param node: Honeycomb node.
1421 :param interface: The interface where the ACL will be enabled.
1422 :param table_name: Name of the classify table.
1424 :type interface: str
1425 :type table_name: str
1426 :return: Content of response.
1428 :raises HoneycombError: If the configuration of interface is not
1432 interface = interface.replace("/", "%2F")
1438 "classify-table": table_name
1441 "classify-table": table_name
1447 path = "/interface/" + interface + "/v3po:acl"
1448 status_code, resp = HcUtil.\
1449 put_honeycomb_data(node, "config_vpp_interfaces", data, path,
1450 data_representation=DataRepresentation.JSON)
1451 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1452 raise HoneycombError(
1453 "The configuration of interface '{0}' was not successful. "
1454 "Status code: {1}.".format(interface, status_code))
1458 def disable_acl_on_interface(node, interface):
1459 """Disable ACL on the given interface.
1461 :param node: Honeycomb node.
1462 :param interface: The interface where the ACL will be disabled.
1464 :type interface: str
1465 :return: Content of response.
1467 :raises HoneycombError: If the configuration of interface is not
1471 interface = interface.replace("/", "%2F")
1473 path = "/interface/" + interface + "/v3po:acl"
1475 status_code, resp = HcUtil.\
1476 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1478 if status_code != HTTPCodes.OK:
1479 raise HoneycombError(
1480 "The configuration of interface '{0}' was not successful. "
1481 "Status code: {1}.".format(interface, status_code))
1485 def create_pbb_sub_interface(node, intf, sub_if_id, params):
1486 """Creates a PBB sub-interface on the given interface and sets its
1489 :param node: Honeycomb node.
1490 :param intf: The interface where PBB sub-interface will be configured.
1491 :param sub_if_id: Sub-interface ID.
1492 :param params: Configuration parameters of the sub-interface to be
1496 :type sub_if_id: str or int
1498 :return: Content of response.
1500 :raises HoneycombError: If the configuration of sub-interface is not
1504 interface = intf.replace("/", "%2F")
1505 path = "/interface/{0}/sub-interfaces:sub-interfaces/sub-interface/" \
1506 "{1}".format(interface, sub_if_id)
1507 status_code, resp = HcUtil. \
1508 put_honeycomb_data(node, "config_vpp_interfaces", params, path,
1509 data_representation=DataRepresentation.JSON)
1510 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1511 raise HoneycombError(
1512 "The configuration of PBB sub-interface '{0}' was not "
1513 "successful. Status code: {1}.".format(intf, status_code))
1517 def delete_pbb_sub_interface(node, intf, sub_if_id):
1518 """Deletes the given PBB sub-interface.
1520 :param node: Honeycomb node.
1521 :param intf: The interface where PBB sub-interface will be deleted.
1522 :param sub_if_id: ID of the PBB sub-interface to be deleted.
1525 :type sub_if_id: str or int
1526 :return: Content of response.
1528 :raises HoneycombError: If the removal of sub-interface is not
1532 interface = intf.replace("/", "%2F")
1533 path = "/interface/{0}/sub-interfaces:sub-interfaces/sub-interface/" \
1534 "{1}".format(interface, sub_if_id)
1536 status_code, resp = HcUtil. \
1537 delete_honeycomb_data(node, "config_vpp_interfaces", path)
1538 if status_code != HTTPCodes.OK:
1539 raise HoneycombError(
1540 "The removal of pbb sub-interface '{0}' was not successful. "
1541 "Status code: {1}.".format(intf, status_code))
1545 def get_pbb_sub_interface_oper_data(node, intf, sub_if_id):
1546 """Retrieves PBB sub-interface operational data from Honeycomb.
1548 :param node: Honeycomb node.
1549 :param intf: The interface where PBB sub-interface is located.
1550 :param sub_if_id: ID of the PBB sub-interface.
1553 :type sub_if_id: str or int
1554 :return: PBB sub-interface operational data.
1556 :raises HoneycombError: If the removal of sub-interface is not
1560 interface = "{0}.{1}".format(intf, sub_if_id)
1561 return InterfaceKeywords.get_interface_oper_data(node, interface)
1564 def check_disabled_interface(node, interface):
1565 """Retrieves list of disabled interface indices from Honeycomb,
1566 and matches with the provided interface by index.
1568 :param node: Honeycomb node.
1569 :param interface: Index number of an interface on the node.
1571 :type interface: int
1572 :return: True if the interface exists in disabled interfaces.
1574 :raises HoneycombError: If the interface is not present
1575 in retrieved list of disabled interfaces.
1577 data = InterfaceKeywords.get_disabled_interfaces_oper_data(node)
1578 # decrement by one = conversion from HC if-index to VPP sw_if_index
1582 if item["index"] == interface:
1584 raise HoneycombError("Interface index {0} not present in list"
1585 " of disabled interfaces.".format(interface))