[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Add persistent guest & hv logging in xenconsoled.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1180964952 -3600
# Node ID edf407a3dd70db0af60617b6c90aa3589d7c1c7d
# Parent  da3185b03113611fd322e439f17103af4d11b064
Add persistent guest & hv logging in xenconsoled.

  * The  --log  command line argument takes one of 4 values

      - none   - no logging   (the default)
      - hv     - log all hypervisor messages
      - guest  - log all guest messages
      - both   - log all guest & hypervisor messages

  * The --log-dir command line argument takes a path to specify where
    to store logfiles. If omitted it defaults to /var/log/xen/console

  * The hypervisor logfile is $LOGDIR/hypervisor.log

  * The guest logfile is  $LOGDIR/guest-[NAME].log

  * If receiving a SIGHUP it will close & re-open all log files to
    enable logrotate to do its magic

  * Fixes the permissions of /var/run/xenconsoled.pid

  * Adds a --pid-file command line argument to override the default
    location of pid file (this is not really related to logging, but
    since I was in that code...)

Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx>
---
 tools/console/daemon/io.c    |  154 ++++++++++++++++++++++++++++++++++++++++++-
 tools/console/daemon/main.c  |   54 ++++++++++++++-
 tools/console/daemon/utils.c |    2 
 3 files changed, 204 insertions(+), 6 deletions(-)

diff -r da3185b03113 -r edf407a3dd70 tools/console/daemon/io.c
--- a/tools/console/daemon/io.c Mon Jun 04 14:40:12 2007 +0100
+++ b/tools/console/daemon/io.c Mon Jun 04 14:49:12 2007 +0100
@@ -43,6 +43,14 @@
 /* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
 #define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
 
+extern int log_reload;
+extern int log_guest;
+extern int log_hv;
+extern char *log_dir;
+
+static int log_hv_fd = -1;
+static int xc_handle = -1;
+
 struct buffer
 {
        char *data;
@@ -56,6 +64,7 @@ struct domain
 {
        int domid;
        int tty_fd;
+       int log_fd;
        bool is_dead;
        struct buffer buffer;
        struct domain *next;
@@ -102,6 +111,19 @@ static void buffer_append(struct domain 
        intf->out_cons = cons;
        xc_evtchn_notify(dom->xce_handle, dom->local_port);
 
+       /* Get the data to the logfile as early as possible because if
+        * no one is listening on the console pty then it will fill up
+        * and handle_tty_write will stop being called.
+        */
+       if (dom->log_fd != -1) {
+               int len = write(dom->log_fd,
+                               buffer->data + buffer->size - size,
+                               size);
+               if (len < 0)
+                       dolog(LOG_ERR, "Write to log failed on domain %d: %d 
(%s)\n",
+                             dom->domid, errno, strerror(errno));
+       }
+
        if (buffer->max_capacity &&
            buffer->size > buffer->max_capacity) {
                /* Discard the middle of the data. */
@@ -142,6 +164,53 @@ static bool domain_is_valid(int domid)
                
        return ret;
 }
+
+static int create_hv_log(void)
+{
+       char logfile[PATH_MAX];
+       int fd;
+       snprintf(logfile, PATH_MAX-1, "%s/hypervisor.log", log_dir);
+       logfile[PATH_MAX-1] = '\0';
+
+       fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644);
+       if (fd == -1)
+               dolog(LOG_ERR, "Failed to open log %s: %d (%s)",
+                     logfile, errno, strerror(errno));
+       return fd;
+}
+
+static int create_domain_log(struct domain *dom)
+{
+       char logfile[PATH_MAX];
+       char *namepath, *data, *s;
+       int fd, len;
+
+       namepath = xs_get_domain_path(xs, dom->domid);
+       s = realloc(namepath, strlen(namepath) + 6);
+       if (s == NULL) {
+               free(namepath);
+               return -1;
+       }
+       strcat(namepath, "/name");
+       data = xs_read(xs, XBT_NULL, namepath, &len);
+       if (!data)
+               return -1;
+       if (!len) {
+               free(data);
+               return -1;
+       }
+
+       snprintf(logfile, PATH_MAX-1, "%s/guest-%s.log", log_dir, data);
+       free(data);
+       logfile[PATH_MAX-1] = '\0';
+
+       fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644);
+       if (fd == -1)
+               dolog(LOG_ERR, "Failed to open log %s: %d (%s)",
+                     logfile, errno, strerror(errno));
+       return fd;
+}
+
 
 static int domain_create_tty(struct domain *dom)
 {
@@ -324,6 +393,9 @@ static int domain_create_ring(struct dom
                }
        }
 
