[igt-dev] [PATCH i-g-t 2/2] i915/kms_chamelium: Pull chameleond logs for debugging

Stuart Summers stuart.summers at intel.com
Fri Feb 15 00:40:43 UTC 2019


IGT currently logs some state information when passing commands
to the Chamelium. There is a daemon running on the Chamelium itself,
chameleond, which logs some additional information locally. Add
a new set of libssh calls to extract those logs to be used in CI
debug.

Signed-off-by: Stuart Summers <stuart.summers at intel.com>
---
 Dockerfile.debian   |   1 +
 Dockerfile.fedora   |   1 +
 lib/igt_chamelium.c | 150 +++++++++++++++++++++++++++++++++++++++++++-
 lib/meson.build     |   4 ++
 meson.build         |   4 +-
 5 files changed, 158 insertions(+), 2 deletions(-)

diff --git a/Dockerfile.debian b/Dockerfile.debian
index b9c3be394..77928a9ef 100644
--- a/Dockerfile.debian
+++ b/Dockerfile.debian
@@ -18,6 +18,7 @@ RUN apt-get install -y \
 			libudev-dev \
 			libgsl-dev \
 			libasound2-dev \
+			libssh-dev \
 			libxmlrpc-core-c3-dev \
 			libjson-c-dev \
 			libcurl4-openssl-dev \
diff --git a/Dockerfile.fedora b/Dockerfile.fedora
index 08a4bd224..b041bf252 100644
--- a/Dockerfile.fedora
+++ b/Dockerfile.fedora
@@ -16,6 +16,7 @@ RUN dnf install -y gcc \
 		json-c-devel \
 		libdrm-devel \
 		libudev-devel \
+		libssh-devel \
 		xmlrpc-c-devel \
 		elfutils-devel \
 		libunwind-devel \
diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c
index 32b859eac..61b563e08 100644
--- a/lib/igt_chamelium.c
+++ b/lib/igt_chamelium.c
@@ -30,6 +30,7 @@
 #include <errno.h>
 #include <xmlrpc-c/base.h>
 #include <xmlrpc-c/client.h>
+#include <libssh/libssh.h>
 #include <pthread.h>
 #include <glib.h>
 #include <pixman.h>
@@ -120,6 +121,8 @@ struct chamelium {
 	struct chamelium_edid *edids;
 	struct chamelium_port *ports;
 	int port_count;
+
+	ssh_session session;
 };
 
 static struct chamelium *cleanup_instance;
@@ -256,6 +259,56 @@ static void *chamelium_fsm_mon(void *data)
 	return NULL;
 }
 
+static void
+chamelium_send_ssh_command(struct chamelium *chamelium, const char *cmd,
+			   bool print_result)
+{
+	int rc;
+	ssh_channel channel;
+
+	channel = ssh_channel_new(chamelium->session);
+	if (channel == NULL)
+		return;
+
+	rc = ssh_channel_open_session(channel);
+	if (rc != SSH_OK)
+		goto free;
+
+	rc = ssh_channel_request_exec(channel, cmd);
+	if (rc != SSH_OK)
+		goto free;
+
+	if (print_result) {
+		int nbytes;
+		char buffer[256];
+
+		nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
+		while (nbytes > 0) {
+			igt_debug("%s", buffer);
+			nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
+		}
+		igt_debug("\n");
+		ssh_channel_send_eof(channel);
+	}
+
+	ssh_channel_close(channel);
+
+free:
+	ssh_channel_free(channel);
+}
+
+static void
+chamelium_clear_chameleond(struct chamelium *chamelium)
+{
+	chamelium_send_ssh_command(chamelium, "> /var/log/chameleond", false);
+}
+
+static void
+chamelium_dump_chameleond(struct chamelium *chamelium)
+{
+	chamelium_send_ssh_command(chamelium, "cat /var/log/chameleond", true);
+}
+
 static xmlrpc_value *chamelium_rpc(struct chamelium *chamelium,
 				   struct chamelium_port *fsm_port,
 				   const char *method_name,
@@ -298,9 +351,11 @@ static xmlrpc_value *chamelium_rpc(struct chamelium *chamelium,
 		igt_cleanup_hotplug(monitor_args.mon);
 	}
 
+	chamelium_dump_chameleond(chamelium);
 	igt_assert_f(!chamelium->env.fault_occurred,
 		     "Chamelium RPC call failed: %s\n",
 		     chamelium->env.fault_string);
+	chamelium_clear_chameleond(chamelium);
 
 	return res;
 }
@@ -1510,7 +1565,7 @@ out:
 	return ret;
 }
 
-static bool chamelium_read_config(struct chamelium *chamelium, int drm_fd)
+static bool chamelium_get_url(struct chamelium *chamelium)
 {
 	GError *error = NULL;
 
@@ -1527,6 +1582,11 @@ static bool chamelium_read_config(struct chamelium *chamelium, int drm_fd)
 		return false;
 	}
 
