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:
6 # http://www.apache.org/licenses/LICENSE-2.0
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.
14 """Keywords to manipulate bridge domain configuration using Honeycomb REST API.
16 The keywords make possible to put and get configuration data and to get
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
28 class BridgeDomainKeywords(object):
29 """Keywords to manipulate bridge domain configuration.
31 Implements keywords which get configuration and operational data about
32 bridge domains and put the bridge domains' parameters using Honeycomb REST
36 PARAMS = ("flood", "forward", "learn", "unknown-unicast-flood",
43 def _configure_bd(node, bd_name, data,
44 data_representation=DataRepresentation.JSON):
45 """Send bridge domain configuration data and check the response.
47 :param node: Honeycomb node.
48 :param bd_name: The name of bridge domain.
49 :param data: Configuration data to be sent in PUT request.
50 :param data_representation: How the data is represented.
54 :type data_representation: DataRepresentation
55 :return: Content of response.
57 :raises HoneycombError: If the status code in response on PUT is not
61 status_code, resp = HcUtil.\
62 put_honeycomb_data(node, "config_bridge_domain", data,
63 data_representation=data_representation)
64 if status_code != HTTPCodes.OK:
66 "The configuration of bridge domain '{0}' was not successful. "
67 "Status code: {1}.".format(bd_name, status_code))
71 def _set_bd_properties(node, bd_name, path, new_value=None):
72 """Set bridge domain properties.
74 This method reads bridge domain configuration data, creates, changes or
75 removes the requested data and puts it back to Honeycomb.
77 :param node: Honeycomb node.
78 :param bd_name: The name of bridge domain.
79 :param path: Path to data we want to change, create or remove.
80 :param new_value: The new value to be set. If None, the item will be
85 :type new_value: str, dict or list
86 :return: Content of response.
88 :raises HoneycombError: If it is not possible to get or set the data.
91 status_code, resp = HcUtil.\
92 get_honeycomb_data(node, "config_bridge_domain")
93 if status_code != HTTPCodes.OK:
95 "Not possible to get configuration information about the "
96 "bridge domains. Status code: {0}.".format(status_code))
99 new_data = HcUtil.set_item_value(resp, path, new_value)
101 new_data = HcUtil.remove_item(resp, path)
103 return BridgeDomainKeywords._configure_bd(node, bd_name, new_data)
106 def _create_bd_structure(bd_name, **kwargs):
107 """Create the bridge domain data structure as it is expected by
110 :param bd_name: Bridge domain name.
111 :param kwargs: Parameters and their values. The accepted parameters are
112 defined in BridgeDomainKeywords.PARAMS.
115 :return: Bridge domain data structure.
119 bd_structure = {"name": bd_name}
121 for param, value in kwargs.items():
122 if param not in BridgeDomainKeywords.PARAMS:
123 raise HoneycombError("The parameter {0} is invalid.".
125 bd_structure[param] = str(value)
130 def get_all_bds_cfg_data(node):
131 """Get configuration data about all bridge domains from Honeycomb.
133 :param node: Honeycomb node.
135 :return: Configuration data about all bridge domains from Honeycomb.
137 :raises HoneycombError: If it is not possible to get configuration data.
140 status_code, resp = HcUtil.\
141 get_honeycomb_data(node, "config_bridge_domain")
142 if status_code != HTTPCodes.OK:
143 raise HoneycombError(
144 "Not possible to get configuration information about the "
145 "bridge domains. Status code: {0}.".format(status_code))
147 return resp["bridge-domains"]["bridge-domain"]
149 except (KeyError, TypeError):
153 def get_bd_cfg_data(node, bd_name):
154 """Get configuration data about the given bridge domain from Honeycomb.
156 :param node: Honeycomb node.
157 :param bd_name: The name of bridge domain.
160 :return: Configuration data about the given bridge domain from
165 intfs = BridgeDomainKeywords.get_all_bds_cfg_data(node)
167 if intf["name"] == bd_name:
172 def get_all_bds_oper_data(node):
173 """Get operational data about all bridge domains from Honeycomb.
175 :param node: Honeycomb node.
177 :return: Operational data about all bridge domains from Honeycomb.
179 :raises HoneycombError: If it is not possible to get operational data.
182 status_code, resp = HcUtil.\
183 get_honeycomb_data(node, "oper_bridge_domains")
184 if status_code != HTTPCodes.OK:
185 raise HoneycombError(
186 "Not possible to get operational information about the "
187 "bridge domains. Status code: {0}.".format(status_code))
189 return resp["bridge-domains"]["bridge-domain"]
191 except (KeyError, TypeError):
195 def get_bd_oper_data(node, bd_name):
196 """Get operational data about the given bridge domain from Honeycomb.
198 :param node: Honeycomb node.
199 :param bd_name: The name of bridge domain.
202 :return: Operational data about the given bridge domain from Honeycomb.
206 intfs = BridgeDomainKeywords.get_all_bds_oper_data(node)
208 if intf["name"] == bd_name:
213 def add_first_bd(node, bd_name, **kwargs):
214 """Add the first bridge domain.
216 If there are any other bridge domains configured, they will be removed.
218 :param node: Honeycomb node.
219 :param bd_name: Bridge domain name.
220 :param kwargs: Parameters and their values. The accepted parameters are
221 defined in BridgeDomainKeywords.PARAMS
225 :return: Bridge domain data structure.
229 path = ("bridge-domains", )
230 new_bd = BridgeDomainKeywords._create_bd_structure(bd_name, **kwargs)
231 bridge_domain = {"bridge-domain": [new_bd, ]}
232 return BridgeDomainKeywords._set_bd_properties(node, bd_name, path,
236 def add_bd(node, bd_name, **kwargs):
237 """Add a bridge domain.
239 :param node: Honeycomb node.
240 :param bd_name: Bridge domain name.
241 :param kwargs: Parameters and their values. The accepted parameters are
242 defined in BridgeDomainKeywords.PARAMS
246 :return: Bridge domain data structure.
250 path = ("bridge-domains", "bridge-domain")
251 new_bd = BridgeDomainKeywords._create_bd_structure(bd_name, **kwargs)
252 bridge_domain = [new_bd, ]
253 return BridgeDomainKeywords._set_bd_properties(node, bd_name, path,
257 def remove_all_bridge_domains(node):
258 """Remove all bridge domains.
260 :param node: Honeycomb node.
262 :return: Content of response.
264 :raises HoneycombError: If it is not possible to remove all bridge
268 data = {"bridge-domains": {"bridge-domain": []}}
270 status_code, resp = HcUtil.\
271 put_honeycomb_data(node, "config_bridge_domain", data)
273 if status_code != HTTPCodes.OK:
274 raise HoneycombError("Not possible to remove all bridge domains. "
275 "Status code: {0}.".format(status_code))
279 def remove_bridge_domain(node, bd_name):
280 """Remove a bridge domain.
282 :param node: Honeycomb node.
283 :param bd_name: The name of bridge domain to be removed.
286 :return: Content of response.
288 :raises HoneycombError:If it is not possible to remove the bridge
292 path = ("bridge-domains", ("bridge-domain", "name", bd_name))
294 status_code, resp = HcUtil.\
295 get_honeycomb_data(node, "config_bridge_domain")
296 if status_code != HTTPCodes.OK:
297 raise HoneycombError(
298 "Not possible to get configuration information about the "
299 "bridge domains. Status code: {0}.".format(status_code))
301 new_data = HcUtil.remove_item(resp, path)
302 status_code, resp = HcUtil.\
303 put_honeycomb_data(node, "config_bridge_domain", new_data)
304 if status_code != HTTPCodes.OK:
305 raise HoneycombError("Not possible to remove bridge domain {0}. "
307 format(bd_name, status_code))
311 def configure_bridge_domain(node, bd_name, param, value):
312 """Configure a bridge domain.
314 :param node: Honeycomb node.
315 :param bd_name: Bridge domain name.
316 :param param: Parameter to set, change or remove. The accepted
317 parameters are defined in BridgeDomainKeywords.PARAMS
318 :param value: The new value to be set, change or remove. If None, the
319 item will be removed.
324 :return: Content of response.
328 if param not in BridgeDomainKeywords.PARAMS:
329 raise HoneycombError("The parameter {0} is invalid.".format(param))
331 path = ("bridge-domains", ("bridge-domain", "name", bd_name), param)
332 return BridgeDomainKeywords.\
333 _set_bd_properties(node, bd_name, path, value)
336 def add_l2_fib_entry(node, bd_name, l2_fib_entry):
337 """Add an L2 FIB entry to the bridge domain's list of L2 FIB entries.
339 :param node: Honeycomb node.
340 :param bd_name: Bridge domain's name.
341 :param l2_fib_entry: L2 FIB entry to be added to the L2 FIB table.
344 :type l2_fib_entry: dict
345 :return: Content of response.
349 path = ("bridge-domains",
350 ("bridge-domain", "name", bd_name),
354 new_l2_fib_entry = [l2_fib_entry, ]
355 return BridgeDomainKeywords._set_bd_properties(
356 node, bd_name, path, new_l2_fib_entry)
359 def modify_l2_fib_entry(node, bd_name, mac, param, value):
360 """Modify an existing L2 FIB entry in the bridge domain's L2 FIB table.
361 The L2 FIB entry is specified by MAC address.
363 :param node: Honeycomb node.
364 :param bd_name: Bridge domain's name.
365 :param mac: MAC address used as the key in L2 FIB data structure.
366 :param param: The parameter to be modified.
367 :param value: The new value of the parameter.
372 :type value: str or int
373 :return: Content of response.
377 path = ("bridge-domains",
378 ("bridge-domain", "name", bd_name),
380 ("l2-fib-entry", "phys-address", mac),
383 return BridgeDomainKeywords._set_bd_properties(
384 node, bd_name, path, value)
387 def remove_l2_fib_entry(node, bd_name, mac):
388 """Remove an L2 FIB entry from bridge domain's L2 FIB table. The
389 entry is specified by MAC address.
391 :param node: Honeycomb node.
392 :param bd_name: Bridge domain's name.
393 :param mac: MAC address used as the key in L2 FIB data structure.
397 :return: Content of response.
399 :raises HoneycombError: If it is not possible to remove the specified
403 path = ("bridge-domains",
404 ("bridge-domain", "name", bd_name),
406 ("l2-fib-entry", "phys-address", str(mac)))
408 status_code, resp = HcUtil.\
409 get_honeycomb_data(node, "config_bridge_domain")
410 if status_code != HTTPCodes.OK:
411 raise HoneycombError("Not possible to get configuration information"
412 " about the L2 FIB entry {0} from bridge "
413 "domain {1}. Status code: {2}.".
414 format(mac, bd_name, status_code))
416 new_data = HcUtil.remove_item(resp, path)
417 status_code, resp = HcUtil.\
418 put_honeycomb_data(node, "config_bridge_domain", new_data)
419 if status_code != HTTPCodes.OK:
420 raise HoneycombError("Not possible to remove L2 FIB entry {0} from "
421 "bridge domain {1}. Status code: {2}.".
422 format(mac, bd_name, status_code))
427 def remove_all_l2_fib_entries(node, bd_name):
428 """Remove all entries from the bridge domain's L2 FIB table.
430 :param node: Honeycomb node.
431 :param bd_name: Bridge domain's name.
434 :return: Content of response.
438 path = ("bridge-domains",
439 ("bridge-domain", "name", bd_name),
442 return BridgeDomainKeywords._set_bd_properties(
443 node, bd_name, path, None)
446 def get_all_l2_fib_entries(node, bd_name):
447 """Retrieves all entries from the bridge domain's L2 FIB table.
449 :param node: Honeycomb node.
450 :param bd_name: Bridge domain's name.
453 :return: Bridge domain's L2 FIB table or empty list if the table does
454 not exist or it is empty.
458 bd_data = BridgeDomainKeywords.get_bd_oper_data(node, bd_name)
460 return bd_data["l2-fib-table"]["l2-fib-entry"]
465 def get_l2_fib_entry(node, bd_name, mac):
466 """Retrieves an entry from bridge domain's L2 FIB table. The entry is
467 specified by MAC address.
469 :param node: Honeycomb node.
470 :param bd_name: Bridge domain's name.
471 :param mac: MAC address used as the key in L2 FIB data structure.
475 :return: The requested entry from bridge domain's L2 FIB table or empty
476 dictionary if it does not exist in the L2 FIB table.
480 l2_fib = BridgeDomainKeywords.get_all_l2_fib_entries(node, bd_name)
482 if entry["phys-address"] == mac: