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")
48 TAP_PARAMS = ("tap-name", "mac", "device-instance")
54 def _configure_interface(node, interface, data,
55 data_representation=DataRepresentation.JSON):
56 """Send interface configuration data and check the response.
58 :param node: Honeycomb node.
59 :param interface: The name of interface.
60 :param data: Configuration data to be sent in PUT request.
61 :param data_representation: How the data is represented.
65 :type data_representation: DataRepresentation
66 :return: Content of response.
68 :raises HoneycombError: If the status code in response on PUT is not
72 status_code, resp = HcUtil.\
73 put_honeycomb_data(node, "config_vpp_interfaces", data,
74 data_representation=data_representation)
75 if status_code != HTTPCodes.OK:
77 "The configuration of interface '{0}' was not successful. "
78 "Status code: {1}.".format(interface, status_code))
82 def get_all_interfaces_cfg_data(node):
83 """Get configuration data about all interfaces from Honeycomb.
85 :param node: Honeycomb node.
87 :return: Configuration data about all interfaces from Honeycomb.
89 :raises HoneycombError: If it is not possible to get configuration data.
92 status_code, resp = HcUtil.\
93 get_honeycomb_data(node, "config_vpp_interfaces")
94 if status_code != HTTPCodes.OK:
96 "Not possible to get configuration information about the "
97 "interfaces. Status code: {0}.".format(status_code))
99 return resp["interfaces"]["interface"]
101 except (KeyError, TypeError):
105 def get_interface_cfg_data(node, interface):
106 """Get configuration data about the given interface from Honeycomb.
108 :param node: Honeycomb node.
109 :param interface: The name of interface.
112 :return: Configuration data about the given interface from Honeycomb.
116 intfs = InterfaceKeywords.get_all_interfaces_cfg_data(node)
118 if intf["name"] == interface:
123 def get_all_interfaces_oper_data(node):
124 """Get operational data about all interfaces from Honeycomb.
126 :param node: Honeycomb node.
128 :return: Operational data about all interfaces from Honeycomb.
130 :raises HoneycombError: If it is not possible to get operational data.
133 status_code, resp = HcUtil.\
134 get_honeycomb_data(node, "oper_vpp_interfaces")
135 if status_code != HTTPCodes.OK:
136 raise HoneycombError(
137 "Not possible to get operational information about the "
138 "interfaces. Status code: {0}.".format(status_code))
140 return resp["interfaces-state"]["interface"]
142 except (KeyError, TypeError):
146 def get_interface_oper_data(node, interface):
147 """Get operational data about the given interface from Honeycomb.
149 :param node: Honeycomb node.
150 :param interface: The name of interface.
153 :return: Operational data about the given interface from Honeycomb.
157 intfs = InterfaceKeywords.get_all_interfaces_oper_data(node)
159 if intf["name"] == interface:
164 def _set_interface_properties(node, interface, path, new_value=None):
165 """Set interface properties.
167 This method reads interface configuration data, creates, changes or
168 removes the requested data and puts it back to Honeycomb.
170 :param node: Honeycomb node.
171 :param interface: The name of interface.
172 :param path: Path to data we want to change / create / remove.
173 :param new_value: The new value to be set. If None, the item will be
178 :type new_value: str, dict or list
179 :return: Content of response.
181 :raises HoneycombError: If it is not possible to get or set the data.
184 status_code, resp = HcUtil.\
185 get_honeycomb_data(node, "config_vpp_interfaces")
186 if status_code != HTTPCodes.OK:
187 raise HoneycombError(
188 "Not possible to get configuration information about the "
189 "interfaces. Status code: {0}.".format(status_code))
192 new_data = HcUtil.set_item_value(resp, path, new_value)
194 new_data = HcUtil.remove_item(resp, path)
195 return InterfaceKeywords._configure_interface(node, interface, new_data)
198 def set_interface_state(node, interface, state="up"):
199 """Set VPP interface state.
201 The keyword changes the administration state of interface to up or down
202 depending on the parameter "state".
204 :param node: Honeycomb node.
205 :param interface: The name of interface.
206 :param state: The requested state, only "up" and "down" are valid
211 :return: Content of response.
213 :raises KeyError: If the argument "state" is nor "up" or "down".
214 :raises HoneycombError: If the interface is not present on the node.
217 intf_state = {"up": "true",
220 path = ("interfaces", ("interface", "name", str(interface)), "enabled")
221 return InterfaceKeywords._set_interface_properties(
222 node, interface, path, intf_state[state.lower()])
225 def set_interface_up(node, interface):
226 """Set the administration state of VPP interface to up.
228 :param node: Honeycomb node.
229 :param interface: The name of interface.
232 :return: Content of response
236 return InterfaceKeywords.set_interface_state(node, interface, "up")
239 def set_interface_down(node, interface):
240 """Set the administration state of VPP interface to down.
242 :param node: Honeycomb node.
243 :param interface: The name of interface.
246 :return: Content of response.
250 return InterfaceKeywords.set_interface_state(node, interface, "down")
253 def add_bridge_domain_to_interface(node, interface, bd_name,
254 split_horizon_group=None, bvi=None):
255 """Add a new bridge domain to an interface and set its parameters.
257 :param node: Honeycomb node.
258 :param interface: The name of interface.
259 :param bd_name: Bridge domain name.
260 :param split_horizon_group: Split-horizon group name.
261 :param bvi: The bridged virtual interface.
265 :type split_horizon_group: str
267 :return: Content of response.
269 :raises HoneycombError: If the interface is not present on the node.
272 v3po_l2 = {"bridge-domain": str(bd_name)}
273 if split_horizon_group:
274 v3po_l2["split-horizon-group"] = str(split_horizon_group)
276 v3po_l2["bridged-virtual-interface"] = str(bvi)
278 path = ("interfaces", ("interface", "name", str(interface)), "v3po:l2")
280 return InterfaceKeywords._set_interface_properties(
281 node, interface, path, v3po_l2)
284 def configure_interface_base(node, interface, param, value):
285 """Configure the base parameters of interface.
287 :param node: Honeycomb node.
288 :param interface: The name of interface.
289 :param param: Parameter to configure (set, change, remove)
290 :param value: The value of parameter. If None, the parameter will be
296 :return: Content of response.
298 :raises HoneycombError: If the parameter is not valid.
301 if param not in InterfaceKeywords.INTF_PARAMS:
302 raise HoneycombError("The parameter {0} is invalid.".format(param))
304 path = ("interfaces", ("interface", "name", interface), param)
305 return InterfaceKeywords._set_interface_properties(
306 node, interface, path, value)
309 def configure_interface_ipv4(node, interface, param, value):
310 """Configure IPv4 parameters of interface
312 :param node: Honeycomb node.
313 :param interface: The name of interface.
314 :param param: Parameter to configure (set, change, remove)
315 :param value: The value of parameter. If None, the parameter will be
321 :return: Content of response.
323 :raises HoneycombError: If the parameter is not valid.
326 if param not in InterfaceKeywords.IPV4_PARAMS:
327 raise HoneycombError("The parameter {0} is invalid.".format(param))
329 path = ("interfaces", ("interface", "name", interface),
330 "ietf-ip:ipv4", param)
331 return InterfaceKeywords._set_interface_properties(
332 node, interface, path, value)
335 def add_first_ipv4_address(node, interface, ip_addr, network):
336 """Add the first IPv4 address.
338 If there are any other addresses configured, they will be removed.
340 :param node: Honeycomb node.
341 :param interface: The name of interface.
342 :param ip_addr: IPv4 address to be set.
343 :param network: Netmask or length of network prefix.
347 :type network: str or int
348 :return: Content of response.
352 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
353 if isinstance(network, basestring):
354 address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
355 elif isinstance(network, int) and (0 < network < 33):
356 address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
358 raise HoneycombError("Value {0} is not a valid netmask or network "
359 "prefix length.".format(network))
360 return InterfaceKeywords._set_interface_properties(
361 node, interface, path, address)
364 def add_ipv4_address(node, interface, ip_addr, network):
367 :param node: Honeycomb node.
368 :param interface: The name of interface.
369 :param ip_addr: IPv4 address to be set.
370 :param network: Netmask or length of network prefix.
374 :type network: str or int
375 :return: Content of response.
379 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
381 if isinstance(network, basestring):
382 address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
383 elif isinstance(network, int) and (0 < network < 33):
384 address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
386 raise HoneycombError("Value {0} is not a valid netmask or network "
387 "prefix length.".format(network))
388 return InterfaceKeywords._set_interface_properties(
389 node, interface, path, address)
392 def remove_all_ipv4_addresses(node, interface):
393 """Remove all IPv4 addresses from interface.
395 :param node: Honeycomb node.
396 :param interface: The name of interface.
399 :return: Content of response.
403 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
405 return InterfaceKeywords._set_interface_properties(
406 node, interface, path, None)
409 def add_first_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
410 """Add the first IPv4 neighbour.
412 If there are any other neighbours configured, they will be removed.
414 :param node: Honeycomb node.
415 :param interface: The name of interface.
416 :param ip_addr: IPv4 address of neighbour to be set.
417 :param link_layer_address: Link layer address.
421 :type link_layer_address: str
422 :return: Content of response.
426 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
427 neighbor = {"neighbor": [{"ip": ip_addr,
428 "link-layer-address": link_layer_address}, ]}
429 return InterfaceKeywords._set_interface_properties(
430 node, interface, path, neighbor)
433 def add_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
434 """Add the IPv4 neighbour.
436 :param node: Honeycomb node.
437 :param interface: The name of interface.
438 :param ip_addr: IPv4 address of neighbour to be set.
439 :param link_layer_address: Link layer address.
443 :type link_layer_address: str
444 :return: Content of response.
448 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
450 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
451 return InterfaceKeywords._set_interface_properties(
452 node, interface, path, neighbor)
455 def remove_all_ipv4_neighbors(node, interface):
456 """Remove all IPv4 neighbours.
458 :param node: Honeycomb node.
459 :param interface: The name of interface.
462 :return: Content of response.
466 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
468 return InterfaceKeywords._set_interface_properties(
469 node, interface, path, None)
472 def configure_interface_ipv6(node, interface, param, value):
473 """Configure IPv6 parameters of interface
475 :param node: Honeycomb node.
476 :param interface: The name of interface.
477 :param param: Parameter to configure (set, change, remove)
478 :param value: The value of parameter. If None, the parameter will be
484 :return: Content of response.
486 :raises HoneycombError: If the parameter is not valid.
489 if param in InterfaceKeywords.IPV6_PARAMS:
490 path = ("interfaces", ("interface", "name", interface),
491 "ietf-ip:ipv6", param)
492 elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
493 path = ("interfaces", ("interface", "name", interface),
494 "ietf-ip:ipv6", "autoconf", param)
496 raise HoneycombError("The parameter {0} is invalid.".format(param))
498 return InterfaceKeywords._set_interface_properties(
499 node, interface, path, value)
502 def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
503 """Add the first IPv6 address.
505 If there are any other addresses configured, they will be removed.
507 :param node: Honeycomb node.
508 :param interface: The name of interface.
509 :param ip_addr: IPv6 address to be set.
510 :param prefix_len: Prefix length.
514 :type prefix_len: str
515 :return: Content of response.
519 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
520 address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
521 return InterfaceKeywords._set_interface_properties(
522 node, interface, path, address)
525 def add_ipv6_address(node, interface, ip_addr, prefix_len):
528 :param node: Honeycomb node.
529 :param interface: The name of interface.
530 :param ip_addr: IPv6 address to be set.
531 :param prefix_len: Prefix length.
535 :type prefix_len: str
536 :return: Content of response.
540 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
542 address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
543 return InterfaceKeywords._set_interface_properties(
544 node, interface, path, address)
547 def remove_all_ipv6_addresses(node, interface):
548 """Remove all IPv6 addresses from interface.
550 :param node: Honeycomb node.
551 :param interface: The name of interface.
554 :return: Content of response.
558 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
560 return InterfaceKeywords._set_interface_properties(
561 node, interface, path, None)
564 def add_first_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
565 """Add the first IPv6 neighbour.
567 If there are any other neighbours configured, they will be removed.
569 :param node: Honeycomb node.
570 :param interface: The name of interface.
571 :param ip_addr: IPv6 address of neighbour to be set.
572 :param link_layer_address: Link layer address.
576 :type link_layer_address: str
577 :return: Content of response.
581 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
582 neighbor = {"neighbor": [{"ip": ip_addr,
583 "link-layer-address": link_layer_address}, ]}
584 return InterfaceKeywords._set_interface_properties(
585 node, interface, path, neighbor)
588 def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
589 """Add the IPv6 neighbour.
591 :param node: Honeycomb node.
592 :param interface: The name of interface.
593 :param ip_addr: IPv6 address of neighbour to be set.
594 :param link_layer_address: Link layer address.
598 :type link_layer_address: str
599 :return: Content of response.
603 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
605 neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
606 return InterfaceKeywords._set_interface_properties(
607 node, interface, path, neighbor)
610 def remove_all_ipv6_neighbors(node, interface):
611 """Remove all IPv6 neighbours.
613 :param node: Honeycomb node.
614 :param interface: The name of interface.
617 :return: Content of response.
621 path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
623 return InterfaceKeywords._set_interface_properties(
624 node, interface, path, None)
627 def configure_interface_ethernet(node, interface, param, value):
628 """Configure the ethernet parameters of interface.
630 :param node: Honeycomb node.
631 :param interface: The name of interface.
632 :param param: Parameter to configure (set, change, remove)
633 :param value: The value of parameter. If None, the parameter will be
639 :return: Content of response.
641 :raises HoneycombError: If the parameter is not valid.
644 if param not in InterfaceKeywords.ETH_PARAMS:
645 raise HoneycombError("The parameter {0} is invalid.".format(param))
646 path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
648 return InterfaceKeywords._set_interface_properties(
649 node, interface, path, value)
652 def configure_interface_routing(node, interface, param, value):
653 """Configure the routing parameters of interface.
655 :param node: Honeycomb node.
656 :param interface: The name of interface.
657 :param param: Parameter to configure (set, change, remove)
658 :param value: The value of parameter. If None, the parameter will be
664 :return: Content of response.
666 :raises HoneycombError: If the parameter is not valid.
669 if param not in InterfaceKeywords.ROUTING_PARAMS:
670 raise HoneycombError("The parameter {0} is invalid.".format(param))
672 path = ("interfaces", ("interface", "name", interface), "v3po:routing",
674 return InterfaceKeywords._set_interface_properties(
675 node, interface, path, value)
678 def create_vxlan_interface(node, interface, **kwargs):
679 """Create a new VxLAN interface.
681 :param node: Honeycomb node.
682 :param interface: The name of interface.
683 :param kwargs: Parameters and their values. The accepted parameters are
684 defined in InterfaceKeywords.VXLAN_PARAMS.
688 :return: Content of response.
690 :raises HoneycombError: If the parameter is not valid.
695 "type": "v3po:vxlan-tunnel",
698 for param, value in kwargs.items():
699 if param not in InterfaceKeywords.VXLAN_PARAMS:
700 raise HoneycombError("The parameter {0} is invalid.".
702 new_vx_lan["v3po:vxlan"][param] = value
704 path = ("interfaces", "interface")
705 vx_lan_structure = [new_vx_lan, ]
706 return InterfaceKeywords._set_interface_properties(
707 node, interface, path, vx_lan_structure)
710 def delete_interface(node, interface):
711 """Delete an interface.
713 :param node: Honeycomb node.
714 :param interface: The name of interface.
717 :return: Content of response.
719 :raises HoneycombError: If it is not possible to get information about
720 interfaces or it is not possible to delete the interface.
723 path = ("interfaces", ("interface", "name", interface))
725 status_code, resp = HcUtil.\
726 get_honeycomb_data(node, "config_vpp_interfaces")
727 if status_code != HTTPCodes.OK:
728 raise HoneycombError(
729 "Not possible to get configuration information about the "
730 "interfaces. Status code: {0}.".format(status_code))
732 new_data = HcUtil.remove_item(resp, path)
733 status_code, resp = HcUtil.\
734 put_honeycomb_data(node, "config_vpp_interfaces", new_data)
735 if status_code != HTTPCodes.OK:
736 raise HoneycombError("Not possible to remove interface {0}. "
738 format(interface, status_code))
742 def configure_interface_vxlan(node, interface, **kwargs):
743 """Configure VxLAN on the interface.
745 The keyword configures VxLAN parameters on the given interface. The type
746 of interface must be set to "v3po:vxlan-tunnel".
747 The new VxLAN parameters overwrite the current configuration. If a
748 parameter in new configuration is missing, it is removed from VxLAN
750 If the dictionary kwargs is empty, VxLAN configuration is removed.
752 :param node: Honeycomb node.
753 :param interface: The name of interface.
754 :param kwargs: Parameters and their values. The accepted parameters are
755 defined in InterfaceKeywords.VXLAN_PARAMS.
759 :return: Content of response.
761 :raises HoneycombError: If the parameter is not valid.
764 vx_lan_structure = dict()
765 for param, value in kwargs.items():
766 if param not in InterfaceKeywords.VXLAN_PARAMS:
767 raise HoneycombError("The parameter {0} is invalid.".
769 vx_lan_structure[param] = value
771 path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
772 return InterfaceKeywords._set_interface_properties(
773 node, interface, path, vx_lan_structure)
776 def configure_interface_l2(node, interface, param, value):
777 """Configure the L2 parameters of interface.
779 :param node: Honeycomb node.
780 :param interface: The name of interface.
781 :param param: Parameter to configure (set, change, remove)
782 :param value: The value of parameter. If None, the parameter will be
788 :return: Content of response.
790 :raises HoneycombError: If the parameter is not valid.
793 if param not in InterfaceKeywords.L2_PARAMS:
794 raise HoneycombError("The parameter {0} is invalid.".format(param))
795 path = ("interfaces", ("interface", "name", interface), "v3po:l2",
797 return InterfaceKeywords._set_interface_properties(
798 node, interface, path, value)
801 def create_tap_interface(node, interface, **kwargs):
802 """Create a new TAP interface.
804 :param node: Honeycomb node.
805 :param interface: The name of interface.
806 :param kwargs: Parameters and their values. The accepted parameters are
807 defined in InterfaceKeywords.TAP_PARAMS.
811 :return: Content of response.
813 :raises HoneycombError: If the parameter is not valid.
821 for param, value in kwargs.items():
822 if param not in InterfaceKeywords.TAP_PARAMS:
823 raise HoneycombError("The parameter {0} is invalid.".
825 new_tap["v3po:tap"][param] = value
827 path = ("interfaces", "interface")
828 new_tap_structure = [new_tap, ]
829 return InterfaceKeywords._set_interface_properties(
830 node, interface, path, new_tap_structure)
833 def configure_interface_tap(node, interface, **kwargs):
834 """Configure TAP on the interface.
836 The keyword configures TAP parameters on the given interface. The type
837 of interface must be set to "v3po:tap".
838 The new TAP parameters overwrite the current configuration. If a
839 parameter in new configuration is missing, it is removed from TAP
841 If the dictionary kwargs is empty, TAP configuration is removed.
843 :param node: Honeycomb node.
844 :param interface: The name of interface.
845 :param kwargs: Parameters and their values. The accepted parameters are
846 defined in InterfaceKeywords.TAP_PARAMS.
850 :return: Content of response.
852 :raises HoneycombError: If the parameter is not valid.
855 tap_structure = dict()
856 for param, value in kwargs.items():
857 if param not in InterfaceKeywords.TAP_PARAMS:
858 raise HoneycombError("The parameter {0} is invalid.".
860 tap_structure[param] = value
862 path = ("interfaces", ("interface", "name", interface), "v3po:tap")
863 return InterfaceKeywords._set_interface_properties(
864 node, interface, path, tap_structure)