+	return true;
+}
+
+static bool chamelium_read_config(struct chamelium *chamelium, int drm_fd)
+{
 	return chamelium_read_port_mappings(chamelium, drm_fd);
 }
 
@@ -1551,6 +1611,84 @@ static void chamelium_exit_handler(int sig)
 		chamelium_deinit(cleanup_instance);
 }
 
+/*
+ * Extract the IP address from the URL in the form:
+ *   http://<ip addr>:<port>
+ *
+ * Expect caller to free the resulting string.
+ */
+static char *
+get_ip_addr_from_url(struct chamelium *chamelium)
+{
+	char *tmp;
+	char *ip_addr;
+	char *port;
+
+	tmp = strrchr(chamelium->url, '/');
+	if (!tmp)
+		return NULL;
+	tmp++;
+
+	port = strrchr(chamelium->url, ':');
+	if (!port)
+		return NULL;
+
+	ip_addr = malloc(strlen(tmp));
+	if (!ip_addr)
+		return NULL;
+
+	strcpy(ip_addr, tmp);
+	ip_addr[port - tmp] = '\0';
+
+	return ip_addr;
+}
+
+static int
+chamelium_ssh_init(struct chamelium *chamelium)
+{
+	int rc;
+	char *ip_addr = get_ip_addr_from_url(chamelium);
+	if (!ip_addr)
+		return false;
+
+	chamelium->session = ssh_new();
+	if (chamelium->session == NULL) {
+		free(ip_addr);
+		return false;
+	}
+
+	ssh_options_set(chamelium->session, SSH_OPTIONS_HOST, ip_addr);
+	ssh_options_set(chamelium->session, SSH_OPTIONS_USER, "root");
+
+	rc = ssh_connect(chamelium->session);
+	if (rc != SSH_OK)
+		goto free;
+
+	/* Currently assuming no password is set */
+	rc = ssh_userauth_none(chamelium->session, NULL);
+	if (rc != SSH_AUTH_SUCCESS)
+		goto disconnect;
+
+	free(ip_addr);
+
+	return true;
+
+disconnect:
+	ssh_disconnect(chamelium->session);
+free:
+	ssh_free(chamelium->session);
+	free(ip_addr);
+
+	return false;
+}
+
+static void
+chamelium_ssh_deinit(struct chamelium *chamelium)
+{
+	ssh_disconnect(chamelium->session);
+	ssh_free(chamelium->session);
+}
+
 /**
  * chamelium_init:
  * @chamelium: The Chamelium instance to use
@@ -1592,6 +1730,14 @@ struct chamelium *chamelium_init(int drm_fd)
 		goto error;
 	}
 
+	if (!chamelium_get_url(chamelium))
+		goto error;
+
+	if (!chamelium_ssh_init(chamelium))
+		goto error;
+
+	chamelium_clear_chameleond(chamelium);
+
 	if (!chamelium_read_config(chamelium, drm_fd))
 		goto error;
 
@@ -1636,6 +1782,8 @@ void chamelium_deinit(struct chamelium *chamelium)
 		free(pos);
 	}
 
+	chamelium_ssh_deinit(chamelium);
+
 	xmlrpc_client_destroy(chamelium->client);
 	xmlrpc_env_clean(&chamelium->env);
 
diff --git a/lib/meson.build b/lib/meson.build
index dd36f8180..40d1cb65e 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -97,6 +97,10 @@ if alsa.found()
 	lib_sources += 'igt_alsa.c'
 endif
 
+if libssh.found()
+	lib_deps += libssh
+endif
+
 if chamelium.found()
 	lib_deps += chamelium
 	lib_sources += 'igt_chamelium.c'
diff --git a/meson.build b/meson.build
index 356a54142..3b4e40ce5 100644
--- a/meson.build
+++ b/meson.build
@@ -166,6 +166,8 @@ cairo = dependency('cairo', version : '>1.12.0', required : true)
 libudev = dependency('libudev', required : true)
 glib = dependency('glib-2.0', required : true)
 
+libssh = dependency('libssh', required : true)
+
 gsl = null_dep
 alsa = null_dep
 if _build_audio or _build_chamelium
@@ -205,7 +207,7 @@ endif
 
 chamelium = null_dep
 chameliuminfo = 'No'
-if _build_chamelium and gsl.found() and xmlrpc.found() and xmlrpc_util.found() and xmlrpc_client.found()
+if _build_chamelium and gsl.found() and libssh.found() and xmlrpc.found() and xmlrpc_util.found() and xmlrpc_client.found()
 	chamelium = declare_dependency(dependencies : [ xmlrpc,
 							xmlrpc_util, xmlrpc_client])
 	config.set('HAVE_CHAMELIUM', 1)
-- 
2.20.1



More information about the igt-dev mailing list