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