Print this page
XXX zone aliases in "prstat -ZA"

@@ -22,27 +22,29 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
  * Portions Copyright 2009 Chad Mynhier
- * Copyright 2012 Joyent, Inc.  All rights reserved.
+ * Copyright 2013 Joyent, Inc.  All rights reserved.
  */
 
 #include <sys/types.h>
 #include <sys/resource.h>
 #include <sys/loadavg.h>
 #include <sys/time.h>
 #include <sys/pset.h>
 #include <sys/vm_usage.h>
+#include <sys/queue.h>
 #include <zone.h>
 #include <libzonecfg.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <dirent.h>
 #include <string.h>
+#include <strings.h>
 #include <errno.h>
 #include <poll.h>
 #include <ctype.h>
 #include <fcntl.h>
 #include <limits.h>

@@ -52,10 +54,12 @@
 
 #include <langinfo.h>
 #include <libintl.h>
 #include <locale.h>
 
+#include <sasl/saslutil.h>
+
 #include "prstat.h"
 #include "prutil.h"
 #include "prtable.h"
 #include "prsort.h"
 #include "prfile.h"

@@ -116,11 +120,11 @@
 #define TASK_LINE \
 "%6d %8d %5s %5s   %3.3s%% %9s %3.3s%% %28s"
 #define PROJECT_LINE \
 "%6d %8d %5s %5s   %3.3s%% %9s %3.3s%% %28s"
 #define ZONE_LINE \
-"%6d %8d %5s %5s   %3.3s%% %9s %3.3s%% %28s"
+"%6d %8d %5s %5s   %3.3s%% %9s %3.3s%% %-28s"
 
 #define TOTAL_LINE \
 "Total: %d processes, %d lwps, load averages: %3.2f, %3.2f, %3.2f"
 
 /* global variables */

@@ -163,10 +167,27 @@
 static volatile uint_t sigtstp = 0;
 static volatile uint_t sigterm = 0;
 
 static long pagesize;
 
+/*
+ * Cache for mapping 'alias' names (an attribute of the zone configuration) to
+ * zone names, for use in -Z output.
+ */
+static uint_t enable_alias_cache = FALSE;
+static SLIST_HEAD(alias_cache_head, alias_cache_entry) alias_cache =
+    SLIST_HEAD_INITIALIZER(alias_cache);
+
+typedef struct alias_cache_entry {
+        char *ace_zonename;
+        char *ace_alias;
+
+        SLIST_ENTRY(alias_cache_entry) ace_linkage;
+} alias_cache_entry_t;
+
+static const char *lookup_zone_alias(const char *);
+
 /* default settings */
 
 static optdesc_t opts = {
         5,                      /* interval between updates, seconds */
         15,                     /* number of lines in top part */

@@ -481,11 +502,11 @@
                                     id->id_nproc, psize, prssize, pmem, ptime,
                                     pcpu, projname);
                         else if (list->l_type == LT_ZONES)
                                 (void) printf(ZONE_LINE, (int)id->id_zoneid,
                                     id->id_nproc, psize, prssize, pmem, ptime,
-                                    pcpu, zonename);
+                                    pcpu, lookup_zone_alias(zonename));
                         else
                                 (void) printf(USER_LINE, id->id_nproc, pname,
                                     psize, prssize, pmem, ptime, pcpu);
                         (void) putp(t_eol);
                         (void) putchar('\n');

@@ -833,10 +854,108 @@
                 lwp->li_sig = usage->pr_sigs - lwp->li_usage.pr_sigs;
                 (void) memcpy(&lwp->li_usage, usage, sizeof (prusage_t));
         }
 }
 
+static alias_cache_entry_t *
+fetch_zone_alias(const char *zonen)
+{
+        zone_dochandle_t zch;
+        alias_cache_entry_t *ace;
+        struct zone_attrtab attrtab;
+        char out[4 * sizeof (attrtab.zone_attr_value)];
+        unsigned outlen = 0;
+        int err;
+
+        /*
+         * Get handle to zone configuration:
+         */
+        if ((zch = zonecfg_init_handle()) == NULL)
+                return (NULL);
+        if (zonecfg_get_handle(zonen, zch) != Z_OK) {
+                zonecfg_fini_handle(zch);
+                return (NULL);
+        }
+
+        /*
+         * Lookup the 'alias' attribute:
+         */
+        bzero(&attrtab, sizeof (attrtab));
+        (void) strlcpy(attrtab.zone_attr_name, "alias",
+            sizeof (attrtab.zone_attr_name));
+        if ((zonecfg_lookup_attr(zch, &attrtab)) != Z_OK) {
+                zonecfg_fini_handle(zch);
+                return (NULL);
+        }
+        zonecfg_fini_handle(zch);
+
+        /*
+         * Attempt to base64 decode the 'alias' attribute value:
+         */
+        if ((err = sasl_decode64(attrtab.zone_attr_value,
+            strlen(attrtab.zone_attr_value), out, sizeof (out), &outlen)) !=
+            SASL_OK) {
+                if (err == SASL_BADPROT) {
+                        /*
+                         * If it was invalid base64, hand the raw value on:
+                         */
+                        (void) strlcpy(out, attrtab.zone_attr_value,
+                            sizeof (out));
+                } else {
+                        /*
+                         * If we failed for any other reason, error out:
+                         */
+                        return (NULL);
+                }
+        }
+
+        /*
+         * Store it in the cache:
+         */
+        if ((ace = calloc(1, sizeof (*ace))) == NULL) {
+                return (NULL);
+        }
+        if ((ace->ace_zonename = strdup(zonen)) == NULL) {
+                free(ace);
+                return (NULL);
+        }
+        if ((ace->ace_alias = strdup(out)) == NULL) {
+                free(ace->ace_zonename);
+                free(ace);
+                return (NULL);
+        }
+
+        SLIST_INSERT_HEAD(&alias_cache, ace, ace_linkage);
+
+        return (ace);
+}
+
+static const char *
+lookup_zone_alias(const char *zonen)
+{
+        alias_cache_entry_t *ace;
+
+        if (enable_alias_cache != TRUE)
+                return (zonen);
+
+        /*
+         * Check if we have a value cached:
+         */
+        SLIST_FOREACH(ace, &alias_cache, ace_linkage) {
+                if (strcmp(ace->ace_zonename, zonen) == 0)
+                        return (ace->ace_alias);
+        }
+
+        /*
+         * If not, try and fetch it from libzonecfg:
+         */
+        if ((ace = fetch_zone_alias(zonen)) != NULL)
+                return (ace->ace_alias);
+
+        return (zonen);
+}
+
 static int
 read_procfile(fd_t **fd, char *pidstr, char *file, void *buf, size_t bufsize)
 {
         char procfile[MAX_PROCFS_PATH];
 

@@ -1374,12 +1493,15 @@
         fd_init(Setrlimit());
 
         pagesize = sysconf(_SC_PAGESIZE);
 
         while ((opt = getopt(argc, argv,
-            "vVcd:HmarRLtu:U:n:p:C:P:h:s:S:j:k:TJz:Z")) != (int)EOF) {
+            "vVcd:HmAarRLtu:U:n:p:C:P:h:s:S:j:k:TJz:Z")) != (int)EOF) {
                 switch (opt) {
+                case 'A':
+                        enable_alias_cache = TRUE;
+                        break;
                 case 'r':
                         opts.o_outpmode |= OPT_NORESOLVE;
                         break;
                 case 'R':
                         opts.o_outpmode |= OPT_REALTIME;