2f7c149684722a5c2138f3f310c87a5ae1a98ce6
[csit.git] / resources / libraries / python / HcAPIKwBridgeDomain.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 bridge domain 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 BridgeDomainKeywords(object):
28     """Keywords to manipulate bridge domain configuration.
29
30     Implements keywords which get configuration and operational data about
31     bridge domains and put the bridge domains' parameters using Honeycomb REST
32     API.
33     """
34
35     PARAMS = ("flood", "forward", "learn", "unknown-unicast-flood",
36               "arp-termination")
37
38     def __init__(self):
39         pass
40
41     @staticmethod
42     def _configure_bd(node, bd_name, data,
43                       data_representation=DataRepresentation.JSON):
44         """Send bridge domain configuration data and check the response.
45
46         :param node: Honeycomb node.
47         :param bd_name: The name of bridge domain.
48         :param data: Configuration data to be sent in PUT request.
49         :param data_representation: How the data is represented.
50         :type node: dict
51         :type bd_name: str
52         :type data: dict
53         :type data_representation: DataRepresentation
54         :return: Content of response.
55         :rtype: bytearray
56         :raises HoneycombError: If the status code in response on PUT is not
57         200 = OK.
58         """
59
60         status_code, resp = HcUtil.\
61             put_honeycomb_data(node, "config_bridge_domain", data,
62                                data_representation=data_representation)
63         if status_code != HTTPCodes.OK:
64             raise HoneycombError(
65                 "The configuration of bridge domain '{0}' was not successful. "
66                 "Status code: {1}.".format(bd_name, status_code))
67         return resp
68
69     @staticmethod
70     def _set_bd_properties(node, bd_name, path, new_value=None):
71         """Set bridge domain properties.
72
73         This method reads bridge domain configuration data, creates, changes or
74         removes the requested data and puts it back to Honeycomb.
75
76         :param node: Honeycomb node.
77         :param bd_name: The name of bridge domain.
78         :param path:  Path to data we want to change, create or remove.
79         :param new_value: The new value to be set. If None, the item will be
80         removed.
81         :type node: dict
82         :type bd_name: str
83         :type path: tuple
84         :type new_value: str, dict or list
85         :return: Content of response.
86         :rtype: bytearray
87         :raises HoneycombError: If it is not possible to get or set the data.
88         """
89
90         status_code, resp = HcUtil.\
91             get_honeycomb_data(node, "config_bridge_domain")
92         if status_code != HTTPCodes.OK:
93             raise HoneycombError(
94                 "Not possible to get configuration information about the "
95                 "bridge domains. Status code: {0}.".format(status_code))
96
97         if new_value:
98             new_data = HcUtil.set_item_value(resp, path, new_value)
99         else:
100             new_data = HcUtil.remove_item(resp, path)
101         return BridgeDomainKeywords._configure_bd(node, bd_name, new_data)
102
103     @staticmethod
104     def _create_bd_structure(bd_name, **kwargs):
105         """Create the bridge domain data structure as it is expected by
106         Honeycomb REST API.
107
108         :param bd_name: Bridge domain name.
109         :param kwargs: Parameters and their values. The accepted parameters are
110         defined in BridgeDomainKeywords.PARAMS.
111         :type bd_name: str
112         :type kwargs: dict
113         :return: Bridge domain data structure.
114         :rtype: dict
115         """
116
117         bd_structure = {"name": bd_name}
118
119         for param, value in kwargs.items():
120             if param not in BridgeDomainKeywords.PARAMS:
121                 raise HoneycombError("The parameter {0} is invalid.".
122                                      format(param))
123             bd_structure[param] = str(value)
124
125         return bd_structure
126
127     @staticmethod
128     def get_all_bds_cfg_data(node):
129         """Get configuration data about all bridge domains from Honeycomb.
130
131         :param node: Honeycomb node.
132         :type node: dict
133         :return: Configuration data about all bridge domains from Honeycomb.
134         :rtype: list
135         :raises HoneycombError: If it is not possible to get configuration data.
136         """
137
138         status_code, resp = HcUtil.\
139             get_honeycomb_data(node, "config_bridge_domain")
140         if status_code != HTTPCodes.OK:
141             raise HoneycombError(
142                 "Not possible to get configuration information about the "
143                 "bridge domains. Status code: {0}.".format(status_code))
144         try:
145             return resp["bridge-domains"]["bridge-domain"]
146
147         except (KeyError, TypeError):
148             return []
149
150     @staticmethod
151     def get_bd_cfg_data(node, bd_name):
152         """Get configuration data about the given bridge domain from Honeycomb.
153
154         :param node: Honeycomb node.
155         :param bd_name: The name of bridge domain.
156         :type node: dict
157         :type bd_name: str
158         :return: Configuration data about the given bridge domain from
159         Honeycomb.
160         :rtype: dict
161         """
162
163         intfs = BridgeDomainKeywords.get_all_bds_cfg_data(node)
164         for intf in intfs:
165             if intf["name"] == bd_name:
166                 return intf
167         return {}
168
169     @staticmethod
170     def get_all_bds_oper_data(node):
171         """Get operational data about all bridge domains from Honeycomb.
172
173         :param node: Honeycomb node.
174         :type node: dict
175         :return: Operational data about all bridge domains from Honeycomb.
176         :rtype: list
177         :raises HoneycombError: If it is not possible to get operational data.
178         """
179
180         status_code, resp = HcUtil.\
181             get_honeycomb_data(node, "oper_bridge_domains")
182         if status_code != HTTPCodes.OK:
183             raise HoneycombError(
184                 "Not possible to get operational information about the "
185                 "bridge domains. Status code: {0}.".format(status_code))
186         try:
187             return resp["bridge-domains"]["bridge-domain"]
188
189         except (KeyError, TypeError):
190             return []
191
192     @staticmethod
193     def get_bd_oper_data(node, bd_name):
194         """Get operational data about the given bridge domain from Honeycomb.
195
196         :param node: Honeycomb node.
197         :param bd_name: The name of bridge domain.
198         :type node: dict
199         :type bd_name: str
200         :return: Operational data about the given bridge domain from Honeycomb.
201         :rtype: dict
202         """
203
204         intfs = BridgeDomainKeywords.get_all_bds_oper_data(node)
205         for intf in intfs:
206             if intf["name"] == bd_name:
207                 return intf
208         return {}
209
210     @staticmethod
211     def add_first_bd(node, bd_name, **kwargs):
212         """Add the first bridge domain.
213
214         If there are any other bridge domains configured, they will be removed.
215
216         :param node: Honeycomb node.
217         :param bd_name: Bridge domain name.
218         :param kwargs: Parameters and their values. The accepted parameters are
219         defined in BridgeDomainKeywords.PARAMS
220         :type node: dict
221         :type bd_name: str
222         :type kwargs: dict
223         :return: Bridge domain data structure.
224         :rtype: dict
225         """
226
227         path = ("bridge-domains", )
228         new_bd = BridgeDomainKeywords._create_bd_structure(bd_name, **kwargs)
229         bridge_domain = {"bridge-domain": [new_bd, ]}
230         return BridgeDomainKeywords._set_bd_properties(node, bd_name, path,
231                                                        bridge_domain)
232
233     @staticmethod
234     def add_bd(node, bd_name, **kwargs):
235         """Add a bridge domain.
236
237         :param node: Honeycomb node.
238         :param bd_name: Bridge domain name.
239         :param kwargs: Parameters and their values. The accepted parameters are
240         defined in BridgeDomainKeywords.PARAMS
241         :type node: dict
242         :type bd_name: str
243         :type kwargs: dict
244         :return: Bridge domain data structure.
245         :rtype: dict
246         """
247
248         path = ("bridge-domains", "bridge-domain")
249         new_bd = BridgeDomainKeywords._create_bd_structure(bd_name, **kwargs)
250         bridge_domain = [new_bd, ]
251         return BridgeDomainKeywords._set_bd_properties(node, bd_name, path,
252                                                        bridge_domain)
253
254     @staticmethod
255     def remove_all_bds(node):
256         """Remove all bridge domains.
257
258         :param node: Honeycomb node.
259         :type node: dict
260         :return: Content of response.
261         :rtype: bytearray
262         :raises HoneycombError: If it is not possible to remove all bridge
263         domains.
264         """
265
266         data = {"bridge-domains": {"bridge-domain": []}}
267         status_code, resp = HcUtil.\
268             put_honeycomb_data(node, "config_bridge_domain", data)
269         if status_code != HTTPCodes.OK:
270             raise HoneycombError("Not possible to remove all bridge domains. "
271                                  "Status code: {0}.".format(status_code))
272         return resp
273
274     @staticmethod
275     def remove_bridge_domain(node, bd_name):
276         """Remove a bridge domain.
277
278         :param node:  Honeycomb node.
279         :param bd_name: The name of bridge domain to be removed.
280         :type node: dict
281         :type bd_name: str
282         :return: Content of response.
283         :rtype: bytearray
284         :raises HoneycombError:If it is not possible to remove the bridge
285         domain.
286         """
287
288         path = ("bridge-domains", ("bridge-domain", "name", bd_name))
289
290         status_code, resp = HcUtil.\
291             get_honeycomb_data(node, "config_bridge_domain")
292         if status_code != HTTPCodes.OK:
293             raise HoneycombError(
294                 "Not possible to get configuration information about the "
295                 "bridge domains. Status code: {0}.".format(status_code))
296
297         new_data = HcUtil.remove_item(resp, path)
298         status_code, resp = HcUtil.\
299             put_honeycomb_data(node, "config_bridge_domain", new_data)
300         if status_code != HTTPCodes.OK:
301             raise HoneycombError("Not possible to remove bridge domain {0}. "
302                                  "Status code: {1}.".
303                                  format(bd_name, status_code))
304         return resp
305
306     @staticmethod
307     def configure_bridge_domain(node, bd_name, param, value):
308         """Configure a bridge domain.
309
310         :param node: Honeycomb node.
311         :param bd_name: Bridge domain name.
312         :param param: Parameter to set, change or remove. The accepted
313         parameters are defined in BridgeDomainKeywords.PARAMS
314         :param value: The new value to be set, change or remove. If None, the
315         item will be removed.
316         :type node: dict
317         :type bd_name: str
318         :type param: str
319         :type value: str
320         :return: Content of response.
321         :rtype: bytearray
322         """
323
324         if param not in BridgeDomainKeywords.PARAMS:
325             raise HoneycombError("The parameter {0} is invalid.".format(param))
326
327         path = ("bridge-domains", ("bridge-domain", "name", bd_name), param)
328         return BridgeDomainKeywords.\
329             _set_bd_properties(node, bd_name, path, value)