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
20 from resources.libraries.python.HTTPRequest import HTTPCodes
21 from resources.libraries.python.honeycomb.HoneycombSetup import HoneycombError
22 from resources.libraries.python.honeycomb.HoneycombUtil \
23 import DataRepresentation
24 from resources.libraries.python.honeycomb.HoneycombUtil \
25 import HoneycombUtil as HcUtil
28 class InterfaceKeywords(object):
29 """Keywords for Interface manipulation.
31 Implements keywords which get configuration and operational data about
32 vpp interfaces and set the interface's parameters using Honeycomb REST API.
35 INTF_PARAMS = ("name", "description", "type", "enabled",
36 "link-up-down-trap-enable")
37 IPV4_PARAMS = ("enabled", "forwarding", "mtu")
38 IPV6_PARAMS = ("enabled", "forwarding", "mtu", "dup-addr-detect-transmits")
39 IPV6_AUTOCONF_PARAMS = ("create-global-addresses",
40 "create-temporary-addresses",
41 "temporary-valid-lifetime",
42 "temporary-preferred-lifetime")
43 ETH_PARAMS = ("mtu", )
44 ROUTING_PARAMS = ("vrf-id", )
45 VXLAN_PARAMS = ("src", "dst", "vni", "encap-vrf-id")
46 L2_PARAMS = ("bridge-domain", "split-horizon-group",
47 "bridged-virtual-interface")
53 def _configure_interface(node, interface, data,
54 data_representation=DataRepresentation.JSON):
55 """Send interface configuration data and check the response.
57 :param node: Honeycomb node.
58 :param interface: The name of interface.
59 :param data: Configuration data to be sent in PUT request.
60 :param data_representation: How the data is represented.
64 :type data_representation: DataRepresentation
65 :return: Content of response.
67 :raises HoneycombError: If the status code in response on PUT is not
71 status_code, resp = HcUtil.\
72 put_honeycomb_data(node, "config_vpp_interfaces", data,
73 data_representation=data_representation)
74 if status_code != HTTPCodes.OK:
76 "The configuration of interface '{0}' was not successful. "
77 "Status code: {1}.".format(interface, status_code))
81 def get_all_interfaces_cfg_data(node):
82 """Get configuration data about all interfaces from Honeycomb.
84 :param node: Honeycomb node.
86 :return: Configuration data about all interfaces from Honeycomb.
88 :raises HoneycombError: If it is not possible to get configuration data.
91 status_code, resp = HcUtil.\
92 get_honeycomb_data(node, "config_vpp_interfaces")
93 if status_code != HTTPCodes.OK:
95 "Not possible to get configuration information about the "
96 "interfaces. Status code: {0}.".format(status_code))
98 return resp["interfaces"]["interface"]
100 except (KeyError, TypeError):
104 def get_interface_cfg_data(node, interface):
105 """Get configuration data about the given interface from Honeycomb.
107 :param node: Honeycomb node.
108 :param interface: The name of interface.
111 :return: Configuration data about the given interface from Honeycomb.
115 intfs = InterfaceKeywords.get_all_interfaces_cfg_data(node)
117 if intf["name"] == interface:
122 def get_all_interfaces_oper_data(node):
123 """Get operational data about all interfaces from Honeycomb.
125 :param node: Honeycomb node.
127 :return: Operational data about all interfaces from Honeycomb.
129 :raises HoneycombError: If it is not possible to get operational data.
132 status_code, resp = HcUtil.\
133 get_honeycomb_data(node, "oper_vpp_interfaces")
134 if status_code != HTTPCodes.OK:
135 raise HoneycombError(
136 "Not possible to get operational information about the "
137 "interfaces. Status code: {0}.".format(status_code))
139 return resp["interfaces-state"]["interface"]
141 except (KeyError, TypeError):
145 def get_interface_oper_data(node, interface):
146 """Get operational data about the given interface from Honeycomb.
148 :param node: Honeycomb node.
149 :param interface: The name of interface.
152 :return: Operational data about the given interface from Honeycomb.
156 intfs = InterfaceKeywords.get_all_interfaces_oper_data(node)
158 if intf["name"] == interface:
163 def _set_interface_properties(node, interface, path, new_value=None):
164 """Set interface properties.
166 This method reads interface configuration data, creates, changes or
167 removes the requested data and puts it back to Honeycomb.
169 :param node: Honeycomb node.
170 :param interface: The name of interface.
171 :param path: Path to data we want to change / create / remove.
172 :param new_value: The new value to be set. If None, the item will be
177 :type new_value: str, dict or list
178 :return: Content of response.
180 :raises HoneycombError: If it is not possible to get or set the data.
183 status_code, resp = HcUtil.\
184 get_honeycomb_data(node, "config_vpp_interfaces")
185 if status_code != HTTPCodes.OK:
186 raise HoneycombError(
187 "Not possible to get configuration information about the "
188 "interfaces. Status code: {0}.".format(status_code))
191 new_data = HcUtil.set_item_value(resp, path, new_value)
193 new_data = HcUtil.remove_item(resp, path)
194 return InterfaceKeywords._configure_interface(node, interface, new_data)
197 def set_interface_state(node, interface, state="up"):
198 """Set VPP interface state.
200 The keyword changes the administration state of interface to up or down
201 depending on the parameter "state".
203 :param node: Honeycomb node.
204 :param interface: The name of interface.
205 :param state: The requested state, only "up" and "down" are valid
210 :return: Content of response.
212 :raises KeyError: If the argument "state" is nor "up" or "down".
213 :raises HoneycombError: If the interface is not present on the node.
216 intf_state = {"up": "true",
219 path = ("interfaces", ("interface", "name", str(interface)), "enabled")
220 return InterfaceKeywords._set_interface_properties(
221 node, interface, path, intf_state[state.lower()])
224 def set_interface_up(node, interface):
225 """Set the administration state of VPP interface to up.
227 :param node: Honeycomb node.
228 :param interface: The name of interface.
231 :return: Content of response
235 return InterfaceKeywords.set_interface_state(node, interface, "up")
238 def set_interface_down(node, interface):
239 """Set the administration state of VPP interface to down.
241 :param node: Honeycomb node.
242 :param interface: The name of interface.
245 :return: Content of response.
249 return InterfaceKeywords.set_interface_state(node, interface, "down")
252 def add_bridge_domain_to_interface(node, interface, bd_name,
253 split_horizon_group=None, bvi=None):
254 """Add a new bridge domain to an interface and set its parameters.
256 :param node: Honeycomb node.
257 :param interface: The name of interface.
258 :param bd_name: Bridge domain name.
259 :param split_horizon_group: Split-horizon group name.
260 :param bvi: The bridged virtual interface.
264 :type split_horizon_group: str
266 :return: Content of response.
268 :raises HoneycombError: If the interface is not present on the node.
271 v3po_l2 = {"bridge-domain": str(bd_name)}
272 if split_horizon_group:
273 v3po_l2["split-horizon-group"] = str(split_horizon_group)
275 v3po_l2["bridged-virtual-interface"] = str(bvi)
277 path = ("interfaces", ("interface", "name", str(interface)), "v3po:l2")
279 return InterfaceKeywords._set_interface_properties(
280 node, interface, path, v3po_l2)
283 def configure_interface_base(node, interface, param, value):
284 """Configure the base parameters of interface.
286 :param node: Honeycomb node.
287 :param interface: The name of interface.
288 :param param: Parameter to configure (set, change, remove)
289 :param value: The value of parameter. If None, the parameter will be
295 :return: Content of response.
297 :raises HoneycombError: If the parameter is not valid.
300 if param not in InterfaceKeywords.INTF_PARAMS:
301 raise HoneycombError("The parameter {0} is invalid.".format(param))
303 path = ("interfaces", ("interface", "name", interface), param)
304 return InterfaceKeywords._set_interface_properties(
305 node, interface, path, value)
308 def configure_interface_ipv4(node, interface, param, value):
309 """Configure IPv4 parameters of interface
311 :param node: Honeycomb node.
312 :param interface: The name of interface.
313 :param param: Parameter to configure (set, change, remove)
314 :param value: The value of parameter. If None, the parameter will be
320 :return: Content of response.
322 :raises HoneycombError: If the parameter is not valid.
325 if param not in InterfaceKeywords.IPV4_PARAMS:
326 raise HoneycombError("The parameter {0} is invalid.".format(param))
328 path = ("interfaces", ("interface", "name", interface),
329 "ietf-ip:ipv4", param)
330 return InterfaceKeywords._set_interface_properties(
331 node, interface, path, value)
334 def add_first_ipv4_address(node, interface, ip_addr, network):
335 """Add the first IPv4 address.
337 If there are any other addresses configured, they will be removed.
339 :param node: Honeycomb node.
340 :param interface: The name of interface.
341 :param ip_addr: IPv4 address to be set.
342 :param network: Netmask or length of network prefix.
346 :type network: str or int
347 :return: Content of response.
351 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
352 if isinstance(network, basestring):
353 address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
354 elif isinstance(network, int) and (0 < network < 33):
355 address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
357 raise HoneycombError("Value {0} is not a valid netmask or network "
358 "prefix length.".format(network))
359 return InterfaceKeywords._set_interface_properties(
360 node, interface, path, address)
363 def add_ipv4_address(node, interface, ip_addr, network):
366 :param node: Honeycomb node.
367 :param interface: The name of interface.
368 :param ip_addr: IPv4 address to be set.
369 :param network: Netmask or length of network prefix.
373 :type network: str or int
374 :return: Content of response.
378 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
380 if isinstance(network, basestring):
381 address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
382 elif isinstance(network, int) and (0 < network < 33):
383 address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
385 raise HoneycombError("Value {0} is not a valid netmask or network "
386 "prefix length.".format(network))
387 return InterfaceKeywords._set_interface_properties(
388 node, interface, path, address)
391 def remove_all_ipv4_addresses(node, interface):
392 """Remove all IPv4 addresses from interface.
394 :param node: Honeycomb node.
395 :param interface: The name of interface.
398 :return: Content of response.
402 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
404 return InterfaceKeywords._set_interface_properties(
405 node, interface, path, None)
408 def add_first_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
409 """Add the first IPv4 neighbour.
411 If there are any other neighbours configured, they will be removed.
413 :param node: Honeycomb node.
414 :param interface: The name of interface.
415 :param ip_addr: IPv4 address of neighbour to be set.
416 :param link_layer_address: Link layer address.
420 :type link_layer_address: str
421 :return: Content of response.
425 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
426 neighbor = {"neighbor": [{"ip": ip_addr,
427 "link-layer-address": link_layer_address}, ]}
428 return InterfaceKeywords._set_interface_properties(
429 node, interface, path, neighbor)
432 def add_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
433 """Add the IPv4 neighbour.
435 :param node: Honeycomb node.
436 :param interface: The name of interface.
437 :param ip_addr: IPv4 address of neighbour to be set.
438 :param link_layer_address: Link layer address.
442 :type link_layer_address: str
443 :return: Content of response.
447 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
449 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
450 return InterfaceKeywords._set_interface_properties(
451 node, interface, path, neighbor)
454 def remove_all_ipv4_neighbors(node, interface):
455 """Remove all IPv4 neighbours.
457 :param node: Honeycomb node.
458 :param interface: The name of interface.
461 :return: Content of response.
465 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
467 return InterfaceKeywords._set_interface_properties(
468 node, interface, path, None)
471 def configure_interface_ipv6(node, interface, param, value):
472 """Configure IPv6 parameters of interface
474 :param node: Honeycomb node.
475 :param interface: The name of interface.
476 :param param: Parameter to configure (set, change, remove)
477 :param value: The value of parameter. If None, the parameter will be
483 :return: Content of response.
485 :raises HoneycombError: If the parameter is not valid.
488 if param in InterfaceKeywords.IPV6_PARAMS:
489 path = ("interfaces", ("interface", "name", interface),
490 "ietf-ip:ipv6", param)
491 elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
492 path = ("interfaces", ("interface", "name", interface),
493 "ietf-ip:ipv6", "autoconf", param)
495 raise HoneycombError("The parameter {0} is invalid.".format(param))
497 return InterfaceKeywords._set_interface_properties(
498 node, interface, path, value)
501 def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
502 """Add the first IPv6 address.
504 If there are any other addresses configured, they will be removed.
506 :param node: Honeycomb node.
507 :param interface: The name of interface.
508 :param ip_addr: IPv6 address to be set.
509 :param prefix_len: Prefix length.
513 :type prefix_len: str
514 :return: Content of response.
518 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
519 address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
520 return InterfaceKeywords._set_interface_properties(
521 node, interface, path, address)
524 def add_ipv6_address(node, interface, ip_addr, prefix_len):
527 :param node: Honeycomb node.
528 :param interface: The name of interface.
529 :param ip_addr: IPv6 address to be set.
530 :param prefix_len: Prefix length.
534 :type prefix_len: str
535 :return: Content of response.
539 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
541 address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
542 return InterfaceKeywords._set_interface_properties(
543 node, interface, path, address)
546 def remove_all_ipv6_addresses(node, interface):
547 """Remove all IPv6 addresses from interface.
549 :param node: Honeycomb node.
550 :param interface: The name of interface.
553 :return: Content of response.
557 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
559 return InterfaceKeywords._set_interface_properties(
560 node, interface, path, None)
563 def add_first_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
564 """Add the first IPv6 neighbour.
566 If there are any other neighbours configured, they will be removed.
568 :param node: Honeycomb node.
569 :param interface: The name of interface.
570 :param ip_addr: IPv6 address of neighbour to be set.
571 :param link_layer_address: Link layer address.
575 :type link_layer_address: str
576 :return: Content of response.
580 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
581 neighbor = {"neighbor": [{"ip": ip_addr,
582 "link-layer-address": link_layer_address}, ]}
583 return InterfaceKeywords._set_interface_properties(
584 node, interface, path, neighbor)
587 def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
588 """Add the IPv6 neighbour.
590 :param node: Honeycomb node.
591 :param interface: The name of interface.
592 :param ip_addr: IPv6 address of neighbour to be set.
593 :param link_layer_address: Link layer address.
597 :type link_layer_address: str
598 :return: Content of response.
602 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
604 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
605 return InterfaceKeywords._set_interface_properties(
606 node, interface, path, neighbor)
609 def remove_all_ipv6_neighbors(node, interface):
610 """Remove all IPv6 neighbours.
612 :param node: Honeycomb node.
613 :param interface: The name of interface.
616 :return: Content of response.
620 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
622 return InterfaceKeywords._set_interface_properties(
623 node, interface, path, None)
626 def configure_interface_ethernet(node, interface, param, value):
627 """Configure the ethernet parameters of interface.
629 :param node: Honeycomb node.
630 :param interface: The name of interface.
631 :param param: Parameter to configure (set, change, remove)
632 :param value: The value of parameter. If None, the parameter will be
638 :return: Content of response.
640 :raises HoneycombError: If the parameter is not valid.
643 if param not in InterfaceKeywords.ETH_PARAMS:
644 raise HoneycombError("The parameter {0} is invalid.".format(param))
645 path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
647 return InterfaceKeywords._set_interface_properties(
648 node, interface, path, value)
651 def configure_interface_routing(node, interface, param, value):
652 """Configure the routing parameters of interface.
654 :param node: Honeycomb node.
655 :param interface: The name of interface.
656 :param param: Parameter to configure (set, change, remove)
657 :param value: The value of parameter. If None, the parameter will be
663 :return: Content of response.
665 :raises HoneycombError: If the parameter is not valid.
668 if param not in InterfaceKeywords.ROUTING_PARAMS:
669 raise HoneycombError("The parameter {0} is invalid.".format(param))
671 path = ("interfaces", ("interface", "name", interface), "v3po:routing",
673 return InterfaceKeywords._set_interface_properties(
674 node, interface, path, value)
677 def create_vxlan_interface(node, interface, **kwargs):
678 """Create a new VxLAN interface.
680 :param node: Honeycomb node.
681 :param interface: The name of interface.
682 :param kwargs: Parameters and their values. The accepted parameters are
683 defined in InterfaceKeywords.VXLAN_PARAMS.
687 :return: Content of response.
689 :raises HoneycombError: If the parameter is not valid.
694 "type": "v3po:vxlan-tunnel",
697 for param, value in kwargs.items():
698 if param not in InterfaceKeywords.VXLAN_PARAMS:
699 raise HoneycombError("The parameter {0} is invalid.".
701 new_vx_lan["v3po:vxlan"][param] = value
703 path = ("interfaces", "interface")
704 vx_lan_structure = [new_vx_lan, ]
705 return InterfaceKeywords._set_interface_properties(
706 node, interface, path, vx_lan_structure)
709 def delete_interface(node, interface):
710 """Delete an interface.
712 :param node: Honeycomb node.
713 :param interface: The name of interface.
716 :return: Content of response.
718 :raises HoneycombError: If it is not possible to get information about
719 interfaces or it is not possible to delete the interface.
722 path = ("interfaces", ("interface", "name", interface))
724 status_code, resp = HcUtil.\
725 get_honeycomb_data(node, "config_vpp_interfaces")
726 if status_code != HTTPCodes.OK:
727 raise HoneycombError(
728 "Not possible to get configuration information about the "
729 "interfaces. Status code: {0}.".format(status_code))
731 new_data = HcUtil.remove_item(resp, path)
732 status_code, resp = HcUtil.\
733 put_honeycomb_data(node, "config_vpp_interfaces", new_data)
734 if status_code != HTTPCodes.OK:
735 raise HoneycombError("Not possible to remove interface {0}. "
737 format(interface, status_code))
741 def configure_interface_vxlan(node, interface, **kwargs):
742 """Configure VxLAN on the interface.
744 The keyword configures VxLAN parameters on the given interface. The type
745 of interface must be set to "v3po:vxlan-tunnel".
746 The new VxLAN parameters overwrite the current configuration. If a
747 parameter in new configuration is missing, it is removed from VxLAN
749 If the dictionary kwargs is empty, VxLAN configuration is removed.
751 :param node: Honeycomb node.
752 :param interface: The name of interface.
753 :param kwargs: Parameters and their values. The accepted parameters are
754 defined in InterfaceKeywords.VXLAN_PARAMS.
758 :return: Content of response.
760 :raises HoneycombError: If the parameter is not valid.
763 vx_lan_structure = dict()
764 for param, value in kwargs.items():
765 if param not in InterfaceKeywords.VXLAN_PARAMS:
766 raise HoneycombError("The parameter {0} is invalid.".
768 vx_lan_structure[param] = value
770 path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
771 return InterfaceKeywords._set_interface_properties(
772 node, interface, path, vx_lan_structure)
775 def configure_interface_l2(node, interface, param, value):
776 """Configure the L2 parameters of interface.
778 :param node: Honeycomb node.
779 :param interface: The name of interface.
780 :param param: Parameter to configure (set, change, remove)
781 :param value: The value of parameter. If None, the parameter will be
787 :return: Content of response.
789 :raises HoneycombError: If the parameter is not valid.
792 if param not in InterfaceKeywords.L2_PARAMS:
793 raise HoneycombError("The parameter {0} is invalid.".format(param))
794 path = ("interfaces", ("interface", "name", interface), "v3po:l2",
796 return InterfaceKeywords._set_interface_properties(
797 node, interface, path, value)