CSIT-523 HC Test: routing
[csit.git] / resources / libraries / python / honeycomb / HcAPIKwInterfaces.py
1 # Copyright (c) 2017 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 = ("ipv4-vrf-id", "ipv6-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 = [{"ip": ip_addr, "netmask": network}]
517         elif isinstance(network, int) and (0 < network < 33):
518             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         interface = Topology.convert_interface_reference(
559             node, interface, "name")
560
561         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
562                 "neighbor")
563         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
564         return InterfaceKeywords._set_interface_properties(
565             node, interface, path, neighbor)
566
567     @staticmethod
568     def remove_all_ipv4_neighbors(node, interface):
569         """Remove all IPv4 neighbours.
570
571         :param node: Honeycomb node.
572         :param interface: The name of interface.
573         :type node: dict
574         :type interface: str
575         :returns: Content of response.
576         :rtype: bytearray
577         """
578
579         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
580                 "neighbor")
581         return InterfaceKeywords._set_interface_properties(
582             node, interface, path, None)
583
584     @staticmethod
585     def configure_interface_ipv6(node, interface, param, value):
586         """Configure IPv6 parameters of interface
587
588         :param node: Honeycomb node.
589         :param interface: The name of interface.
590         :param param: Parameter to configure (set, change, remove)
591         :param value: The value of parameter. If None, the parameter will be
592         removed.
593         :type node: dict
594         :type interface: str
595         :type param: str
596         :type value: str
597         :returns: Content of response.
598         :rtype: bytearray
599         :raises HoneycombError: If the parameter is not valid.
600         """
601
602         if param in InterfaceKeywords.IPV6_PARAMS:
603             path = ("interfaces", ("interface", "name", interface),
604                     "ietf-ip:ipv6", param)
605         elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
606             path = ("interfaces", ("interface", "name", interface),
607                     "ietf-ip:ipv6", "autoconf", param)
608         else:
609             raise HoneycombError("The parameter {0} is invalid.".format(param))
610
611         return InterfaceKeywords._set_interface_properties(
612             node, interface, path, value)
613
614     @staticmethod
615     def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
616         """Add the first IPv6 address.
617
618         If there are any other addresses configured, they will be removed.
619
620         :param node: Honeycomb node.
621         :param interface: The name of interface.
622         :param ip_addr: IPv6 address to be set.
623         :param prefix_len: Prefix length.
624         :type node: dict
625         :type interface: str
626         :type ip_addr: str
627         :type prefix_len: str
628         :returns: Content of response.
629         :rtype: bytearray
630         """
631
632         interface = Topology.convert_interface_reference(
633             node, interface, "name")
634
635         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
636         address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
637         return InterfaceKeywords._set_interface_properties(
638             node, interface, path, address)
639
640     @staticmethod
641     def add_ipv6_address(node, interface, ip_addr, prefix_len):
642         """Add IPv6 address.
643
644         :param node: Honeycomb node.
645         :param interface: The name of interface.
646         :param ip_addr: IPv6 address to be set.
647         :param prefix_len: Prefix length.
648         :type node: dict
649         :type interface: str
650         :type ip_addr: str
651         :type prefix_len: str
652         :returns: Content of response.
653         :rtype: bytearray
654         """
655
656         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
657                 "address")
658         address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
659         return InterfaceKeywords._set_interface_properties(
660             node, interface, path, address)
661
662     @staticmethod
663     def remove_all_ipv6_addresses(node, interface):
664         """Remove all IPv6 addresses from interface.
665
666         :param node: Honeycomb node.
667         :param interface: The name of interface.
668         :type node: dict
669         :type interface: str
670         :returns: Content of response.
671         :rtype: bytearray
672         """
673
674         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
675                 "address")
676         return InterfaceKeywords._set_interface_properties(
677             node, interface, path, None)
678
679     @staticmethod
680     def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
681         """Add the IPv6 neighbour.
682
683         :param node: Honeycomb node.
684         :param interface: The name of interface.
685         :param ip_addr: IPv6 address of neighbour to be set.
686         :param link_layer_address: Link layer address.
687         :type node: dict
688         :type interface: str
689         :type ip_addr: str
690         :type link_layer_address: str
691         :returns: Content of response.
692         :rtype: bytearray
693         """
694
695         interface = Topology.convert_interface_reference(
696             node, interface, "name")
697
698         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
699                 "neighbor")
700         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
701         return InterfaceKeywords._set_interface_properties(
702             node, interface, path, neighbor)
703
704     @staticmethod
705     def remove_all_ipv6_neighbors(node, interface):
706         """Remove all IPv6 neighbours.
707
708         :param node: Honeycomb node.
709         :param interface: The name of interface.
710         :type node: dict
711         :type interface: str
712         :returns: Content of response.
713         :rtype: bytearray
714         """
715
716         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
717                 "neighbor")
718         return InterfaceKeywords._set_interface_properties(
719             node, interface, path, None)
720
721     @staticmethod
722     def configure_interface_ethernet(node, interface, param, value):
723         """Configure the ethernet parameters of interface.
724
725         :param node: Honeycomb node.
726         :param interface: The name of interface.
727         :param param: Parameter to configure (set, change, remove)
728         :param value: The value of parameter. If None, the parameter will be
729         removed.
730         :type node: dict
731         :type interface: str
732         :type param: str
733         :type value: str
734         :returns: Content of response.
735         :rtype: bytearray
736         :raises HoneycombError: If the parameter is not valid.
737         """
738
739         if param not in InterfaceKeywords.ETH_PARAMS:
740             raise HoneycombError("The parameter {0} is invalid.".format(param))
741         path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
742                 param)
743         return InterfaceKeywords._set_interface_properties(
744             node, interface, path, value)
745
746     @staticmethod
747     def configure_interface_routing(node, interface, param, value):
748         """Configure the routing parameters of interface.
749
750         :param node: Honeycomb node.
751         :param interface: The name of interface.
752         :param param: Parameter to configure (set, change, remove)
753         :param value: The value of parameter. If None, the parameter will be
754         removed.
755         :type node: dict
756         :type interface: str
757         :type param: str
758         :type value: str
759         :returns: Content of response.
760         :rtype: bytearray
761         :raises HoneycombError: If the parameter is not valid.
762         """
763
764         interface = Topology.convert_interface_reference(
765             node, interface, "name")
766
767         if param not in InterfaceKeywords.ROUTING_PARAMS:
768             raise HoneycombError("The parameter {0} is invalid.".format(param))
769
770         path = ("interfaces", ("interface", "name", interface), "v3po:routing",
771                 param)
772         return InterfaceKeywords._set_interface_properties(
773             node, interface, path, value)
774
775     @staticmethod
776     def create_vxlan_interface(node, interface, **kwargs):
777         """Create a new VxLAN interface.
778
779         :param node: Honeycomb node.
780         :param interface: The name of interface.
781         :param kwargs: Parameters and their values. The accepted parameters are
782         defined in InterfaceKeywords.VXLAN_PARAMS.
783         :type node: dict
784         :type interface: str
785         :type kwargs: dict
786         :returns: Content of response.
787         :rtype: bytearray
788         :raises HoneycombError: If the parameter is not valid.
789         """
790
791         new_vx_lan = {
792             "name": interface,
793             "type": "v3po:vxlan-tunnel",
794             "v3po:vxlan": {}
795         }
796         for param, value in kwargs.items():
797             if param not in InterfaceKeywords.VXLAN_PARAMS:
798                 raise HoneycombError("The parameter {0} is invalid.".
799                                      format(param))
800             new_vx_lan["v3po:vxlan"][param] = value
801
802         path = ("interfaces", "interface")
803         vx_lan_structure = [new_vx_lan, ]
804         return InterfaceKeywords._set_interface_properties(
805             node, interface, path, vx_lan_structure)
806
807     @staticmethod
808     def delete_interface(node, interface):
809         """Delete an interface.
810
811         :param node: Honeycomb node.
812         :param interface: The name of interface.
813         :type node: dict
814         :type interface: str
815         :returns: Content of response.
816         :rtype: bytearray
817         :raises HoneycombError: If it is not possible to get information about
818         interfaces or it is not possible to delete the interface.
819         """
820
821         path = ("interfaces", ("interface", "name", interface))
822
823         status_code, resp = HcUtil.\
824             get_honeycomb_data(node, "config_vpp_interfaces")
825         if status_code != HTTPCodes.OK:
826             raise HoneycombError(
827                 "Not possible to get configuration information about the "
828                 "interfaces. Status code: {0}.".format(status_code))
829
830         new_data = HcUtil.remove_item(resp, path)
831         status_code, resp = HcUtil.\
832             put_honeycomb_data(node, "config_vpp_interfaces", new_data)
833         if status_code != HTTPCodes.OK:
834             raise HoneycombError("Not possible to remove interface {0}. "
835                                  "Status code: {1}.".
836                                  format(interface, status_code))
837         return resp
838
839     @staticmethod
840     def configure_interface_vxlan(node, interface, **kwargs):
841         """Configure VxLAN on the interface.
842
843         The keyword configures VxLAN parameters on the given interface. The type
844         of interface must be set to "v3po:vxlan-tunnel".
845         The new VxLAN parameters overwrite the current configuration. If a
846         parameter in new configuration is missing, it is removed from VxLAN
847         configuration.
848         If the dictionary kwargs is empty, VxLAN configuration is removed.
849
850         :param node: Honeycomb node.
851         :param interface: The name of interface.
852         :param kwargs: Parameters and their values. The accepted parameters are
853         defined in InterfaceKeywords.VXLAN_PARAMS.
854         :type node: dict
855         :type interface: str
856         :type kwargs: dict
857         :returns: Content of response.
858         :rtype: bytearray
859         :raises HoneycombError: If the parameter is not valid.
860         """
861
862         vx_lan_structure = dict()
863         for param, value in kwargs.items():
864             if param not in InterfaceKeywords.VXLAN_PARAMS:
865                 raise HoneycombError("The parameter {0} is invalid.".
866                                      format(param))
867             vx_lan_structure[param] = value
868
869         path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
870         return InterfaceKeywords._set_interface_properties(
871             node, interface, path, vx_lan_structure)
872
873     @staticmethod
874     def configure_interface_l2(node, interface, param, value):
875         """Configure the L2 parameters of interface.
876
877         :param node: Honeycomb node.
878         :param interface: The name of interface.
879         :param param: Parameter to configure (set, change, remove)
880         :param value: The value of parameter. If None, the parameter will be
881         removed.
882         :type node: dict
883         :type interface: str
884         :type param: str
885         :type value: str
886         :returns: Content of response.
887         :rtype: bytearray
888         :raises HoneycombError: If the parameter is not valid.
889         """
890
891         if param not in InterfaceKeywords.L2_PARAMS:
892             raise HoneycombError("The parameter {0} is invalid.".format(param))
893         path = ("interfaces", ("interface", "name", interface), "v3po:l2",
894                 param)
895         return InterfaceKeywords._set_interface_properties(
896             node, interface, path, value)
897
898     @staticmethod
899     def create_tap_interface(node, interface, **kwargs):
900         """Create a new TAP interface.
901
902         :param node: Honeycomb node.
903         :param interface: The name of interface.
904         :param kwargs: Parameters and their values. The accepted parameters are
905         defined in InterfaceKeywords.TAP_PARAMS.
906         :type node: dict
907         :type interface: str
908         :type kwargs: dict
909         :returns: Content of response.
910         :rtype: bytearray
911         :raises HoneycombError: If the parameter is not valid.
912         """
913
914         new_tap = {
915             "name": interface,
916             "type": "v3po:tap",
917             "v3po:tap": {}
918         }
919         for param, value in kwargs.items():
920             if param not in InterfaceKeywords.TAP_PARAMS:
921                 raise HoneycombError("The parameter {0} is invalid.".
922                                      format(param))
923             new_tap["v3po:tap"][param] = value
924
925         path = ("interfaces", "interface")
926         new_tap_structure = [new_tap, ]
927         return InterfaceKeywords._set_interface_properties(
928             node, interface, path, new_tap_structure)
929
930     @staticmethod
931     def configure_interface_tap(node, interface, **kwargs):
932         """Configure TAP on the interface.
933
934         The keyword configures TAP parameters on the given interface. The type
935         of interface must be set to "v3po:tap".
936         The new TAP parameters overwrite the current configuration. If a
937         parameter in new configuration is missing, it is removed from TAP
938         configuration.
939         If the dictionary kwargs is empty, TAP configuration is removed.
940
941         :param node: Honeycomb node.
942         :param interface: The name of interface.
943         :param kwargs: Parameters and their values. The accepted parameters are
944         defined in InterfaceKeywords.TAP_PARAMS.
945         :type node: dict
946         :type interface: str
947         :type kwargs: dict
948         :returns: Content of response.
949         :rtype: bytearray
950         :raises HoneycombError: If the parameter is not valid.
951         """
952
953         tap_structure = dict()
954         for param, value in kwargs.items():
955             if param not in InterfaceKeywords.TAP_PARAMS:
956                 raise HoneycombError("The parameter {0} is invalid.".
957                                      format(param))
958             tap_structure[param] = value
959
960         path = ("interfaces", ("interface", "name", interface), "v3po:tap")
961         return InterfaceKeywords._set_interface_properties(
962             node, interface, path, tap_structure)
963
964     @staticmethod
965     def configure_interface_vhost_user(node, interface, **kwargs):
966         """Configure vhost-user on the interface.
967
968         The keyword configures vhost-user parameters on the given interface.
969         The type of interface must be set to "v3po:vhost-user".
970         The new vhost-user parameters overwrite the current configuration. If a
971         parameter in new configuration is missing, it is removed from vhost-user
972         configuration.
973         If the dictionary kwargs is empty, vhost-user configuration is removed.
974
975         :param node: Honeycomb node.
976         :param interface: The name of interface.
977         :param kwargs: Parameters and their values. The accepted parameters are
978         defined in InterfaceKeywords.VHOST_USER_PARAMS.
979         :type node: dict
980         :type interface: str
981         :type kwargs: dict
982         :returns: Content of response.
983         :rtype: bytearray
984         :raises HoneycombError: If the parameter is not valid.
985         """
986
987         vhost_structure = dict()
988         for param, value in kwargs.items():
989             if param not in InterfaceKeywords.VHOST_USER_PARAMS:
990                 raise HoneycombError("The parameter {0} is invalid.".
991                                      format(param))
992             vhost_structure[param] = value
993
994         path = ("interfaces", ("interface", "name", interface),
995                 "v3po:vhost-user")
996         return InterfaceKeywords._set_interface_properties(
997             node, interface, path, vhost_structure)
998
999     @staticmethod
1000     def create_vhost_user_interface(node, interface, **kwargs):
1001         """Create a new vhost-user interface.
1002
1003         :param node: Honeycomb node.
1004         :param interface: The name of interface.
1005         :param kwargs: Parameters and their values. The accepted parameters are
1006         defined in InterfaceKeywords.VHOST_USER_PARAMS.
1007         :type node: dict
1008         :type interface: str
1009         :type kwargs: dict
1010         :returns: Content of response.
1011         :rtype: bytearray
1012         :raises HoneycombError: If the parameter is not valid.
1013         """
1014
1015         new_vhost = {
1016             "name": interface,
1017             "type": "v3po:vhost-user",
1018             "v3po:vhost-user": {}
1019         }
1020         for param, value in kwargs.items():
1021             if param not in InterfaceKeywords.VHOST_USER_PARAMS:
1022                 raise HoneycombError("The parameter {0} is invalid.".
1023                                      format(param))
1024             new_vhost["v3po:vhost-user"][param] = value
1025
1026         path = ("interfaces", "interface")
1027         new_vhost_structure = [new_vhost, ]
1028         return InterfaceKeywords._set_interface_properties(
1029             node, interface, path, new_vhost_structure)
1030
1031     @staticmethod
1032     def create_sub_interface(node, super_interface, match, tags=None, **kwargs):
1033         """Create a new sub-interface.
1034
1035         :param node: Honeycomb node.
1036         :param super_interface: Super interface.
1037         :param match: Match type. The valid values are defined in
1038         InterfaceKeywords.SUB_IF_MATCH.
1039         :param tags: List of tags.
1040         :param kwargs: Parameters and their values. The accepted parameters are
1041         defined in InterfaceKeywords.SUB_IF_PARAMS.
1042         :type node: dict
1043         :type super_interface: str
1044         :type match: str
1045         :type tags: list
1046         :type kwargs: dict
1047         :returns: Content of response.
1048         :rtype: bytearray
1049         :raises HoneycombError: If the parameter is not valid.
1050         :raises KeyError: If the parameter 'match' is invalid.
1051         """
1052
1053         match_type = {
1054             "default":
1055                 {"default": {}},
1056             "untagged":
1057                 {"untagged": {}},
1058             "vlan-tagged":
1059                 {"vlan-tagged": {"match-exact-tags": "false"}},
1060             "vlan-tagged-exact-match":
1061                 {"vlan-tagged": {"match-exact-tags": "true"}}
1062         }
1063
1064         new_sub_interface = {
1065             "tags": {
1066                 "tag": []
1067             },
1068         }
1069
1070         for param, value in kwargs.items():
1071             if param in InterfaceKeywords.SUB_IF_PARAMS:
1072                 new_sub_interface[param] = value
1073             else:
1074                 raise HoneycombError("The parameter {0} is invalid.".
1075                                      format(param))
1076         try:
1077             new_sub_interface["match"] = match_type[match]
1078         except KeyError:
1079             raise HoneycombError("The value '{0}' of parameter 'match' is "
1080                                  "invalid.".format(match))
1081
1082         if tags:
1083             new_sub_interface["tags"]["tag"].extend(tags)
1084
1085         path = ("interfaces",
1086                 ("interface", "name", super_interface),
1087                 "vpp-vlan:sub-interfaces",
1088                 "sub-interface")
1089         new_sub_interface_structure = [new_sub_interface, ]
1090         return InterfaceKeywords._set_interface_properties(
1091             node, super_interface, path, new_sub_interface_structure)
1092
1093     @staticmethod
1094     def get_sub_interface_oper_data(node, super_interface, identifier):
1095         """Retrieves sub-interface operational data using Honeycomb API.
1096
1097         :param node: Honeycomb node.
1098         :param super_interface: Super interface.
1099         :param identifier: The ID of sub-interface.
1100         :type node: dict
1101         :type super_interface: str
1102         :type identifier: int
1103         :returns: Sub-interface operational data.
1104         :rtype: dict
1105         :raises HoneycombError: If there is no sub-interface with the given ID.
1106         """
1107
1108         if_data = InterfaceKeywords.get_interface_oper_data(node,
1109                                                             super_interface)
1110         for sub_if in if_data["vpp-vlan:sub-interfaces"]["sub-interface"]:
1111             if str(sub_if["identifier"]) == str(identifier):
1112                 return sub_if
1113
1114         raise HoneycombError("The interface {0} does not have sub-interface "
1115                              "with ID {1}".format(super_interface, identifier))
1116
1117     @staticmethod
1118     def remove_all_sub_interfaces(node, super_interface):
1119         """Remove all sub-interfaces from the given interface.
1120
1121         :param node: Honeycomb node.
1122         :param super_interface: Super interface.
1123         :type node: dict
1124         :type super_interface: str
1125         :returns: Content of response.
1126         :rtype: bytearray
1127         """
1128
1129         path = ("interfaces",
1130                 ("interface", "name", super_interface),
1131                 "vpp-vlan:sub-interfaces")
1132
1133         return InterfaceKeywords._set_interface_properties(
1134             node, super_interface, path, {})
1135
1136     @staticmethod
1137     def set_sub_interface_state(node, super_interface, identifier, state):
1138         """Set the administrative state of sub-interface.
1139
1140         :param node: Honeycomb node.
1141         :param super_interface: Super interface.
1142         :param identifier: The ID of sub-interface.
1143         :param state: Required sub-interface state - up or down.
1144         :type node: dict
1145         :type super_interface: str
1146         :type identifier: int
1147         :type state: str
1148         :returns: Content of response.
1149         :rtype: bytearray
1150         """
1151
1152         intf_state = {"up": "true",
1153                       "down": "false"}
1154
1155         path = ("interfaces",
1156                 ("interface", "name", super_interface),
1157                 "vpp-vlan:sub-interfaces",
1158                 ("sub-interface", "identifier", int(identifier)),
1159                 "enabled")
1160
1161         return InterfaceKeywords._set_interface_properties(
1162             node, super_interface, path, intf_state[state])
1163
1164     @staticmethod
1165     def add_bridge_domain_to_sub_interface(node, super_interface, identifier,
1166                                            config):
1167         """Add a sub-interface to a bridge domain and set its parameters.
1168
1169         :param node: Honeycomb node.
1170         :param super_interface: Super interface.
1171         :param identifier: The ID of sub-interface.
1172         :param config: Bridge domain configuration.
1173         :type node: dict
1174         :type super_interface: str
1175         :type identifier: int
1176         :type config: dict
1177         :returns: Content of response.
1178         :rtype: bytearray
1179         """
1180
1181         path = ("interfaces",
1182                 ("interface", "name", super_interface),
1183                 "vpp-vlan:sub-interfaces",
1184                 ("sub-interface", "identifier", int(identifier)),
1185                 "l2")
1186
1187         return InterfaceKeywords._set_interface_properties(
1188             node, super_interface, path, config)
1189
1190     @staticmethod
1191     def get_bd_data_from_sub_interface(node, super_interface, identifier):
1192         """Get the operational data about the bridge domain from sub-interface.
1193
1194         :param node: Honeycomb node.
1195         :param super_interface: Super interface.
1196         :param identifier: The ID of sub-interface.
1197         :type node: dict
1198         :type super_interface: str
1199         :type identifier: int
1200         :returns: Operational data about the bridge domain.
1201         :rtype: dict
1202         :raises HoneycombError: If there is no sub-interface with the given ID.
1203         """
1204
1205         try:
1206             bd_data = InterfaceKeywords.get_sub_interface_oper_data(
1207                 node, super_interface, identifier)["l2"]
1208             return bd_data
1209         except KeyError:
1210             raise HoneycombError("The operational data does not contain "
1211                                  "information about a bridge domain.")
1212
1213     @staticmethod
1214     def configure_tag_rewrite(node, super_interface, identifier, config):
1215         """Add / change / disable vlan tag rewrite on a sub-interface.
1216
1217         :param node: Honeycomb node.
1218         :param super_interface: Super interface.
1219         :param identifier: The ID of sub-interface.
1220         :param config: Rewrite tag configuration.
1221         :type node: dict
1222         :type super_interface: str
1223         :type identifier: int
1224         :type config: dict
1225         :returns: Content of response.
1226         :rtype: bytearray
1227         """
1228
1229         path = ("interfaces",
1230                 ("interface", "name", super_interface),
1231                 "vpp-vlan:sub-interfaces",
1232                 ("sub-interface", "identifier", int(identifier)),
1233                 "l2",
1234                 "rewrite")
1235
1236         return InterfaceKeywords._set_interface_properties(
1237             node, super_interface, path, config)
1238
1239     @staticmethod
1240     def get_tag_rewrite_oper_data(node, super_interface, identifier):
1241         """Get the operational data about tag rewrite.
1242
1243         :param node: Honeycomb node.
1244         :param super_interface: Super interface.
1245         :param identifier: The ID of sub-interface.
1246         :type node: dict
1247         :type super_interface: str
1248         :type identifier: int
1249         :returns: Operational data about tag rewrite.
1250         :rtype: dict
1251         :raises HoneycombError: If there is no sub-interface with the given ID.
1252         """
1253
1254         try:
1255             tag_rewrite = InterfaceKeywords.get_sub_interface_oper_data(
1256                 node, super_interface, identifier)["l2"]["rewrite"]
1257             return tag_rewrite
1258         except KeyError:
1259             raise HoneycombError("The operational data does not contain "
1260                                  "information about the tag-rewrite.")
1261
1262     @staticmethod
1263     def add_ip_address_to_sub_interface(node, super_interface, identifier,
1264                                         ip_addr, network, ip_version):
1265         """Add an ipv4 address to the specified sub-interface, with the provided
1266         netmask or network prefix length. Any existing ipv4 addresses on the
1267         sub-interface will be replaced.
1268
1269         :param node: Honeycomb node.
1270         :param super_interface: Super interface.
1271         :param identifier: The ID of sub-interface.
1272         :param ip_addr: IPv4 address to be set.
1273         :param network: Network mask or network prefix length.
1274         :param ip_version: ipv4 or ipv6
1275         :type node: dict
1276         :type super_interface: str
1277         :type identifier: int
1278         :type ip_addr: str
1279         :type network: str or int
1280         :type ip_version: string
1281         :returns: Content of response.
1282         :rtype: bytearray
1283         :raises HoneycombError: If the provided netmask or prefix is not valid.
1284         """
1285
1286         path = ("interfaces",
1287                 ("interface", "name", super_interface),
1288                 "vpp-vlan:sub-interfaces",
1289                 ("sub-interface", "identifier", int(identifier)),
1290                 ip_version.lower())
1291
1292         if isinstance(network, basestring) and ip_version.lower() == "ipv4":
1293             address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
1294
1295         elif isinstance(network, int) and 0 < network < 33:
1296             address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
1297
1298         else:
1299             raise HoneycombError("{0} is not a valid netmask or prefix length."
1300                                  .format(network))
1301
1302         return InterfaceKeywords._set_interface_properties(
1303             node, super_interface, path, address)
1304
1305     @staticmethod
1306     def remove_all_ip_addresses_from_sub_interface(node, super_interface,
1307                                                    identifier, ip_version):
1308         """Remove all ipv4 addresses from the specified sub-interface.
1309
1310         :param node: Honeycomb node.
1311         :param super_interface: Super interface.
1312         :param identifier: The ID of sub-interface.
1313         :param ip_version: ipv4 or ipv6
1314         :type node: dict
1315         :type super_interface: str
1316         :type identifier: int
1317         :type ip_version: string
1318         :returns: Content of response.
1319         :rtype: bytearray
1320         """
1321
1322         path = ("interfaces",
1323                 ("interface", "name", super_interface),
1324                 "vpp-vlan:sub-interfaces",
1325                 ("sub-interface", "identifier", int(identifier)),
1326                 str(ip_version), "address")
1327
1328         return InterfaceKeywords._set_interface_properties(
1329             node, super_interface, path, None)
1330
1331     @staticmethod
1332     def compare_data_structures(data, ref, _path=''):
1333         """Checks if data obtained from UUT is as expected. If it is not,
1334         proceeds down the list/dictionary tree and finds the point of mismatch.
1335
1336         :param data: Data to be checked.
1337         :param ref: Referential data used for comparison.
1338         :param _path: Used in recursive calls, stores the path taken down
1339         the JSON tree.
1340         :type data: dict
1341         :type ref: dict
1342         :type _path: str
1343
1344         :raises HoneycombError: If the data structures do not match in some way,
1345         or if they are not in deserialized JSON format.
1346         """
1347
1348         if data == ref:
1349             return True
1350
1351         elif isinstance(data, dict) and isinstance(ref, dict):
1352             for key in ref:
1353                 if key not in data:
1354                     raise HoneycombError(
1355                         "Key {key} is not present in path {path}. Keys in path:"
1356                         "{data_keys}".format(
1357                             key=key,
1358                             path=_path,
1359                             data_keys=data.keys()))
1360
1361                 if data[key] != ref[key]:
1362                     if isinstance(data[key], list) \
1363                             or isinstance(data[key], dict):
1364                         InterfaceKeywords.compare_data_structures(
1365                             data[key], ref[key],
1366                             _path + '[{0}]'.format(key))
1367                     else:
1368                         raise HoneycombError(
1369                             "Data mismatch, key {key} in path {path} has value"
1370                             " {data}, but should be {ref}".format(
1371                                 key=key,
1372                                 path=_path,
1373                                 data=data[key],
1374                                 ref=ref[key]))
1375
1376         elif isinstance(data, list) and isinstance(ref, list):
1377             for item in ref:
1378                 if item not in data:
1379                     if isinstance(item, dict):
1380                         InterfaceKeywords.compare_data_structures(
1381                             data[0], item,
1382                             _path + '[{0}]'.format(ref.index(item)))
1383                     else:
1384                         raise HoneycombError(
1385                             "Data mismatch, list item {index} in path {path}"
1386                             " has value {data}, but should be {ref}".format(
1387                                 index=ref.index(item),
1388                                 path=_path,
1389                                 data=data[0],
1390                                 ref=item))
1391
1392         else:
1393             raise HoneycombError(
1394                 "Unexpected data type {data_type} in path {path}, reference"
1395                 " type is {ref_type}. Must be list or dictionary.".format(
1396                     data_type=type(data),
1397                     ref_type=type(ref),
1398                     path=_path))
1399
1400     @staticmethod
1401     def compare_interface_lists(list1, list2):
1402         """Compare provided lists of interfaces by name.
1403
1404         :param list1: List of interfaces.
1405         :param list2: List of interfaces.
1406         :type list1: list
1407         :type list2: list
1408         :raises HoneycombError: If an interface exists in only one of the lists.
1409         """
1410
1411         ignore = ["vx_tunnel0", "vxlan_gpe_tunnel0"]
1412         # these have no equivalent in config data and no effect on VPP
1413
1414         names1 = [x['name'] for x in list1]
1415         names2 = [x['name'] for x in list2]
1416
1417         for name in names1:
1418             if name not in names2 and name not in ignore:
1419                 raise HoneycombError("Interface {0} not present in list {1}"
1420                                      .format(name, list2))
1421         for name in names2:
1422             if name not in names1 and name not in ignore:
1423                 raise HoneycombError("Interface {0} not present in list {1}"
1424                                      .format(name, list1))
1425
1426     @staticmethod
1427     def create_vxlan_gpe_interface(node, interface, **kwargs):
1428         """Create a new VxLAN GPE interface.
1429
1430         :param node: Honeycomb node.
1431         :param interface: The name of interface to be created.
1432         :param kwargs: Parameters and their values. The accepted parameters are
1433         defined in InterfaceKeywords.VXLAN_GPE_PARAMS.
1434         :type node: dict
1435         :type interface: str
1436         :type kwargs: dict
1437         :returns: Content of response.
1438         :rtype: bytearray
1439         :raises HoneycombError: If a parameter in kwargs is not valid.
1440         """
1441
1442         new_vxlan_gpe = {
1443             "name": interface,
1444             "type": "v3po:vxlan-gpe-tunnel",
1445             "v3po:vxlan-gpe": {}
1446         }
1447         for param, value in kwargs.items():
1448             if param in InterfaceKeywords.INTF_PARAMS:
1449                 new_vxlan_gpe[param] = value
1450             elif param in InterfaceKeywords.VXLAN_GPE_PARAMS:
1451                 new_vxlan_gpe["v3po:vxlan-gpe"][param] = value
1452             else:
1453                 raise HoneycombError("The parameter {0} is invalid.".
1454                                      format(param))
1455         path = ("interfaces", "interface")
1456         vxlan_gpe_structure = [new_vxlan_gpe, ]
1457         return InterfaceKeywords._set_interface_properties(
1458             node, interface, path, vxlan_gpe_structure)
1459
1460     @staticmethod
1461     def enable_acl_on_interface(node, interface, table_name):
1462         """Enable ACL on the given interface.
1463
1464         :param node: Honeycomb node.
1465         :param interface: The interface where the ACL will be enabled.
1466         :param table_name: Name of the classify table.
1467         :type node: dict
1468         :type interface: str
1469         :type table_name: str
1470         :returns: Content of response.
1471         :rtype: bytearray
1472         :raises HoneycombError: If the configuration of interface is not
1473         successful.
1474         """
1475
1476         interface = interface.replace("/", "%2F")
1477
1478         data = {
1479             "v3po:acl": {
1480                 "ingress": {
1481                     "ip4-acl": {
1482                         "classify-table": table_name
1483                     },
1484                     "l2-acl": {
1485                         "classify-table": table_name
1486                     }
1487                 }
1488             }
1489         }
1490
1491         path = "/interface/" + interface + "/v3po:acl"
1492         status_code, resp = HcUtil.\
1493             put_honeycomb_data(node, "config_vpp_interfaces", data, path,
1494                                data_representation=DataRepresentation.JSON)
1495         if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1496             raise HoneycombError(
1497                 "The configuration of interface '{0}' was not successful. "
1498                 "Status code: {1}.".format(interface, status_code))
1499         return resp
1500
1501     @staticmethod
1502     def disable_acl_on_interface(node, interface):
1503         """Disable ACL on the given interface.
1504
1505         :param node: Honeycomb node.
1506         :param interface: The interface where the ACL will be disabled.
1507         :type node: dict
1508         :type interface: str
1509         :returns: Content of response.
1510         :rtype: bytearray
1511         :raises HoneycombError: If the configuration of interface is not
1512         successful.
1513         """
1514
1515         interface = interface.replace("/", "%2F")
1516
1517         path = "/interface/" + interface + "/v3po:acl"
1518
1519         status_code, resp = HcUtil.\
1520             delete_honeycomb_data(node, "config_vpp_interfaces", path)
1521
1522         if status_code != HTTPCodes.OK:
1523             raise HoneycombError(
1524                 "The configuration of interface '{0}' was not successful. "
1525                 "Status code: {1}.".format(interface, status_code))
1526         return resp
1527
1528     @staticmethod
1529     def create_pbb_sub_interface(node, intf, params):
1530         """Creates a PBB sub-interface on the given interface and sets its
1531         parameters.
1532
1533         :param node: Honeycomb node.
1534         :param intf: The interface where PBB sub-interface will be configured.
1535         :param params: Configuration parameters of the sub-interface to be
1536         created.
1537         :type node: dict
1538         :type intf: str
1539         :type params: dict
1540         :returns: Content of response.
1541         :rtype: bytearray
1542         :raises HoneycombError: If the configuration of sub-interface is not
1543         successful.
1544         """
1545
1546         interface = intf.replace("/", "%2F")
1547         path = "/interface/{0}/pbb-rewrite/".format(interface)
1548         status_code, resp = HcUtil. \
1549             put_honeycomb_data(node, "config_vpp_interfaces", params, path,
1550                                data_representation=DataRepresentation.JSON)
1551         if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1552             raise HoneycombError(
1553                 "The configuration of PBB sub-interface '{0}' was not "
1554                 "successful. Status code: {1}.".format(intf, status_code))
1555         return resp
1556
1557     @staticmethod
1558     def delete_pbb_sub_interface(node, intf):
1559         """Deletes the given PBB sub-interface.
1560
1561         :param node: Honeycomb node.
1562         :param intf: The interface where PBB sub-interface will be deleted.
1563         :type node: dict
1564         :type intf: str
1565         :returns: Content of response.
1566         :rtype: bytearray
1567         :raises HoneycombError: If the removal of sub-interface is not
1568         successful.
1569         """
1570
1571         interface = intf.replace("/", "%2F")
1572         path = "/interface/{0}/pbb-rewrite".format(interface)
1573
1574         status_code, resp = HcUtil. \
1575             delete_honeycomb_data(node, "config_vpp_interfaces", path)
1576         if status_code != HTTPCodes.OK:
1577             raise HoneycombError(
1578                 "The removal of pbb sub-interface '{0}' was not successful. "
1579                 "Status code: {1}.".format(intf, status_code))
1580         return resp
1581
1582     @staticmethod
1583     def get_pbb_sub_interface_oper_data(node, intf, sub_if_id):
1584         """Retrieves PBB sub-interface operational data from Honeycomb.
1585
1586         :param node: Honeycomb node.
1587         :param intf: The interface where PBB sub-interface is located.
1588         :param sub_if_id: ID of the PBB sub-interface.
1589         :type node: dict
1590         :type intf: str
1591         :type sub_if_id: str or int
1592         :returns: PBB sub-interface operational data.
1593         :rtype: dict
1594         :raises HoneycombError: If the removal of sub-interface is not
1595         successful.
1596         """
1597
1598         raise NotImplementedError
1599
1600     @staticmethod
1601     def check_disabled_interface(node, interface):
1602         """Retrieves list of disabled interface indices from Honeycomb,
1603         and matches with the provided interface by index.
1604
1605         :param node: Honeycomb node.
1606         :param interface: Index number of an interface on the node.
1607         :type node: dict
1608         :type interface: int
1609         :returns: True if the interface exists in disabled interfaces.
1610         :rtype: bool
1611         :raises HoneycombError: If the interface is not present
1612          in retrieved list of disabled interfaces.
1613          """
1614         data = InterfaceKeywords.get_disabled_interfaces_oper_data(node)
1615         # decrement by one = conversion from HC if-index to VPP sw_if_index
1616         interface -= 1
1617
1618         for item in data:
1619             if item["index"] == interface:
1620                 return True
1621         raise HoneycombError("Interface index {0} not present in list"
1622                              " of disabled interfaces.".format(interface))
1623
1624     @staticmethod
1625     def configure_interface_span(node, dst_interface, *src_interfaces):
1626         """Configure SPAN port mirroring on the specified interfaces. If no
1627          source interface is provided, SPAN will be disabled.
1628
1629         :param node: Honeycomb node.
1630         :param dst_interface: Interface to mirror packets to.
1631         :param src_interfaces: List of interfaces to mirror packets from.
1632         :type node: dict
1633         :type dst_interface: str
1634         :type src_interfaces: list of str
1635         :returns: Content of response.
1636         :rtype: bytearray
1637         :raises HoneycombError: If SPAN could not be configured.
1638         """
1639
1640         interface = dst_interface.replace("/", "%2F")
1641         path = "/interface/" + interface + "/span"
1642
1643         if not src_interfaces:
1644             status_code, _ = HcUtil.delete_honeycomb_data(
1645                 node, "config_vpp_interfaces", path)
1646
1647         data = {
1648             "span": {
1649                 "mirrored-interfaces": {
1650                     "mirrored-interface": src_interfaces
1651                 }
1652             }
1653         }
1654
1655         status_code, _ = HcUtil.put_honeycomb_data(
1656             node, "config_vpp_interfaces", data, path)
1657
1658         if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
1659             raise HoneycombError(
1660                 "Configuring SPAN failed. Status code:{0}".format(status_code))
1661
1662     @staticmethod
1663     def add_interface_local0_to_topology(node):
1664         """Use Topology methods to add interface "local0" to working topology,
1665         if not already present.
1666
1667         :param node: DUT node.
1668         :type node: dict
1669         """
1670
1671         if Topology.get_interface_by_sw_index(node, 0) is None:
1672             local0_key = Topology.add_new_port(node, "localzero")
1673             Topology.update_interface_sw_if_index(node, local0_key, 0)
1674             Topology.update_interface_name(node, local0_key, "local0")