+ ssh.exec_command_sudo(cmd)
+
+ @staticmethod
+ def print_ports(node):
+ """Uses "sudo netstat -anp | grep java" to print port where a java
+ application listens.
+
+ :param node: Honeycomb node where we want to print the ports.
+ :type node: dict
+ """
+
+ cmds = ("netstat -anp | grep java",
+ "ps -ef | grep [h]oneycomb")
+
+ logger.info("Checking node {} ...".format(node['host']))
+ for cmd in cmds:
+ logger.info("Command: {}".format(cmd))
+ ssh = SSH()
+ ssh.connect(node)
+ ssh.exec_command_sudo(cmd)
+
+ @staticmethod
+ def configure_log_level(node, level):
+ """Set Honeycomb logging to the specified level.
+
+ :param node: Honeycomb node.
+ :param level: Log level (INFO, DEBUG, TRACE).
+ :type node: dict
+ :type level: str
+ """
+
+ find = 'logger name=\\"io.fd\\"'
+ replace = '<logger name=\\"io.fd\\" level=\\"{0}\\"/>'.format(level)
+
+ argument = '"/{0}/c\\ {1}"'.format(find, replace)
+ path = "{0}/config/logback.xml".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))
+
+ @staticmethod
+ def manage_honeycomb_features(node, feature, disable=False):
+ """Configure Honeycomb to use features that are disabled by default, or
+ disable previously enabled features.
+
+ ..Note:: If the module is not enabled in VPP, Honeycomb will
+ be unable to establish VPP connection.
+
+ :param node: Honeycomb node.
+ :param feature: Feature to enable.
+ :param disable: Disable the specified feature instead of enabling it.
+ :type node: dict
+ :type feature: string
+ :type disable: bool
+ :raises HoneycombError: If the configuration could not be changed.
+ """
+
+ disabled_features = {
+ "NSH": "io.fd.hc2vpp.vppnsh.impl.VppNshModule"
+ }
+
+ ssh = SSH()
+ ssh.connect(node)
+
+ if feature in disabled_features.keys():
+ # uncomment by replacing the entire line
+ find = replace = "{0}".format(disabled_features[feature])
+ if disable:
+ replace = "// {0}".format(find)
+
+ argument = '"/{0}/c\\ {1}"'.format(find, replace)
+ path = "{0}/modules/*module-config"\
+ .format(Const.REMOTE_HC_DIR)
+ command = "sed -i {0} {1}".format(argument, path)
+
+ (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))
+ else:
+ raise HoneycombError(
+ "Unrecognized feature {0}.".format(feature))
+
+ @staticmethod
+ def copy_java_libraries(node):
+ """Copy Java libraries installed by vpp-api-java package to honeycomb
+ lib folder.
+
+ This is a (temporary?) workaround for jvpp version mismatches.
+
+ :param node: Honeycomb node
+ :type node: dict
+ """
+
+ ssh = SSH()
+ ssh.connect(node)
+ (_, stdout, _) = ssh.exec_command_sudo(
+ "ls /usr/share/java | grep ^jvpp-*")
+
+ files = stdout.split("\n")[:-1]
+ for item in files:
+ # example filenames:
+ # jvpp-registry-17.04.jar
+ # jvpp-core-17.04.jar
+
+ parts = item.split("-")
+ version = "{0}-SNAPSHOT".format(parts[2][:5])
+ artifact_id = "{0}-{1}".format(parts[0], parts[1])
+
+ directory = "{0}/lib/io/fd/vpp/{1}/{2}".format(
+ Const.REMOTE_HC_DIR, artifact_id, version)
+ cmd = "sudo mkdir -p {0}; " \
+ "sudo cp /usr/share/java/{1} {0}/{2}-{3}.jar".format(
+ directory, item, artifact_id, version)
+
+ (ret_code, _, stderr) = ssh.exec_command(cmd)
+ if ret_code != 0:
+ raise HoneycombError("Failed to copy JVPP libraries on "
+ "node {0}, {1}".format(node, stderr))
+
+ @staticmethod
+ def copy_odl_client(node, odl_name, src_path, dst_path):
+ """Copy ODL Client from source path to destination path.
+
+ :param node: Honeycomb node.
+ :param odl_name: Name of ODL client version to use.
+ :param src_path: Source Path where to find ODl client.
+ :param dst_path: Destination path.
+ :type node: dict
+ :type odl_name: str
+ :type src_path: str
+ :type dst_path: str
+ :raises HoneycombError: If the operation fails.
+ """
+
+ ssh = SSH()
+ ssh.connect(node)
+
+ cmd = "sudo rm -rf {dst}/*karaf_{odl_name} && " \
+ "cp -r {src}/*karaf_{odl_name}* {dst}".format(
+ src=src_path, odl_name=odl_name, dst=dst_path)
+
+ ret_code, _, _ = ssh.exec_command_sudo(cmd, timeout=180)
+ if int(ret_code) != 0:
+ raise HoneycombError(
+ "Failed to copy ODL client on node {0}".format(node["host"]))
+
+ @staticmethod
+ def setup_odl_client(node, path):
+ """Start ODL client on the specified node.
+
+ Karaf should be located in the provided path, and VPP and Honeycomb
+ should already be running, otherwise the start will fail.
+ :param node: Node to start ODL client on.
+ :param path: Path to ODL client on node.
+ :type node: dict
+ :type path: str
+ :raises HoneycombError: If Honeycomb fails to start.
+ """
+
+ logger.console("\nStarting ODL client ...")
+ ssh = SSH()
+ ssh.connect(node)
+
+ cmd = "{path}/*karaf*/bin/start clean".format(path=path)
+ 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 install_odl_features(node, path, *features):
+ """Install required features on a running ODL client.
+
+ :param node: Honeycomb node.
+ :param path: Path to ODL client on node.
+ :param features: Optional, list of additional features to install.
+ :type node: dict
+ :type path: str
+ :type features: list
+ """
+
+ ssh = SSH()
+ ssh.connect(node)
+
+ cmd = "{path}/*karaf*/bin/client -u karaf feature:install " \
+ "odl-restconf-all " \
+ "odl-netconf-connector-all " \
+ "odl-netconf-topology".format(path=path)
+ for feature in features:
+ cmd += " {0}".format(feature)
+
+ ret_code, _, _ = ssh.exec_command_sudo(cmd, timeout=250)
+
+ if int(ret_code) != 0:
+ raise HoneycombError("Feature install did not succeed.")
+
+ @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))