CSIT-424: HC Test: JSON comparison function rework
[csit.git] / resources / libraries / python / honeycomb / HcAPIKwInterfaces.py
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:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
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.
13
14 """Keywords to manipulate interface configuration using Honeycomb REST API.
15
16 The keywords make possible to put and get configuration data and to get
17 operational data.
18 """
19 from robot.api import logger
20
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
28
29
30 class InterfaceKeywords(object):
31     """Keywords for Interface manipulation.
32
33     Implements keywords which get configuration and operational data about
34     vpp interfaces and set the interface's parameters using Honeycomb REST API.
35     """
36
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",
54                      "vlan-type",
55                      "enabled")
56     SUB_IF_MATCH = ("default",
57                     "untagged",
58                     "vlan-tagged",
59                     "vlan-tagged-exact-match")
60     BD_PARAMS = ("bridge-domain",
61                  "split-horizon-group",
62                  "bridged-virtual-interface")
63     VXLAN_GPE_PARAMS = ("local",
64                         "remote",
65                         "vni",
66                         "next-protocol",
67                         "encap-vrf-id",
68                         "decap-vrf-id")
69
70     def __init__(self):
71         pass
72
73     @staticmethod
74     def _configure_interface(node, interface, data,
75                              data_representation=DataRepresentation.JSON):
76         """Send interface configuration data and check the response.
77
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.
82         :type node: dict
83         :type interface: str
84         :type data: dict
85         :type data_representation: DataRepresentation
86         :returns: Content of response.
87         :rtype: bytearray
88         :raises HoneycombError: If the status code in response on PUT is not
89         200 = OK.
90         """
91
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):
96             raise HoneycombError(
97                 "The configuration of interface '{0}' was not successful. "
98                 "Status code: {1}.".format(interface, status_code))
99         return resp
100
101     @staticmethod
102     def get_all_interfaces_cfg_data(node):
103         """Get configuration data about all interfaces from Honeycomb.
104
105         :param node: Honeycomb node.
106         :type node: dict
107         :returns: Configuration data about all interfaces from Honeycomb.
108         :rtype: list
109         :raises HoneycombError: If it is not possible to get configuration data.
110         """
111
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))
118         try:
119             return resp["interfaces"]["interface"]
120
121         except (KeyError, TypeError):
122             return []
123
124     @staticmethod
125     def get_interface_cfg_data(node, interface):
126         """Get configuration data about the given interface from Honeycomb.
127
128         :param node: Honeycomb node.
129         :param interface: The name of interface.
130         :type node: dict
131         :type interface: str
132         :returns: Configuration data about the given interface from Honeycomb.
133         :rtype: dict
134         """
135
136         intfs = InterfaceKeywords.get_all_interfaces_cfg_data(node)
137         for intf in intfs:
138             if intf["name"] == interface:
139                 return intf
140         return {}
141
142     @staticmethod
143     def get_all_interfaces_oper_data(node):
144         """Get operational data about all interfaces from Honeycomb.
145
146         :param node: Honeycomb node.
147         :type node: dict
148         :returns: Operational data about all interfaces from Honeycomb.
149         :rtype: list
150         :raises HoneycombError: If it is not possible to get operational data.
151         """
152
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))
159         try:
160             return resp["interfaces-state"]["interface"]
161
162         except (KeyError, TypeError):
163             return []
164
165     @staticmethod
166     def get_disabled_interfaces_oper_data(node):
167         """Get operational data about all disabled interfaces from Honeycomb.
168
169         :param node: Honeycomb node.
170         :type node: dict
171         :returns: Operational data about disabled interfaces.
172         :rtype: list
173         :raises HoneycombError: If it is not possible to get operational data.
174         """
175
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."
181             )
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))
186         try:
187             return resp["disabled-interfaces"]["disabled-interface-index"]
188
189         except (KeyError, TypeError):
190             return []
191
192     @staticmethod
193     def get_interface_oper_data(node, interface):
194         """Get operational data about the given interface from Honeycomb.
195
196         :param node: Honeycomb node.
197         :param interface: The name of interface.
198         :type node: dict
199         :type interface: str
200         :returns: Operational data about the given interface from Honeycomb.
201         :rtype: dict
202         """
203
204         intfs = InterfaceKeywords.get_all_interfaces_oper_data(node)
205         for intf in intfs:
206             if intf["name"] == interface:
207                 return intf
208         return {}
209
210     @staticmethod
211     def _set_interface_properties(node, interface, path, new_value=None):
212         """Set interface properties.
213
214         This method reads interface configuration data, creates, changes or
215         removes the requested data and puts it back to Honeycomb.
216
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
221         removed.
222         :type node: dict
223         :type interface: str
224         :type path: tuple
225         :type new_value: str, dict or list
226         :returns: Content of response.
227         :rtype: bytearray
228         :raises HoneycombError: If it is not possible to get or set the data.
229         """
230
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))
237
238         if new_value:
239             new_data = HcUtil.set_item_value(resp, path, new_value)
240         else:
241             new_data = HcUtil.remove_item(resp, path)
242         return InterfaceKeywords._configure_interface(node, interface, new_data)
243
244     @staticmethod
245     def set_interface_state(node, interface, state="up"):
246         """Set VPP interface state.
247
248         The keyword changes the administration state of interface to up or down
249         depending on the parameter "state".
250
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
254         values.
255         :type node: dict
256         :type interface: str
257         :type state: str
258         :returns: Content of response.
259         :rtype: bytearray
260         :raises KeyError: If the argument "state" is nor "up" or "down".
261         :raises HoneycombError: If the interface is not present on the node.
262         """
263
264         intf_state = {"up": "true",
265                       "down": "false"}
266
267         interface = Topology.convert_interface_reference(
268             node, interface, "name")
269
270         intf = interface.replace("/", "%2F")
271         path = "/interface/{0}".format(intf)
272
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))
279
280         resp["interface"][0]["enabled"] = intf_state[state.lower()]
281
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))
289         return resp
290
291     @staticmethod
292     def set_interface_up(node, interface):
293         """Set the administration state of VPP interface to up.
294
295         :param node: Honeycomb node.
296         :param interface: The name of interface.
297         :type node: dict
298         :type interface: str
299         :returns: Content of response
300         :rtype: bytearray
301         """
302
303         return InterfaceKeywords.set_interface_state(node, interface, "up")
304
305     @staticmethod
306     def set_interface_down(node, interface):
307         """Set the administration state of VPP interface to down.
308
309         :param node: Honeycomb node.
310         :param interface: The name of interface.
311         :type node: dict
312         :type interface: str
313         :returns: Content of response.
314         :rtype: bytearray
315         """
316
317         return InterfaceKeywords.set_interface_state(node, interface, "down")
318
319     @staticmethod
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.
323
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.
329         :type node: dict
330         :type interface: str
331         :type bd_name: str
332         :type split_horizon_group: str
333         :type bvi: str
334         :returns: Content of response.
335         :rtype: bytearray
336         :raises HoneycombError: If the interface is not present on the node.
337         """
338
339         interface = Topology.convert_interface_reference(
340             node, interface, "name")
341
342         v3po_l2 = {"bridge-domain": str(bd_name)}
343         if split_horizon_group:
344             v3po_l2["split-horizon-group"] = str(split_horizon_group)
345         if bvi:
346             v3po_l2["bridged-virtual-interface"] = str(bvi)
347
348         path = ("interfaces", ("interface", "name", str(interface)), "v3po:l2")
349
350         return InterfaceKeywords._set_interface_properties(
351             node, interface, path, v3po_l2)
352
353     @staticmethod
354     def remove_bridge_domain_from_interface(node, interface):
355         """Remove bridge domain assignment from interface.
356
357         :param node: Honeycomb node.
358         :param interface: Interface name, key, link name or sw_if_index.
359         :type node: dict
360         :type interface: str or int
361
362         :raises HoneycombError: If the operation fails.
363         """
364
365         interface = Topology.convert_interface_reference(
366             node, interface, "name")
367
368         intf = interface.replace("/", "%2F")
369
370         path = "/interface/{0}/v3po:l2".format(intf)
371
372         status_code, response = HcUtil.delete_honeycomb_data(
373             node, "config_vpp_interfaces", path)
374
375         if status_code != HTTPCodes.OK:
376             if '"error-tag":"data-missing"' in response:
377                 logger.debug("Data does not exist in path.")
378             else:
379                 raise HoneycombError(
380                     "Could not remove bridge domain assignment from interface "
381                     "'{0}'. Status code: {1}.".format(interface, status_code))
382
383     @staticmethod
384     def get_bd_oper_data_from_interface(node, interface):
385         """Returns operational data about bridge domain settings in the
386         interface.
387
388         :param node: Honeycomb node.
389         :param interface: The name of interface.
390         :type node: dict
391         :type interface: str
392         :returns: Operational data about bridge domain settings in the
393         interface.
394         :rtype: dict
395         """
396
397         if_data = InterfaceKeywords.get_interface_oper_data(node, interface)
398
399         if if_data:
400             try:
401                 return if_data["v3po:l2"]
402             except KeyError:
403                 return {}
404         return {}
405
406     @staticmethod
407     def configure_interface_base(node, interface, param, value):
408         """Configure the base parameters of interface.
409
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
414         removed.
415         :type node: dict
416         :type interface: str
417         :type param: str
418         :type value: str
419         :returns: Content of response.
420         :rtype: bytearray
421         :raises HoneycombError: If the parameter is not valid.
422         """
423
424         if param not in InterfaceKeywords.INTF_PARAMS:
425             raise HoneycombError("The parameter {0} is invalid.".format(param))
426
427         path = ("interfaces", ("interface", "name", interface), param)
428         return InterfaceKeywords._set_interface_properties(
429             node, interface, path, value)
430
431     @staticmethod
432     def configure_interface_ipv4(node, interface, param, value):
433         """Configure IPv4 parameters of interface.
434
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
439         removed.
440         :type node: dict
441         :type interface: str
442         :type param: str
443         :type value: str
444         :returns: Content of response.
445         :rtype: bytearray
446         :raises HoneycombError: If the parameter is not valid.
447         """
448
449         interface = Topology.convert_interface_reference(
450             node, interface, "name")
451
452         if param not in InterfaceKeywords.IPV4_PARAMS:
453             raise HoneycombError("The parameter {0} is invalid.".format(param))
454
455         path = ("interfaces", ("interface", "name", interface),
456                 "ietf-ip:ipv4", param)
457         return InterfaceKeywords._set_interface_properties(
458             node, interface, path, value)
459
460     @staticmethod
461     def add_first_ipv4_address(node, interface, ip_addr, network):
462         """Add the first IPv4 address.
463
464         If there are any other addresses configured, they will be removed.
465
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.
470         :type node: dict
471         :type interface: str
472         :type ip_addr: str
473         :type network: str or int
474         :returns: Content of response.
475         :rtype: bytearray
476         :raises HoneycombError: If the provided netmask or prefix is not valid.
477         """
478
479         interface = Topology.convert_interface_reference(
480             node, interface, "name")
481
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}, ]}
487         else:
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)
492
493     @staticmethod
494     def add_ipv4_address(node, interface, ip_addr, network):
495         """Add IPv4 address.
496
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.
501         :type node: dict
502         :type interface: str
503         :type ip_addr: str
504         :type network: str or int
505         :returns: Content of response.
506         :rtype: bytearray
507         :raises HoneycombError: If the provided netmask or prefix is not valid.
508         """
509
510         interface = Topology.convert_interface_reference(
511             node, interface, "name")
512
513         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
514                 "address")
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}, ]}
519         else:
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)
524
525     @staticmethod
526     def remove_all_ipv4_addresses(node, interface):
527         """Remove all IPv4 addresses from interface.
528
529         :param node: Honeycomb node.
530         :param interface: The name of interface.
531         :type node: dict
532         :type interface: str
533         :returns: Content of response.
534         :rtype: bytearray
535         """
536
537         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
538                 "address")
539         return InterfaceKeywords._set_interface_properties(
540             node, interface, path, None)
541
542     @staticmethod
543     def add_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
544         """Add the IPv4 neighbour.
545
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.
550         :type node: dict
551         :type interface: str
552         :type ip_addr: str
553         :type link_layer_address: str
554         :returns: Content of response.
555         :rtype: bytearray
556         """
557
558         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
559                 "neighbor")
560         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
561         return InterfaceKeywords._set_interface_properties(
562             node, interface, path, neighbor)
563
564     @staticmethod
565     def remove_all_ipv4_neighbors(node, interface):
566         """Remove all IPv4 neighbours.
567
568         :param node: Honeycomb node.
569         :param interface: The name of interface.
570         :type node: dict
571         :type interface: str
572         :returns: Content of response.
573         :rtype: bytearray
574         """
575
576         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
577                 "neighbor")
578         return InterfaceKeywords._set_interface_properties(
579             node, interface, path, None)
580
581     @staticmethod
582     def configure_interface_ipv6(node, interface, param, value):
583         """Configure IPv6 parameters of interface
584
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
589         removed.
590         :type node: dict
591         :type interface: str
592         :type param: str
593         :type value: str
594         :returns: Content of response.
595         :rtype: bytearray
596         :raises HoneycombError: If the parameter is not valid.
597         """
598
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)
605         else:
606             raise HoneycombError("The parameter {0} is invalid.".format(param))
607
608         return InterfaceKeywords._set_interface_properties(
609             node, interface, path, value)
610
611     @staticmethod
612     def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
613         """Add the first IPv6 address.
614
615         If there are any other addresses configured, they will be removed.
616
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.
621         :type node: dict
622         :type interface: str
623         :type ip_addr: str
624         :type prefix_len: str
625         :returns: Content of response.
626         :rtype: bytearray
627         """
628
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)
633
634     @staticmethod
635     def add_ipv6_address(node, interface, ip_addr, prefix_len):
636         """Add IPv6 address.
637
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.
642         :type node: dict
643         :type interface: str
644         :type ip_addr: str
645         :type prefix_len: str
646         :returns: Content of response.
647         :rtype: bytearray
648         """
649
650         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
651                 "address")
652         address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
653         return InterfaceKeywords._set_interface_properties(
654             node, interface, path, address)
655
656     @staticmethod
657     def remove_all_ipv6_addresses(node, interface):
658         """Remove all IPv6 addresses from interface.
659
660         :param node: Honeycomb node.
661         :param interface: The name of interface.
662         :type node: dict
663         :type interface: str
664         :returns: Content of response.
665         :rtype: bytearray
666         """
667
668         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
669                 "address")
670         return InterfaceKeywords._set_interface_properties(
671             node, interface, path, None)
672
673     @staticmethod
674     def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
675         """Add the IPv6 neighbour.
676
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.
681         :type node: dict
682         :type interface: str
683         :type ip_addr: str
684         :type link_layer_address: str
685         :returns: Content of response.
686         :rtype: bytearray
687         """
688
689         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
690                 "neighbor")
691         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
692         return InterfaceKeywords._set_interface_properties(
693             node, interface, path, neighbor)
694
695     @staticmethod
696     def remove_all_ipv6_neighbors(node, interface):
697         """Remove all IPv6 neighbours.
698
699         :param node: Honeycomb node.
700         :param interface: The name of interface.
701         :type node: dict
702         :type interface: str
703         :returns: Content of response.
704         :rtype: bytearray
705         """
706
707         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
708                 "neighbor")
709         return InterfaceKeywords._set_interface_properties(
710             node, interface, path, None)
711
712     @staticmethod
713     def configure_interface_ethernet(node, interface, param, value):
714         """Configure the ethernet parameters of interface.
715
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
720         removed.
721         :type node: dict
722         :type interface: str
723         :type param: str
724         :type value: str
725         :returns: Content of response.
726         :rtype: bytearray
727         :raises HoneycombError: If the parameter is not valid.
728         """
729
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",
733                 param)
734         return InterfaceKeywords._set_interface_properties(
735             node, interface, path, value)
736
737     @staticmethod
738     def configure_interface_routing(node, interface, param, value):
739         """Configure the routing parameters of interface.
740
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
745         removed.
746         :type node: dict
747         :type interface: str
748         :type param: str
749         :type value: str
750         :returns: Content of response.
751         :rtype: bytearray
752         :raises HoneycombError: If the parameter is not valid.
753         """
754
755         if param not in InterfaceKeywords.ROUTING_PARAMS:
756             raise HoneycombError("The parameter {0} is invalid.".format(param))
757
758         path = ("interfaces", ("interface", "name", interface), "v3po:routing",
759                 param)
760         return InterfaceKeywords._set_interface_properties(
761             node, interface, path, value)
762
763     @staticmethod
764     def create_vxlan_interface(node, interface, **kwargs):
765         """Create a new VxLAN interface.
766
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.
771         :type node: dict
772         :type interface: str
773         :type kwargs: dict
774         :returns: Content of response.
775         :rtype: bytearray
776         :raises HoneycombError: If the parameter is not valid.
777         """
778
779         new_vx_lan = {
780             "name": interface,
781             "type": "v3po:vxlan-tunnel",
782             "v3po:vxlan": {}
783         }
784         for param, value in kwargs.items():
785             if param not in InterfaceKeywords.VXLAN_PARAMS:
786                 raise HoneycombError("The parameter {0} is invalid.".
787                                      format(param))
788             new_vx_lan["v3po:vxlan"][param] = value
789
790         path = ("interfaces", "interface")
791         vx_lan_structure = [new_vx_lan, ]
792         return InterfaceKeywords._set_interface_properties(
793             node, interface, path, vx_lan_structure)
794
795     @staticmethod
796     def delete_interface(node, interface):
797         """Delete an interface.
798
799         :param node: Honeycomb node.
800         :param interface: The name of interface.
801         :type node: dict
802         :type interface: str
803         :returns: Content of response.
804         :rtype: bytearray
805         :raises HoneycombError: If it is not possible to get information about
806         interfaces or it is not possible to delete the interface.
807         """
808
809         path = ("interfaces", ("interface", "name", interface))
810
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))
817
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}. "
823                                  "Status code: {1}.".
824                                  format(interface, status_code))
825         return resp
826
827     @staticmethod
828     def configure_interface_vxlan(node, interface, **kwargs):
829         """Configure VxLAN on the interface.
830
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
835         configuration.
836         If the dictionary kwargs is empty, VxLAN configuration is removed.
837
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.
842         :type node: dict
843         :type interface: str
844         :type kwargs: dict
845         :returns: Content of response.
846         :rtype: bytearray
847         :raises HoneycombError: If the parameter is not valid.
848         """
849
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.".
854                                      format(param))
855             vx_lan_structure[param] = value
856
857         path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
858         return InterfaceKeywords._set_interface_properties(
859             node, interface, path, vx_lan_structure)
860
861     @staticmethod
862     def configure_interface_l2(node, interface, param, value):
863         """Configure the L2 parameters of interface.
864
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
869         removed.
870         :type node: dict
871         :type interface: str
872         :type param: str
873         :type value: str
874         :returns: Content of response.
875         :rtype: bytearray
876         :raises HoneycombError: If the parameter is not valid.
877         """
878
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",
882                 param)
883         return InterfaceKeywords._set_interface_properties(
884             node, interface, path, value)
885
886     @staticmethod
887     def create_tap_interface(node, interface, **kwargs):
888         """Create a new TAP interface.
889
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.
894         :type node: dict
895         :type interface: str
896         :type kwargs: dict
897         :returns: Content of response.
898         :rtype: bytearray
899         :raises HoneycombError: If the parameter is not valid.
900         """
901
902         new_tap = {
903             "name": interface,
904             "type": "v3po:tap",
905             "v3po:tap": {}
906         }
907         for param, value in kwargs.items():
908             if param not in InterfaceKeywords.TAP_PARAMS:
909                 raise HoneycombError("The parameter {0} is invalid.".
910                                      format(param))
911             new_tap["v3po:tap"][param] = value
912
913         path = ("interfaces", "interface")
914         new_tap_structure = [new_tap, ]
915         return InterfaceKeywords._set_interface_properties(
916             node, interface, path, new_tap_structure)
917
918     @staticmethod
919     def configure_interface_tap(node, interface, **kwargs):
920         """Configure TAP on the interface.
921
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
926         configuration.
927         If the dictionary kwargs is empty, TAP configuration is removed.
928
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.
933         :type node: dict
934         :type interface: str
935         :type kwargs: dict
936         :returns: Content of response.
937         :rtype: bytearray
938         :raises HoneycombError: If the parameter is not valid.
939         """
940
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.".
945                                      format(param))
946             tap_structure[param] = value
947
948         path = ("interfaces", ("interface", "name", interface), "v3po:tap")
949         return InterfaceKeywords._set_interface_properties(
950             node, interface, path, tap_structure)
951
952     @staticmethod
953     def configure_interface_vhost_user(node, interface, **kwargs):
954         """Configure vhost-user on the interface.
955
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
960         configuration.
961         If the dictionary kwargs is empty, vhost-user configuration is removed.
962
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.
967         :type node: dict
968         :type interface: str
969         :type kwargs: dict
970         :returns: Content of response.
971         :rtype: bytearray
972         :raises HoneycombError: If the parameter is not valid.
973         """
974
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.".
979                                      format(param))
980             vhost_structure[param] = value
981
982         path = ("interfaces", ("interface", "name", interface),
983                 "v3po:vhost-user")
984         return InterfaceKeywords._set_interface_properties(
985             node, interface, path, vhost_structure)
986
987     @staticmethod
988     def create_vhost_user_interface(node, interface, **kwargs):
989         """Create a new vhost-user interface.
990
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.
995         :type node: dict
996         :type interface: str
997         :type kwargs: dict
998         :returns: Content of response.
999         :rtype: bytearray
1000         :raises HoneycombError: If the parameter is not valid.
1001         """
1002
1003         new_vhost = {
1004             "name": interface,
1005             "type": "v3po:vhost-user",
1006             "v3po:vhost-user": {}
1007         }
1008         for param, value in kwargs.items():
1009             if param not in InterfaceKeywords.VHOST_USER_PARAMS:
1010                 raise HoneycombError("The parameter {0} is invalid.".
1011                                      format(param))
1012             new_vhost["v3po:vhost-user"][param] = value
1013
1014         path = ("interfaces", "interface")
1015         new_vhost_structure = [new_vhost, ]
1016         return InterfaceKeywords._set_interface_properties(
1017             node, interface, path, new_vhost_structure)
1018
1019     @staticmethod
1020     def create_sub_interface(node, super_interface, match, tags=None, **kwargs):
1021         """Create a new sub-interface.
1022
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.
1030         :type node: dict
1031         :type super_interface: str
1032         :type match: str
1033         :type tags: list
1034         :type kwargs: dict
1035         :returns: Content of response.
1036         :rtype: bytearray
1037         :raises HoneycombError: If the parameter is not valid.
1038         :raises KeyError: If the parameter 'match' is invalid.
1039         """
1040
1041         match_type = {
1042             "default":
1043                 {"default": {}},
1044             "untagged":
1045                 {"untagged": {}},
1046             "vlan-tagged":
1047                 {"vlan-tagged": {"match-exact-tags": "false"}},
1048             "vlan-tagged-exact-match":
1049                 {"vlan-tagged": {"match-exact-tags": "true"}}
1050         }
1051
1052         new_sub_interface = {
1053             "tags": {
1054                 "tag": []
1055             },
1056         }
1057
1058         for param, value in kwargs.items():
1059             if param in InterfaceKeywords.SUB_IF_PARAMS:
1060                 new_sub_interface[param] = value
1061             else:
1062                 raise HoneycombError("The parameter {0} is invalid.".
1063                                      format(param))
1064         try:
1065             new_sub_interface["match"] = match_type[match]
1066         except KeyError:
1067             raise HoneycombError("The value '{0}' of parameter 'match' is "
1068                                  "invalid.".format(match))
1069
1070         if tags:
1071             new_sub_interface["tags"]["tag"].extend(tags)
1072
1073         path = ("interfaces",
1074                 ("interface", "name", super_interface),
1075                 "vpp-vlan:sub-interfaces",
1076                 "sub-interface")
1077         new_sub_interface_structure = [new_sub_interface, ]
1078         return InterfaceKeywords._set_interface_properties(
1079             node, super_interface, path, new_sub_interface_structure)
1080
1081     @staticmethod
1082     def get_sub_interface_oper_data(node, super_interface, identifier):
1083         """Retrieves sub-interface operational data using Honeycomb API.
1084
1085         :param node: Honeycomb node.
1086         :param super_interface: Super interface.
1087         :param identifier: The ID of sub-interface.
1088         :type node: dict
1089         :type super_interface: str
1090         :type identifier: int
1091         :returns: Sub-interface operational data.
1092         :rtype: dict
1093         :raises HoneycombError: If there is no sub-interface with the given ID.
1094         """
1095
1096         if_data = InterfaceKeywords.get_interface_oper_data(node,
1097                                                             super_interface)
1098         for sub_if in if_data["vpp-vlan:sub-interfaces"]["sub-interface"]:
1099             if str(sub_if["identifier"]) == str(identifier):
1100                 return sub_if
1101
1102         raise HoneycombError("The interface {0} does not have sub-interface "
1103                              "with ID {1}".format(super_interface, identifier))
1104
1105     @staticmethod
1106     def remove_all_sub_interfaces(node, super_interface):
1107         """Remove all sub-interfaces from the given interface.
1108
1109         :param node: Honeycomb node.
1110         :param super_interface: Super interface.
1111         :type node: dict
1112         :type super_interface: str
1113         :returns: Content of response.
1114         :rtype: bytearray
1115         """
1116
1117         path = ("interfaces",
1118                 ("interface", "name", super_interface),
1119                 "vpp-vlan:sub-interfaces")
1120
1121         return InterfaceKeywords._set_interface_properties(
1122             node, super_interface, path, {})
1123
1124     @staticmethod
1125     def set_sub_interface_state(node, super_interface, identifier, state):
1126         """Set the administrative state of sub-interface.
1127
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.
1132         :type node: dict
1133         :type super_interface: str
1134         :type identifier: int
1135         :type state: str
1136         :returns: Content of response.
1137         :rtype: bytearray
1138         """
1139
1140         intf_state = {"up": "true",
1141                       "down": "false"}
1142
1143         path = ("interfaces",
1144                 ("interface", "name", super_interface),
1145                 "vpp-vlan:sub-interfaces",
1146                 ("sub-interface", "identifier", identifier),
1147                 "enabled")
1148
1149         return InterfaceKeywords._set_interface_properties(
1150             node, super_interface, path, intf_state[state])
1151
1152     @staticmethod
1153     def add_bridge_domain_to_sub_interface(node, super_interface, identifier,
1154                                            config):
1155         """Add a sub-interface to a bridge domain and set its parameters.
1156
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.
1161         :type node: dict
1162         :type super_interface: str
1163         :type identifier: int
1164         :type config: dict
1165         :returns: Content of response.
1166         :rtype: bytearray
1167         """
1168
1169         path = ("interfaces",
1170                 ("interface", "name", super_interface),
1171                 "vpp-vlan:sub-interfaces",
1172                 ("sub-interface", "identifier", int(identifier)),
1173                 "l2")
1174
1175         return InterfaceKeywords._set_interface_properties(
1176             node, super_interface, path, config)
1177
1178     @staticmethod
1179     def get_bd_data_from_sub_interface(node, super_interface, identifier):
1180         """Get the operational data about the bridge domain from sub-interface.
1181
1182         :param node: Honeycomb node.
1183         :param super_interface: Super interface.
1184         :param identifier: The ID of sub-interface.
1185         :type node: dict
1186         :type super_interface: str
1187         :type identifier: int
1188         :returns: Operational data about the bridge domain.
1189         :rtype: dict
1190         :raises HoneycombError: If there is no sub-interface with the given ID.
1191         """
1192
1193         try:
1194             bd_data = InterfaceKeywords.get_sub_interface_oper_data(
1195                 node, super_interface, identifier)["l2"]
1196             return bd_data
1197         except KeyError:
1198             raise HoneycombError("The operational data does not contain "
1199                                  "information about a bridge domain.")
1200
1201     @staticmethod
1202     def configure_tag_rewrite(node, super_interface, identifier, config):
1203         """Add / change / disable vlan tag rewrite on a sub-interface.
1204
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.
1209         :type node: dict
1210         :type super_interface: str
1211         :type identifier: int
1212         :type config: dict
1213         :returns: Content of response.
1214         :rtype: bytearray
1215         """
1216
1217         path = ("interfaces",
1218                 ("interface", "name", super_interface),
1219                 "vpp-vlan:sub-interfaces",
1220                 ("sub-interface", "identifier", int(identifier)),
1221                 "l2",
1222                 "rewrite")
1223
1224         return InterfaceKeywords._set_interface_properties(
1225             node, super_interface, path, config)
1226
1227     @staticmethod
1228     def get_tag_rewrite_oper_data(node, super_interface, identifier):
1229         """Get the operational data about tag rewrite.
1230
1231         :param node: Honeycomb node.
1232         :param super_interface: Super interface.
1233         :param identifier: The ID of sub-interface.
1234         :type node: dict
1235         :type super_interface: str
1236         :type identifier: int
1237         :returns: Operational data about tag rewrite.
1238         :rtype: dict
1239         :raises HoneycombError: If there is no sub-interface with the given ID.
1240         """
1241
1242         try:
1243             tag_rewrite = InterfaceKeywords.get_sub_interface_oper_data(
1244                 node, super_interface, identifier)["l2"]["rewrite"]
1245             return tag_rewrite
1246         except KeyError:
1247             raise HoneycombError("The operational data does not contain "
1248                                  "information about the tag-rewrite.")
1249
1250     @staticmethod
1251     def add_ipv4_address_to_sub_interface(node, super_interface, identifier,
1252                                           ip_addr, network):
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.
1256
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.
1262         :type node: dict
1263         :type super_interface: str
1264         :type identifier: int
1265         :type ip_addr: str
1266         :type network: str or int
1267         :returns: Content of response.
1268         :rtype: bytearray
1269         :raises HoneycombError: If the provided netmask or prefix is not valid.
1270         """
1271
1272         path = ("interfaces",
1273                 ("interface", "name", super_interface),
1274                 "vpp-vlan:sub-interfaces",
1275                 ("sub-interface", "identifier", int(identifier)),
1276                 "ipv4")
1277
1278         if isinstance(network, basestring):
1279             address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
1280
1281         elif isinstance(network, int) and 0 < network < 33:
1282             address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
1283
1284         else:
1285             raise HoneycombError("{0} is not a valid netmask or prefix length."
1286                                  .format(network))
1287
1288         return InterfaceKeywords._set_interface_properties(
1289             node, super_interface, path, address)
1290
1291     @staticmethod
1292     def remove_all_ipv4_addresses_from_sub_interface(node, super_interface,
1293                                                      identifier):
1294         """Remove all ipv4 addresses from the specified sub-interface.
1295
1296         :param node: Honeycomb node.
1297         :param super_interface: Super interface.
1298         :param identifier: The ID of sub-interface.
1299         :type node: dict
1300         :type super_interface: str
1301         :type identifier: int
1302         :returns: Content of response.
1303         :rtype: bytearray
1304         """
1305
1306         path = ("interfaces",
1307                 ("interface", "name", super_interface),
1308                 "vpp-vlan:sub-interfaces",
1309                 ("sub-interface", "identifier", int(identifier)),
1310                 "ipv4", "address")
1311
1312         return InterfaceKeywords._set_interface_properties(
1313             node, super_interface, path, None)
1314
1315     @staticmethod
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.
1319
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
1323         the JSON tree.
1324         :type data: dict
1325         :type ref: dict
1326         :type _path: str
1327
1328         :raises HoneycombError: If the data structures do not match in some way,
1329         or if they are not in deserialized JSON format.
1330         """
1331
1332         if data == ref:
1333             return True
1334
1335         elif isinstance(data, dict) and isinstance(ref, dict):
1336             for key in ref:
1337                 if key not in data:
1338                     raise HoneycombError(
1339                         "Key {key} is not present in path {path}. Keys in path:"
1340                         "{data_keys}".format(
1341                             key=key,
1342                             path=_path,
1343                             data_keys=data.keys()))
1344
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))
1351                     else:
1352                         raise HoneycombError(
1353                             "Data mismatch, key {key} in path {path} has value"
1354                             " {data}, but should be {ref}".format(
1355                                 key=key,
1356                                 path=_path,
1357                                 data=data[key],
1358                                 ref=ref[key]))
1359
1360         elif isinstance(data, list) and isinstance(ref, list):
1361             for item in ref:
1362                 if item not in data:
1363                     if isinstance(item, dict):
1364                         InterfaceKeywords.compare_data_structures(
1365                             data[0], item,
1366                             _path + '[{0}]'.format(ref.index(item)))
1367                     else:
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),
1372                                 path=_path,
1373                                 data=data[0],
1374                                 ref=item))
1375
1376         else:
1377             raise HoneycombError(
1378                 "Unexpected data type {data_type}, reference type is"
1379                 " {ref_type}. Must be list or dictionary.".format(
1380                     data_type=type(data),
1381                     ref_type=type(ref)))
1382
1383     @staticmethod
1384     def compare_interface_lists(list1, list2):
1385         """Compare provided lists of interfaces by name.
1386
1387         :param list1: List of interfaces.
1388         :param list2: List of interfaces.
1389         :type list1: list
1390         :type list2: list
1391         :raises HoneycombError: If an interface exists in only one of the lists.
1392         """
1393
1394         ignore = ["vx_tunnel0", "vxlan_gpe_tunnel0"]
1395         # these have no equivalent in config data and no effect on VPP
1396
1397         names1 = [x['name'] for x in list1]
1398         names2 = [x['name'] for x in list2]
1399
1400         for name in names1:
1401             if name not in names2 and name not in ignore:
1402                 raise HoneycombError("Interface {0} not present in list {1}"
1403                                      .format(name, list2))
1404         for name in names2:
1405             if name not in names1 and name not in ignore:
1406                 raise HoneycombError("Interface {0} not present in list {1}"
1407                                      .format(name, list1))
1408
1409     @staticmethod
1410     def create_vxlan_gpe_interface(node, interface, **kwargs):
1411         """Create a new VxLAN GPE interface.
1412
1413         :param node: Honeycomb node.
1414         :param interface: The name of interface to be created.
1415         :param kwargs: Parameters and their values. The accepted parameters are
1416         defined in InterfaceKeywords.VXLAN_GPE_PARAMS.
1417         :type node: dict
1418         :type interface: str
1419         :type kwargs: dict
1420         :returns: Content of response.
1421         :rtype: bytearray
1422         :raises HoneycombError: If a parameter in kwargs is not valid.
1423         """
1424
1425         new_vxlan_gpe = {
1426             "name": interface,
1427             "type": "v3po:vxlan-gpe-tunnel",
1428             "v3po:vxlan-gpe": {}
1429         }
1430         for param, value in kwargs.items():
1431             if param in InterfaceKeywords.INTF_PARAMS:
1432                 new_vxlan_gpe[param] = value
1433             elif param in InterfaceKeywords.VXLAN_GPE_PARAMS:
1434                 new_vxlan_gpe["v3po:vxlan-gpe"][param] = value
1435             else:
1436                 raise HoneycombError("The parameter {0} is invalid.".
1437                                      format(param))
1438         path = ("interfaces", "interface")
1439         vxlan_gpe_structure = [new_vxlan_gpe, ]
1440         return InterfaceKeywords._set_interface_properties(
1441             node, interface, path, vxlan_gpe_structure)
1442
1443     @staticmethod
1444     def enable_acl_on_interface(node, interface, table_name):
1445         """Enable ACL on the given interface.
1446
1447         :param node: Honeycomb node.
1448         :param interface: The interface where the ACL will be enabled.
1449         :param table_name: Name of the classify table.
1450         :type node: dict
1451         :type interface: str
1452         :type table_name: str
1453         :returns: Content of response.
1454         :rtype: bytearray
1455         :raises HoneycombError: If the configuration of interface is not
1456         successful.
1457         """
1458
1459         interface = interface.replace("/", "%2F")
1460
1461         data = {
1462             "v3po:acl": {
1463                 "ingress": {
1464                     "ip4-acl": {
1465                         "classify-table": table_name
1466                     },
1467                     "l2-acl": {
1468                         "classify-table": table_name
1469                     }
1470                 }
1471             }
1472         }
1473
1474         path = "/interface/" + interface + "/v3po:acl"
1475         status_code, resp = HcUtil.\
1476             put_honeycomb_data(node, "config_vpp_interfaces", data, path,
1477                                data_representation=DataRepresentation.JSON)
1478         if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1479             raise HoneycombError(
1480                 "The configuration of interface '{0}' was not successful. "
1481                 "Status code: {1}.".format(interface, status_code))
1482         return resp
1483
1484     @staticmethod
1485     def disable_acl_on_interface(node, interface):
1486         """Disable ACL on the given interface.
1487
1488         :param node: Honeycomb node.
1489         :param interface: The interface where the ACL will be disabled.
1490         :type node: dict
1491         :type interface: str
1492         :returns: Content of response.
1493         :rtype: bytearray
1494         :raises HoneycombError: If the configuration of interface is not
1495         successful.
1496         """
1497
1498         interface = interface.replace("/", "%2F")
1499
1500         path = "/interface/" + interface + "/v3po:acl"
1501
1502         status_code, resp = HcUtil.\
1503             delete_honeycomb_data(node, "config_vpp_interfaces", path)
1504
1505         if status_code != HTTPCodes.OK:
1506             raise HoneycombError(
1507                 "The configuration of interface '{0}' was not successful. "
1508                 "Status code: {1}.".format(interface, status_code))
1509         return resp
1510
1511     @staticmethod
1512     def create_pbb_sub_interface(node, intf, params):
1513         """Creates a PBB sub-interface on the given interface and sets its
1514         parameters.
1515
1516         :param node: Honeycomb node.
1517         :param intf: The interface where PBB sub-interface will be configured.
1518         :param params: Configuration parameters of the sub-interface to be
1519         created.
1520         :type node: dict
1521         :type intf: str
1522         :type params: dict
1523         :returns: Content of response.
1524         :rtype: bytearray
1525         :raises HoneycombError: If the configuration of sub-interface is not
1526         successful.
1527         """
1528
1529         interface = intf.replace("/", "%2F")
1530         path = "/interface/{0}/pbb-rewrite/".format(interface)
1531         status_code, resp = HcUtil. \
1532             put_honeycomb_data(node, "config_vpp_interfaces", params, path,
1533                                data_representation=DataRepresentation.JSON)
1534         if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1535             raise HoneycombError(
1536                 "The configuration of PBB sub-interface '{0}' was not "
1537                 "successful. Status code: {1}.".format(intf, status_code))
1538         return resp
1539
1540     @staticmethod
1541     def delete_pbb_sub_interface(node, intf):
1542         """Deletes the given PBB sub-interface.
1543
1544         :param node: Honeycomb node.
1545         :param intf: The interface where PBB sub-interface will be deleted.
1546         :type node: dict
1547         :type intf: str
1548         :returns: Content of response.
1549         :rtype: bytearray
1550         :raises HoneycombError: If the removal of sub-interface is not
1551         successful.
1552         """
1553
1554         interface = intf.replace("/", "%2F")
1555         path = "/interface/{0}/pbb-rewrite".format(interface)
1556
1557         status_code, resp = HcUtil. \
1558             delete_honeycomb_data(node, "config_vpp_interfaces", path)
1559         if status_code != HTTPCodes.OK:
1560             raise HoneycombError(
1561                 "The removal of pbb sub-interface '{0}' was not successful. "
1562                 "Status code: {1}.".format(intf, status_code))
1563         return resp
1564
1565     @staticmethod
1566     def get_pbb_sub_interface_oper_data(node, intf, sub_if_id):
1567         """Retrieves PBB sub-interface operational data from Honeycomb.
1568
1569         :param node: Honeycomb node.
1570         :param intf: The interface where PBB sub-interface is located.
1571         :param sub_if_id: ID of the PBB sub-interface.
1572         :type node: dict
1573         :type intf: str
1574         :type sub_if_id: str or int
1575         :returns: PBB sub-interface operational data.
1576         :rtype: dict
1577         :raises HoneycombError: If the removal of sub-interface is not
1578         successful.
1579         """
1580
1581         raise NotImplementedError
1582
1583     @staticmethod
1584     def check_disabled_interface(node, interface):
1585         """Retrieves list of disabled interface indices from Honeycomb,
1586         and matches with the provided interface by index.
1587
1588         :param node: Honeycomb node.
1589         :param interface: Index number of an interface on the node.
1590         :type node: dict
1591         :type interface: int
1592         :returns: True if the interface exists in disabled interfaces.
1593         :rtype: bool
1594         :raises HoneycombError: If the interface is not present
1595          in retrieved list of disabled interfaces.
1596          """
1597         data = InterfaceKeywords.get_disabled_interfaces_oper_data(node)
1598         # decrement by one = conversion from HC if-index to VPP sw_if_index
1599         interface -= 1
1600
1601         for item in data:
1602             if item["index"] == interface:
1603                 return True
1604         raise HoneycombError("Interface index {0} not present in list"
1605                              " of disabled interfaces.".format(interface))
1606
1607     @staticmethod
1608     def configure_interface_span(node, dst_interface, *src_interfaces):
1609         """Configure SPAN port mirroring on the specified interfaces. If no
1610          source interface is provided, SPAN will be disabled.
1611
1612         :param node: Honeycomb node.
1613         :param dst_interface: Interface to mirror packets to.
1614         :param src_interfaces: List of interfaces to mirror packets from.
1615         :type node: dict
1616         :type dst_interface: str
1617         :type src_interfaces: list of str
1618         :returns: Content of response.
1619         :rtype: bytearray
1620         :raises HoneycombError: If SPAN could not be configured.
1621         """
1622
1623         interface = dst_interface.replace("/", "%2F")
1624         path = "/interface/" + interface + "/span"
1625
1626         if not src_interfaces:
1627             status_code, _ = HcUtil.delete_honeycomb_data(
1628                 node, "config_vpp_interfaces", path)
1629
1630         data = {
1631             "span": {
1632                 "mirrored-interfaces": {
1633                     "mirrored-interface": src_interfaces
1634                 }
1635             }
1636         }
1637
1638         status_code, _ = HcUtil.put_honeycomb_data(
1639             node, "config_vpp_interfaces", data, path)
1640
1641         if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1642             raise HoneycombError(
1643                 "Configuring SPAN failed. Status code:{0}".format(status_code))
1644
1645     @staticmethod
1646     def add_interface_local0_to_topology(node):
1647         """Use Topology methods to add interface "local0" to working topology,
1648         if not already present.
1649
1650         :param node: DUT node.
1651         :type node: dict
1652         """
1653
1654         if Topology.get_interface_by_sw_index(node, 0) is None:
1655             local0_key = Topology.add_new_port(node, "localzero")
1656             Topology.update_interface_sw_if_index(node, local0_key, 0)
1657             Topology.update_interface_name(node, local0_key, "local0")