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