Add iACL IPv4/IPv6 tests.
[csit.git] / resources / libraries / python / 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
21 from resources.libraries.python.HTTPRequest import HTTPCodes
22 from resources.libraries.python.HoneycombSetup import HoneycombError
23 from resources.libraries.python.HoneycombUtil import HoneycombUtil as HcUtil
24 from resources.libraries.python.HoneycombUtil import DataRepresentation
25
26
27 class InterfaceKeywords(object):
28     """Keywords for Interface manipulation.
29
30     Implements keywords which get configuration and operational data about
31     vpp interfaces and set the interface's parameters using Honeycomb REST API.
32     """
33
34     INTF_PARAMS = ("name", "description", "type", "enabled",
35                    "link-up-down-trap-enable")
36     IPV4_PARAMS = ("enabled", "forwarding", "mtu")
37     IPV6_PARAMS = ("enabled", "forwarding", "mtu", "dup-addr-detect-transmits")
38     IPV6_AUTOCONF_PARAMS = ("create-global-addresses",
39                             "create-temporary-addresses",
40                             "temporary-valid-lifetime",
41                             "temporary-preferred-lifetime")
42     ETH_PARAMS = ("mtu", )
43     ROUTING_PARAMS = ("vrf-id", )
44     VXLAN_PARAMS = ("src", "dst", "vni", "encap-vrf-id")
45     L2_PARAMS = ("bridge-domain", "split-horizon-group",
46                  "bridged-virtual-interface")
47
48     def __init__(self):
49         pass
50
51     @staticmethod
52     def _configure_interface(node, interface, data,
53                              data_representation=DataRepresentation.JSON):
54         """Send interface configuration data and check the response.
55
56         :param node: Honeycomb node.
57         :param interface: The name of interface.
58         :param data: Configuration data to be sent in PUT request.
59         :param data_representation: How the data is represented.
60         :type node: dict
61         :type interface: str
62         :type data: dict
63         :type data_representation: DataRepresentation
64         :return: Content of response.
65         :rtype: bytearray
66         :raises HoneycombError: If the status code in response on PUT is not
67         200 = OK.
68         """
69
70         status_code, resp = HcUtil.\
71             put_honeycomb_data(node, "config_vpp_interfaces", data,
72                                data_representation=data_representation)
73         if status_code != HTTPCodes.OK:
74             raise HoneycombError(
75                 "The configuration of interface '{0}' was not successful. "
76                 "Status code: {1}.".format(interface, status_code))
77         return resp
78
79     @staticmethod
80     def get_all_interfaces_cfg_data(node):
81         """Get configuration data about all interfaces from Honeycomb.
82
83         :param node: Honeycomb node.
84         :type node: dict
85         :return: Configuration data about all interfaces from Honeycomb.
86         :rtype: list
87         :raises HoneycombError: If it is not possible to get configuration data.
88         """
89
90         status_code, resp = HcUtil.\
91             get_honeycomb_data(node, "config_vpp_interfaces")
92         if status_code != HTTPCodes.OK:
93             raise HoneycombError(
94                 "Not possible to get configuration information about the "
95                 "interfaces. Status code: {0}.".format(status_code))
96         try:
97             return resp["interfaces"]["interface"]
98
99         except (KeyError, TypeError):
100             return []
101
102     @staticmethod
103     def get_interface_cfg_data(node, interface):
104         """Get configuration data about the given interface from Honeycomb.
105
106         :param node: Honeycomb node.
107         :param interface: The name of interface.
108         :type node: dict
109         :type interface: str
110         :return: Configuration data about the given interface from Honeycomb.
111         :rtype: dict
112         """
113
114         intfs = InterfaceKeywords.get_all_interfaces_cfg_data(node)
115         for intf in intfs:
116             if intf["name"] == interface:
117                 return intf
118         return {}
119
120     @staticmethod
121     def get_all_interfaces_oper_data(node):
122         """Get operational data about all interfaces from Honeycomb.
123
124         :param node: Honeycomb node.
125         :type node: dict
126         :return: Operational data about all interfaces from Honeycomb.
127         :rtype: list
128         :raises HoneycombError: If it is not possible to get operational data.
129         """
130
131         status_code, resp = HcUtil.\
132             get_honeycomb_data(node, "oper_vpp_interfaces")
133         if status_code != HTTPCodes.OK:
134             raise HoneycombError(
135                 "Not possible to get operational information about the "
136                 "interfaces. Status code: {0}.".format(status_code))
137         try:
138             return resp["interfaces-state"]["interface"]
139
140         except (KeyError, TypeError):
141             return []
142
143     @staticmethod
144     def get_interface_oper_data(node, interface):
145         """Get operational data about the given interface from Honeycomb.
146
147         :param node: Honeycomb node.
148         :param interface: The name of interface.
149         :type node: dict
150         :type interface: str
151         :return: Operational data about the given interface from Honeycomb.
152         :rtype: dict
153         """
154
155         intfs = InterfaceKeywords.get_all_interfaces_oper_data(node)
156         for intf in intfs:
157             if intf["name"] == interface:
158                 return intf
159         return {}
160
161     @staticmethod
162     def _set_interface_properties(node, interface, path, new_value=None):
163         """Set interface properties.
164
165         This method reads interface configuration data, creates, changes or
166         removes the requested data and puts it back to Honeycomb.
167
168         :param node: Honeycomb node.
169         :param interface: The name of interface.
170         :param path:  Path to data we want to change / create / remove.
171         :param new_value: The new value to be set. If None, the item will be
172         removed.
173         :type node: dict
174         :type interface: str
175         :type path: tuple
176         :type new_value: str, dict or list
177         :return: Content of response.
178         :rtype: bytearray
179         :raises HoneycombError: If it is not possible to get or set the data.
180         """
181
182         status_code, resp = HcUtil.\
183             get_honeycomb_data(node, "config_vpp_interfaces")
184         if status_code != HTTPCodes.OK:
185             raise HoneycombError(
186                 "Not possible to get configuration information about the "
187                 "interfaces. Status code: {0}.".format(status_code))
188
189         if new_value:
190             new_data = HcUtil.set_item_value(resp, path, new_value)
191         else:
192             new_data = HcUtil.remove_item(resp, path)
193         return InterfaceKeywords._configure_interface(node, interface, new_data)
194
195     @staticmethod
196     def set_interface_state(node, interface, state="up"):
197         """Set VPP interface state.
198
199         The keyword changes the administration state of interface to up or down
200         depending on the parameter "state".
201
202         :param node: Honeycomb node.
203         :param interface: The name of interface.
204         :param state: The requested state, only "up" and "down" are valid
205         values.
206         :type node: dict
207         :type interface: str
208         :type state: str
209         :return: Content of response.
210         :rtype: bytearray
211         :raises KeyError: If the argument "state" is nor "up" or "down".
212         :raises HoneycombError: If the interface is not present on the node.
213         """
214
215         intf_state = {"up": "true",
216                       "down": "false"}
217
218         path = ("interfaces", ("interface", "name", str(interface)), "enabled")
219         return InterfaceKeywords._set_interface_properties(
220             node, interface, path, intf_state[state.lower()])
221
222     @staticmethod
223     def set_interface_up(node, interface):
224         """Set the administration state of VPP interface to up.
225
226         :param node: Honeycomb node.
227         :param interface: The name of interface.
228         :type node: dict
229         :type interface: str
230         :return: Content of response
231         :rtype: bytearray
232         """
233
234         return InterfaceKeywords.set_interface_state(node, interface, "up")
235
236     @staticmethod
237     def set_interface_down(node, interface):
238         """Set the administration state of VPP interface to down.
239
240         :param node: Honeycomb node.
241         :param interface: The name of interface.
242         :type node: dict
243         :type interface: str
244         :return: Content of response.
245         :rtype: bytearray
246         """
247
248         return InterfaceKeywords.set_interface_state(node, interface, "down")
249
250     @staticmethod
251     def add_bridge_domain_to_interface(node, interface, bd_name,
252                                        split_horizon_group=None, bvi=None):
253         """Add a new bridge domain to an interface and set its parameters.
254
255         :param node: Honeycomb node.
256         :param interface: The name of interface.
257         :param bd_name: Bridge domain name.
258         :param split_horizon_group: Split-horizon group name.
259         :param bvi: The bridged virtual interface.
260         :type node: dict
261         :type interface: str
262         :type bd_name: str
263         :type split_horizon_group: str
264         :type bvi: str
265         :return: Content of response.
266         :rtype: bytearray
267         :raises HoneycombError: If the interface is not present on the node.
268         """
269
270         v3po_l2 = {"bridge-domain": str(bd_name)}
271         if split_horizon_group:
272             v3po_l2["split-horizon-group"] = str(split_horizon_group)
273         if bvi:
274             v3po_l2["bridged-virtual-interface"] = str(bvi)
275
276         path = ("interfaces", ("interface", "name", str(interface)), "v3po:l2")
277
278         return InterfaceKeywords._set_interface_properties(
279             node, interface, path, v3po_l2)
280
281     @staticmethod
282     def configure_interface_base(node, interface, param, value):
283         """Configure the base parameters of interface.
284
285         :param node: Honeycomb node.
286         :param interface: The name of interface.
287         :param param: Parameter to configure (set, change, remove)
288         :param value: The value of parameter. If None, the parameter will be
289         removed.
290         :type node: dict
291         :type interface: str
292         :type param: str
293         :type value: str
294         :return: Content of response.
295         :rtype: bytearray
296         :raises HoneycombError: If the parameter is not valid.
297         """
298
299         if param not in InterfaceKeywords.INTF_PARAMS:
300             raise HoneycombError("The parameter {0} is invalid.".format(param))
301
302         path = ("interfaces", ("interface", "name", interface), param)
303         return InterfaceKeywords._set_interface_properties(
304             node, interface, path, value)
305
306     @staticmethod
307     def configure_interface_ipv4(node, interface, param, value):
308         """Configure IPv4 parameters of interface
309
310         :param node: Honeycomb node.
311         :param interface: The name of interface.
312         :param param: Parameter to configure (set, change, remove)
313         :param value: The value of parameter. If None, the parameter will be
314         removed.
315         :type node: dict
316         :type interface: str
317         :type param: str
318         :type value: str
319         :return: Content of response.
320         :rtype: bytearray
321         :raises HoneycombError: If the parameter is not valid.
322         """
323
324         if param not in InterfaceKeywords.IPV4_PARAMS:
325             raise HoneycombError("The parameter {0} is invalid.".format(param))
326
327         path = ("interfaces", ("interface", "name", interface),
328                 "ietf-ip:ipv4", param)
329         return InterfaceKeywords._set_interface_properties(
330             node, interface, path, value)
331
332     @staticmethod
333     def add_first_ipv4_address(node, interface, ip_addr, netmask):
334         """Add the first IPv4 address.
335
336         If there are any other addresses configured, they will be removed.
337
338         :param node: Honeycomb node.
339         :param interface: The name of interface.
340         :param ip_addr: IPv4 address to be set.
341         :param netmask: Netmask.
342         :type node: dict
343         :type interface: str
344         :type ip_addr: str
345         :type netmask: str
346         :return: Content of response.
347         :rtype: bytearray
348         """
349
350         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
351         address = {"address": [{"ip": ip_addr, "netmask": netmask}, ]}
352         return InterfaceKeywords._set_interface_properties(
353             node, interface, path, address)
354
355     @staticmethod
356     def add_ipv4_address(node, interface, ip_addr, netmask):
357         """Add IPv4 address.
358
359         :param node: Honeycomb node.
360         :param interface: The name of interface.
361         :param ip_addr: IPv4 address to be set.
362         :param netmask: Netmask.
363         :type node: dict
364         :type interface: str
365         :type ip_addr: str
366         :type netmask: str
367         :return: Content of response.
368         :rtype: bytearray
369         """
370
371         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
372                 "address")
373         address = [{"ip": ip_addr, "prefix-length": netmask}, ]
374         return InterfaceKeywords._set_interface_properties(
375             node, interface, path, address)
376
377     @staticmethod
378     def remove_all_ipv4_addresses(node, interface):
379         """Remove all IPv4 addresses from interface.
380
381         :param node: Honeycomb node.
382         :param interface: The name of interface.
383         :type node: dict
384         :type interface: str
385         :return: Content of response.
386         :rtype: bytearray
387         """
388
389         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
390                 "address")
391         return InterfaceKeywords._set_interface_properties(
392             node, interface, path, None)
393
394     @staticmethod
395     def add_first_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
396         """Add the first IPv4 neighbour.
397
398         If there are any other neighbours configured, they will be removed.
399
400         :param node: Honeycomb node.
401         :param interface: The name of interface.
402         :param ip_addr: IPv4 address of neighbour to be set.
403         :param link_layer_address: Link layer address.
404         :type node: dict
405         :type interface: str
406         :type ip_addr: str
407         :type link_layer_address: str
408         :return: Content of response.
409         :rtype: bytearray
410         """
411
412         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
413         neighbor = {"neighbor": [{"ip": ip_addr,
414                                   "link-layer-address": link_layer_address}, ]}
415         return InterfaceKeywords._set_interface_properties(
416             node, interface, path, neighbor)
417
418     @staticmethod
419     def add_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
420         """Add the IPv4 neighbour.
421
422         :param node: Honeycomb node.
423         :param interface: The name of interface.
424         :param ip_addr: IPv4 address of neighbour to be set.
425         :param link_layer_address: Link layer address.
426         :type node: dict
427         :type interface: str
428         :type ip_addr: str
429         :type link_layer_address: str
430         :return: Content of response.
431         :rtype: bytearray
432         """
433
434         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
435                 "neighbor")
436         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
437         return InterfaceKeywords._set_interface_properties(
438             node, interface, path, neighbor)
439
440     @staticmethod
441     def remove_all_ipv4_neighbors(node, interface):
442         """Remove all IPv4 neighbours.
443
444         :param node: Honeycomb node.
445         :param interface: The name of interface.
446         :type node: dict
447         :type interface: str
448         :return: Content of response.
449         :rtype: bytearray
450         """
451
452         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
453                 "neighbor")
454         return InterfaceKeywords._set_interface_properties(
455             node, interface, path, None)
456
457     @staticmethod
458     def configure_interface_ipv6(node, interface, param, value):
459         """Configure IPv6 parameters of interface
460
461         :param node: Honeycomb node.
462         :param interface: The name of interface.
463         :param param: Parameter to configure (set, change, remove)
464         :param value: The value of parameter. If None, the parameter will be
465         removed.
466         :type node: dict
467         :type interface: str
468         :type param: str
469         :type value: str
470         :return: Content of response.
471         :rtype: bytearray
472         :raises HoneycombError: If the parameter is not valid.
473         """
474
475         if param in InterfaceKeywords.IPV6_PARAMS:
476             path = ("interfaces", ("interface", "name", interface),
477                     "ietf-ip:ipv6", param)
478         elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
479             path = ("interfaces", ("interface", "name", interface),
480                     "ietf-ip:ipv6", "autoconf", param)
481         else:
482             raise HoneycombError("The parameter {0} is invalid.".format(param))
483
484         return InterfaceKeywords._set_interface_properties(
485             node, interface, path, value)
486
487     @staticmethod
488     def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
489         """Add the first IPv6 address.
490
491         If there are any other addresses configured, they will be removed.
492
493         :param node: Honeycomb node.
494         :param interface: The name of interface.
495         :param ip_addr: IPv6 address to be set.
496         :param prefix_len: Prefix length.
497         :type node: dict
498         :type interface: str
499         :type ip_addr: str
500         :type prefix_len: str
501         :return: Content of response.
502         :rtype: bytearray
503         """
504
505         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
506         address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
507         return InterfaceKeywords._set_interface_properties(
508             node, interface, path, address)
509
510     @staticmethod
511     def add_ipv6_address(node, interface, ip_addr, prefix_len):
512         """Add IPv6 address.
513
514         :param node: Honeycomb node.
515         :param interface: The name of interface.
516         :param ip_addr: IPv6 address to be set.
517         :param prefix_len: Prefix length.
518         :type node: dict
519         :type interface: str
520         :type ip_addr: str
521         :type prefix_len: str
522         :return: Content of response.
523         :rtype: bytearray
524         """
525
526         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
527                 "address")
528         address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
529         return InterfaceKeywords._set_interface_properties(
530             node, interface, path, address)
531
532     @staticmethod
533     def remove_all_ipv6_addresses(node, interface):
534         """Remove all IPv6 addresses from interface.
535
536         :param node: Honeycomb node.
537         :param interface: The name of interface.
538         :type node: dict
539         :type interface: str
540         :return: Content of response.
541         :rtype: bytearray
542         """
543
544         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
545                 "address")
546         return InterfaceKeywords._set_interface_properties(
547             node, interface, path, None)
548
549     @staticmethod
550     def add_first_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
551         """Add the first IPv6 neighbour.
552
553         If there are any other neighbours configured, they will be removed.
554
555         :param node: Honeycomb node.
556         :param interface: The name of interface.
557         :param ip_addr: IPv6 address of neighbour to be set.
558         :param link_layer_address: Link layer address.
559         :type node: dict
560         :type interface: str
561         :type ip_addr: str
562         :type link_layer_address: str
563         :return: Content of response.
564         :rtype: bytearray
565         """
566
567         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
568         neighbor = {"neighbor": [{"ip": ip_addr,
569                                   "link-layer-address": link_layer_address}, ]}
570         return InterfaceKeywords._set_interface_properties(
571             node, interface, path, neighbor)
572
573     @staticmethod
574     def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
575         """Add the IPv6 neighbour.
576
577         :param node: Honeycomb node.
578         :param interface: The name of interface.
579         :param ip_addr: IPv6 address of neighbour to be set.
580         :param link_layer_address: Link layer address.
581         :type node: dict
582         :type interface: str
583         :type ip_addr: str
584         :type link_layer_address: str
585         :return: Content of response.
586         :rtype: bytearray
587         """
588
589         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
590                 "neighbor")
591         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
592         return InterfaceKeywords._set_interface_properties(
593             node, interface, path, neighbor)
594
595     @staticmethod
596     def remove_all_ipv6_neighbors(node, interface):
597         """Remove all IPv6 neighbours.
598
599         :param node: Honeycomb node.
600         :param interface: The name of interface.
601         :type node: dict
602         :type interface: str
603         :return: Content of response.
604         :rtype: bytearray
605         """
606
607         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
608                 "neighbor")
609         return InterfaceKeywords._set_interface_properties(
610             node, interface, path, None)
611
612     @staticmethod
613     def configure_interface_ethernet(node, interface, param, value):
614         """Configure the ethernet parameters of interface.
615
616         :param node: Honeycomb node.
617         :param interface: The name of interface.
618         :param param: Parameter to configure (set, change, remove)
619         :param value: The value of parameter. If None, the parameter will be
620         removed.
621         :type node: dict
622         :type interface: str
623         :type param: str
624         :type value: str
625         :return: Content of response.
626         :rtype: bytearray
627         :raises HoneycombError: If the parameter is not valid.
628         """
629
630         if param not in InterfaceKeywords.ETH_PARAMS:
631             raise HoneycombError("The parameter {0} is invalid.".format(param))
632         path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
633                 param)
634         return InterfaceKeywords._set_interface_properties(
635             node, interface, path, value)
636
637     @staticmethod
638     def configure_interface_routing(node, interface, param, value):
639         """Configure the routing parameters of interface.
640
641         :param node: Honeycomb node.
642         :param interface: The name of interface.
643         :param param: Parameter to configure (set, change, remove)
644         :param value: The value of parameter. If None, the parameter will be
645         removed.
646         :type node: dict
647         :type interface: str
648         :type param: str
649         :type value: str
650         :return: Content of response.
651         :rtype: bytearray
652         :raises HoneycombError: If the parameter is not valid.
653         """
654
655         if param not in InterfaceKeywords.ROUTING_PARAMS:
656             raise HoneycombError("The parameter {0} is invalid.".format(param))
657
658         path = ("interfaces", ("interface", "name", interface), "v3po:routing",
659                 param)
660         return InterfaceKeywords._set_interface_properties(
661             node, interface, path, value)
662
663     @staticmethod
664     def configure_interface_vxlan(node, interface, param, value):
665         """Configure the VxLAN parameters of interface.
666
667         :param node: Honeycomb node.
668         :param interface: The name of interface.
669         :param param: Parameter to configure (set, change, remove)
670         :param value: The value of parameter. If None, the parameter will be
671         removed.
672         :type node: dict
673         :type interface: str
674         :type param: str
675         :type value: str
676         :return: Content of response.
677         :rtype: bytearray
678         :raises HoneycombError: If the parameter is not valid.
679         """
680
681         if param not in InterfaceKeywords.VXLAN_PARAMS:
682             raise HoneycombError("The parameter {0} is invalid.".format(param))
683
684         path = ("interfaces", ("interface", "name", interface), "v3po:vxlan",
685                 param)
686         return InterfaceKeywords._set_interface_properties(
687             node, interface, path, value)
688
689     @staticmethod
690     def configure_interface_l2(node, interface, param, value):
691         """Configure the L2 parameters of interface.
692
693         :param node: Honeycomb node.
694         :param interface: The name of interface.
695         :param param: Parameter to configure (set, change, remove)
696         :param value: The value of parameter. If None, the parameter will be
697         removed.
698         :type node: dict
699         :type interface: str
700         :type param: str
701         :type value: str
702         :return: Content of response.
703         :rtype: bytearray
704         :raises HoneycombError: If the parameter is not valid.
705         """
706
707         if param not in InterfaceKeywords.L2_PARAMS:
708             raise HoneycombError("The parameter {0} is invalid.".format(param))
709         path = ("interfaces", ("interface", "name", interface), "v3po:l2",
710                 param)
711         return InterfaceKeywords._set_interface_properties(
712             node, interface, path, value)