spice: added thread for rpm package installation and spice-vdagent execution 94/29594/3
authorsungmin ha <sungmin82.ha@samsung.com>
Thu, 30 Oct 2014 07:36:59 +0000 (16:36 +0900)
committersungmin ha <sungmin82.ha@samsung.com>
Thu, 30 Oct 2014 08:48:07 +0000 (17:48 +0900)
Change-Id: Ib3260b6bc5289eb7eb53fa2fedfa4277d95f8aea
Signed-off-by: sungmin ha <sungmin82.ha@samsung.com>
tizen/src/util/osutil-linux.c
tizen/src/util/osutil.h
vl.c

index c4139f60b7e5b29fb8f4d261dbffe29dffdbd9fd..7b1eacdbb29533b6f9cca5af633f118056b06980 100644 (file)
@@ -55,6 +55,7 @@
 #include <sys/sysinfo.h>
 #ifdef CONFIG_SPICE
 #include <dirent.h>
+#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)
index c8587269153a0c758a8a02a1841d0a621c236078..e0edb0baf6575ff90f8654e487698f7ba63278b5 100644 (file)
@@ -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 7095d729a8e52851311b41382c5e25e44d970608..3561e99430213bc7bac59f80d87f8953f87f0023 100644 (file)
--- 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
     }