]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
* src/virsh.c: added a logging option to a file based on
authorDaniel Veillard <veillard@redhat.com>
Wed, 6 Jun 2007 12:24:31 +0000 (12:24 +0000)
committerDaniel Veillard <veillard@redhat.com>
Wed, 6 Jun 2007 12:24:31 +0000 (12:24 +0000)
  Nobuhiro Itou patch
* src/xen_internal.c: small TODO comment from Atsushi SAKAI
Daniel

ChangeLog
src/virsh.c
src/xen_internal.c

index 16a4a63bd2f86ed3a213632c18e690f60f291930..5d1a42591d081c07dcb1b289c76af498aa79ce76 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Wed Jun  6 14:22:36 CEST 2007 Daniel Veillard <veillard@redhat.com>
+
+       * src/virsh.c: added a logging option to a file based on
+         Nobuhiro Itou patch
+       * src/xen_internal.c: small TODO comment from Atsushi SAKAI
+
 Wed Jun  6 09:20:23 CEST 2007 Daniel Veillard <veillard@redhat.com>
 
        * po/*: merge all po from Red Hat/Fedora translations, and 
index de0d6c4aaa27108766cd78b8f149a218063db21b..7b17956f9c248dc968712cccc187fe1be7becb1d 100644 (file)
@@ -30,6 +30,8 @@
 #include <fcntl.h>
 #include <locale.h>
 #include <assert.h>
+#include <errno.h>
+#include <sys/stat.h>
 
 #include <libxml/parser.h>
 #include <libxml/tree.h>
@@ -57,6 +59,33 @@ static char *progname;
         ((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
           ((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)
 
+/**
+ * The log configuration
+ */
+#define MSG_BUFFER    4096
+#define SIGN_NAME     "virsh"
+#define DIR_MODE      (S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)  /* 0755 */
+#define FILE_MODE     (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH)                                /* 0644 */
+#define LOCK_MODE     (S_IWUSR | S_IRUSR)                                                    /* 0600 */
+#define LVL_DEBUG     "DEBUG"
+#define LVL_INFO      "INFO"
+#define LVL_NOTICE    "NOTICE"
+#define LVL_WARNING   "WARNING"
+#define LVL_ERROR     "ERROR"
+
+/**
+ * vshErrorLevel:
+ *
+ * Indicates the level of an log message
+ */
+typedef enum {
+    VSH_ERR_DEBUG = 0,
+    VSH_ERR_INFO,
+    VSH_ERR_NOTICE,
+    VSH_ERR_WARNING,
+    VSH_ERR_ERROR
+} vshErrorLevel;
+
 /*
  * The error handler for virtsh
  */
@@ -176,6 +205,8 @@ typedef struct __vshControl {
     int readonly;               /* connect readonly (first time only, not
                                  * during explicit connect command)
                                  */
+    char *logfile;              /* log file name */
+    int log_fd;                 /* log file descriptor */
 } __vshControl;
 
 
@@ -186,6 +217,9 @@ static void vshError(vshControl * ctl, int doexit, const char *format, ...)
 static int vshInit(vshControl * ctl);
 static int vshDeinit(vshControl * ctl);
 static void vshUsage(vshControl * ctl, const char *cmdname);
+static void vshOpenLogFile(vshControl *ctl);
+static void vshOutputLogFile(vshControl *ctl, int log_level, const char *format, va_list ap);
+static void vshCloseLogFile(vshControl *ctl);
 
 static int vshParseArgv(vshControl * ctl, int argc, char **argv);
 
