From 7587ba18c9b044f0361ff02a2aebf9369362bfc8 Mon Sep 17 00:00:00 2001 From: sungmin ha Date: Thu, 30 Oct 2014 16:36:59 +0900 Subject: [PATCH] spice: added thread for rpm package installation and spice-vdagent execution Change-Id: Ib3260b6bc5289eb7eb53fa2fedfa4277d95f8aea Signed-off-by: sungmin ha --- tizen/src/util/osutil-linux.c | 219 ++++++++++++++++++++++++++++++++-- tizen/src/util/osutil.h | 1 + vl.c | 2 + 3 files changed, 215 insertions(+), 7 deletions(-) diff --git a/tizen/src/util/osutil-linux.c b/tizen/src/util/osutil-linux.c index c4139f60b7..7b1eacdbb2 100644 --- a/tizen/src/util/osutil-linux.c +++ b/tizen/src/util/osutil-linux.c @@ -55,6 +55,7 @@ #include #ifdef CONFIG_SPICE #include +#include "hw/virtio/maru_virtio_evdi.h" #endif MULTI_DEBUG_CHANNEL(emulator, osutil); @@ -456,9 +457,13 @@ void get_host_proxy_os(char *http_proxy, char *https_proxy, char *ftp_proxy, cha #ifdef CONFIG_SPICE #define PID_MAX_COUNT 256 +#define countof(X) ( (size_t) ( sizeof(X)/sizeof*(X) ) ) const char *execution_file_websocket = "websockify.py"; const char *execution_file_node = "node"; const char *node_proc_name = "emulator-x86-web"; +static const char *sdb_push_path = "/home/developer/"; +static const char *must_have_pkgs[] = {"emuld", "spice-protocol", "spice-vdagent"}; +static const char *systemd_services[] = {"spice-vdagent.service", "spice-vdagentd.service"}; void get_process_id(char const *process_name, char *first_param, int *pid, int *pscount) { @@ -495,7 +500,7 @@ void get_process_id(char const *process_name, char *first_param, int *pid, int * if (strstr(mptr, process_name) != NULL) { if (!first_param || strstr(&cmdline[current_len + 1], first_param) != NULL) { if (sizeof(pid) < *pscount + 1) { - WARN("PID array size is not enough.\n"); + ERR("PID array size is not enough.\n"); return; } pid[*pscount] = atoi(dir_entry_p->d_name); @@ -539,9 +544,9 @@ void execute_websocket(int port) ret = execl(websocket_path, execution_file_websocket, websocket_port, local_port, (char *)0); if (ret == 127) { - WARN("Can't execute websocket.\n"); + ERR("Can't execute websocket.\n"); } else if (ret == -1) { - WARN("Fork error!\n"); + ERR("Fork error!\n"); } } @@ -563,9 +568,9 @@ void execute_nodejs(void) ret = execl(nodejs_path, execution_file_node, webviewer_script, (char *)0); if (ret == 127) { - WARN("Can't execute node server.\n"); + ERR("Can't execute node server.\n"); } else if (ret == -1) { - WARN("Fork error!\n"); + ERR("Fork error!\n"); } } @@ -602,12 +607,12 @@ static void nodejs_notify_exit(Notifier *notifier, void *data) get_process_id("spicevmc", NULL, pid, &pscount); if (pscount == 1) { INFO("Detected the last spice emulator.\n"); - pid[0] = 0; + memset(pid, 0, sizeof(pid)); pscount = 0; get_process_id(node_proc_name, NULL, pid, &pscount); for (i = 0; i < pscount; i++) { INFO("Will be killed %s, PID: %d\n", node_proc_name, pid[i]); - kill(pid[i], SIGTERM); + kill(pid[i], SIGKILL); } } } @@ -658,6 +663,206 @@ void nodejs_init(void) INFO("Aleady running node server.\n"); } } + +static int get_pkg_install_cnt(char const *pkg) +{ + FILE *fp; + char buf[255]; + int pkg_cnt = 0; + char const *bin_dir = get_bin_path(); + char const *relative_path = "../../sdb"; + char cmd[strlen(bin_dir) + strlen(relative_path) + strlen(pkg) + 80]; + + /* check rpm pkg in guest */ + sprintf(cmd, "%s%s -s emulator-%d shell \"rpm -qa | grep %s | wc -l\" 2>/dev/null", + bin_dir, relative_path, get_device_serial_number(), pkg); + fp = popen(cmd, "r"); + if (fp == NULL) { + ERR("%s failed\n", cmd); + return -1; + } + + /* The last output line is pkg cnt. */ + memset(buf, 0, sizeof(buf)); + while (fgets(buf, sizeof(buf), fp)) { + if (strlen(buf) == 0) { + pclose(fp); + return -1; + } + } + pclose(fp); + pkg_cnt = atoi(buf); + + return pkg_cnt; +} + +static bool send_cmd(char const *cmd) +{ + int sndlen = 15; /* HEADER(CMD + LENGTH + GROUP + ACTION) + 1 */ + char* sndbuf; + bool ret = false; + short length = strlen(cmd); + + sndlen += strlen(cmd); + sndbuf = (char*) g_malloc0(sndlen); + if (!sndbuf) { + ERR("g_malloc0 failed!\n"); + return false; + } + + memset(sndbuf, 0, sndlen); + memcpy(sndbuf, "cmd", 3); + memcpy(sndbuf + 10, &length, 2); + memcpy(sndbuf + 14, cmd, strlen(cmd)); + + TRACE("send to evdi: %s, %s\n", sndbuf, sndbuf + 14); + + ret = send_to_evdi(route_ij, sndbuf, sndlen); + g_free(sndbuf); + + if (!ret) { + ERR("send to evdi failed!\n"); + return false; + } + + return true; +} + +static bool install_pkg(char const *pkg, char *installed_pkg) +{ + char const *bin_dir = get_bin_path(); + char const *remote_bin_dir = get_remote_bin_path(); + char const *relative_path = "../../sdb"; + char pkg_fname[255]; + char cmd[strlen(bin_dir) + strlen(relative_path) + sizeof(pkg_fname) + 48]; + DIR *dir_p; + struct dirent *dir_entry_p; + + /* to find a file, including pkg name */ + dir_p = opendir(remote_bin_dir); + memset(pkg_fname, 0, sizeof(pkg_fname)); + while (NULL != (dir_entry_p = readdir(dir_p))) { + if (strncmp(dir_entry_p->d_name, pkg, strlen(pkg)) == 0) { + strncpy(pkg_fname, dir_entry_p->d_name, strlen(dir_entry_p->d_name)); + break; + } + } + closedir(dir_p); + + if (strlen(pkg_fname) == 0) { + ERR("%s package is not exist in %s\n", pkg, remote_bin_dir); + return false; + } + + /* sdb push pkg to guest */ + memset(cmd, 0, sizeof(cmd)); + sprintf(cmd, "%s%s -s emulator-%d push %s%s %s 2>/dev/null", bin_dir, relative_path, + get_device_serial_number(), remote_bin_dir, pkg_fname, sdb_push_path); + int ret = system(cmd); + if (ret == 127) { + ERR("%s can't execute /bin/sh!\n", cmd); + return false; + } else if(ret == -1) { + ERR("%s fork error!\n", cmd); + return false; + } + + /* install pkg */ + memset(cmd, 0, sizeof(cmd)); + sprintf(cmd, "rpm -i %s%s\n", sdb_push_path, pkg_fname); + if (send_cmd(cmd) == false) { + ERR("%s install failed\n", pkg_fname); + return false; + } + + strncpy(installed_pkg, pkg_fname, strlen(pkg_fname)); + + return true; +} + +static void* pkg_check_thread(void *args) +{ + int i = 0; + int repeat_cnt = 0; + int repeat_period = 500000; /* 0.5 sec */ + int repeat_max = 40; + int install_cnt = 0; + bool is_pkg_pushed = false; + char const *bin_dir = get_bin_path(); + char const *relative_path = "../../sdb"; + char cmd[strlen(bin_dir) + strlen(relative_path) + 80]; + char installed_pkgs[countof(must_have_pkgs) - 1][255]; + + /* check sdb connection */ + INFO("Waiting sdb connection...\n"); + while (get_pkg_install_cnt(must_have_pkgs[0]) < 1) { + usleep(repeat_period); + if (++repeat_cnt == repeat_max) { + ERR("SDB connection failed\n"); + pthread_exit(NULL); + } + } + INFO("SDB connected.\n"); + + /* pkg push and install */ + for (i = 1; i < countof(must_have_pkgs); i++) { + if (get_pkg_install_cnt(must_have_pkgs[i]) < 1) { + INFO("Installing %s...\n", must_have_pkgs[i]); + memset(installed_pkgs[i - 1], 0, sizeof(installed_pkgs[i - 1])); + if (install_pkg(must_have_pkgs[i], installed_pkgs[i - 1]) == false) { + ERR("Install %s failed\n", must_have_pkgs[i]); + pthread_exit(NULL); + } + + /* To make sure pkg is completely installed. */ + repeat_cnt = 0; + while (get_pkg_install_cnt(must_have_pkgs[i]) < 1) { + usleep(repeat_period); + if (++repeat_cnt == repeat_max) { + ERR("Install %s failed\n", must_have_pkgs[i]); + pthread_exit(NULL); + } + } + + install_cnt++; + is_pkg_pushed = true; + INFO("Installed %s\n", must_have_pkgs[i]); + } else { + INFO("Already installed %s\n", must_have_pkgs[i]); + } + } + + /* start vdagent */ + for (i = 0; i < countof(systemd_services); i++) { + memset(cmd, 0, sizeof(cmd)); + sprintf(cmd, "systemctl start %s\n", systemd_services[i]); + if (send_cmd(cmd) == false) { + ERR("%s failed\n", cmd); + } else { + INFO("Started %s\n", systemd_services[i]); + } + } + + /* delete vdagent pkgs */ + if (is_pkg_pushed) { + for (; install_cnt > 0; install_cnt--) { + sprintf(cmd, "rm %s%s", sdb_push_path, installed_pkgs[install_cnt - 1]); + if (send_cmd(cmd) == false) { + ERR("%s%s delete failed\n", sdb_push_path, installed_pkgs[install_cnt - 1]); + } else { + TRACE("%s%s delete succeed\n", sdb_push_path, installed_pkgs[install_cnt - 1]); + } + } + } + + pthread_exit(NULL); +} + +void spice_pkg_install(void) { + QemuThread check_thread_id; + qemu_thread_create(&check_thread_id, "pkg_check_thread", pkg_check_thread, (void *) + NULL, QEMU_THREAD_DETACHED); +} #endif bool make_sdcard_lock_os(char *sdcard) diff --git a/tizen/src/util/osutil.h b/tizen/src/util/osutil.h index c858726915..e0edb0baf6 100644 --- a/tizen/src/util/osutil.h +++ b/tizen/src/util/osutil.h @@ -103,6 +103,7 @@ void execute_nodejs(void); void clean_websocket_port(int signal); void nodejs_init(void); void websocket_init(void); +void spice_pkg_install(void); #endif static inline int get_timeofday(char *buf, size_t size) diff --git a/vl.c b/vl.c index 7095d729a8..3561e99430 100644 --- a/vl.c +++ b/vl.c @@ -165,6 +165,7 @@ extern int enable_spice; #if defined(CONFIG_SPICE) && defined(CONFIG_LINUX) extern void websocket_init(void); extern void nodejs_init(void); +extern void spice_pkg_install(void); #endif #endif @@ -4657,6 +4658,7 @@ int main(int argc, char **argv, char **envp) if (using_spice) { qemu_spice_display_init(); #if defined(CONFIG_MARU) && defined(CONFIG_LINUX) + spice_pkg_install(); websocket_init(); #endif } -- 2.34.1