From 28e17b8002b50a04cdd6c9e74c15cdc4aa33a5e2 Mon Sep 17 00:00:00 2001 From: Tibor Frank Date: Tue, 12 Jul 2016 14:46:22 +0200 Subject: [PATCH] CSIT-53: HC Keywords: Policy - security groups - add keywords to manipulate ACL data using Honeycomb REST API Change-Id: Ia08faba216c5476113c0b3249de9c434eaa26a17 Signed-off-by: Tibor Frank --- resources/libraries/python/honeycomb/HcAPIKwACL.py | 264 +++++++++++++++++++++ .../python/honeycomb/HcAPIKwInterfaces.py | 68 +++++- .../libraries/python/honeycomb/HoneycombUtil.py | 21 +- .../templates/honeycomb/config_classify_table.url | 1 + .../templates/honeycomb/oper_classify_table.url | 1 + 5 files changed, 348 insertions(+), 7 deletions(-) create mode 100644 resources/libraries/python/honeycomb/HcAPIKwACL.py create mode 100644 resources/templates/honeycomb/config_classify_table.url create mode 100644 resources/templates/honeycomb/oper_classify_table.url diff --git a/resources/libraries/python/honeycomb/HcAPIKwACL.py b/resources/libraries/python/honeycomb/HcAPIKwACL.py new file mode 100644 index 0000000000..c11e325194 --- /dev/null +++ b/resources/libraries/python/honeycomb/HcAPIKwACL.py @@ -0,0 +1,264 @@ +# Copyright (c) 2016 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""This module implements keywords to manipulate ACL data structures using +Honeycomb REST API.""" + +from resources.libraries.python.HTTPRequest import HTTPCodes +from resources.libraries.python.honeycomb.HoneycombSetup import HoneycombError +from resources.libraries.python.honeycomb.HoneycombUtil \ + import HoneycombUtil as HcUtil +from resources.libraries.python.honeycomb.HoneycombUtil \ + import DataRepresentation + + +class ACLKeywords(object): + """Implementation of keywords which make it possible to: + - add classify table(s), + - remove classify table(s), + - get operational data about classify table(s), + - add classify session(s), + - remove classify session(s), + - get operational data about classify sessions(s). + """ + + def __init__(self): + pass + + @staticmethod + def _set_classify_table_properties(node, path, data=None): + """Set classify table properties and check the return code. + + :param node: Honeycomb node. + :param path: Path which is added to the base path to identify the data. + :param data: The new data to be set. If None, the item will be removed. + :type node: dict + :type path: str + :type data: dict + :return: Content of response. + :rtype: bytearray + :raises HoneycombError: If the status code in response to PUT is not + 200 = OK. + """ + + if data: + status_code, resp = HcUtil.\ + put_honeycomb_data(node, "config_classify_table", data, path, + data_representation=DataRepresentation.JSON) + else: + status_code, resp = HcUtil.\ + delete_honeycomb_data(node, "config_classify_table", path) + + if status_code != HTTPCodes.OK: + raise HoneycombError( + "The configuration of classify table was not successful. " + "Status code: {0}.".format(status_code)) + return resp + + @staticmethod + def add_classify_table(node, table): + """Add a classify table to the list of classify tables. The keyword does + not validate given data. + + :param node: Honeycomb node. + :param table: Classify table to be added. + :type node: dict + :type table: dict + :return: Content of response. + :rtype: bytearray + """ + + path = "/classify-table/" + table["name"] + data = {"classify-table": [table, ]} + return ACLKeywords._set_classify_table_properties(node, path, data) + + @staticmethod + def remove_all_classify_tables(node): + """Remove all classify tables defined on the node. + + :param node: Honeycomb node. + :type node: dict + :return: Content of response. + :rtype: bytearray + """ + + return ACLKeywords._set_classify_table_properties(node, path="") + + @staticmethod + def remove_classify_table(node, table_name): + """Remove the given classify table. + + :param node: Honeycomb node. + :param table_name: Name of the classify table to be removed. + :type node: dict + :type table_name: str + :return: Content of response. + :rtype: bytearray + """ + + path = "/classify-table/" + table_name + return ACLKeywords._set_classify_table_properties(node, path) + + @staticmethod + def get_all_classify_tables_oper_data(node): + """Get operational data about all classify tables present on the node. + + :param node: Honeycomb node. + :type node: dict + :return: List of classify tables. + :rtype: list + """ + + status_code, resp = HcUtil.\ + get_honeycomb_data(node, "oper_classify_table") + + if status_code != HTTPCodes.OK: + raise HoneycombError( + "Not possible to get operational information about the " + "classify tables. Status code: {0}.".format(status_code)) + try: + return resp["vpp-classifier"]["classify-table"] + except (KeyError, TypeError): + return [] + + @staticmethod + def get_classify_table_oper_data(node, table_name): + """Get operational data about the given classify table. + + :param node: Honeycomb node. + :param table_name: Name of the classify table. + :type node: dict + :type table_name: str + :return: Operational data about the given classify table. + :rtype: dict + """ + + path = "/classify-table/" + table_name + status_code, resp = HcUtil.\ + get_honeycomb_data(node, "oper_classify_table", path) + + if status_code != HTTPCodes.OK: + raise HoneycombError( + "Not possible to get operational information about the " + "classify tables. Status code: {0}.".format(status_code)) + try: + return resp["classify-table"][0] + except (KeyError, TypeError): + return [] + + @staticmethod + def get_all_classify_tables_cfg_data(node): + """Get configuration data about all classify tables present on the node. + + :param node: Honeycomb node. + :type node: dict + :return: List of classify tables. + :rtype: list + """ + + status_code, resp = HcUtil.\ + get_honeycomb_data(node, "config_classify_table") + + if status_code != HTTPCodes.OK: + raise HoneycombError( + "Not possible to get operational information about the " + "classify tables. Status code: {0}.".format(status_code)) + try: + return resp["vpp-classifier"]["classify-table"] + except (KeyError, TypeError): + return [] + + @staticmethod + def add_classify_session(node, table_name, session): + """Add a classify session to the classify table. + + :param node: Honeycomb node. + :param table_name: Name of the classify table. + :param session: Classify session to be added to the classify table. + :type node: dict + :type table_name: str + :type session: dict + :return: Content of response. + :rtype: bytearray + """ + + path = "/classify-table/" + table_name + \ + "/classify-session/" + session["match"] + data = {"classify-session": [session, ]} + return ACLKeywords._set_classify_table_properties(node, path, data) + + @staticmethod + def remove_classify_session(node, table_name, session_match): + """Remove the given classify session from the classify table. + + :param node: Honeycomb node. + :param table_name: Name of the classify table. + :param session_match: Classify session match. + :type node: dict + :type table_name: str + :type session_match: str + :return: Content of response. + :rtype: bytearray + """ + + path = "/classify-table/" + table_name + \ + "/classify-session/" + session_match + return ACLKeywords._set_classify_table_properties(node, path) + + @staticmethod + def get_all_classify_sessions_oper_data(node, table_name): + """Get operational data about all classify sessions in the classify + table. + + :param node: Honeycomb node. + :param table_name: Name of the classify table. + :type node: dict + :type table_name: str + :return: List of classify sessions present in the classify table. + :rtype: list + """ + + table_data = ACLKeywords.get_classify_table_oper_data(node, table_name) + try: + return table_data["classify-table"][0]["classify-session"] + except (KeyError, TypeError): + return [] + + @staticmethod + def get_classify_session_oper_data(node, table_name, session_match): + """Get operational data about the given classify session in the classify + table. + + :param node: Honeycomb node. + :param table_name: Name of the classify table. + :param session_match: Classify session match. + :type node: dict + :type table_name: str + :type session_match: str + :return: Classify session operational data. + :rtype: dict + """ + + path = "/classify-table/" + table_name + \ + "/classify-session/" + session_match + status_code, resp = HcUtil.\ + get_honeycomb_data(node, "oper_classify_table", path) + + if status_code != HTTPCodes.OK: + raise HoneycombError( + "Not possible to get operational information about the " + "classify tables. Status code: {0}.".format(status_code)) + try: + return resp["classify-session"][0] + except (KeyError, TypeError): + return {} diff --git a/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py b/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py index 4feb22e90a..ff1589f217 100644 --- a/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py +++ b/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py @@ -1200,7 +1200,7 @@ class InterfaceKeywords(object): node, super_interface, path, address) @staticmethod - def remove_all_ipv4_addresses_from_sub_interface(node, super_interface, + def remove_all_ipv4_addresses_from_sub_interface(node, super_interface, # pylint: disable=invalid-name identifier): """Remove all ipv4 addresses from the specified sub-interface. @@ -1305,3 +1305,69 @@ class InterfaceKeywords(object): vxlan_gpe_structure = [new_vxlan_gpe, ] return InterfaceKeywords._set_interface_properties( node, interface, path, vxlan_gpe_structure) + + @staticmethod + def enable_acl_on_interface(node, interface, table_name): + """Enable ACL on the given interface. + + :param node: Honeycomb node. + :param interface: The interface where the ACL will be enabled. + :param table_name: Name of the classify table. + :type node: dict + :type interface: str + :type table_name: str + :return: Content of response. + :rtype: bytearray + :raises HoneycombError: If the configuration of interface is not + successful. + """ + + interface = interface.replace("/", "%2F") + + data = { + "v3po:acl": { + "l2-acl": { + "classify-table": table_name + }, + "ip4-acl": { + "classify-table": table_name + } + } + } + + path = "/interface/" + interface + "/v3po:acl" + status_code, resp = HcUtil.\ + put_honeycomb_data(node, "config_vpp_interfaces", data, path, + data_representation=DataRepresentation.JSON) + if status_code != HTTPCodes.OK: + raise HoneycombError( + "The configuration of interface '{0}' was not successful. " + "Status code: {1}.".format(interface, status_code)) + return resp + + @staticmethod + def disable_acl_on_interface(node, interface): + """Disable ACL on the given interface. + + :param node: Honeycomb node. + :param interface: The interface where the ACL will be disabled. + :type node: dict + :type interface: str + :return: Content of response. + :rtype: bytearray + :raises HoneycombError: If the configuration of interface is not + successful. + """ + + interface = interface.replace("/", "%2F") + + path = "/interface/" + interface + "/v3po:acl" + + status_code, resp = HcUtil.\ + delete_honeycomb_data(node, "config_vpp_interfaces", path) + + if status_code != HTTPCodes.OK: + raise HoneycombError( + "The configuration of interface '{0}' was not successful. " + "Status code: {1}.".format(interface, status_code)) + return resp diff --git a/resources/libraries/python/honeycomb/HoneycombUtil.py b/resources/libraries/python/honeycomb/HoneycombUtil.py index 2f8392ecb5..8f1392c972 100644 --- a/resources/libraries/python/honeycomb/HoneycombUtil.py +++ b/resources/libraries/python/honeycomb/HoneycombUtil.py @@ -285,24 +285,27 @@ class HoneycombUtil(object): return origin_data @staticmethod - def get_honeycomb_data(node, url_file): + def get_honeycomb_data(node, url_file, path=""): """Retrieve data from Honeycomb according to given URL. :param node: Honeycomb node. :param url_file: URL file. The argument contains only the name of file without extension, not the full path. + :param path: Path which is added to the base path to identify the data. :type node: dict :type url_file: str + :type path: str :return: Status code and content of response. :rtype tuple """ - path = HoneycombUtil.read_path_from_url_file(url_file) + base_path = HoneycombUtil.read_path_from_url_file(url_file) + path = base_path + path status_code, resp = HTTPRequest.get(node, path) return status_code, loads(resp) @staticmethod - def put_honeycomb_data(node, url_file, data, + def put_honeycomb_data(node, url_file, data, path="", data_representation=DataRepresentation.JSON): """Send configuration data using PUT request and return the status code and response content. @@ -311,10 +314,12 @@ class HoneycombUtil(object): :param url_file: URL file. The argument contains only the name of file without extension, not the full path. :param data: Configuration data to be sent to Honeycomb. + :param path: Path which is added to the base path to identify the data. :param data_representation: How the data is represented. :type node: dict :type url_file: str :type data: dict, str + :type path: str :type data_representation: DataRepresentation :return: Status code and content of response. :rtype: tuple @@ -332,7 +337,8 @@ class HoneycombUtil(object): logger.trace(data) - path = HoneycombUtil.read_path_from_url_file(url_file) + base_path = HoneycombUtil.read_path_from_url_file(url_file) + path = base_path + path return HTTPRequest.put(node=node, path=path, headers=header, payload=data) @@ -373,17 +379,20 @@ class HoneycombUtil(object): payload=data, timeout=timeout) @staticmethod - def delete_honeycomb_data(node, url_file): + def delete_honeycomb_data(node, url_file, path=""): """Delete data from Honeycomb according to given URL. :param node: Honeycomb node. :param url_file: URL file. The argument contains only the name of file without extension, not the full path. + :param path: Path which is added to the base path to identify the data. :type node: dict :type url_file: str + :type path: str :return: Status code and content of response. :rtype tuple """ - path = HoneycombUtil.read_path_from_url_file(url_file) + base_path = HoneycombUtil.read_path_from_url_file(url_file) + path = base_path + path return HTTPRequest.delete(node, path) diff --git a/resources/templates/honeycomb/config_classify_table.url b/resources/templates/honeycomb/config_classify_table.url new file mode 100644 index 0000000000..986b1173ac --- /dev/null +++ b/resources/templates/honeycomb/config_classify_table.url @@ -0,0 +1 @@ +/restconf/config/vpp-classifier:vpp-classifier \ No newline at end of file diff --git a/resources/templates/honeycomb/oper_classify_table.url b/resources/templates/honeycomb/oper_classify_table.url new file mode 100644 index 0000000000..f9fd294a8f --- /dev/null +++ b/resources/templates/honeycomb/oper_classify_table.url @@ -0,0 +1 @@ +/restconf/operational/vpp-classifier:vpp-classifier-state \ No newline at end of file -- 2.16.6