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."""
17 from resources.libraries.python.topology import Topology
18 from resources.libraries.python.HTTPRequest import HTTPCodes
19 from resources.libraries.python.honeycomb.HoneycombSetup import HoneycombError
20 from resources.libraries.python.honeycomb.HoneycombUtil \
21 import HoneycombUtil as HcUtil
22 from resources.libraries.python.honeycomb.HoneycombUtil \
23 import DataRepresentation
26 class ACLKeywords(object):
27 """Implementation of keywords which make it possible to:
28 - add classify table(s),
29 - remove classify table(s),
30 - get operational data about classify table(s),
31 - add classify session(s),
32 - remove classify session(s),
33 - get operational data about classify sessions(s).
40 def _set_classify_table_properties(node, path, data=None):
41 """Set classify 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 to PUT is not
56 status_code, resp = HcUtil.\
57 put_honeycomb_data(node, "config_classify_table", data, path,
58 data_representation=DataRepresentation.JSON)
60 status_code, resp = HcUtil.\
61 delete_honeycomb_data(node, "config_classify_table", path)
63 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
65 "The configuration of classify table was not successful. "
66 "Status code: {0}.".format(status_code))
70 def add_classify_table(node, table):
71 """Add a classify table to the list of classify tables. The keyword does
72 not validate given data.
74 :param node: Honeycomb node.
75 :param table: Classify table to be added.
78 :return: Content of response.
82 path = "/classify-table/" + table["name"]
83 data = {"classify-table": [table, ]}
84 return ACLKeywords._set_classify_table_properties(node, path, data)
87 def remove_all_classify_tables(node):
88 """Remove all classify tables defined on the node.
90 :param node: Honeycomb node.
92 :return: Content of response.
96 return ACLKeywords._set_classify_table_properties(node, path="")
99 def remove_classify_table(node, table_name):
100 """Remove the given classify table.
102 :param node: Honeycomb node.
103 :param table_name: Name of the classify table to be removed.
105 :type table_name: str
106 :return: Content of response.
110 path = "/classify-table/" + table_name
111 return ACLKeywords._set_classify_table_properties(node, path)
114 def get_all_classify_tables_oper_data(node):
115 """Get operational data about all classify tables present on the node.
117 :param node: Honeycomb node.
119 :return: List of classify tables.
123 status_code, resp = HcUtil.\
124 get_honeycomb_data(node, "oper_classify_table")
126 if status_code != HTTPCodes.OK:
127 raise HoneycombError(
128 "Not possible to get operational information about the "
129 "classify tables. Status code: {0}.".format(status_code))
131 return resp["vpp-classifier"]["classify-table"]
132 except (KeyError, TypeError):
136 def get_classify_table_oper_data(node, table_name):
137 """Get operational data about the given classify table.
139 :param node: Honeycomb node.
140 :param table_name: Name of the classify table.
142 :type table_name: str
143 :return: Operational data about the given classify table.
147 path = "/classify-table/" + table_name
148 status_code, resp = HcUtil.\
149 get_honeycomb_data(node, "oper_classify_table", path)
151 if status_code != HTTPCodes.OK:
152 raise HoneycombError(
153 "Not possible to get operational information about the "
154 "classify tables. Status code: {0}.".format(status_code))
156 return resp["classify-table"][0]
157 except (KeyError, TypeError):
161 def get_all_classify_tables_cfg_data(node):
162 """Get configuration data about all classify tables present on the node.
164 :param node: Honeycomb node.
166 :return: List of classify tables.
170 status_code, resp = HcUtil.\
171 get_honeycomb_data(node, "config_classify_table")
173 if status_code != HTTPCodes.OK:
174 raise HoneycombError(
175 "Not possible to get operational information about the "
176 "classify tables. Status code: {0}.".format(status_code))
178 return resp["vpp-classifier"]["classify-table"]
179 except (KeyError, TypeError):
183 def add_classify_session(node, table_name, session):
184 """Add a classify session to the classify table.
186 :param node: Honeycomb node.
187 :param table_name: Name of the classify table.
188 :param session: Classify session to be added to the classify table.
190 :type table_name: str
192 :return: Content of response.
196 path = "/classify-table/" + table_name + \
197 "/classify-session/" + session["match"]
198 data = {"classify-session": [session, ]}
199 return ACLKeywords._set_classify_table_properties(node, path, data)
202 def remove_classify_session(node, table_name, session_match):
203 """Remove the given classify session from the classify table.
205 :param node: Honeycomb node.
206 :param table_name: Name of the classify table.
207 :param session_match: Classify session match.
209 :type table_name: str
210 :type session_match: str
211 :return: Content of response.
215 path = "/classify-table/" + table_name + \
216 "/classify-session/" + session_match
217 return ACLKeywords._set_classify_table_properties(node, path)
220 def get_all_classify_sessions_oper_data(node, table_name):
221 """Get operational data about all classify sessions in the classify
224 :param node: Honeycomb node.
225 :param table_name: Name of the classify table.
227 :type table_name: str
228 :return: List of classify sessions present in the classify table.
232 table_data = ACLKeywords.get_classify_table_oper_data(node, table_name)
234 return table_data["classify-table"][0]["classify-session"]
235 except (KeyError, TypeError):
239 def get_classify_session_oper_data(node, table_name, session_match):
240 """Get operational data about the given classify session in the classify
243 :param node: Honeycomb node.
244 :param table_name: Name of the classify table.
245 :param session_match: Classify session match.
247 :type table_name: str
248 :type session_match: str
249 :return: Classify session operational data.
253 path = "/classify-table/" + table_name + \
254 "/classify-session/" + session_match
255 status_code, resp = HcUtil.\
256 get_honeycomb_data(node, "oper_classify_table", path)
258 if status_code != HTTPCodes.OK:
259 raise HoneycombError(
260 "Not possible to get operational information about the "
261 "classify tables. Status code: {0}.".format(status_code))
263 return resp["classify-session"][0]
264 except (KeyError, TypeError):
268 def create_ietf_classify_chain(node, list_name, layer, data):
269 """Create classify chain using the ietf-acl node.
271 :param node: Honeycomb node.
272 :param list_name: Name for the classify list.
273 :param layer: Network layer to classify on.
274 :param data: Dictionary of settings to send to Honeycomb.
280 :return: Content of response.
282 :raises HoneycombError: If the operation fails.
284 layer = layer.lower()
285 suffix_dict = {"l2": "eth",
291 suffix = suffix_dict[layer]
293 raise ValueError("Unexpected value of layer argument {0}."
294 "Valid options are: {1}"
295 .format(layer, suffix_dict.keys()))
298 path = "/acl/vpp-acl:{0}-acl/{1}"
300 path = "/acl/ietf-access-control-list:{0}-acl/{1}"
302 path = path.format(suffix, list_name)
304 status_code, resp = HcUtil.put_honeycomb_data(
305 node, "config_ietf_classify_chain", data, path)
307 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
308 raise HoneycombError(
309 "Could not create classify chain."
310 "Status code: {0}.".format(status_code))
315 def set_ietf_interface_acl(node, interface, layer, direction, list_name,
316 default_action, mode=None):
317 """Assign an interface to an ietf-acl classify chain.
319 :param node: Honeycomb node.
320 :param interface: Name of an interface on the node.
321 :param layer: Network layer to classify packets on.
322 Valid options are: L2, L3, L4. Mixed ACL not supported yet.
323 :param direction: Classify incoming or outgiong packets.
324 Valid options are: ingress, egress
325 :param list_name: Name of an ietf-acl classify chain.
326 :param default_action: Default classifier action: permit or deny.
327 :param mode: When using mixed layers, this specifies operational mode
328 of the interface - L2 or L3. If layer is not "mixed", this argument
331 :type interface: str or int
335 :type default_action: str
338 :return: Content of response.
340 :raises HoneycombError: If the operation fails.
343 layer = layer.lower()
346 interface = Topology.convert_interface_reference(
347 node, interface, "name")
349 interface = interface.replace("/", "%2F")
351 if direction not in ("ingress", "egress"):
352 raise ValueError("Unknown traffic direction {0}. "
353 "Valid options are: ingress, egress."
356 path = "/interface/{0}/ietf-acl/{1}/access-lists".format(
357 interface, direction)
360 "ietf": "ietf-access-control-list:{0}-acl",
361 "vpp": "vpp-acl:{0}-acl"}
363 "l2": {"mode": "l2", "acl_type": types['ietf'].format("eth")},
364 "l3_ip4": {"mode": "l3", "acl_type": types['ietf'].format("ipv4")},
365 "l3_ip6": {"mode": "l3", "acl_type": types['ietf'].format("ipv6")},
366 "mixed": {"mode": mode, "acl_type": types['vpp'].format("mixed")}
374 "type": layers[layer]['acl_type'],
378 "default-action": default_action,
379 "mode": layers[layer]['mode']
383 raise ValueError("Unknown network layer {0}. "
384 "Valid options are: {1}".format(
385 layer, layers.keys()))
387 status_code, resp = HcUtil.put_honeycomb_data(
388 node, "config_vpp_interfaces", data, path)
390 if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
391 raise HoneycombError(
392 "Could not configure ACL on interface. "
393 "Status code: {0}.".format(status_code))
398 def delete_ietf_interface_acls(node, interface):
399 """Remove all ietf-acl assignments from an interface.
401 :param node: Honeycomb node.
402 :param interface: Name of an interface on the node.
404 :type interface: str or int"""
406 interface = Topology.convert_interface_reference(
407 node, interface, "name")
409 interface = interface.replace("/", "%2F")
411 path = "/interface/{0}/ietf-acl/".format(interface)
412 status_code, _ = HcUtil.delete_honeycomb_data(
413 node, "config_vpp_interfaces", path)
415 if status_code != HTTPCodes.OK:
416 raise HoneycombError(
417 "Could not remove ACL assignment from interface. "
418 "Status code: {0}.".format(status_code))
421 def delete_ietf_classify_chains(node):
422 """Remove all classify chains from the ietf-acl node.
424 :param node: Honeycomb node.
428 status_code, _ = HcUtil.delete_honeycomb_data(
429 node, "config_ietf_classify_chain")
431 if status_code != HTTPCodes.OK:
432 raise HoneycombError(
433 "Could not remove ietf-acl chain. "
434 "Status code: {0}.".format(status_code))