1 # Copyright (c) 2018 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 """This module implements keywords to manipulate LISP data structures using
15 Honeycomb REST API."""
17 from resources.libraries.python.HTTPRequest import HTTPCodes
18 from resources.libraries.python.honeycomb.HoneycombSetup import HoneycombError
19 from resources.libraries.python.honeycomb.HoneycombUtil \
20 import HoneycombUtil as HcUtil
21 from resources.libraries.python.honeycomb.HoneycombUtil \
22 import DataRepresentation
23 from resources.libraries.python.topology import Topology
26 class LispKeywords(object):
27 """Implementation of keywords which make it possible to:
28 - enable/disable LISP feature
29 - configure LISP mappings
30 - configure locator sets
31 - configure map resolver
32 - configure LISP PITR feature
33 - read operational data for all of the above
41 def _set_lisp_properties(node, path, data=None):
42 """Set LISP properties and check the return code.
44 :param node: Honeycomb node.
45 :param path: Path which is added to the base path to identify the data.
46 :param data: The new data to be set. If None, the item will be removed.
50 :returns: Content of response.
52 :raises HoneycombError: If the status code in response to PUT is not
53 200 = OK or 201 = ACCEPTED.
57 status_code, resp = HcUtil.\
58 put_honeycomb_data(node, "config_lisp", data, path,
59 data_representation=DataRepresentation.JSON)
61 status_code, resp = HcUtil.\
62 delete_honeycomb_data(node, "config_lisp", path)
64 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
66 "Lisp configuration unsuccessful. "
67 "Status code: {0}.".format(status_code))
72 def get_lisp_operational_data(node):
73 """Retrieve Lisp properties from Honeycomb operational data.
75 :param node: Honeycomb node.
77 :returns: List operational data.
81 status_code, resp = HcUtil.get_honeycomb_data(node, "oper_lisp")
83 if status_code != HTTPCodes.OK:
84 raise HoneycombError("Could not retrieve LISP operational data."
85 "Status code: {0}.".format(status_code))
87 # get rid of empty vni-table entry
88 resp["lisp-state"]["lisp-feature-data"]["eid-table"][
91 "virtual-network-identifier": 0,
92 "vrf-subtable": {"table-id": 0}
98 def verify_map_server_data_from_honeycomb(data, ip_addresses):
99 """Verify whether MAP server data from Honeycomb is correct.
101 :param data: LISP operational data containing map server IP addresses.
102 :param ip_addresses: IP addresses to verify map server data against.
104 :type ip_addresses: list
105 :returns: Boolean Value indicating equality of IP Lists.
110 data['lisp-state']['lisp-feature-data']['map-servers']['map-server']
112 data = sorted([entry['ip-address'] for entry in data])
115 return data == ip_addresses
118 def verify_map_server_data_from_vat(data, ip_addresses):
119 """Verify whether MAP server data from VAT is correct.
121 :param data: LISP operational data containing map server IP addresses.
122 :param ip_addresses: IP addresses to verify map server data against.
124 :type ip_addresses: list
125 :returns: Boolean Value indicating equality of IP Lists.
129 data = sorted([entry['map-server'] for entry in data])
132 return data == ip_addresses
135 def set_lisp_state(node, state=True):
136 """Enable or disable the LISP feature.
138 :param node: Honeycomb node.
139 :param state: Enable or disable LISP.
142 :returns: Content of response.
144 :raises HoneycombError: If the return code is not 200:OK
148 ret_code, data = HcUtil.get_honeycomb_data(node, "config_lisp")
149 if ret_code == HTTPCodes.OK:
150 data["lisp"]["enable"] = bool(state)
151 elif ret_code == HTTPCodes.NOT_FOUND:
152 data = {"lisp": {"enable": bool(state)}}
154 raise HoneycombError("Unexpected return code when getting existing"
155 " LISP configuration.")
157 return LispKeywords._set_lisp_properties(node, '', data)
160 def set_rloc_probe_state(node, state=False):
161 """Enable or disable the Routing Locator probe.
163 :param node: Honeycomb node.
164 :param state: Enable or Disable the Rloc probe.
167 :returns: Content of response.
171 path = "/lisp-feature-data/rloc-probe"
175 "enabled": bool(state)
179 return LispKeywords._set_lisp_properties(node, path, data)
182 def add_locator(node, interface, locator_set, priority=1, weight=1):
183 """Configure a new LISP locator set.
185 :param node: Honeycomb node.
186 :param interface: An interface on the node.
187 :param locator_set: Name for the new locator set.
188 :param priority: Priority parameter for the locator.
189 :param weight: Weight parameter for the locator.
192 :type locator_set: str
195 :returns: Content of response.
199 interface = Topology.convert_interface_reference(
200 node, interface, "name")
202 path = "/lisp-feature-data/locator-sets/locator-set" \
203 "/{0}".format(locator_set)
209 "interface-ref": interface,
210 "priority": priority,
216 return LispKeywords._set_lisp_properties(node, path, data)
219 def configure_lisp_mapping(node, data):
220 """Modify eid-table configuration to the data provided.
222 :param node: Honeycomb node.
223 :param data: Settings for the LISP mappings.
226 :returns: Content of response.
230 path = "/lisp-feature-data/eid-table"
231 return LispKeywords._set_lisp_properties(node, path, data)
234 def configure_lisp_map_request_mode(node, option):
235 """Modify LISP Map Request Mode configuration to the data provided.
237 :param node: Honeycomb node.
238 :param option: Settings for the LISP map request mode.
241 :returns: Content of response.
246 "map-request-mode": {
251 path = "/lisp-feature-data/map-request-mode"
252 return LispKeywords._set_lisp_properties(node, path, data)
255 def add_lisp_adjacency(node, vni_id, map_name, adjacency_name, data):
256 """Add an adjacency to an existing LISP mapping.
258 :param node: Honeycomb node.
259 :param vni_id: vni_id of the mapping.
260 :param map_name: Name of the mapping.
261 :param adjacency_name: Name for the new adjacency.
262 :param data: Adjacency settings.
266 :type adjacency_name: str
268 :returns: Content of response.
273 "/lisp-feature-data/eid-table/vni-table/{vni_id}/"
274 "vrf-subtable/remote-mappings/remote-mapping/{map_name}/"
275 "adjacencies/adjacency/{adjacency_name}"
280 adjacency_name=adjacency_name
283 return LispKeywords._set_lisp_properties(node, path, data)
286 def add_map_resolver(node, ip_address):
287 """Configure map resolver with the specified IP address.
289 :param node: Honeycomb node.
290 :param ip_address: IP address to configure map resolver with.
292 :type ip_address: str
293 :returns: Content of response.
297 path = "/lisp-feature-data/map-resolvers/map-resolver/{0}".format(
302 "ip-address": ip_address
306 return LispKeywords._set_lisp_properties(node, path, data)
309 def set_map_register(node, map_register=False):
310 """Configure Map Register.
312 :param node: Honeycomb node.
313 :param map_register: Enable or disable Map Register.
315 :type map_register: bool
316 :returns: Content of response.
320 path = "/lisp-feature-data/map-register"
324 "enabled": bool(map_register)
328 return LispKeywords._set_lisp_properties(node, path, data)
331 def set_map_request_mode(node, src_dst=False):
332 """Configure Map Request Mode.
334 :param node: Honeycomb node.
335 :param src_dst: Configure Map Request Mode with source destination.
338 :returns: Content of response.
342 path = "/lisp-feature-data/map-request-mode"
345 "map-request-mode": {
346 "mode": "source-destination" if src_dst
347 else "target-destination"
351 return LispKeywords._set_lisp_properties(node, path, data)
354 def delete_map_resolver(node):
355 """Delete an existing map resolver.
357 :param node: Honeycomb node
359 :returns: Content of response
363 path = "/lisp-feature-data/map-resolvers"
365 return LispKeywords._set_lisp_properties(node, path)
368 def add_map_server(node, *ip_addresses):
369 """Configure map server with the specified IP addresses.
371 :param node: Honeycomb node.
372 :param ip_addresses: IP addresses to configure map server with.
374 :type ip_addresses: list
375 :returns: Content of response.
379 path = "/lisp-feature-data/map-servers"
384 {"ip-address": ip_address} for ip_address in ip_addresses
389 return LispKeywords._set_lisp_properties(node, path, data)
392 def delete_map_server(node):
393 """Delete all map servers.
395 :param node: Honeycomb node
397 :returns: Content of response
401 path = "/lisp-feature-data/map-servers"
403 return LispKeywords._set_lisp_properties(node, path)
406 def configure_pitr(node, locator_set=None):
407 """Configure PITR feature with the specified locator set. If not locator
408 set is specified, disable PITR instead.
410 :param node: Honeycomb node.
411 :param locator_set: Name of a locator set. Optional.
413 :type locator_set: str
414 :returns: Content of response.
418 path = "/lisp-feature-data/pitr-cfg"
423 "locator-set": locator_set
429 return LispKeywords._set_lisp_properties(node, path, data)
432 def configure_petr(node, ip_address):
433 """Configure PETR feature with the specified IP. If no IP
434 specified, disable PETR instead.
436 :param node: Honeycomb node.
437 :param ip_address: IPv6 address.
439 :type ip_address: str
440 :returns: Content of response.
444 path = "/lisp-feature-data/petr-cfg"
449 "petr-address": ip_address
455 return LispKeywords._set_lisp_properties(node, path, data)
458 def disable_lisp(node):
459 """Remove all LISP settings on the node.
461 :param node: Honeycomb node.
463 :returns: Content of response.
467 return LispKeywords._set_lisp_properties(node, "")
470 class LispGPEKeywords(object):
471 """Implementation of keywords which make it possible to:
472 - enable/disable LISP GPE feature
473 - configure LISP GPE forwarding entries
474 - read operational data for all of the above
482 def _set_lispgpe_properties(node, path, data=None):
483 """Set LISP GPE properties and check the return code.
485 :param node: Honeycomb node.
486 :param path: Path which is added to the base path to identify the data.
487 :param data: The new data to be set. If None, the item will be removed.
491 :returns: Content of response.
493 :raises HoneycombError: If the status code in response to PUT is not
494 200 = OK or 201 = ACCEPTED.
498 status_code, resp = HcUtil.\
499 put_honeycomb_data(node, "config_lisp_gpe", data, path,
500 data_representation=DataRepresentation.JSON)
502 status_code, resp = HcUtil.\
503 delete_honeycomb_data(node, "config_lisp_gpe", path)
505 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
506 raise HoneycombError(
507 "Lisp GPE configuration unsuccessful. "
508 "Status code: {0}.".format(status_code))
513 def get_lispgpe_operational_data(node):
514 """Retrieve LISP GPE properties from Honeycomb operational data.
516 :param node: Honeycomb node.
518 :returns: LISP GPE operational data.
520 :raises HoneycombError: If the status code in response to GET is not
524 status_code, resp = HcUtil.get_honeycomb_data(node, "oper_lisp_gpe")
526 if status_code != HTTPCodes.OK:
527 raise HoneycombError("Could not retrieve Lisp GPE operational data."
528 "Status code: {0}.".format(status_code))
533 def get_lispgpe_mapping(node, name):
534 """Retrieve LISP GPE operational data and parse for a specific mapping.
536 :param node: Honeycomb node.
537 :param name: Name of the mapping to look for.
540 :returns: LISP GPE mapping.
542 :raises HoneycombError: If the mapping is not present in operational
546 data = LispGPEKeywords.get_lispgpe_operational_data(node)
548 data = data["gpe-state"]["gpe-feature-data"]["gpe-entry-table"] \
551 raise HoneycombError("No mappings present in operational data.")
553 if item["id"] == name:
557 raise HoneycombError("Mapping with name {name} not found in "
558 "operational data.".format(name=name))
563 def get_lispgpe_config_data(node):
564 """Retrieve LISP GPE properties from Honeycomb config data.
566 :param node: Honeycomb node.
568 :returns: LISP GPE config data.
570 :raises HoneycombError: If the status code in response to GET is not
574 status_code, resp = HcUtil.get_honeycomb_data(node, "config_lisp_gpe")
576 if status_code != HTTPCodes.OK:
577 raise HoneycombError("Could not retrieve Lisp GPE config data."
578 "Status code: {0}.".format(status_code))
583 def set_lispgpe_state(node, state=True):
584 """Enable or disable the LISP GPE feature.
586 :param node: Honeycomb node.
587 :param state: Enable or disable LISP.
590 :returns: Content of response.
592 :raises HoneycombError: If the return code is not 200:OK
596 ret_code, data = HcUtil.get_honeycomb_data(node, "config_lisp_gpe")
597 if ret_code == HTTPCodes.OK:
598 data["gpe"]["gpe-feature-data"]["enable"] = bool(state)
599 elif ret_code == HTTPCodes.NOT_FOUND:
600 data = {"gpe": {"gpe-feature-data": {"enable": bool(state)}}}
602 raise HoneycombError("Unexpected return code when getting existing"
603 " Lisp GPE configuration.")
605 return LispGPEKeywords._set_lispgpe_properties(node, '', data)
608 def configure_lispgpe_mapping(node, data=None):
609 """Modify LISP GPE mapping configuration to the data provided.
611 :param node: Honeycomb node.
612 :param data: Settings for the LISP GPE mappings.
615 :returns: Content of response.
619 path = "/gpe-feature-data/gpe-entry-table"
621 data = {"gpe-entry-table": {"gpe-entry": data}}
622 return LispGPEKeywords._set_lispgpe_properties(node, path, data)
624 return LispGPEKeywords._set_lispgpe_properties(node, path)
627 def add_lispgpe_mapping(node, name, data):
628 """Add the specified LISP GPE mapping.
630 :param node: Honeycomb node.
631 :param name: Name for the mapping.
632 :param data: Mapping details.
636 :returns: Content of response.
640 path = "/gpe-feature-data/gpe-entry-table/gpe-entry/{name}".format(
643 data = {"gpe-entry": data}
644 return LispGPEKeywords._set_lispgpe_properties(node, path, data)
647 def delete_lispgpe_mapping(node, mapping):
648 """Delete the specified LISP GPE mapping from configuration.
650 :param node: Honeycomb node.
651 :param mapping: Name of the mapping to remove.
654 :returns: Content of response.
658 path = "/gpe-feature-data/gpe-entry-table/gpe-entry/{0}".format(mapping)
659 return LispGPEKeywords._set_lispgpe_properties(node, path)
662 def disable_lispgpe(node):
663 """Remove all LISP GPE settings on the node.
665 :param node: Honeycomb node.
667 :returns: Content of response.
671 return LispGPEKeywords._set_lispgpe_properties(node, "")