@@ -3365,6 +3399,10 @@ vshDebug(vshControl * ctl, int level, const char *format, ...)
 {
     va_list ap;
 
+    va_start(ap, format);
+    vshOutputLogFile(ctl, VSH_ERR_DEBUG, format, ap);
+    va_end(ap);
+
     if (level > ctl->debug)
         return;
 
@@ -3392,6 +3430,10 @@ vshError(vshControl * ctl, int doexit, const char *format, ...)
 {
     va_list ap;
 
+    va_start(ap, format);
+    vshOutputLogFile(ctl, VSH_ERR_ERROR, format, ap);
+    va_end(ap);
+
     if (doexit)
         fprintf(stderr, _("%s: error: "), progname);
     else
@@ -3459,6 +3501,8 @@ vshInit(vshControl * ctl)
 
     ctl->uid = getuid();
 
+    vshOpenLogFile(ctl);
+
     /* set up the library error handler */
     virSetErrorFunc(NULL, virshErrorHandler);
 
@@ -3478,6 +3522,128 @@ vshInit(vshControl * ctl)
     return TRUE;
 }
 
+/**
+ * vshOpenLogFile:
+ *
+ * Open log file.
+ */
+static void
+vshOpenLogFile(vshControl *ctl)
+{
+    struct stat st;
+
+    if (ctl->logfile == NULL)
+        return;
+
+    /* check log file */
+    if (stat(ctl->logfile, &st) == -1) {
+        switch (errno) {
+            case ENOENT:
+                break;
+            default:
+                vshError(ctl, TRUE, _("failed to get the log file information"));
+                break;
+        }
+    } else {
+        if (!S_ISREG(st.st_mode)) {
+            vshError(ctl, TRUE, _("the log path is not a file"));
+        }
+    }
+
+    /* log file open */
+    if ((ctl->log_fd = open(ctl->logfile, O_WRONLY | O_APPEND | O_CREAT | O_SYNC, FILE_MODE)) < 0) {
+        vshError(ctl, TRUE, _("failed to open the log file. check the log file path"));
+    }
+}
+
+/**
+ * vshOutputLogFile:
+ *
+ * Outputting an error to log file.
+ */
+static void
+vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, va_list ap)
+{
+    char msg_buf[MSG_BUFFER];
+    const char *lvl = "";
+    struct timeval stTimeval;
+    struct tm *stTm;
+
+    if (ctl->log_fd == -1)
+        return;
+
+    /**
+     * create log format
+     *
+     * [YYYY.MM.DD HH:MM:SS SIGNATURE PID] LOG_LEVEL message
+    */
+    gettimeofday(&stTimeval, NULL);
+    stTm = localtime(&stTimeval.tv_sec);
+    snprintf(msg_buf, sizeof(msg_buf),
+             "[%d.%02d.%02d %02d:%02d:%02d ",
+             (1900 + stTm->tm_year),
+             (1 + stTm->tm_mon),
+             (stTm->tm_mday),
+             (stTm->tm_hour),
+             (stTm->tm_min),
+             (stTm->tm_sec));
+    snprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf),
+             "%s] ", SIGN_NAME);
+    switch (log_level) {
+        case VSH_ERR_DEBUG:
+            lvl = LVL_DEBUG;
+            break;
+        case VSH_ERR_INFO:
+            lvl = LVL_INFO;
+            break;
+        case VSH_ERR_NOTICE:
+            lvl = LVL_INFO;
+            break;
+        case VSH_ERR_WARNING:
+            lvl = LVL_WARNING;
+            break;
+        case VSH_ERR_ERROR:
+            lvl = LVL_ERROR;
+            break;
+        default:
+            lvl = LVL_DEBUG;
+            break;
+    }
+    snprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf),
+             "%s ", lvl);
+    vsnprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf),
+              msg_format, ap);
+
+    if (msg_buf[strlen(msg_buf) - 1] != '\n')
+        snprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf), "\n");
+
+    /* write log */
+    if (write(ctl->log_fd, msg_buf, strlen(msg_buf)) == -1) {
+        vshCloseLogFile(ctl);
+        vshError(ctl, FALSE, _("failed to write the log file"));
+    }
+}
+
+/**
+ * vshCloseLogFile:
+ *
+ * Close log file.
+ */
+static void
+vshCloseLogFile(vshControl *ctl)
+{
+    /* log file close */
+    if (ctl->log_fd >= 0) {
+        close(ctl->log_fd);
+        ctl->log_fd = -1;
+    }
+
+    if (ctl->logfile) {
+        free(ctl->logfile);
+        ctl->logfile = NULL;
+    }
+}
+
 /* -----------------
  * Readline stuff
  * -----------------
@@ -3601,6 +3767,8 @@ vshReadlineInit(void)
 static int
 vshDeinit(vshControl * ctl)
 {
+    vshCloseLogFile(ctl);
+
     if (ctl->conn) {
         if (virConnectClose(ctl->conn) != 0) {
             ctl->conn = NULL;   /* prevent recursive call from vshError() */
@@ -3629,6 +3797,7 @@ vshUsage(vshControl * ctl, const char *cmdname)
                           "    -h | --help             this help\n"
                           "    -q | --quiet            quiet mode\n"
                           "    -t | --timing           print timing information\n"
+                          "    -l | --log <file>       output logging to file\n"
                           "    -v | --version          program version\n\n"
                           "  commands (non interactive mode):\n"), progname);
 
@@ -3663,6 +3832,7 @@ vshParseArgv(vshControl * ctl, int argc, char **argv)
         {"version", 0, 0, 'v'},
         {"connect", 1, 0, 'c'},
         {"readonly", 0, 0, 'r'},
+        {"log", 1, 0, 'l'},
         {0, 0, 0, 0}
     };
 
@@ -3705,7 +3875,7 @@ vshParseArgv(vshControl * ctl, int argc, char **argv)
     end = end ? : argc;
 
     /* standard (non-command) options */
-    while ((arg = getopt_long(end, argv, "d:hqtc:vr", opt, &idx)) != -1) {
+    while ((arg = getopt_long(end, argv, "d:hqtc:vrl:", opt, &idx)) != -1) {
         switch (arg) {
         case 'd':
             ctl->debug = atoi(optarg);
@@ -3728,6 +3898,9 @@ vshParseArgv(vshControl * ctl, int argc, char **argv)
         case 'r':
             ctl->readonly = TRUE;
             break;
+        case 'l':
+            ctl->logfile = vshStrdup(ctl, optarg);
+            break;
         default:
             vshError(ctl, TRUE,
                      _("unsupported option '-%c'. See --help."), arg);
@@ -3794,6 +3967,7 @@ main(int argc, char **argv)
 
     memset(ctl, 0, sizeof(vshControl));
     ctl->imode = TRUE;          /* default is interactive mode */
+    ctl->log_fd = -1;           /* Initialize log file descriptor */
 
     if ((defaultConn = getenv("VIRSH_DEFAULT_CONNECT_URI"))) {
         ctl->name = strdup(defaultConn);
index e777d417b606e9a9fdb71a8c2ea6a1a8e6149095..f6649cc36e7255b62a479b4e85b83582e2dce362 100644 (file)
@@ -1016,6 +1016,7 @@ xenHypervisorGetSchedulerType(virDomainPtr domain, int *nparams)
     /*
      * Support only dom_interface_version >=5
      * (Xen3.1.0 or later)
+     * TODO: check on Xen 3.0.3
      */
     if (dom_interface_version < 5) {
         virXenErrorFunc(VIR_ERR_NO_XEN, __FUNCTION__,