Add tests for Honeycomb L2 FIB support
[csit.git] / resources / libraries / python / honeycomb / HcAPIKwInterfaces.py
1 # Copyright (c) 2016 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """Keywords to manipulate interface configuration using Honeycomb REST API.
15
16 The keywords make possible to put and get configuration data and to get
17 operational data.
18 """
19
20 from resources.libraries.python.HTTPRequest import HTTPCodes
21 from resources.libraries.python.honeycomb.HoneycombSetup import HoneycombError
22 from resources.libraries.python.honeycomb.HoneycombUtil \
23     import DataRepresentation
24 from resources.libraries.python.honeycomb.HoneycombUtil \
25     import HoneycombUtil as HcUtil
26
27
28 # pylint: disable=too-many-public-methods
29 # pylint: disable=too-many-lines
30 class InterfaceKeywords(object):
31     """Keywords for Interface manipulation.
32
33     Implements keywords which get configuration and operational data about
34     vpp interfaces and set the interface's parameters using Honeycomb REST API.
35     """
36
37     INTF_PARAMS = ("name", "description", "type", "enabled",
38                    "link-up-down-trap-enable", "v3po:l2", "v3po:vxlan-gpe",
39                    "vpp-vlan:sub-interfaces")
40     IPV4_PARAMS = ("enabled", "forwarding", "mtu")
41     IPV6_PARAMS = ("enabled", "forwarding", "mtu", "dup-addr-detect-transmits")
42     IPV6_AUTOCONF_PARAMS = ("create-global-addresses",
43                             "create-temporary-addresses",
44                             "temporary-valid-lifetime",
45                             "temporary-preferred-lifetime")
46     ETH_PARAMS = ("mtu", )
47     ROUTING_PARAMS = ("vrf-id", )
48     VXLAN_PARAMS = ("src", "dst", "vni", "encap-vrf-id")
49     L2_PARAMS = ("bridge-domain", "split-horizon-group",
50                  "bridged-virtual-interface")
51     TAP_PARAMS = ("tap-name", "mac", "device-instance")
52     VHOST_USER_PARAMS = ("socket", "role")
53     SUB_IF_PARAMS = ("identifier",
54                      "vlan-type",
55                      "enabled")
56     SUB_IF_MATCH = ("default",
57                     "untagged",
58                     "vlan-tagged",
59                     "vlan-tagged-exact-match")
60     BD_PARAMS = ("bridge-domain",
61                  "split-horizon-group",
62                  "bridged-virtual-interface")
63     VXLAN_GPE_PARAMS = ("local",
64                         "remote",
65                         "vni",
66                         "next-protocol",
67                         "encap-vrf-id",
68                         "decap-vrf-id")
69
70     def __init__(self):
71         pass
72
73     @staticmethod
74     def _configure_interface(node, interface, data,
75                              data_representation=DataRepresentation.JSON):
76         """Send interface configuration data and check the response.
77
78         :param node: Honeycomb node.
79         :param interface: The name of interface.
80         :param data: Configuration data to be sent in PUT request.
81         :param data_representation: How the data is represented.
82         :type node: dict
83         :type interface: str
84         :type data: dict
85         :type data_representation: DataRepresentation
86         :return: 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 != HTTPCodes.OK:
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         :return: 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         :return: 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         :return: 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_interface_oper_data(node, interface):
167         """Get operational data about the given interface from Honeycomb.
168
169         :param node: Honeycomb node.
170         :param interface: The name of interface.
171         :type node: dict
172         :type interface: str
173         :return: Operational data about the given interface from Honeycomb.
174         :rtype: dict
175         """
176
177         intfs = InterfaceKeywords.get_all_interfaces_oper_data(node)
178         for intf in intfs:
179             if intf["name"] == interface:
180                 return intf
181         return {}
182
183     @staticmethod
184     def _set_interface_properties(node, interface, path, new_value=None):
185         """Set interface properties.
186
187         This method reads interface configuration data, creates, changes or
188         removes the requested data and puts it back to Honeycomb.
189
190         :param node: Honeycomb node.
191         :param interface: The name of interface.
192         :param path:  Path to data we want to change / create / remove.
193         :param new_value: The new value to be set. If None, the item will be
194         removed.
195         :type node: dict
196         :type interface: str
197         :type path: tuple
198         :type new_value: str, dict or list
199         :return: Content of response.
200         :rtype: bytearray
201         :raises HoneycombError: If it is not possible to get or set the data.
202         """
203
204         status_code, resp = HcUtil.\
205             get_honeycomb_data(node, "config_vpp_interfaces")
206         if status_code != HTTPCodes.OK:
207             raise HoneycombError(
208                 "Not possible to get configuration information about the "
209                 "interfaces. Status code: {0}.".format(status_code))
210
211         if new_value:
212             new_data = HcUtil.set_item_value(resp, path, new_value)
213         else:
214             new_data = HcUtil.remove_item(resp, path)
215         return InterfaceKeywords._configure_interface(node, interface, new_data)
216
217     @staticmethod
218     def set_interface_state(node, interface, state="up"):
219         """Set VPP interface state.
220
221         The keyword changes the administration state of interface to up or down
222         depending on the parameter "state".
223
224         :param node: Honeycomb node.
225         :param interface: The name of interface.
226         :param state: The requested state, only "up" and "down" are valid
227         values.
228         :type node: dict
229         :type interface: str
230         :type state: str
231         :return: Content of response.
232         :rtype: bytearray
233         :raises KeyError: If the argument "state" is nor "up" or "down".
234         :raises HoneycombError: If the interface is not present on the node.
235         """
236
237         intf_state = {"up": "true",
238                       "down": "false"}
239
240         path = ("interfaces", ("interface", "name", str(interface)), "enabled")
241         return InterfaceKeywords._set_interface_properties(
242             node, interface, path, intf_state[state.lower()])
243
244     @staticmethod
245     def set_interface_up(node, interface):
246         """Set the administration state of VPP interface to up.
247
248         :param node: Honeycomb node.
249         :param interface: The name of interface.
250         :type node: dict
251         :type interface: str
252         :return: Content of response
253         :rtype: bytearray
254         """
255
256         return InterfaceKeywords.set_interface_state(node, interface, "up")
257
258     @staticmethod
259     def set_interface_down(node, interface):
260         """Set the administration state of VPP interface to down.
261
262         :param node: Honeycomb node.
263         :param interface: The name of interface.
264         :type node: dict
265         :type interface: str
266         :return: Content of response.
267         :rtype: bytearray
268         """
269
270         return InterfaceKeywords.set_interface_state(node, interface, "down")
271
272     @staticmethod
273     def add_bridge_domain_to_interface(node, interface, bd_name,
274                                        split_horizon_group=None, bvi=None):
275         """Add a new bridge domain to an interface and set its parameters.
276
277         :param node: Honeycomb node.
278         :param interface: The name of interface.
279         :param bd_name: Bridge domain name.
280         :param split_horizon_group: Split-horizon group name.
281         :param bvi: The bridged virtual interface.
282         :type node: dict
283         :type interface: str
284         :type bd_name: str
285         :type split_horizon_group: str
286         :type bvi: str
287         :return: Content of response.
288         :rtype: bytearray
289         :raises HoneycombError: If the interface is not present on the node.
290         """
291
292         v3po_l2 = {"bridge-domain": str(bd_name)}
293         if split_horizon_group:
294             v3po_l2["split-horizon-group"] = str(split_horizon_group)
295         if bvi:
296             v3po_l2["bridged-virtual-interface"] = str(bvi)
297
298         path = ("interfaces", ("interface", "name", str(interface)), "v3po:l2")
299
300         return InterfaceKeywords._set_interface_properties(
301             node, interface, path, v3po_l2)
302
303     @staticmethod
304     def get_bd_oper_data_from_interface(node, interface):
305         """Returns operational data about bridge domain settings in the
306         interface.
307
308         :param node: Honeycomb node.
309         :param interface: The name of interface.
310         :type interface: str
311         :type param: str
312         :return: Operational data about bridge domain settings in the
313         interface.
314         :rtype: dict
315         """
316
317         if_data = InterfaceKeywords.get_interface_oper_data(node, interface)
318
319         if if_data:
320             try:
321                 return if_data["v3po:l2"]
322             except KeyError:
323                 return {}
324         return {}
325
326     @staticmethod
327     def configure_interface_base(node, interface, param, value):
328         """Configure the base parameters of interface.
329
330         :param node: Honeycomb node.
331         :param interface: The name of interface.
332         :param param: Parameter to configure (set, change, remove)
333         :param value: The value of parameter. If None, the parameter will be
334         removed.
335         :type node: dict
336         :type interface: str
337         :type param: str
338         :type value: str
339         :return: Content of response.
340         :rtype: bytearray
341         :raises HoneycombError: If the parameter is not valid.
342         """
343
344         if param not in InterfaceKeywords.INTF_PARAMS:
345             raise HoneycombError("The parameter {0} is invalid.".format(param))
346
347         path = ("interfaces", ("interface", "name", interface), param)
348         return InterfaceKeywords._set_interface_properties(
349             node, interface, path, value)
350
351     @staticmethod
352     def configure_interface_ipv4(node, interface, param, value):
353         """Configure IPv4 parameters of interface
354
355         :param node: Honeycomb node.
356         :param interface: The name of interface.
357         :param param: Parameter to configure (set, change, remove)
358         :param value: The value of parameter. If None, the parameter will be
359         removed.
360         :type node: dict
361         :type interface: str
362         :type param: str
363         :type value: str
364         :return: Content of response.
365         :rtype: bytearray
366         :raises HoneycombError: If the parameter is not valid.
367         """
368
369         if param not in InterfaceKeywords.IPV4_PARAMS:
370             raise HoneycombError("The parameter {0} is invalid.".format(param))
371
372         path = ("interfaces", ("interface", "name", interface),
373                 "ietf-ip:ipv4", param)
374         return InterfaceKeywords._set_interface_properties(
375             node, interface, path, value)
376
377     @staticmethod
378     def add_first_ipv4_address(node, interface, ip_addr, network):
379         """Add the first IPv4 address.
380
381         If there are any other addresses configured, they will be removed.
382
383         :param node: Honeycomb node.
384         :param interface: The name of interface.
385         :param ip_addr: IPv4 address to be set.
386         :param network: Netmask or length of network prefix.
387         :type node: dict
388         :type interface: str
389         :type ip_addr: str
390         :type network: str or int
391         :return: Content of response.
392         :rtype: bytearray
393         """
394
395         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
396         if isinstance(network, basestring):
397             address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
398         elif isinstance(network, int) and (0 < network < 33):
399             address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
400         else:
401             raise HoneycombError("Value {0} is not a valid netmask or network "
402                                  "prefix length.".format(network))
403         return InterfaceKeywords._set_interface_properties(
404             node, interface, path, address)
405
406     @staticmethod
407     def add_ipv4_address(node, interface, ip_addr, network):
408         """Add IPv4 address.
409
410         :param node: Honeycomb node.
411         :param interface: The name of interface.
412         :param ip_addr: IPv4 address to be set.
413         :param network: Netmask or length of network prefix.
414         :type node: dict
415         :type interface: str
416         :type ip_addr: str
417         :type network: str or int
418         :return: Content of response.
419         :rtype: bytearray
420         """
421
422         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
423                 "address")
424         if isinstance(network, basestring):
425             address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
426         elif isinstance(network, int) and (0 < network < 33):
427             address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
428         else:
429             raise HoneycombError("Value {0} is not a valid netmask or network "
430                                  "prefix length.".format(network))
431         return InterfaceKeywords._set_interface_properties(
432             node, interface, path, address)
433
434     @staticmethod
435     def remove_all_ipv4_addresses(node, interface):
436         """Remove all IPv4 addresses from interface.
437
438         :param node: Honeycomb node.
439         :param interface: The name of interface.
440         :type node: dict
441         :type interface: str
442         :return: Content of response.
443         :rtype: bytearray
444         """
445
446         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
447                 "address")
448         return InterfaceKeywords._set_interface_properties(
449             node, interface, path, None)
450
451     @staticmethod
452     def add_first_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
453         """Add the first IPv4 neighbour.
454
455         If there are any other neighbours configured, they will be removed.
456
457         :param node: Honeycomb node.
458         :param interface: The name of interface.
459         :param ip_addr: IPv4 address of neighbour to be set.
460         :param link_layer_address: Link layer address.
461         :type node: dict
462         :type interface: str
463         :type ip_addr: str
464         :type link_layer_address: str
465         :return: Content of response.
466         :rtype: bytearray
467         """
468
469         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
470         neighbor = {"neighbor": [{"ip": ip_addr,
471                                   "link-layer-address": link_layer_address}, ]}
472         return InterfaceKeywords._set_interface_properties(
473             node, interface, path, neighbor)
474
475     @staticmethod
476     def add_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
477         """Add the IPv4 neighbour.
478
479         :param node: Honeycomb node.
480         :param interface: The name of interface.
481         :param ip_addr: IPv4 address of neighbour to be set.
482         :param link_layer_address: Link layer address.
483         :type node: dict
484         :type interface: str
485         :type ip_addr: str
486         :type link_layer_address: str
487         :return: Content of response.
488         :rtype: bytearray
489         """
490
491         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
492                 "neighbor")
493         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
494         return InterfaceKeywords._set_interface_properties(
495             node, interface, path, neighbor)
496
497     @staticmethod
498     def remove_all_ipv4_neighbors(node, interface):
499         """Remove all IPv4 neighbours.
500
501         :param node: Honeycomb node.
502         :param interface: The name of interface.
503         :type node: dict
504         :type interface: str
505         :return: Content of response.
506         :rtype: bytearray
507         """
508
509         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
510                 "neighbor")
511         return InterfaceKeywords._set_interface_properties(
512             node, interface, path, None)
513
514     @staticmethod
515     def configure_interface_ipv6(node, interface, param, value):
516         """Configure IPv6 parameters of interface
517
518         :param node: Honeycomb node.
519         :param interface: The name of interface.
520         :param param: Parameter to configure (set, change, remove)
521         :param value: The value of parameter. If None, the parameter will be
522         removed.
523         :type node: dict
524         :type interface: str
525         :type param: str
526         :type value: str
527         :return: Content of response.
528         :rtype: bytearray
529         :raises HoneycombError: If the parameter is not valid.
530         """
531
532         if param in InterfaceKeywords.IPV6_PARAMS:
533             path = ("interfaces", ("interface", "name", interface),
534                     "ietf-ip:ipv6", param)
535         elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
536             path = ("interfaces", ("interface", "name", interface),
537                     "ietf-ip:ipv6", "autoconf", param)
538         else:
539             raise HoneycombError("The parameter {0} is invalid.".format(param))
540
541         return InterfaceKeywords._set_interface_properties(
542             node, interface, path, value)
543
544     @staticmethod
545     def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
546         """Add the first IPv6 address.
547
548         If there are any other addresses configured, they will be removed.
549
550         :param node: Honeycomb node.
551         :param interface: The name of interface.
552         :param ip_addr: IPv6 address to be set.
553         :param prefix_len: Prefix length.
554         :type node: dict
555         :type interface: str
556         :type ip_addr: str
557         :type prefix_len: str
558         :return: Content of response.
559         :rtype: bytearray
560         """
561
562         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
563         address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
564         return InterfaceKeywords._set_interface_properties(
565             node, interface, path, address)
566
567     @staticmethod
568     def add_ipv6_address(node, interface, ip_addr, prefix_len):
569         """Add IPv6 address.
570
571         :param node: Honeycomb node.
572         :param interface: The name of interface.
573         :param ip_addr: IPv6 address to be set.
574         :param prefix_len: Prefix length.
575         :type node: dict
576         :type interface: str
577         :type ip_addr: str
578         :type prefix_len: str
579         :return: Content of response.
580         :rtype: bytearray
581         """
582
583         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
584                 "address")
585         address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
586         return InterfaceKeywords._set_interface_properties(
587             node, interface, path, address)
588
589     @staticmethod
590     def remove_all_ipv6_addresses(node, interface):
591         """Remove all IPv6 addresses from interface.
592
593         :param node: Honeycomb node.
594         :param interface: The name of interface.
595         :type node: dict
596         :type interface: str
597         :return: Content of response.
598         :rtype: bytearray
599         """
600
601         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
602                 "address")
603         return InterfaceKeywords._set_interface_properties(
604             node, interface, path, None)
605
606     @staticmethod
607     def add_first_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
608         """Add the first IPv6 neighbour.
609
610         If there are any other neighbours configured, they will be removed.
611
612         :param node: Honeycomb node.
613         :param interface: The name of interface.
614         :param ip_addr: IPv6 address of neighbour to be set.
615         :param link_layer_address: Link layer address.
616         :type node: dict
617         :type interface: str
618         :type ip_addr: str
619         :type link_layer_address: str
620         :return: Content of response.
621         :rtype: bytearray
622         """
623
624         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
625         neighbor = {"neighbor": [{"ip": ip_addr,
626                                   "link-layer-address": link_layer_address}, ]}
627         return InterfaceKeywords._set_interface_properties(
628             node, interface, path, neighbor)
629
630     @staticmethod
631     def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
632         """Add the IPv6 neighbour.
633
634         :param node: Honeycomb node.
635         :param interface: The name of interface.
636         :param ip_addr: IPv6 address of neighbour to be set.
637         :param link_layer_address: Link layer address.
638         :type node: dict
639         :type interface: str
640         :type ip_addr: str
641         :type link_layer_address: str
642         :return: Content of response.
643         :rtype: bytearray
644         """
645
646         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
647                 "neighbor")
648         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
649         return InterfaceKeywords._set_interface_properties(
650             node, interface, path, neighbor)
651
652     @staticmethod
653     def remove_all_ipv6_neighbors(node, interface):
654         """Remove all IPv6 neighbours.
655
656         :param node: Honeycomb node.
657         :param interface: The name of interface.
658         :type node: dict
659         :type interface: str
660         :return: Content of response.
661         :rtype: bytearray
662         """
663
664         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
665                 "neighbor")
666         return InterfaceKeywords._set_interface_properties(
667             node, interface, path, None)
668
669     @staticmethod
670     def configure_interface_ethernet(node, interface, param, value):
671         """Configure the ethernet parameters of interface.
672
673         :param node: Honeycomb node.
674         :param interface: The name of interface.
675         :param param: Parameter to configure (set, change, remove)
676         :param value: The value of parameter. If None, the parameter will be
677         removed.
678         :type node: dict
679         :type interface: str
680         :type param: str
681         :type value: str
682         :return: Content of response.
683         :rtype: bytearray
684         :raises HoneycombError: If the parameter is not valid.
685         """
686
687         if param not in InterfaceKeywords.ETH_PARAMS:
688             raise HoneycombError("The parameter {0} is invalid.".format(param))
689         path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
690                 param)
691         return InterfaceKeywords._set_interface_properties(
692             node, interface, path, value)
693
694     @staticmethod
695     def configure_interface_routing(node, interface, param, value):
696         """Configure the routing parameters of interface.
697
698         :param node: Honeycomb node.
699         :param interface: The name of interface.
700         :param param: Parameter to configure (set, change, remove)
701         :param value: The value of parameter. If None, the parameter will be
702         removed.
703         :type node: dict
704         :type interface: str
705         :type param: str
706         :type value: str
707         :return: Content of response.
708         :rtype: bytearray
709         :raises HoneycombError: If the parameter is not valid.
710         """
711
712         if param not in InterfaceKeywords.ROUTING_PARAMS:
713             raise HoneycombError("The parameter {0} is invalid.".format(param))
714
715         path = ("interfaces", ("interface", "name", interface), "v3po:routing",
716                 param)
717         return InterfaceKeywords._set_interface_properties(
718             node, interface, path, value)
719
720     @staticmethod
721     def create_vxlan_interface(node, interface, **kwargs):
722         """Create a new VxLAN interface.
723
724         :param node: Honeycomb node.
725         :param interface: The name of interface.
726         :param kwargs: Parameters and their values. The accepted parameters are
727         defined in InterfaceKeywords.VXLAN_PARAMS.
728         :type node: dict
729         :type interface: str
730         :type kwargs: dict
731         :return: Content of response.
732         :rtype: bytearray
733         :raises HoneycombError: If the parameter is not valid.
734         """
735
736         new_vx_lan = {
737             "name": interface,
738             "type": "v3po:vxlan-tunnel",
739             "v3po:vxlan": {}
740         }
741         for param, value in kwargs.items():
742             if param not in InterfaceKeywords.VXLAN_PARAMS:
743                 raise HoneycombError("The parameter {0} is invalid.".
744                                      format(param))
745             new_vx_lan["v3po:vxlan"][param] = value
746
747         path = ("interfaces", "interface")
748         vx_lan_structure = [new_vx_lan, ]
749         return InterfaceKeywords._set_interface_properties(
750             node, interface, path, vx_lan_structure)
751
752     @staticmethod
753     def delete_interface(node, interface):
754         """Delete an interface.
755
756         :param node: Honeycomb node.
757         :param interface: The name of interface.
758         :type node: dict
759         :type interface: str
760         :return: Content of response.
761         :rtype: bytearray
762         :raises HoneycombError: If it is not possible to get information about
763         interfaces or it is not possible to delete the interface.
764         """
765
766         path = ("interfaces", ("interface", "name", interface))
767
768         status_code, resp = HcUtil.\
769             get_honeycomb_data(node, "config_vpp_interfaces")
770         if status_code != HTTPCodes.OK:
771             raise HoneycombError(
772                 "Not possible to get configuration information about the "
773                 "interfaces. Status code: {0}.".format(status_code))
774
775         new_data = HcUtil.remove_item(resp, path)
776         status_code, resp = HcUtil.\
777             put_honeycomb_data(node, "config_vpp_interfaces", new_data)
778         if status_code != HTTPCodes.OK:
779             raise HoneycombError("Not possible to remove interface {0}. "
780                                  "Status code: {1}.".
781                                  format(interface, status_code))
782         return resp
783
784     @staticmethod
785     def configure_interface_vxlan(node, interface, **kwargs):
786         """Configure VxLAN on the interface.
787
788         The keyword configures VxLAN parameters on the given interface. The type
789         of interface must be set to "v3po:vxlan-tunnel".
790         The new VxLAN parameters overwrite the current configuration. If a
791         parameter in new configuration is missing, it is removed from VxLAN
792         configuration.
793         If the dictionary kwargs is empty, VxLAN configuration is removed.
794
795         :param node: Honeycomb node.
796         :param interface: The name of interface.
797         :param kwargs: Parameters and their values. The accepted parameters are
798         defined in InterfaceKeywords.VXLAN_PARAMS.
799         :type node: dict
800         :type interface: str
801         :type kwargs: dict
802         :return: Content of response.
803         :rtype: bytearray
804         :raises HoneycombError: If the parameter is not valid.
805         """
806
807         vx_lan_structure = dict()
808         for param, value in kwargs.items():
809             if param not in InterfaceKeywords.VXLAN_PARAMS:
810                 raise HoneycombError("The parameter {0} is invalid.".
811                                      format(param))
812             vx_lan_structure[param] = value
813
814         path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
815         return InterfaceKeywords._set_interface_properties(
816             node, interface, path, vx_lan_structure)
817
818     @staticmethod
819     def configure_interface_l2(node, interface, param, value):
820         """Configure the L2 parameters of interface.
821
822         :param node: Honeycomb node.
823         :param interface: The name of interface.
824         :param param: Parameter to configure (set, change, remove)
825         :param value: The value of parameter. If None, the parameter will be
826         removed.
827         :type node: dict
828         :type interface: str
829         :type param: str
830         :type value: str
831         :return: Content of response.
832         :rtype: bytearray
833         :raises HoneycombError: If the parameter is not valid.
834         """
835
836         if param not in InterfaceKeywords.L2_PARAMS:
837             raise HoneycombError("The parameter {0} is invalid.".format(param))
838         path = ("interfaces", ("interface", "name", interface), "v3po:l2",
839                 param)
840         return InterfaceKeywords._set_interface_properties(
841             node, interface, path, value)
842
843     @staticmethod
844     def create_tap_interface(node, interface, **kwargs):
845         """Create a new TAP interface.
846
847         :param node: Honeycomb node.
848         :param interface: The name of interface.
849         :param kwargs: Parameters and their values. The accepted parameters are
850         defined in InterfaceKeywords.TAP_PARAMS.
851         :type node: dict
852         :type interface: str
853         :type kwargs: dict
854         :return: Content of response.
855         :rtype: bytearray
856         :raises HoneycombError: If the parameter is not valid.
857         """
858
859         new_tap = {
860             "name": interface,
861             "type": "v3po:tap",
862             "v3po:tap": {}
863         }
864         for param, value in kwargs.items():
865             if param not in InterfaceKeywords.TAP_PARAMS:
866                 raise HoneycombError("The parameter {0} is invalid.".
867                                      format(param))
868             new_tap["v3po:tap"][param] = value
869
870         path = ("interfaces", "interface")
871         new_tap_structure = [new_tap, ]
872         return InterfaceKeywords._set_interface_properties(
873             node, interface, path, new_tap_structure)
874
875     @staticmethod
876     def configure_interface_tap(node, interface, **kwargs):
877         """Configure TAP on the interface.
878
879         The keyword configures TAP parameters on the given interface. The type
880         of interface must be set to "v3po:tap".
881         The new TAP parameters overwrite the current configuration. If a
882         parameter in new configuration is missing, it is removed from TAP
883         configuration.
884         If the dictionary kwargs is empty, TAP configuration is removed.
885
886         :param node: Honeycomb node.
887         :param interface: The name of interface.
888         :param kwargs: Parameters and their values. The accepted parameters are
889         defined in InterfaceKeywords.TAP_PARAMS.
890         :type node: dict
891         :type interface: str
892         :type kwargs: dict
893         :return: Content of response.
894         :rtype: bytearray
895         :raises HoneycombError: If the parameter is not valid.
896         """
897
898         tap_structure = dict()
899         for param, value in kwargs.items():
900             if param not in InterfaceKeywords.TAP_PARAMS:
901                 raise HoneycombError("The parameter {0} is invalid.".
902                                      format(param))
903             tap_structure[param] = value
904
905         path = ("interfaces", ("interface", "name", interface), "v3po:tap")
906         return InterfaceKeywords._set_interface_properties(
907             node, interface, path, tap_structure)
908
909     @staticmethod
910     def configure_interface_vhost_user(node, interface, **kwargs):
911         """Configure vhost-user on the interface.
912
913         The keyword configures vhost-user parameters on the given interface.
914         The type of interface must be set to "v3po:vhost-user".
915         The new vhost-user parameters overwrite the current configuration. If a
916         parameter in new configuration is missing, it is removed from vhost-user
917         configuration.
918         If the dictionary kwargs is empty, vhost-user configuration is removed.
919
920         :param node: Honeycomb node.
921         :param interface: The name of interface.
922         :param kwargs: Parameters and their values. The accepted parameters are
923         defined in InterfaceKeywords.VHOST_USER_PARAMS.
924         :type node: dict
925         :type interface: str
926         :type kwargs: dict
927         :return: Content of response.
928         :rtype: bytearray
929         :raises HoneycombError: If the parameter is not valid.
930         """
931
932         vhost_structure = dict()
933         for param, value in kwargs.items():
934             if param not in InterfaceKeywords.VHOST_USER_PARAMS:
935                 raise HoneycombError("The parameter {0} is invalid.".
936                                      format(param))
937             vhost_structure[param] = value
938
939         path = ("interfaces", ("interface", "name", interface),
940                 "v3po:vhost-user")
941         return InterfaceKeywords._set_interface_properties(
942             node, interface, path, vhost_structure)
943
944     @staticmethod
945     def create_vhost_user_interface(node, interface, **kwargs):
946         """Create a new vhost-user interface.
947
948         :param node: Honeycomb node.
949         :param interface: The name of interface.
950         :param kwargs: Parameters and their values. The accepted parameters are
951         defined in InterfaceKeywords.VHOST_USER_PARAMS.
952         :type node: dict
953         :type interface: str
954         :type kwargs: dict
955         :return: Content of response.
956         :rtype: bytearray
957         :raises HoneycombError: If the parameter is not valid.
958         """
959
960         new_vhost = {
961             "name": interface,
962             "type": "v3po:vhost-user",
963             "v3po:vhost-user": {}
964         }
965         for param, value in kwargs.items():
966             if param not in InterfaceKeywords.VHOST_USER_PARAMS:
967                 raise HoneycombError("The parameter {0} is invalid.".
968                                      format(param))
969             new_vhost["v3po:vhost-user"][param] = value
970
971         path = ("interfaces", "interface")
972         new_vhost_structure = [new_vhost, ]
973         return InterfaceKeywords._set_interface_properties(
974             node, interface, path, new_vhost_structure)
975
976     @staticmethod
977     def create_sub_interface(node, super_interface, match, tags=None, **kwargs):
978         """Create a new sub-interface.
979
980         :param node: Honeycomb node.
981         :param super_interface: Super interface.
982         :param match: Match type. The valid values are defined in
983         InterfaceKeywords.SUB_IF_MATCH.
984         :param tags: List of tags.
985         :param kwargs: Parameters and their values. The accepted parameters are
986         defined in InterfaceKeywords.SUB_IF_PARAMS.
987         :type node: dict
988         :type super_interface: str
989         :type match: str
990         :type tags: list
991         :type kwargs: dict
992         :return: Content of response.
993         :rtype: bytearray
994         :raises HoneycombError: If the parameter is not valid.
995         :raises KeyError: If the parameter 'match' is invalid.
996         """
997
998         match_type = {
999             "default":
1000                 {"default": {}},
1001             "untagged":
1002                 {"untagged": {}},
1003             "vlan-tagged":
1004                 {"vlan-tagged": {"match-exact-tags": "false"}},
1005             "vlan-tagged-exact-match":
1006                 {"vlan-tagged": {"match-exact-tags": "true"}}
1007         }
1008
1009         new_sub_interface = {
1010             "tags": {
1011                 "tag": []
1012             },
1013         }
1014
1015         for param, value in kwargs.items():
1016             if param in InterfaceKeywords.SUB_IF_PARAMS:
1017                 new_sub_interface[param] = value
1018             else:
1019                 raise HoneycombError("The parameter {0} is invalid.".
1020                                      format(param))
1021         try:
1022             new_sub_interface["match"] = match_type[match]
1023         except KeyError:
1024             raise HoneycombError("The value '{0}' of parameter 'match' is "
1025                                  "invalid.".format(match))
1026
1027         if tags:
1028             new_sub_interface["tags"]["tag"].extend(tags)
1029
1030         path = ("interfaces",
1031                 ("interface", "name", super_interface),
1032                 "vpp-vlan:sub-interfaces",
1033                 "sub-interface")
1034         new_sub_interface_structure = [new_sub_interface, ]
1035         return InterfaceKeywords._set_interface_properties(
1036             node, super_interface, path, new_sub_interface_structure)
1037
1038     @staticmethod
1039     def get_sub_interface_oper_data(node, super_interface, identifier):
1040         """Retrieves sub-interface operational data using Honeycomb API.
1041
1042         :param node: Honeycomb node.
1043         :param super_interface: Super interface.
1044         :param identifier: The ID of sub-interface.
1045         :type node: dict
1046         :type super_interface: str
1047         :type identifier: int
1048         :return: Sub-interface operational data.
1049         :rtype: dict
1050         :raises HoneycombError: If there is no sub-interface with the given ID.
1051         """
1052
1053         if_data = InterfaceKeywords.get_interface_oper_data(node,
1054                                                             super_interface)
1055         for sub_if in if_data["vpp-vlan:sub-interfaces"]["sub-interface"]:
1056             if str(sub_if["identifier"]) == str(identifier):
1057                 return sub_if
1058
1059         raise HoneycombError("The interface {0} does not have sub-interface "
1060                              "with ID {1}".format(super_interface, identifier))
1061
1062     @staticmethod
1063     def remove_all_sub_interfaces(node, super_interface):
1064         """Remove all sub-interfaces from the given interface.
1065
1066         :param node: Honeycomb node.
1067         :param super_interface: Super interface.
1068         :type node: dict
1069         :type super_interface: str
1070         :return: Content of response.
1071         :rtype: bytearray
1072         """
1073
1074         path = ("interfaces",
1075                 ("interface", "name", super_interface),
1076                 "vpp-vlan:sub-interfaces")
1077
1078         return InterfaceKeywords._set_interface_properties(
1079             node, super_interface, path, {})
1080
1081     @staticmethod
1082     def set_sub_interface_state(node, super_interface, identifier, state):
1083         """Set the administrative state of sub-interface.
1084
1085         :param node: Honeycomb node.
1086         :param super_interface: Super interface.
1087         :param identifier: The ID of sub-interface.
1088         :param state: Required sub-interface state - up or down.
1089         :type node: dict
1090         :type super_interface: str
1091         :type identifier: int
1092         :type state: str
1093         :return: Content of response.
1094         :rtype: bytearray
1095         """
1096
1097         intf_state = {"up": "true",
1098                       "down": "false"}
1099
1100         path = ("interfaces",
1101                 ("interface", "name", super_interface),
1102                 "vpp-vlan:sub-interfaces",
1103                 ("sub-interface", "identifier", identifier),
1104                 "enabled")
1105
1106         return InterfaceKeywords._set_interface_properties(
1107             node, super_interface, path, intf_state[state])
1108
1109     @staticmethod
1110     def add_bridge_domain_to_sub_interface(node, super_interface, identifier,
1111                                            config):
1112         """Add a sub-interface to a bridge domain and set its parameters.
1113
1114         :param node: Honeycomb node.
1115         :param super_interface: Super interface.
1116         :param identifier: The ID of sub-interface.
1117         :param config: Bridge domain configuration.
1118         :type node: dict
1119         :type super_interface: str
1120         :type identifier: int
1121         :type config: dict
1122         :return: Content of response.
1123         :rtype: bytearray
1124         """
1125
1126         path = ("interfaces",
1127                 ("interface", "name", super_interface),
1128                 "vpp-vlan:sub-interfaces",
1129                 ("sub-interface", "identifier", int(identifier)),
1130                 "l2")
1131
1132         return InterfaceKeywords._set_interface_properties(
1133             node, super_interface, path, config)
1134
1135     @staticmethod
1136     def get_bd_data_from_sub_interface(node, super_interface, identifier):
1137         """Get the operational data about the bridge domain from sub-interface.
1138
1139         :param node: Honeycomb node.
1140         :param super_interface: Super interface.
1141         :param identifier: The ID of sub-interface.
1142         :type node: dict
1143         :type super_interface: str
1144         :type identifier: int
1145         :return: Operational data about the bridge domain.
1146         :rtype: dict
1147         :raises HoneycombError: If there is no sub-interface with the given ID.
1148         """
1149
1150         try:
1151             bd_data = InterfaceKeywords.get_sub_interface_oper_data(
1152                 node, super_interface, identifier)["l2"]
1153             return bd_data
1154         except KeyError:
1155             raise HoneycombError("The operational data does not contain "
1156                                  "information about a bridge domain.")
1157
1158     @staticmethod
1159     def configure_tag_rewrite(node, super_interface, identifier, config):
1160         """Add / change / disable vlan tag rewrite on a sub-interface.
1161
1162         :param node: Honeycomb node.
1163         :param super_interface: Super interface.
1164         :param identifier: The ID of sub-interface.
1165         :param config: Rewrite tag configuration.
1166         :type node: dict
1167         :type super_interface: str
1168         :type identifier: int
1169         :type config: dict
1170         :return: Content of response.
1171         :rtype: bytearray
1172         """
1173
1174         path = ("interfaces",
1175                 ("interface", "name", super_interface),
1176                 "vpp-vlan:sub-interfaces",
1177                 ("sub-interface", "identifier", int(identifier)),
1178                 "l2",
1179                 "rewrite")
1180
1181         return InterfaceKeywords._set_interface_properties(
1182             node, super_interface, path, config)
1183
1184     @staticmethod
1185     def get_tag_rewrite_oper_data(node, super_interface, identifier):
1186         """Get the operational data about tag rewrite.
1187
1188         :param node: Honeycomb node.
1189         :param super_interface: Super interface.
1190         :param identifier: The ID of sub-interface.
1191         :type node: dict
1192         :type super_interface: str
1193         :type identifier: int
1194         :return: Operational data about tag rewrite.
1195         :rtype: dict
1196         :raises HoneycombError: If there is no sub-interface with the given ID.
1197         """
1198
1199         try:
1200             tag_rewrite = InterfaceKeywords.get_sub_interface_oper_data(
1201                 node, super_interface, identifier)["l2"]["rewrite"]
1202             return tag_rewrite
1203         except KeyError:
1204             raise HoneycombError("The operational data does not contain "
1205                                  "information about the tag-rewrite.")
1206
1207     @staticmethod
1208     def compare_data_structures(data, ref):
1209         """Checks if data obtained from UUT is as expected.
1210
1211         :param data: Data to be checked.
1212         :param ref: Referential data used for comparison.
1213         :type data: dict
1214         :type ref: dict
1215         :raises HoneycombError: If a parameter from referential data is not
1216         present in operational data or if it has different value.
1217         """
1218
1219         for key, item in ref.items():
1220             try:
1221                 if data[key] != item:
1222                     raise HoneycombError("The value of parameter '{0}' is "
1223                                          "incorrect. It should be "
1224                                          "'{1}' but it is '{2}'".
1225                                          format(key, item, data[key]))
1226             except KeyError:
1227                 raise HoneycombError("The parameter '{0}' is not present in "
1228                                      "operational data".format(key))
1229
1230     @staticmethod
1231     def compare_interface_lists(list1, list2):
1232         """Compare provided lists of interfaces by name.
1233
1234         :param list1: List of interfaces.
1235         :param list2: List of interfaces.
1236         :type list1: list
1237         :type list2: list
1238         :raises HoneycombError: If an interface exists in only one of the lists.
1239         """
1240
1241         ignore = ["vx_tunnel0", "vxlan_gpe_tunnel0"]
1242         # these have no equivalent in config data and no effect on VPP
1243
1244         names1 = [x['name'] for x in list1]
1245         names2 = [x['name'] for x in list2]
1246
1247         for name in names1:
1248             if name not in names2 and name not in ignore:
1249                 raise HoneycombError("Interface {0} not present in list {1}"
1250                                      .format(name, list2))
1251         for name in names2:
1252             if name not in names1 and name not in ignore:
1253                 raise HoneycombError("Interface {0} not present in list {1}"
1254                                      .format(name, list1))
1255
1256     @staticmethod
1257     def create_vxlan_gpe_interface(node, interface, **kwargs):
1258         """Create a new VxLAN GPE interface.
1259
1260         :param node: Honeycomb node.
1261         :param interface: The name of interface to be created.
1262         :param kwargs: Parameters and their values. The accepted parameters are
1263         defined in InterfaceKeywords.VXLAN_GPE_PARAMS.
1264         :type node: dict
1265         :type interface: str
1266         :type kwargs: dict
1267         :return: Content of response.
1268         :rtype: bytearray
1269         :raises HoneycombError: If a parameter in kwargs is not valid.
1270         """
1271
1272         new_vxlan_gpe = {
1273             "name": interface,
1274             "type": "v3po:vxlan-gpe-tunnel",
1275             "v3po:vxlan-gpe": {}
1276         }
1277         for param, value in kwargs.items():
1278             if param in InterfaceKeywords.INTF_PARAMS:
1279                 new_vxlan_gpe[param] = value
1280             elif param in InterfaceKeywords.VXLAN_GPE_PARAMS:
1281                 new_vxlan_gpe["v3po:vxlan-gpe"][param] = value
1282             else:
1283                 raise HoneycombError("The parameter {0} is invalid.".
1284                                      format(param))
1285         path = ("interfaces", "interface")
1286         vxlan_gpe_structure = [new_vxlan_gpe, ]
1287         return InterfaceKeywords._set_interface_properties(
1288             node, interface, path, vxlan_gpe_structure)