1 # Copyright (c) 2017 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 routing tables using
15 Honeycomb REST API."""
17 from robot.api import logger
19 from resources.libraries.python.topology import Topology
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 HoneycombUtil as HcUtil
24 from resources.libraries.python.honeycomb.HoneycombUtil \
25 import DataRepresentation
26 from resources.libraries.python.VatExecutor import VatTerminal
29 class RoutingKeywords(object):
30 """Implementation of keywords which make it possible to:
31 - add/remove routing tables,
32 - add/remove routing table entries
33 - get operational data about routing tables,
40 def _set_routing_table_properties(node, path, data=None):
41 """Set routing table properties and check the return code.
43 :param node: Honeycomb node.
44 :param path: Path which is added to the base path to identify the data.
45 :param data: The new data to be set. If None, the item will be removed.
49 :return: Content of response.
51 :raises HoneycombError: If the status code in response is not
56 status_code, resp = HcUtil.\
57 put_honeycomb_data(node, "config_routing_table", data, path,
58 data_representation=DataRepresentation.JSON)
60 status_code, resp = HcUtil.\
61 delete_honeycomb_data(node, "config_routing_table", path)
63 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
64 if data is None and '"error-tag":"data-missing"' in resp:
65 logger.debug("data does not exist in path.")
68 "The configuration of routing table was not successful. "
69 "Status code: {0}.".format(status_code))
73 def configure_routing_table(node, name, ip_version, data, vrf=1,
75 """Configure a routing table according to the data provided.
77 :param node: Honeycomb node.
78 :param name: Name for the table.
79 :param ip_version: IP protocol version, ipv4 or ipv6.
80 :param data: Route configuration that should be set.
81 :param vrf: vrf-id to attach configuration to.
82 :param special: Must be True if the configuration is a special route.
89 :returns: Content of response.
93 ip_version = "hc2vpp-ietf-{0}-unicast-routing:{0}".format(
95 protocol = "vpp-routing:vpp-protocol-attributes"
97 ip_version = ip_version
98 protocol = "vpp-protocol-attributes"
101 "routing-protocol": [
104 "description": "hc2vpp-csit test route",
119 path = "/routing-protocol/{0}".format(name)
120 return RoutingKeywords._set_routing_table_properties(
121 node, path, full_data)
124 def delete_routing_table(node, name):
125 """Delete the specified routing table from configuration data.
127 :param node: Honeycomb node.
128 :param name: Name of the table.
131 :returns: Content of response.
135 path = "/routing-protocol/{0}".format(name)
136 return RoutingKeywords._set_routing_table_properties(node, path)
139 def get_routing_table_oper(node, name, ip_version):
140 """Retrieve operational data about the specified routing table.
142 :param node: Honeycomb node.
143 :param name: Name of the routing table.
144 :param ip_version: IP protocol version, ipv4 or ipv6.
147 :type ip_version: str
148 :returns: Routing table operational data.
150 :raises HoneycombError: If the operation fails.
153 path = "/routing-protocol/{0}".format(name)
154 status_code, resp = HcUtil.\
155 get_honeycomb_data(node, "oper_routing_table", path)
157 if status_code != HTTPCodes.OK:
158 raise HoneycombError(
159 "Not possible to get operational information about the "
160 "classify tables. Status code: {0}.".format(status_code))
162 data = RoutingKeywords.clean_routing_oper_data(
163 resp['routing-protocol'][0]['static-routes']
164 ['hc2vpp-ietf-{0}-unicast-routing:{0}'.format(ip_version)]['route'])
169 def clean_routing_oper_data(data):
170 """Prepare received routing operational data to be verified against
173 :param data: Routing operational data.
175 :returns: Routing operational data without entry ID numbers.
180 # ID values are auto-incremented based on existing routes in VPP
182 if "next-hop-list" in item.keys():
183 for item2 in item["next-hop-list"]["next-hop"]:
184 item2.pop("id", None)
186 if "next-hop-list" in item.keys():
187 # List items come in random order
188 item["next-hop-list"]["next-hop"].sort()
193 def log_routing_configuration(node):
194 """Retrieve route configuration using VAT and print the response
197 :param node: VPP node.
201 with VatTerminal(node) as vat:
202 vat.vat_terminal_exec_cmd("ip_fib_dump")
205 def configure_interface_slaac(node, interface, slaac_data=None):
206 """Configure SLAAC on the specified interfaces.
208 :param node: Honeycomb node.
209 :param interface: Interface to configure SLAAC.
210 :param slaac_data: Dictionary of configurations to apply. \
211 If it is None then the existing configuration is removed.
214 :type slaac_data: dict of dicts
215 :returns: Content of response.
217 :raises HoneycombError: If RA could not be configured.
220 interface = Topology.convert_interface_reference(
221 node, interface, 'name')
222 interface_orig = interface
223 interface = interface.replace('/', '%2F')
224 path = 'interface/' + interface
227 status_code, _ = HcUtil.delete_honeycomb_data(
228 node, 'config_slaac', path)
233 'name': interface_orig,
234 'ipv6-router-advertisements': slaac_data
239 status_code, _ = HcUtil.put_honeycomb_data(
240 node, 'config_slaac', data, path)
242 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
243 raise HoneycombError(
244 'Configuring SLAAC failed. Status code:{0}'.format(status_code))
247 def get_interface_slaac_oper_data(node, interface):
248 """Get operational data about SLAAC table present on the node.
250 :param node: Honeycomb node.
251 :param interface: Interface SLAAC data are retrieved from.
254 :returns: dict of SLAAC operational data.
256 :raises HoneycombError: If status code differs from successful.
258 interface = Topology.convert_interface_reference(
259 node, interface, 'name')
260 interface = interface.replace('/', '%2F')
261 path = 'interface/' + interface
263 status_code, resp = HcUtil.\
264 get_honeycomb_data(node, "config_slaac", path)
266 if status_code != HTTPCodes.OK:
267 raise HoneycombError(
268 "Not possible to get operational information about SLAAC. "
269 "Status code: {0}.".format(status_code))
271 dict_of_str = resp['interface'][0][
272 'hc2vpp-ietf-ipv6-unicast-routing:ipv6-router-advertisements']
273 return {k: str(v) for k, v in dict_of_str.items()}
274 except (KeyError, TypeError):
278 def configure_policer(node, policy_name, policer_data=None):
279 """Configure Policer on the specified node.
281 :param node: Honeycomb node.
282 :param policer_data: Dictionary of configurations to apply. \
283 If it is None then the existing configuration is removed.
285 :type policer_data: dict
286 :returns: Content of response.
288 :raises HoneycombError: If policer could not be configured.
291 path = '/' + policy_name
294 status_code, _ = HcUtil.delete_honeycomb_data(
295 node, 'config_policer', path)
298 'policer': policer_data
301 status_code, _ = HcUtil.put_honeycomb_data(
302 node, 'config_policer', data, path)
304 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
305 raise HoneycombError(
306 'Configuring policer failed. Status code:{0}'\
307 .format(status_code))
310 def get_policer_oper_data(node, policy_name):
311 """Get operational data about Policer on the node.
313 :param node: Honeycomb node.
315 :returns: dict of Policer operational data.
317 :raises HoneycombError: If status code differs from successful.
320 path = '/' + policy_name
322 status_code, resp = HcUtil.\
323 get_honeycomb_data(node, "oper_policer", path)
325 if status_code != HTTPCodes.OK:
326 raise HoneycombError(
327 "Not possible to get operational information about Policer. "
328 "Status code: {0}.".format(status_code))
330 return resp['policer']
331 except (KeyError, TypeError):