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