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 """This module implements keywords to manipulate ACL data structures using
15 Honeycomb REST API."""
16 from robot.api import logger
18 from resources.libraries.python.topology import Topology
19 from resources.libraries.python.HTTPRequest import HTTPCodes
20 from resources.libraries.python.honeycomb.HoneycombSetup import HoneycombError
21 from resources.libraries.python.honeycomb.HoneycombUtil \
22 import HoneycombUtil as HcUtil
23 from resources.libraries.python.honeycomb.HoneycombUtil \
24 import DataRepresentation
27 class ACLKeywords(object):
28 """Implementation of keywords which make it possible to:
29 - add classify table(s),
30 - remove classify table(s),
31 - get operational data about classify table(s),
32 - add classify session(s),
33 - remove classify session(s),
34 - get operational data about classify sessions(s).
41 def _set_classify_table_properties(node, path, data=None):
42 """Set classify table 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
57 status_code, resp = HcUtil.\
58 put_honeycomb_data(node, "config_classify_table", data, path,
59 data_representation=DataRepresentation.JSON)
61 status_code, resp = HcUtil.\
62 delete_honeycomb_data(node, "config_classify_table", path)
64 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
65 if data is None and '"error-tag":"data-missing"' in resp:
66 logger.debug("data does not exist in path.")
69 "The configuration of classify table was not successful. "
70 "Status code: {0}.".format(status_code))
74 def add_classify_table(node, table):
75 """Add a classify table to the list of classify tables. The keyword does
76 not validate given data.
78 :param node: Honeycomb node.
79 :param table: Classify table to be added.
82 :returns: Content of response.
86 path = "/classify-table/" + table["name"]
87 data = {"classify-table": [table, ]}
88 return ACLKeywords._set_classify_table_properties(node, path, data)
91 def remove_all_classify_tables(node):
92 """Remove all classify tables defined on the node.
94 :param node: Honeycomb node.
96 :returns: Content of response.
100 return ACLKeywords._set_classify_table_properties(node, path="")
103 def remove_classify_table(node, table_name):
104 """Remove the given classify table.
106 :param node: Honeycomb node.
107 :param table_name: Name of the classify table to be removed.
109 :type table_name: str
110 :returns: Content of response.
114 path = "/classify-table/" + table_name
115 return ACLKeywords._set_classify_table_properties(node, path)
118 def get_all_classify_tables_oper_data(node):
119 """Get operational data about all classify tables present on the node.
121 :param node: Honeycomb node.
123 :returns: List of classify tables.
127 status_code, resp = HcUtil.\
128 get_honeycomb_data(node, "oper_classify_table")
130 if status_code != HTTPCodes.OK:
131 raise HoneycombError(
132 "Not possible to get operational information about the "
133 "classify tables. Status code: {0}.".format(status_code))
135 return resp["vpp-classifier-state"]["classify-table"]
138 def get_classify_table_oper_data(node, table_name):
139 """Get operational data about the given classify table.
141 :param node: Honeycomb node.
142 :param table_name: Name of the classify table.
144 :type table_name: str
145 :returns: Operational data about the given classify table.
149 tables = ACLKeywords.get_all_classify_tables_oper_data(node)
151 if table["name"] == table_name:
153 raise HoneycombError("Table {0} not found in ACL table list.".format(
157 def get_all_classify_tables_cfg_data(node):
158 """Get configuration data about all classify tables present on the node.
160 :param node: Honeycomb node.
162 :returns: List of classify tables.
166 status_code, resp = HcUtil.\
167 get_honeycomb_data(node, "config_classify_table")
169 if status_code != HTTPCodes.OK:
170 raise HoneycombError(
171 "Not possible to get operational information about the "
172 "classify tables. Status code: {0}.".format(status_code))
174 return resp["vpp-classifier"]["classify-table"]
175 except (KeyError, TypeError):
179 def add_classify_session(node, table_name, session):
180 """Add a classify session to the classify table.
182 :param node: Honeycomb node.
183 :param table_name: Name of the classify table.
184 :param session: Classify session to be added to the classify table.
186 :type table_name: str
188 :returns: Content of response.
192 path = "/classify-table/" + table_name + \
193 "/classify-session/" + session["match"]
194 data = {"classify-session": [session, ]}
195 return ACLKeywords._set_classify_table_properties(node, path, data)
198 def remove_classify_session(node, table_name, session_match):
199 """Remove the given classify session from the classify table.
201 :param node: Honeycomb node.
202 :param table_name: Name of the classify table.
203 :param session_match: Classify session match.
205 :type table_name: str
206 :type session_match: str
207 :returns: Content of response.
211 path = "/classify-table/" + table_name + \
212 "/classify-session/" + session_match
213 return ACLKeywords._set_classify_table_properties(node, path)
216 def get_all_classify_sessions_oper_data(node, table_name):
217 """Get operational data about all classify sessions in the classify
220 :param node: Honeycomb node.
221 :param table_name: Name of the classify table.
223 :type table_name: str
224 :returns: List of classify sessions present in the classify table.
228 table_data = ACLKeywords.get_classify_table_oper_data(node, table_name)
230 return table_data["classify-session"]
233 def get_classify_session_oper_data(node, table_name, session_match):
234 """Get operational data about the given classify session in the classify
237 :param node: Honeycomb node.
238 :param table_name: Name of the classify table.
239 :param session_match: Classify session match.
241 :type table_name: str
242 :type session_match: str
243 :returns: Classify session operational data.
245 :raises HoneycombError: If no session the specified match Id is found.
248 sessions = ACLKeywords.get_all_classify_sessions_oper_data(
250 for session in sessions:
251 if session["match"] == session_match:
253 raise HoneycombError(
254 "Session with match value \"{0}\" not found"
255 " under ACL table {1}.".format(session_match, table_name))
258 def create_acl_plugin_classify_chain(node, list_name, data, macip=False):
259 """Create classify chain using the ietf-acl node.
261 :param node: Honeycomb node.
262 :param list_name: Name for the classify list.
263 :param data: Dictionary of settings to send to Honeycomb.
264 :param macip: Use simple MAC+IP classifier. Optional.
270 :returns: Content of response.
272 :raises HoneycombError: If the operation fails.
276 path = "/acl/vpp-acl:vpp-macip-acl/{0}".format(list_name)
278 path = "/acl/vpp-acl:vpp-acl/{0}".format(list_name)
280 status_code, resp = HcUtil.put_honeycomb_data(
281 node, "config_plugin_acl", data, path)
283 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
284 raise HoneycombError(
285 "Could not create classify chain."
286 "Status code: {0}.".format(status_code))
291 def set_acl_plugin_interface(node, interface, acl_name,
292 direction, macip=False):
293 """Assign an interface to an ietf-acl classify chain.
295 :param node: Honeycomb node.
296 :param interface: Name of an interface on the node.
297 :param acl_name: Name of an ACL chain configured through ACL-plugin.
298 :param direction: Classify incoming or outgiong packets.
299 Valid options are: ingress, egress
300 :param macip: Use simple MAC+IP classifier. Optional.
302 :type interface: str or int
307 :returns: Content of response.
309 :raises ValueError: If the direction argument is incorrect.
310 :raises HoneycombError: If the operation fails.
313 interface = Topology.convert_interface_reference(
314 node, interface, "name")
316 interface = interface.replace("/", "%2F")
318 if direction not in ("ingress", "egress"):
319 raise ValueError("Unknown traffic direction {0}. "
320 "Valid options are: ingress, egress."
323 path = "/interface/{0}/interface-acl:acl/{1}".format(
324 interface, direction)
330 "type": "vpp-acl:vpp-macip-acl",
340 "type": "vpp-acl:vpp-acl",
347 status_code, resp = HcUtil.put_honeycomb_data(
348 node, "config_vpp_interfaces", data, path)
350 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
351 raise HoneycombError(
352 "Could not configure ACL on interface. "
353 "Status code: {0}.".format(status_code))
358 def delete_interface_plugin_acls(node, interface):
359 """Remove all plugin-acl assignments from an interface.
361 :param node: Honeycomb node.
362 :param interface: Name of an interface on the node.
364 :type interface: str or int
367 interface = Topology.convert_interface_reference(
368 node, interface, "name")
370 interface = interface.replace("/", "%2F")
372 path = "/interface/{0}/interface-acl:acl/".format(interface)
373 status_code, _ = HcUtil.delete_honeycomb_data(
374 node, "config_vpp_interfaces", path)
376 if status_code != HTTPCodes.OK:
377 raise HoneycombError(
378 "Could not remove ACL assignment from interface. "
379 "Status code: {0}.".format(status_code))
382 def delete_acl_plugin_classify_chains(node):
383 """Remove all plugin-ACL classify chains.
385 :param node: Honeycomb node.
389 status_code, _ = HcUtil.delete_honeycomb_data(
390 node, "config_plugin_acl")
392 if status_code != HTTPCodes.OK:
393 raise HoneycombError(
394 "Could not remove plugin-acl chain. "
395 "Status code: {0}.".format(status_code))