+       if (log_guest)
+               dom->log_fd = create_domain_log(dom);
+
  out:
        return err;
 }
@@ -351,6 +423,7 @@ static bool watch_domain(struct domain *
        return success;
 }
 
+
 static struct domain *create_domain(int domid)
 {
        struct domain *dom;
@@ -382,6 +455,8 @@ static struct domain *create_domain(int 
        strcat(dom->conspath, "/console");
 
        dom->tty_fd = -1;
+       dom->log_fd = -1;
+
        dom->is_dead = false;
        dom->buffer.data = 0;
        dom->buffer.consumed = 0;
@@ -442,6 +517,10 @@ static void cleanup_domain(struct domain
        if (d->tty_fd != -1) {
                close(d->tty_fd);
                d->tty_fd = -1;
+       }
+       if (d->log_fd != -1) {
+               close(d->log_fd);
+               d->log_fd = -1;
        }
 
        free(d->buffer.data);
@@ -604,13 +683,54 @@ static void handle_xs(void)
        free(vec);
 }
 
+static void handle_hv_logs(void)
+{
+       char buffer[1024*16];
+       char *bufptr = buffer;
+       unsigned int size = sizeof(buffer);
+       if (xc_readconsolering(xc_handle, &bufptr, &size, 1) == 0) {
+               int len = write(log_hv_fd, buffer, size);
+               if (len < 0)
+                       dolog(LOG_ERR, "Failed to write hypervisor log: %d 
(%s)",
+                             errno, strerror(errno));
+       }
+}
+
+static void handle_log_reload(void)
+{
+       if (log_guest) {
+               struct domain *d;
+               for (d = dom_head; d; d = d->next) {
+                       if (d->log_fd != -1)
+                               close(d->log_fd);
+                       d->log_fd = create_domain_log(d);
+               }
+       }
+
+       if (log_hv) {
+               if (log_hv_fd != -1)
+                       close(log_hv_fd);
+               log_hv_fd = create_hv_log();
+       }
+}
+
 void handle_io(void)
 {
        fd_set readfds, writefds;
        int ret;
 
-       do {
+       if (log_hv) {
+               xc_handle = xc_interface_open();
+               if (xc_handle == -1)
+                       dolog(LOG_ERR, "Failed to open xc handle: %d (%s)",
+                             errno, strerror(errno));
+               else
+                       log_hv_fd = create_hv_log();
+       }
+
+       for (;;) {
                struct domain *d, *n;
+               struct timeval timeout = { 1, 0 }; /* Read HV logs every 1 
second */
                int max_fd = -1;
 
                FD_ZERO(&readfds);
@@ -636,7 +756,30 @@ void handle_io(void)
                        }
                }
 
-               ret = select(max_fd + 1, &readfds, &writefds, 0, NULL);
+               /* XXX I wish we didn't have to busy wait for hypervisor logs
+                * but there's no obvious way to get event channel notifications
+                * for new HV log data as we can with guest */
+               ret = select(max_fd + 1, &readfds, &writefds, 0, log_hv_fd != 
-1 ? &timeout : NULL);
+
+               if (ret == -1) {
+                       if (errno == EINTR) {
+                               if (log_reload) {
+                                       handle_log_reload();
+                                       log_reload = 0;
+                               }
+                               continue;
+                       }
+                       dolog(LOG_ERR, "Failure in select: %d (%s)",
+                             errno, strerror(errno));
+                       break;
+               }
+
+               /* Check for timeout */
+               if (ret == 0) {
+                       if (log_hv_fd != -1)
+                               handle_hv_logs();
+                       continue;
+               }
 
                if (FD_ISSET(xs_fileno(xs), &readfds))
                        handle_xs();
@@ -656,7 +799,12 @@ void handle_io(void)
                        if (d->is_dead)
                                cleanup_domain(d);
                }
-       } while (ret > -1);
+       }
+
+       if (log_hv_fd != -1)
+               close(log_hv_fd);
+       if (xc_handle != -1)
+               xc_interface_close(xc_handle);
 }
 
 /*
diff -r da3185b03113 -r edf407a3dd70 tools/console/daemon/main.c
--- a/tools/console/daemon/main.c       Mon Jun 04 14:40:12 2007 +0100
+++ b/tools/console/daemon/main.c       Mon Jun 04 14:49:12 2007 +0100
@@ -23,6 +23,8 @@
 #include <stdio.h>
 #include <errno.h>
 #include <unistd.h>
+#include <string.h>
+#include <signal.h>
 #include <sys/types.h>
 
 #include "xenctrl.h"
@@ -30,9 +32,19 @@
 #include "utils.h"
 #include "io.h"
 
+int log_reload = 0;
+int log_guest = 0;
+int log_hv = 0;
+char *log_dir = NULL;
+
+static void handle_hup(int sig)
+{
+        log_reload = 1;
+}
+
 static void usage(char *name)
 {
-       printf("Usage: %s [-h] [-V] [-v] [-i]\n", name);
+       printf("Usage: %s [-h] [-V] [-v] [-i] [--log=none|guest|hv|all] 
[--log-dir=DIR] [--pid-file=PATH]\n", name);
 }
 
 static void version(char *name)
@@ -48,6 +60,9 @@ int main(int argc, char **argv)
                { "version", 0, 0, 'V' },
                { "verbose", 0, 0, 'v' },
                { "interactive", 0, 0, 'i' },
+               { "log", 1, 0, 'l' },
+               { "log-dir", 1, 0, 'r' },
+               { "pid-file", 1, 0, 'p' },
                { 0 },
        };
        bool is_interactive = false;
@@ -55,6 +70,7 @@ int main(int argc, char **argv)
        int syslog_option = LOG_CONS;
        int syslog_mask = LOG_WARNING;
        int opt_ind = 0;
+       char *pidfile = NULL;
 
        while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) {
                switch (ch) {
@@ -71,6 +87,22 @@ int main(int argc, char **argv)
                case 'i':
                        is_interactive = true;
                        break;
+               case 'l':
+                       if (!strcmp(optarg, "all")) {
+                             log_hv = 1;
+                             log_guest = 1;
+                       } else if (!strcmp(optarg, "hv")) {
+                             log_hv = 1;
+                       } else if (!strcmp(optarg, "guest")) {
+                             log_guest = 1;
+                       }
+                       break;
+               case 'r':
+                       log_dir = strdup(optarg);
+                       break;
+               case 'p':
+                       pidfile = strdup(optarg);
+                       break;
                case '?':
                        fprintf(stderr,
                                "Try `%s --help' for more information\n",
@@ -79,16 +111,22 @@ int main(int argc, char **argv)
                }
        }
 
+       if (!log_dir) {
+               log_dir = strdup("/var/log/xen/console");
+       }
+
        if (geteuid() != 0) {
                fprintf(stderr, "%s requires root to run.\n", argv[0]);
                exit(EPERM);
        }
 
+       signal(SIGHUP, handle_hup);
+
        openlog("xenconsoled", syslog_option, LOG_DAEMON);
        setlogmask(syslog_mask);
 
        if (!is_interactive) {
-               daemonize("/var/run/xenconsoled.pid");
+               daemonize(pidfile ? pidfile : "/var/run/xenconsoled.pid");
        }
 
        if (!xen_setup())
@@ -99,6 +137,18 @@ int main(int argc, char **argv)
        handle_io();
 
        closelog();
+       free(log_dir);
+       free(pidfile);
 
        return 0;
 }
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -r da3185b03113 -r edf407a3dd70 tools/console/daemon/utils.c
--- a/tools/console/daemon/utils.c      Mon Jun 04 14:40:12 2007 +0100
+++ b/tools/console/daemon/utils.c      Mon Jun 04 14:49:12 2007 +0100
@@ -86,7 +86,7 @@ void daemonize(const char *pidfile)
        if (chdir("/") < 0)
                exit (1);
 
-       fd = open(pidfile, O_RDWR | O_CREAT);
+       fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR);
        if (fd == -1) {
                exit(1);
        }

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.