From 4f4eaa1d52f3bdbe3caecdc1d6a024c369a2834a Mon Sep 17 00:00:00 2001 From: selias Date: Tue, 7 Mar 2017 15:42:02 +0100 Subject: CSIT-536 HC Test: support testing with ODL client Reuses existing restconf test cases to test Honeycomb's netconf interface. When seding the requests to ODL's Honeycomb mountpoint, ODL translates these requests to netconf RPCs. Add new tag "honeycomb_odl" that excludes incompatible test cases. Change-Id: Ie293449da0129b02db85e30aa4f3266928d7d9f6 Signed-off-by: selias --- .../python/honeycomb/HcAPIKwInterfaces.py | 2 +- .../libraries/python/honeycomb/HcPersistence.py | 40 ++++++ .../libraries/python/honeycomb/HoneycombSetup.py | 138 +++++++++++++++++++++ 3 files changed, 179 insertions(+), 1 deletion(-) (limited to 'resources/libraries/python/honeycomb') diff --git a/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py b/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py index 3351ebf5d3..b4746e2118 100644 --- a/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py +++ b/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py @@ -1544,7 +1544,7 @@ class InterfaceKeywords(object): """ interface = intf.replace("/", "%2F") - path = "/interface/{0}/pbb-rewrite/".format(interface) + path = "/interface/{0}/pbb-rewrite".format(interface) status_code, resp = HcUtil. \ put_honeycomb_data(node, "config_vpp_interfaces", params, path, data_representation=DataRepresentation.JSON) diff --git a/resources/libraries/python/honeycomb/HcPersistence.py b/resources/libraries/python/honeycomb/HcPersistence.py index c76a276098..83d756f9d3 100644 --- a/resources/libraries/python/honeycomb/HcPersistence.py +++ b/resources/libraries/python/honeycomb/HcPersistence.py @@ -102,3 +102,43 @@ class HcPersistence(object): for command in commands: (_, stdout, _) = ssh.exec_command_sudo(command) logger.info(stdout) + + + @staticmethod + def configure_persistence(node, state): + """Enable or disable Honeycomb configuration data persistence. + + :param node: Honeycomb node. + :param state: Enable or Disable. + :type node: dict + :type state: str + :raises ValueError: If the state argument is incorrect. + :raises HoneycombError: If the operation fails. + """ + + state = state.lower() + if state == "enable": + state = "true" + elif state == "disable": + state = "false" + else: + raise ValueError("Unexpected value of state argument:" + " {0} provided. Must be enable or disable." + .format(state)) + + for setting in ("persist-config", "persist-context"): + # find the setting, replace entire line with 'setting: state' + find = '\\"{setting}\\":'.format(setting=setting) + replace = '\\"{setting}\\": \\"{state}\\",'.format( + setting=setting, state=state) + + argument = '"/{0}/c\\ {1}"'.format(find, replace) + path = "{0}/config/honeycomb.json".format(Const.REMOTE_HC_DIR) + command = "sed -i {0} {1}".format(argument, path) + + ssh = SSH() + ssh.connect(node) + (ret_code, _, stderr) = ssh.exec_command_sudo(command) + if ret_code != 0: + raise HoneycombError("Failed to modify configuration on " + "node {0}, {1}".format(node, stderr)) diff --git a/resources/libraries/python/honeycomb/HoneycombSetup.py b/resources/libraries/python/honeycomb/HoneycombSetup.py index 239ac10191..117b3e57c4 100644 --- a/resources/libraries/python/honeycomb/HoneycombSetup.py +++ b/resources/libraries/python/honeycomb/HoneycombSetup.py @@ -103,6 +103,36 @@ class HoneycombSetup(object): raise HoneycombError('Node(s) {0} failed to stop Honeycomb.'. format(errors)) + @staticmethod + def restart_honeycomb_and_vpp_on_duts(*nodes): + """Restart the Honeycomb service on specified DUT nodes. + + Use the keyword "Check Honeycomb Startup State" to check when Honeycomb + is fully restarted. + :param nodes: List of nodes to restart Honeycomb on. + :type nodes: list + :raises HoneycombError: If Honeycomb failed to restart. + """ + logger.console("\nRestarting Honeycomb service ...") + + cmd = "sudo service honeycomb restart && sudo service vpp restart" + errors = [] + + for node in nodes: + if node['type'] == NodeType.DUT: + ssh = SSH() + ssh.connect(node) + (ret_code, _, _) = ssh.exec_command_sudo(cmd) + if int(ret_code) != 0: + errors.append(node['host']) + else: + logger.info("Restart of Honeycomb and VPP on node {0} is " + "in progress ...".format(node['host'])) + if errors: + raise HoneycombError('Node(s) {0} failed to restart Honeycomb' + ' and/or VPP.'. + format(errors)) + @staticmethod def check_honeycomb_startup_state(*nodes): """Check state of Honeycomb service during startup on specified nodes. @@ -372,3 +402,111 @@ class HoneycombSetup(object): if ret_code != 0: raise HoneycombError("Failed to copy JVPP libraries on " "node {0}, {1}".format(node, stderr)) + + @staticmethod + def find_odl_client(node): + """Check if there is a karaf directory in home. + + :param node: Honeycomb node. + :type node: dict + :returns: True if ODL client is present on node, else False. + :rtype: bool + """ + + ssh = SSH() + ssh.connect(node) + (ret_code, stdout, _) = ssh.exec_command_sudo( + "ls ~ | grep karaf") + + logger.debug(stdout) + return not bool(ret_code) + + @staticmethod + def start_odl_client(node): + """Start ODL client on the specified node. + + karaf should be located in home directory, and VPP and Honeycomb should + already be running, otherwise the start will fail. + :param node: Nodes to start ODL client on. + :type node: dict + :raises HoneycombError: If Honeycomb fails to start. + """ + + logger.console("\nStarting ODL client ...") + + cmd = "~/*karaf*/bin/start" + + ssh = SSH() + ssh.connect(node) + (ret_code, _, _) = ssh.exec_command_sudo(cmd) + if int(ret_code) != 0: + raise HoneycombError('Node {0} failed to start ODL.'. + format(node['host'])) + else: + logger.info("Starting the ODL client on node {0} is " + "in progress ...".format(node['host'])) + + @staticmethod + def check_odl_startup_state(node): + """Check the status of ODL client startup. + + :param node: Honeycomb node. + :param node: dict + :returns: True when ODL is started. + :rtype: bool + :raises HoneycombError: When the response is not code 200: OK. + """ + + path = HcUtil.read_path_from_url_file( + "odl_client/odl_netconf_connector") + expected_status_codes = (HTTPCodes.UNAUTHORIZED, + HTTPCodes.FORBIDDEN, + HTTPCodes.NOT_FOUND, + HTTPCodes.SERVICE_UNAVAILABLE, + HTTPCodes.INTERNAL_SERVER_ERROR) + + status_code, _ = HTTPRequest.get(node, path, timeout=10, + enable_logging=False) + if status_code == HTTPCodes.OK: + logger.info("ODL client on node {0} is up and running". + format(node['host'])) + elif status_code in expected_status_codes: + if status_code == HTTPCodes.UNAUTHORIZED: + logger.info('Unauthorized. If this triggers keyword ' + 'timeout, verify username and password.') + raise HoneycombError('ODL client on node {0} running but ' + 'not yet ready.'.format(node['host']), + enable_logging=False) + else: + raise HoneycombError('Unexpected return code: {0}.'. + format(status_code)) + return True + + @staticmethod + def mount_honeycomb_on_odl(node): + """Tell ODL client to mount Honeycomb instance over netconf. + + :param node: Honeycomb node. + :type node: dict + :raises HoneycombError: When the response is not code 200: OK. + """ + + path = HcUtil.read_path_from_url_file( + "odl_client/odl_netconf_connector") + + url_file = "{0}/{1}".format(Const.RESOURCES_TPL_HC, + "odl_client/mount_honeycomb.xml") + + with open(url_file) as template: + data = template.read() + + status_code, _ = HTTPRequest.post( + node, path, headers={"Content-Type": "application/xml"}, + payload=data, timeout=10, enable_logging=False) + + if status_code == HTTPCodes.OK: + logger.info("ODL mount point configured successfully.") + elif status_code == HTTPCodes.CONFLICT: + logger.warn("ODL mount point was already configured.") + else: + raise HoneycombError('Mount point configuration not successful') -- cgit 1.2.3-korg