Modify tests for Honeycomb sub-interfaces
[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 configure_interface_base(node, interface, param, value):
305         """Configure the base parameters of interface.
306
307         :param node: Honeycomb node.
308         :param interface: The name of interface.
309         :param param: Parameter to configure (set, change, remove)
310         :param value: The value of parameter. If None, the parameter will be
311         removed.
312         :type node: dict
313         :type interface: str
314         :type param: str
315         :type value: str
316         :return: Content of response.
317         :rtype: bytearray
318         :raises HoneycombError: If the parameter is not valid.
319         """
320
321         if param not in InterfaceKeywords.INTF_PARAMS:
322             raise HoneycombError("The parameter {0} is invalid.".format(param))
323
324         path = ("interfaces", ("interface", "name", interface), param)
325         return InterfaceKeywords._set_interface_properties(
326             node, interface, path, value)
327
328     @staticmethod
329     def configure_interface_ipv4(node, interface, param, value):
330         """Configure IPv4 parameters of interface
331
332         :param node: Honeycomb node.
333         :param interface: The name of interface.
334         :param param: Parameter to configure (set, change, remove)
335         :param value: The value of parameter. If None, the parameter will be
336         removed.
337         :type node: dict
338         :type interface: str
339         :type param: str
340         :type value: str
341         :return: Content of response.
342         :rtype: bytearray
343         :raises HoneycombError: If the parameter is not valid.
344         """
345
346         if param not in InterfaceKeywords.IPV4_PARAMS:
347             raise HoneycombError("The parameter {0} is invalid.".format(param))
348
349         path = ("interfaces", ("interface", "name", interface),
350                 "ietf-ip:ipv4", param)
351         return InterfaceKeywords._set_interface_properties(
352             node, interface, path, value)
353
354     @staticmethod
355     def add_first_ipv4_address(node, interface, ip_addr, network):
356         """Add the first IPv4 address.
357
358         If there are any other addresses configured, they will be removed.
359
360         :param node: Honeycomb node.
361         :param interface: The name of interface.
362         :param ip_addr: IPv4 address to be set.
363         :param network: Netmask or length of network prefix.
364         :type node: dict
365         :type interface: str
366         :type ip_addr: str
367         :type network: str or int
368         :return: Content of response.
369         :rtype: bytearray
370         """
371
372         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
373         if isinstance(network, basestring):
374             address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
375         elif isinstance(network, int) and (0 < network < 33):
376             address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
377         else:
378             raise HoneycombError("Value {0} is not a valid netmask or network "
379                                  "prefix length.".format(network))
380         return InterfaceKeywords._set_interface_properties(
381             node, interface, path, address)
382
383     @staticmethod
384     def add_ipv4_address(node, interface, ip_addr, network):
385         """Add IPv4 address.
386
387         :param node: Honeycomb node.
388         :param interface: The name of interface.
389         :param ip_addr: IPv4 address to be set.
390         :param network: Netmask or length of network prefix.
391         :type node: dict
392         :type interface: str
393         :type ip_addr: str
394         :type network: str or int
395         :return: Content of response.
396         :rtype: bytearray
397         """
398
399         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
400                 "address")
401         if isinstance(network, basestring):
402             address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
403         elif isinstance(network, int) and (0 < network < 33):
404             address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
405         else:
406             raise HoneycombError("Value {0} is not a valid netmask or network "
407                                  "prefix length.".format(network))
408         return InterfaceKeywords._set_interface_properties(
409             node, interface, path, address)
410
411     @staticmethod
412     def remove_all_ipv4_addresses(node, interface):
413         """Remove all IPv4 addresses from interface.
414
415         :param node: Honeycomb node.
416         :param interface: The name of interface.
417         :type node: dict
418         :type interface: str
419         :return: Content of response.
420         :rtype: bytearray
421         """
422
423         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
424                 "address")
425         return InterfaceKeywords._set_interface_properties(
426             node, interface, path, None)
427
428     @staticmethod
429     def add_first_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
430         """Add the first IPv4 neighbour.
431
432         If there are any other neighbours configured, they will be removed.
433
434         :param node: Honeycomb node.
435         :param interface: The name of interface.
436         :param ip_addr: IPv4 address of neighbour to be set.
437         :param link_layer_address: Link layer address.
438         :type node: dict
439         :type interface: str
440         :type ip_addr: str
441         :type link_layer_address: str
442         :return: Content of response.
443         :rtype: bytearray
444         """
445
446         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
447         neighbor = {"neighbor": [{"ip": ip_addr,
448                                   "link-layer-address": link_layer_address}, ]}
449         return InterfaceKeywords._set_interface_properties(
450             node, interface, path, neighbor)
451
452     @staticmethod
453     def add_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
454         """Add the IPv4 neighbour.
455
456         :param node: Honeycomb node.
457         :param interface: The name of interface.
458         :param ip_addr: IPv4 address of neighbour to be set.
459         :param link_layer_address: Link layer address.
460         :type node: dict
461         :type interface: str
462         :type ip_addr: str
463         :type link_layer_address: str
464         :return: Content of response.
465         :rtype: bytearray
466         """
467
468         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
469                 "neighbor")
470         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
471         return InterfaceKeywords._set_interface_properties(
472             node, interface, path, neighbor)
473
474     @staticmethod
475     def remove_all_ipv4_neighbors(node, interface):
476         """Remove all IPv4 neighbours.
477
478         :param node: Honeycomb node.
479         :param interface: The name of interface.
480         :type node: dict
481         :type interface: str
482         :return: Content of response.
483         :rtype: bytearray
484         """
485
486         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
487                 "neighbor")
488         return InterfaceKeywords._set_interface_properties(
489             node, interface, path, None)
490
491     @staticmethod
492     def configure_interface_ipv6(node, interface, param, value):
493         """Configure IPv6 parameters of interface
494
495         :param node: Honeycomb node.
496         :param interface: The name of interface.
497         :param param: Parameter to configure (set, change, remove)
498         :param value: The value of parameter. If None, the parameter will be
499         removed.
500         :type node: dict
501         :type interface: str
502         :type param: str
503         :type value: str
504         :return: Content of response.
505         :rtype: bytearray
506         :raises HoneycombError: If the parameter is not valid.
507         """
508
509         if param in InterfaceKeywords.IPV6_PARAMS:
510             path = ("interfaces", ("interface", "name", interface),
511                     "ietf-ip:ipv6", param)
512         elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
513             path = ("interfaces", ("interface", "name", interface),
514                     "ietf-ip:ipv6", "autoconf", param)
515         else:
516             raise HoneycombError("The parameter {0} is invalid.".format(param))
517
518         return InterfaceKeywords._set_interface_properties(
519             node, interface, path, value)
520
521     @staticmethod
522     def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
523         """Add the first IPv6 address.
524
525         If there are any other addresses configured, they will be removed.
526
527         :param node: Honeycomb node.
528         :param interface: The name of interface.
529         :param ip_addr: IPv6 address to be set.
530         :param prefix_len: Prefix length.
531         :type node: dict
532         :type interface: str
533         :type ip_addr: str
534         :type prefix_len: str
535         :return: Content of response.
536         :rtype: bytearray
537         """
538
539         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
540         address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
541         return InterfaceKeywords._set_interface_properties(
542             node, interface, path, address)
543
544     @staticmethod
545     def add_ipv6_address(node, interface, ip_addr, prefix_len):
546         """Add IPv6 address.
547
548         :param node: Honeycomb node.
549         :param interface: The name of interface.
550         :param ip_addr: IPv6 address to be set.
551         :param prefix_len: Prefix length.
552         :type node: dict
553         :type interface: str
554         :type ip_addr: str
555         :type prefix_len: str
556         :return: Content of response.
557         :rtype: bytearray
558         """
559
560         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
561                 "address")
562         address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
563         return InterfaceKeywords._set_interface_properties(
564             node, interface, path, address)
565
566     @staticmethod
567     def remove_all_ipv6_addresses(node, interface):
568         """Remove all IPv6 addresses from interface.
569
570         :param node: Honeycomb node.
571         :param interface: The name of interface.
572         :type node: dict
573         :type interface: str
574         :return: Content of response.
575         :rtype: bytearray
576         """
577
578         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
579                 "address")
580         return InterfaceKeywords._set_interface_properties(
581             node, interface, path, None)
582
583     @staticmethod
584     def add_first_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
585         """Add the first IPv6 neighbour.
586
587         If there are any other neighbours configured, they will be removed.
588
589         :param node: Honeycomb node.
590         :param interface: The name of interface.
591         :param ip_addr: IPv6 address of neighbour to be set.
592         :param link_layer_address: Link layer address.
593         :type node: dict
594         :type interface: str
595         :type ip_addr: str
596         :type link_layer_address: str
597         :return: Content of response.
598         :rtype: bytearray
599         """
600
601         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
602         neighbor = {"neighbor": [{"ip": ip_addr,
603                                   "link-layer-address": link_layer_address}, ]}
604         return InterfaceKeywords._set_interface_properties(
605             node, interface, path, neighbor)
606
607     @staticmethod
608     def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
609         """Add the IPv6 neighbour.
610
611         :param node: Honeycomb node.
612         :param interface: The name of interface.
613         :param ip_addr: IPv6 address of neighbour to be set.
614         :param link_layer_address: Link layer address.
615         :type node: dict
616         :type interface: str
617         :type ip_addr: str
618         :type link_layer_address: str
619         :return: Content of response.
620         :rtype: bytearray
621         """
622
623         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
624                 "neighbor")
625         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
626         return InterfaceKeywords._set_interface_properties(
627             node, interface, path, neighbor)
628
629     @staticmethod
630     def remove_all_ipv6_neighbors(node, interface):
631         """Remove all IPv6 neighbours.
632
633         :param node: Honeycomb node.
634         :param interface: The name of interface.
635         :type node: dict
636         :type interface: str
637         :return: Content of response.
638         :rtype: bytearray
639         """
640
641         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
642                 "neighbor")
643         return InterfaceKeywords._set_interface_properties(
644             node, interface, path, None)
645
646     @staticmethod
647     def configure_interface_ethernet(node, interface, param, value):
648         """Configure the ethernet parameters of interface.
649
650         :param node: Honeycomb node.
651         :param interface: The name of interface.
652         :param param: Parameter to configure (set, change, remove)
653         :param value: The value of parameter. If None, the parameter will be
654         removed.
655         :type node: dict
656         :type interface: str
657         :type param: str
658         :type value: str
659         :return: Content of response.
660         :rtype: bytearray
661         :raises HoneycombError: If the parameter is not valid.
662         """
663
664         if param not in InterfaceKeywords.ETH_PARAMS:
665             raise HoneycombError("The parameter {0} is invalid.".format(param))
666         path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
667                 param)
668         return InterfaceKeywords._set_interface_properties(
669             node, interface, path, value)
670
671     @staticmethod
672     def configure_interface_routing(node, interface, param, value):
673         """Configure the routing parameters of interface.
674
675         :param node: Honeycomb node.
676         :param interface: The name of interface.
677         :param param: Parameter to configure (set, change, remove)
678         :param value: The value of parameter. If None, the parameter will be
679         removed.
680         :type node: dict
681         :type interface: str
682         :type param: str
683         :type value: str
684         :return: Content of response.
685         :rtype: bytearray
686         :raises HoneycombError: If the parameter is not valid.
687         """
688
689         if param not in InterfaceKeywords.ROUTING_PARAMS:
690             raise HoneycombError("The parameter {0} is invalid.".format(param))
691
692         path = ("interfaces", ("interface", "name", interface), "v3po:routing",
693                 param)
694         return InterfaceKeywords._set_interface_properties(
695             node, interface, path, value)
696
697     @staticmethod
698     def create_vxlan_interface(node, interface, **kwargs):
699         """Create a new VxLAN interface.
700
701         :param node: Honeycomb node.
702         :param interface: The name of interface.
703         :param kwargs: Parameters and their values. The accepted parameters are
704         defined in InterfaceKeywords.VXLAN_PARAMS.
705         :type node: dict
706         :type interface: str
707         :type kwargs: dict
708         :return: Content of response.
709         :rtype: bytearray
710         :raises HoneycombError: If the parameter is not valid.
711         """
712
713         new_vx_lan = {
714             "name": interface,
715             "type": "v3po:vxlan-tunnel",
716             "v3po:vxlan": {}
717         }
718         for param, value in kwargs.items():
719             if param not in InterfaceKeywords.VXLAN_PARAMS:
720                 raise HoneycombError("The parameter {0} is invalid.".
721                                      format(param))
722             new_vx_lan["v3po:vxlan"][param] = value
723
724         path = ("interfaces", "interface")
725         vx_lan_structure = [new_vx_lan, ]
726         return InterfaceKeywords._set_interface_properties(
727             node, interface, path, vx_lan_structure)
728
729     @staticmethod
730     def delete_interface(node, interface):
731         """Delete an interface.
732
733         :param node: Honeycomb node.
734         :param interface: The name of interface.
735         :type node: dict
736         :type interface: str
737         :return: Content of response.
738         :rtype: bytearray
739         :raises HoneycombError: If it is not possible to get information about
740         interfaces or it is not possible to delete the interface.
741         """
742
743         path = ("interfaces", ("interface", "name", interface))
744
745         status_code, resp = HcUtil.\
746             get_honeycomb_data(node, "config_vpp_interfaces")
747         if status_code != HTTPCodes.OK:
748             raise HoneycombError(
749                 "Not possible to get configuration information about the "
750                 "interfaces. Status code: {0}.".format(status_code))
751
752         new_data = HcUtil.remove_item(resp, path)
753         status_code, resp = HcUtil.\
754             put_honeycomb_data(node, "config_vpp_interfaces", new_data)
755         if status_code != HTTPCodes.OK:
756             raise HoneycombError("Not possible to remove interface {0}. "
757                                  "Status code: {1}.".
758                                  format(interface, status_code))
759         return resp
760
761     @staticmethod
762     def configure_interface_vxlan(node, interface, **kwargs):
763         """Configure VxLAN on the interface.
764
765         The keyword configures VxLAN parameters on the given interface. The type
766         of interface must be set to "v3po:vxlan-tunnel".
767         The new VxLAN parameters overwrite the current configuration. If a
768         parameter in new configuration is missing, it is removed from VxLAN
769         configuration.
770         If the dictionary kwargs is empty, VxLAN configuration is removed.
771
772         :param node: Honeycomb node.
773         :param interface: The name of interface.
774         :param kwargs: Parameters and their values. The accepted parameters are
775         defined in InterfaceKeywords.VXLAN_PARAMS.
776         :type node: dict
777         :type interface: str
778         :type kwargs: dict
779         :return: Content of response.
780         :rtype: bytearray
781         :raises HoneycombError: If the parameter is not valid.
782         """
783
784         vx_lan_structure = dict()
785         for param, value in kwargs.items():
786             if param not in InterfaceKeywords.VXLAN_PARAMS:
787                 raise HoneycombError("The parameter {0} is invalid.".
788                                      format(param))
789             vx_lan_structure[param] = value
790
791         path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
792         return InterfaceKeywords._set_interface_properties(
793             node, interface, path, vx_lan_structure)
794
795     @staticmethod
796     def configure_interface_l2(node, interface, param, value):
797         """Configure the L2 parameters of interface.
798
799         :param node: Honeycomb node.
800         :param interface: The name of interface.
801         :param param: Parameter to configure (set, change, remove)
802         :param value: The value of parameter. If None, the parameter will be
803         removed.
804         :type node: dict
805         :type interface: str
806         :type param: str
807         :type value: str
808         :return: Content of response.
809         :rtype: bytearray
810         :raises HoneycombError: If the parameter is not valid.
811         """
812
813         if param not in InterfaceKeywords.L2_PARAMS:
814             raise HoneycombError("The parameter {0} is invalid.".format(param))
815         path = ("interfaces", ("interface", "name", interface), "v3po:l2",
816                 param)
817         return InterfaceKeywords._set_interface_properties(
818             node, interface, path, value)
819
820     @staticmethod
821     def create_tap_interface(node, interface, **kwargs):
822         """Create a new TAP interface.
823
824         :param node: Honeycomb node.
825         :param interface: The name of interface.
826         :param kwargs: Parameters and their values. The accepted parameters are
827         defined in InterfaceKeywords.TAP_PARAMS.
828         :type node: dict
829         :type interface: str
830         :type kwargs: dict
831         :return: Content of response.
832         :rtype: bytearray
833         :raises HoneycombError: If the parameter is not valid.
834         """
835
836         new_tap = {
837             "name": interface,
838             "type": "v3po:tap",
839             "v3po:tap": {}
840         }
841         for param, value in kwargs.items():
842             if param not in InterfaceKeywords.TAP_PARAMS:
843                 raise HoneycombError("The parameter {0} is invalid.".
844                                      format(param))
845             new_tap["v3po:tap"][param] = value
846
847         path = ("interfaces", "interface")
848         new_tap_structure = [new_tap, ]
849         return InterfaceKeywords._set_interface_properties(
850             node, interface, path, new_tap_structure)
851
852     @staticmethod
853     def configure_interface_tap(node, interface, **kwargs):
854         """Configure TAP on the interface.
855
856         The keyword configures TAP parameters on the given interface. The type
857         of interface must be set to "v3po:tap".
858         The new TAP parameters overwrite the current configuration. If a
859         parameter in new configuration is missing, it is removed from TAP
860         configuration.
861         If the dictionary kwargs is empty, TAP 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.TAP_PARAMS.
867         :type node: dict
868         :type interface: str
869         :type kwargs: dict
870         :return: Content of response.
871         :rtype: bytearray
872         :raises HoneycombError: If the parameter is not valid.
873         """
874
875         tap_structure = dict()
876         for param, value in kwargs.items():
877             if param not in InterfaceKeywords.TAP_PARAMS:
878                 raise HoneycombError("The parameter {0} is invalid.".
879                                      format(param))
880             tap_structure[param] = value
881
882         path = ("interfaces", ("interface", "name", interface), "v3po:tap")
883         return InterfaceKeywords._set_interface_properties(
884             node, interface, path, tap_structure)
885
886     @staticmethod
887     def configure_interface_vhost_user(node, interface, **kwargs):
888         """Configure vhost-user on the interface.
889
890         The keyword configures vhost-user parameters on the given interface.
891         The type of interface must be set to "v3po:vhost-user".
892         The new vhost-user parameters overwrite the current configuration. If a
893         parameter in new configuration is missing, it is removed from vhost-user
894         configuration.
895         If the dictionary kwargs is empty, vhost-user configuration is removed.
896
897         :param node: Honeycomb node.
898         :param interface: The name of interface.
899         :param kwargs: Parameters and their values. The accepted parameters are
900         defined in InterfaceKeywords.VHOST_USER_PARAMS.
901         :type node: dict
902         :type interface: str
903         :type kwargs: dict
904         :return: Content of response.
905         :rtype: bytearray
906         :raises HoneycombError: If the parameter is not valid.
907         """
908
909         vhost_structure = dict()
910         for param, value in kwargs.items():
911             if param not in InterfaceKeywords.VHOST_USER_PARAMS:
912                 raise HoneycombError("The parameter {0} is invalid.".
913                                      format(param))
914             vhost_structure[param] = value
915
916         path = ("interfaces", ("interface", "name", interface),
917                 "v3po:vhost-user")
918         return InterfaceKeywords._set_interface_properties(
919             node, interface, path, vhost_structure)
920
921     @staticmethod
922     def create_vhost_user_interface(node, interface, **kwargs):
923         """Create a new vhost-user interface.
924
925         :param node: Honeycomb node.
926         :param interface: The name of interface.
927         :param kwargs: Parameters and their values. The accepted parameters are
928         defined in InterfaceKeywords.VHOST_USER_PARAMS.
929         :type node: dict
930         :type interface: str
931         :type kwargs: dict
932         :return: Content of response.
933         :rtype: bytearray
934         :raises HoneycombError: If the parameter is not valid.
935         """
936
937         new_vhost = {
938             "name": interface,
939             "type": "v3po:vhost-user",
940             "v3po:vhost-user": {}
941         }
942         for param, value in kwargs.items():
943             if param not in InterfaceKeywords.VHOST_USER_PARAMS:
944                 raise HoneycombError("The parameter {0} is invalid.".
945                                      format(param))
946             new_vhost["v3po:vhost-user"][param] = value
947
948         path = ("interfaces", "interface")
949         new_vhost_structure = [new_vhost, ]
950         return InterfaceKeywords._set_interface_properties(
951             node, interface, path, new_vhost_structure)
952
953     @staticmethod
954     def create_sub_interface(node, super_interface, match, tags=None, **kwargs):
955         """Create a new sub-interface.
956
957         :param node: Honeycomb node.
958         :param super_interface: Super interface.
959         :param match: Match type. The valid values are defined in
960         InterfaceKeywords.SUB_IF_MATCH.
961         :param tags: List of tags.
962         :param kwargs: Parameters and their values. The accepted parameters are
963         defined in InterfaceKeywords.SUB_IF_PARAMS.
964         :type node: dict
965         :type super_interface: str
966         :type match: str
967         :type tags: list
968         :type kwargs: dict
969         :return: Content of response.
970         :rtype: bytearray
971         :raises HoneycombError: If the parameter is not valid.
972         :raises KeyError: If the parameter 'match' is invalid.
973         """
974
975         match_type = {
976             "default":
977                 {"default": {}},
978             "untagged":
979                 {"untagged": {}},
980             "vlan-tagged":
981                 {"vlan-tagged": {"match-exact-tags": "false"}},
982             "vlan-tagged-exact-match":
983                 {"vlan-tagged": {"match-exact-tags": "true"}}
984         }
985
986         new_sub_interface = {
987             "tags": {
988                 "tag": []
989             },
990         }
991
992         for param, value in kwargs.items():
993             if param in InterfaceKeywords.SUB_IF_PARAMS:
994                 new_sub_interface[param] = value
995             else:
996                 raise HoneycombError("The parameter {0} is invalid.".
997                                      format(param))
998         try:
999             new_sub_interface["match"] = match_type[match]
1000         except KeyError:
1001             raise HoneycombError("The value '{0}' of parameter 'match' is "
1002                                  "invalid.".format(match))
1003
1004         if tags:
1005             new_sub_interface["tags"]["tag"].extend(tags)
1006
1007         path = ("interfaces",
1008                 ("interface", "name", super_interface),
1009                 "vpp-vlan:sub-interfaces",
1010                 "sub-interface")
1011         new_sub_interface_structure = [new_sub_interface, ]
1012         return InterfaceKeywords._set_interface_properties(
1013             node, super_interface, path, new_sub_interface_structure)
1014
1015     @staticmethod
1016     def get_sub_interface_oper_data(node, super_interface, identifier):
1017         """Retrieves sub-interface operational data using Honeycomb API.
1018
1019         :param node: Honeycomb node.
1020         :param super_interface: Super interface.
1021         :param identifier: The ID of sub-interface.
1022         :type node: dict
1023         :type super_interface: str
1024         :type identifier: int
1025         :return: Sub-interface operational data.
1026         :rtype: dict
1027         :raises HoneycombError: If there is no sub-interface with the given ID.
1028         """
1029
1030         if_data = InterfaceKeywords.get_interface_oper_data(node,
1031                                                             super_interface)
1032         for sub_if in if_data["vpp-vlan:sub-interfaces"]["sub-interface"]:
1033             if str(sub_if["identifier"]) == str(identifier):
1034                 return sub_if
1035
1036         raise HoneycombError("The interface {0} does not have sub-interface "
1037                              "with ID {1}".format(super_interface, identifier))
1038
1039     @staticmethod
1040     def remove_all_sub_interfaces(node, super_interface):
1041         """Remove all sub-interfaces from the given interface.
1042
1043         :param node: Honeycomb node.
1044         :param super_interface: Super interface.
1045         :type node: dict
1046         :type super_interface: str
1047         :return: Content of response.
1048         :rtype: bytearray
1049         """
1050
1051         path = ("interfaces",
1052                 ("interface", "name", super_interface),
1053                 "vpp-vlan:sub-interfaces")
1054
1055         return InterfaceKeywords._set_interface_properties(
1056             node, super_interface, path, {})
1057
1058     @staticmethod
1059     def set_sub_interface_state(node, super_interface, identifier, state):
1060         """Set the administrative state of sub-interface.
1061
1062         :param node: Honeycomb node.
1063         :param super_interface: Super interface.
1064         :param identifier: The ID of sub-interface.
1065         :param state: Required sub-interface state - up or down.
1066         :type node: dict
1067         :type super_interface: str
1068         :type identifier: int
1069         :type state: str
1070         :return: Content of response.
1071         :rtype: bytearray
1072         """
1073
1074         intf_state = {"up": "true",
1075                       "down": "false"}
1076
1077         path = ("interfaces",
1078                 ("interface", "name", super_interface),
1079                 "vpp-vlan:sub-interfaces",
1080                 ("sub-interface", "identifier", identifier),
1081                 "enabled")
1082
1083         return InterfaceKeywords._set_interface_properties(
1084             node, super_interface, path, intf_state[state])
1085
1086     @staticmethod
1087     def add_bridge_domain_to_sub_interface(node, super_interface, identifier,
1088                                            config):
1089         """Add a sub-interface to a bridge domain and set its parameters.
1090
1091         :param node: Honeycomb node.
1092         :param super_interface: Super interface.
1093         :param identifier: The ID of sub-interface.
1094         :param config: Bridge domain configuration.
1095         :type node: dict
1096         :type super_interface: str
1097         :type identifier: int
1098         :type config: dict
1099         :return: Content of response.
1100         :rtype: bytearray
1101         """
1102
1103         path = ("interfaces",
1104                 ("interface", "name", super_interface),
1105                 "vpp-vlan:sub-interfaces",
1106                 ("sub-interface", "identifier", int(identifier)),
1107                 "l2")
1108
1109         return InterfaceKeywords._set_interface_properties(
1110             node, super_interface, path, config)
1111
1112     @staticmethod
1113     def get_bd_data_from_sub_interface(node, super_interface, identifier):
1114         """Get the operational data about the bridge domain from sub-interface.
1115
1116         :param node: Honeycomb node.
1117         :param super_interface: Super interface.
1118         :param identifier: The ID of sub-interface.
1119         :type node: dict
1120         :type super_interface: str
1121         :type identifier: int
1122         :return: Operational data about the bridge domain.
1123         :rtype: dict
1124         :raises HoneycombError: If there is no sub-interface with the given ID.
1125         """
1126
1127         try:
1128             bd_data = InterfaceKeywords.get_sub_interface_oper_data(
1129                 node, super_interface, identifier)["l2"]
1130             return bd_data
1131         except KeyError:
1132             raise HoneycombError("The operational data does not contain "
1133                                  "information about a bridge domain.")
1134
1135     @staticmethod
1136     def configure_tag_rewrite(node, super_interface, identifier, config):
1137         """Add / change / disable vlan tag rewrite on a sub-interface.
1138
1139         :param node: Honeycomb node.
1140         :param super_interface: Super interface.
1141         :param identifier: The ID of sub-interface.
1142         :param config: Rewrite tag configuration.
1143         :type node: dict
1144         :type super_interface: str
1145         :type identifier: int
1146         :type config: dict
1147         :return: Content of response.
1148         :rtype: bytearray
1149         """
1150
1151         path = ("interfaces",
1152                 ("interface", "name", super_interface),
1153                 "vpp-vlan:sub-interfaces",
1154                 ("sub-interface", "identifier", int(identifier)),
1155                 "l2",
1156                 "rewrite")
1157
1158         return InterfaceKeywords._set_interface_properties(
1159             node, super_interface, path, config)
1160
1161     @staticmethod
1162     def get_tag_rewrite_oper_data(node, super_interface, identifier):
1163         """Get the operational data about tag rewrite.
1164
1165         :param node: Honeycomb node.
1166         :param super_interface: Super interface.
1167         :param identifier: The ID of sub-interface.
1168         :type node: dict
1169         :type super_interface: str
1170         :type identifier: int
1171         :return: Operational data about tag rewrite.
1172         :rtype: dict
1173         :raises HoneycombError: If there is no sub-interface with the given ID.
1174         """
1175
1176         try:
1177             tag_rewrite = InterfaceKeywords.get_sub_interface_oper_data(
1178                 node, super_interface, identifier)["l2"]["rewrite"]
1179             return tag_rewrite
1180         except KeyError:
1181             raise HoneycombError("The operational data does not contain "
1182                                  "information about the tag-rewrite.")
1183
1184     @staticmethod
1185     def compare_data_structures(data, ref):
1186         """Checks if data obtained from UUT is as expected.
1187
1188         :param data: Data to be checked.
1189         :param ref: Referential data used for comparison.
1190         :type data: dict
1191         :type ref: dict
1192         :raises HoneycombError: If a parameter from referential data is not
1193         present in operational data or if it has different value.
1194         """
1195
1196         for key, item in ref.items():
1197             try:
1198                 if data[key] != item:
1199                     raise HoneycombError("The value of parameter '{0}' is "
1200                                          "incorrect. It should be "
1201                                          "'{1}' but it is '{2}'".
1202                                          format(key, item, data[key]))
1203             except KeyError:
1204                 raise HoneycombError("The parameter '{0}' is not present in "
1205                                      "operational data".format(key))
1206
1207     @staticmethod
1208     def compare_interface_lists(list1, list2):
1209         """Compare provided lists of interfaces by name.
1210
1211         :param list1: List of interfaces.
1212         :param list2: List of interfaces.
1213         :type list1: list
1214         :type list2: list
1215         :raises HoneycombError: If an interface exists in only one of the lists.
1216         """
1217
1218         ignore = ["vx_tunnel0", "vxlan_gpe_tunnel0"]
1219         # these have no equivalent in config data and no effect on VPP
1220
1221         names1 = [x['name'] for x in list1]
1222         names2 = [x['name'] for x in list2]
1223
1224         for name in names1:
1225             if name not in names2 and name not in ignore:
1226                 raise HoneycombError("Interface {0} not present in list {1}"
1227                                      .format(name, list2))
1228         for name in names2:
1229             if name not in names1 and name not in ignore:
1230                 raise HoneycombError("Interface {0} not present in list {1}"
1231                                      .format(name, list1))
1232
1233     @staticmethod
1234     def create_vxlan_gpe_interface(node, interface, **kwargs):
1235         """Create a new VxLAN GPE interface.
1236
1237         :param node: Honeycomb node.
1238         :param interface: The name of interface to be created.
1239         :param kwargs: Parameters and their values. The accepted parameters are
1240         defined in InterfaceKeywords.VXLAN_GPE_PARAMS.
1241         :type node: dict
1242         :type interface: str
1243         :type kwargs: dict
1244         :return: Content of response.
1245         :rtype: bytearray
1246         :raises HoneycombError: If a parameter in kwargs is not valid.
1247         """
1248
1249         new_vxlan_gpe = {
1250             "name": interface,
1251             "type": "v3po:vxlan-gpe-tunnel",
1252             "v3po:vxlan-gpe": {}
1253         }
1254         for param, value in kwargs.items():
1255             if param in InterfaceKeywords.INTF_PARAMS:
1256                 new_vxlan_gpe[param] = value
1257             elif param in InterfaceKeywords.VXLAN_GPE_PARAMS:
1258                 new_vxlan_gpe["v3po:vxlan-gpe"][param] = value
1259             else:
1260                 raise HoneycombError("The parameter {0} is invalid.".
1261                                      format(param))
1262         path = ("interfaces", "interface")
1263         vxlan_gpe_structure = [new_vxlan_gpe, ]
1264         return InterfaceKeywords._set_interface_properties(
1265             node, interface, path, vxlan_gpe_structure)