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