]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] add "description", "node" and show-node"/"show-desc", remove "node-name", v2
authorKrzysztof Piotr Oledzki <ole@ans.pl>
Fri, 2 Oct 2009 20:51:14 +0000 (22:51 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 3 Oct 2009 05:10:14 +0000 (07:10 +0200)
This patch implements "description" (proxy and global) and "node" (global)
options, removes "node-name" and adds "show-node" & "show-desc" options
for "stats". It also changes the way the header lines (with proxy name) and
the statistics are displayed, so stats no longer look so clumsy with very
long names.

Instead of "node-name" it is possible to use show-node/show-desc with
an optional parameter that overrides a default node/description.

backend cust-0045
        # report specific values for this customer
        stats show-node Europe
        stats show-desc Master node for Europe, Asia, Africa

doc/configuration.txt
include/common/uri_auth.h
include/types/global.h
include/types/proxy.h
src/cfgparse.c
src/dumpstats.c
src/haproxy.c
src/uri_auth.c

index 2055a09a30ef18ad46eb6e30b9f7773c4cfc0257..c7e582df9800fa04aaf55d6d4e2950f7c83d2686 100644 (file)
@@ -383,6 +383,8 @@ The following keywords are supported in the "global" section :
    - ulimit-n
    - user
    - stats
+   - node
+   - description
   
  * Performance tuning
    - maxconn
@@ -514,6 +516,21 @@ user <user name>
   Similar to "uid" but uses the UID of user name <user name> from /etc/passwd.
   See also "uid" and "group".
 
+node <name>
+  Only letters, digits, hyphen and underscore are allowed, like in DNS names.
+
+  This statement is useful in HA configurations where two or more processes or
+  servers share the same IP address. By setting a different node-name on all
+  nodes, it becomes easy to immediately spot what server is handling the
+  traffic.
+
+description <text>
+  Add a text that describes the instance.
+
+  Please note that it is required to escape certain characters (# for example)
+  and this text is inserted into a html page so you should avoid using
+  "<" and ">" characters.
+
 
 3.2. Performance tuning
 -----------------------
@@ -696,6 +713,7 @@ clitimeout                  X          X         X         -  (deprecated)
 contimeout                  X          -         X         X  (deprecated)
 cookie                      X          -         X         X
 default_backend             -          X         X         -
+description                 -          X         X         X
 disabled                    X          X         X         X
 dispatch                    -          -         X         X
 enabled                     X          X         X         X
@@ -3785,22 +3803,43 @@ stats enable
   See also : "stats auth", "stats realm", "stats uri"
 
 
-stats node-name [ <name> ]
+stats show-node [ <name> ]
   Enable reporting of a host name on the statistics page.
   May be used in sections :   defaults | frontend | listen | backend
                                  yes   |    no    |   yes  |   yes
-  Arguments :
-    <name>    is an optional name to be reported. If unspecified, the system's
-              hostname is automatically used instead.
+  Arguments:
+    <name>    is an optional name to be reported. If unspecified, the
+              node name from global section is automatically used instead.
 
-  The node-name is read as a single word, so any spaces in it should be escaped
-  using a backslash ('\'). If it is left unspecified, the system's hostname is
-  used instead.
+  This statement is useful for users that offer shared services to their
+  customers, where node or description might be different on a stats page
+  provided for each customer.
 
-  This statement is useful in HA configurations where two or more processes or
-  servers share a same IP address. By setting a different node-name on all
-  nodes, it becomes easy to immediately spot what server is handling the
-  traffic.
+  Though this statement alone is enough to enable statistics reporting, it is
+  recommended to set all other settings in order to avoid relying on default
+  unobvious parameters.
+
+  Example:
+    # internal monitoring access (unlimited)
+    backend private_monitoring
+        stats enable
+        stats show-node Europe-1
+        stats uri       /admin?stats
+        stats refresh   5s
+
+  See also: "show-desc", "stats enable", "stats uri", and "node" in global section.
+
+
+stats show-desc [ <description> ]
+  Enable reporting of a description on the statistics page.
+  May be used in sections :   defaults | frontend | listen | backend
+                                 yes   |    no    |   yes  |   yes
+
+    <name>    is an optional description to be reported. If unspecified, the
+              description from global section is automatically used instead.
+
+  This statement is useful for users that offer shared services to their
+  customers, where node or description should be different for each customer.
 
   Though this statement alone is enough to enable statistics reporting, it is
   recommended to set all other settings in order to avoid relying on default
@@ -3810,11 +3849,11 @@ stats node-name [ <name> ]
     # internal monitoring access (unlimited)
     backend private_monitoring
         stats enable
-        stats node-name master
+        stats show-desc Master node for Europe, Asia, Africa
         stats uri       /admin?stats
         stats refresh   5s
 
-  See also : "stats enable", "stats uri"
+  See also: "show-node", "stats enable", "stats uri" and "description" in global section.
 
 
 stats realm <realm>
index 132be218dfe7267e379ac6c1000556fb220fcd5d..3a7fd9c74117321986c93cafba67ebbdfb5ffdb1 100644 (file)
@@ -32,13 +32,15 @@ struct stat_scope {
 };
 
 #define        ST_HIDEVER      0x00000001      /* do not report the version and reldate */
+#define        ST_SHNODE       0x00000002      /* show node name */
+#define        ST_SHDESC       0x00000004      /* show description */
 
 /* later we may link them to support multiple URI matching */
 struct uri_auth {
        int uri_len;                    /* the prefix length */
        char *uri_prefix;               /* the prefix we want to match */
        char *auth_realm;               /* the realm reported to the client */
-       char *node_name;                /* the node name reported to the client */
+       char *node, *desc;              /* node name & description reported in this stats */
        int refresh;                    /* refresh interval for the browser (in seconds) */
        int flags;                      /* some flags describing the statistics page */
        struct user_auth *users;        /* linked list of valid user:passwd couples */
@@ -75,7 +77,8 @@ struct uri_auth *stats_set_refresh(struct uri_auth **root, int interval);
 struct uri_auth *stats_set_flag(struct uri_auth **root, int flag);
 struct uri_auth *stats_add_auth(struct uri_auth **root, char *user);
 struct uri_auth *stats_add_scope(struct uri_auth **root, char *scope);
-struct uri_auth *stats_set_node_name(struct uri_auth **root, char *name);
+struct uri_auth *stats_set_node(struct uri_auth **root, char *name);
+struct uri_auth *stats_set_desc(struct uri_auth **root, char *desc);
 
 #endif /* _COMMON_URI_AUTH_H */
 
index 4d349c3136985b697524902e64422fbcd7a57256..3a8faa953d3d5883a82c4c1ac682386b93e296c6 100644 (file)
@@ -70,6 +70,7 @@ struct global {
        int spread_checks;
        char *chroot;
        char *pidfile;
+       char *node, *desc;              /* node name & description */
        int logfac1, logfac2;
        int loglev1, loglev2;
        int minlvl1, minlvl2;
index 8c93e555bca1b67ce79ea860570ea1f1526d873a..2cdf6895cbd38ac629eff35c65e520b8986a1de1 100644 (file)
@@ -233,7 +233,7 @@ struct proxy {
                int httpreq;                    /* maximum time for complete HTTP request */
                int check;                      /* maximum time for complete check */
        } timeout;
-       char *id;                               /* proxy id */
+       char *id, *desc;                        /* proxy id (name) and description */
        struct list pendconns;                  /* pending connections with no server assigned yet */
        int nbpend, nbpend_max;                 /* number of pending connections with no server assigned yet */
        int totpend;                            /* total number of pending connections on this instance (for stats) */
index 793865478af995044be6c9d527b927d121802598..3e74634531644b03e6516c8cc9136afa5adda4bf 100644 (file)
@@ -603,6 +603,52 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
                }
                global.chroot = strdup(args[1]);
        }
+       else if (!strcmp(args[0], "description")) {
+               int i, len=0;
+               char *d;
+
+               if (!*args[1]) {
+                       Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
+                               file, linenum, args[0]);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
+               }
+
+               for(i=1; *args[i]; i++)
+                       len += strlen(args[i])+1;
+
+               if (global.desc)
+                       free(global.desc);
+
+               global.desc = d = (char *)calloc(1, len);
+
+               d += sprintf(d, "%s", args[1]);
+               for(i=2; *args[i]; i++)
+                       d += sprintf(d, " %s", args[i]);
+       }
+       else if (!strcmp(args[0], "node")) {
+               int i;
+               char c;
+
+               for (i=0; args[1][i]; i++) {
+                       c = args[1][i];
+                       if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
+                               break;
+               }
+
+               if (!i || args[1][i]) {
+                       Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
+                               " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
+                               file, linenum, args[0]);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
+               }
+
+               if (global.node)
+                       free(global.node);
+
+               global.node = strdup(args[1]);
+       }
        else if (!strcmp(args[0], "pidfile")) {
                if (global.pidfile != NULL) {
                        Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
@@ -728,6 +774,7 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
                Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
                err_code |= ERR_ALERT | ERR_FATAL;
        }
+
  out:
        return err_code;
 }
@@ -1179,6 +1226,27 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                                goto out;
                        }
        }
+       else if (!strcmp(args[0], "description")) {
+               int i, len=0;
+               char *d;
+
+               if (!*args[1]) {
+                       Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
+                               file, linenum, args[0]);
+                       return -1;
+               }
+
+               for(i=1; *args[i]; i++)
+                       len += strlen(args[i])+1;
+
+               d = (char *)calloc(1, len);
+               curproxy->desc = d;
+
+               d += sprintf(d, "%s", args[1]);
+               for(i=2; *args[i]; i++)
+                       d += sprintf(d, " %s", args[i]);
+
+       }
        else if (!strcmp(args[0], "disabled")) {  /* disables this proxy */
                curproxy->state = PR_STSTOPPED;
        }
@@ -1744,7 +1812,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                        curproxy->uri_auth = NULL; /* we must detach from the default config */
 
                if (*(args[1]) == 0) {
-                       Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'node-name', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
+                       Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable', 'hide-version', 'show-node', 'show-desc'.\n", file, linenum, args[0]);
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                } else if (!strcmp(args[1], "uri")) {
@@ -1767,12 +1835,6 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                                err_code |= ERR_ALERT | ERR_ABORT;
                                goto out;
                        }
-               } else if (!strcmp(args[1], "node-name")) {
-                       if (!stats_set_node_name(&curproxy->uri_auth, *(args[2]) ? args[2] : hostname)) {
-                               Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
-                               err_code |= ERR_ALERT | ERR_ABORT;
-                               goto out;
-                       }
                } else if (!strcmp(args[1], "refresh")) {
                        unsigned interval;
 
@@ -1819,6 +1881,61 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                                err_code |= ERR_ALERT | ERR_ABORT;
                                goto out;
                        }
+               } else if (!strcmp(args[1], "show-node")) {
+
+                       if (*args[2]) {
+                               int i;
+                               char c;
+
+                               for (i=0; args[2][i]; i++) {
+                                       c = args[2][i];
+                                       if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-')
+                                               break;
+                               }
+
+                               if (!i || args[2][i]) {
+                                       Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
+                                               "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
+                                               file, linenum, args[0], args[1]);
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
+                               }
+                       }
+
+                       if (!stats_set_node(&curproxy->uri_auth, args[2])) {
+                               Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
+                               err_code |= ERR_ALERT | ERR_ABORT;
+                               goto out;
+                       }
+               } else if (!strcmp(args[1], "show-desc")) {
+                       char *desc = NULL;
+
+                       if (*args[2]) {
+                               int i, len=0;
+                               char *d;
+
+                               for(i=2; *args[i]; i++)
+                                       len += strlen(args[i])+1;
+
+                               desc = d = (char *)calloc(1, len);
+
+                               d += sprintf(d, "%s", args[2]);
+                               for(i=3; *args[i]; i++)
+                                       d += sprintf(d, " %s", args[i]);
+                       }
+
+                       if (!*args[2] && !global.desc)
+                               Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
+                                       file, linenum, args[1]);
+                       else {
+                               if (!stats_set_desc(&curproxy->uri_auth, desc)) {
+                                       free(desc);
+                                       Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
+                                       err_code |= ERR_ALERT | ERR_ABORT;
+                                       goto out;
+                               }
+                               free(desc);
+                       }
                } else {
                        Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
                              file, linenum, args[0]);
index 86ce23e86e6b4f2f86c31a7a3c09da535f60e1ef..7199fe07e5cc6b043afd1829d36cd412baf69afb 100644 (file)
@@ -574,6 +574,8 @@ int stats_dump_raw(struct session *s, struct buffer *rep, struct uri_auth *uri)
                                     "PipesFree: %d\n"
                                     "Tasks: %d\n"
                                     "Run_queue: %d\n"
+                                    "node: %s\n"
+                                    "description: %s\n"
                                     "",
                                     global.nbproc,
                                     relative_pid,
@@ -584,7 +586,8 @@ int stats_dump_raw(struct session *s, struct buffer *rep, struct uri_auth *uri)
                                     global.rlimit_nofile,
                                     global.maxsock, global.maxconn, global.maxpipes,
                                     actconn, pipes_used, pipes_free,
-                                    nb_tasks_cur, run_queue_cur
+                                    nb_tasks_cur, run_queue_cur,
+                                    global.node, global.desc?global.desc:""
                                     );
                        if (buffer_write_chunk(rep, &msg) >= 0)
                                return 0;
@@ -752,8 +755,7 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri)
                             " border-color: black;"
                             " border-bottom-style: solid;"
                             "}\n"
-                            ".pxname   {background: #b00040;color: #ffff40;font-weight: bold;}\n"
-                            ".titre    {background: #20D0D0;color: #000000;font-weight: bold;}\n"
+                            ".titre    {background: #20D0D0;color: #000000; font-weight: bold;}\n"
                             ".total    {background: #20D0D0;color: #ffff80;}\n"
                             ".frontend {background: #e8e8d0;}\n"
                             ".backend  {background: #e8e8d0;}\n"
@@ -775,14 +777,16 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri)
                             "table.tbl { border-collapse: collapse; border-style: none;}\n"
                             "table.tbl td { border-width: 1px 1px 1px 1px; border-style: solid solid solid solid; padding: 2px 3px; border-color: gray;}\n"
                             "table.tbl th { border-width: 1px; border-style: solid solid solid solid; border-color: gray;}\n"
+                            "table.tbl th.pxname {background: #b00040; color: #ffff40; font-weight: bold; border-style: solid solid none solid; padding: 2px 3px;}\n"
                             "table.tbl th.empty { border-style: none; empty-cells: hide; background: white;}\n"
+                            "table.tbl th.desc { background: white; border-style: solid solid none solid; text-align: left; padding: 2px 3px;}\n"
                             "table.lgd { border-collapse: collapse; border-width: 1px; border-style: none none none solid; border-color: black;}\n"
                             "table.lgd td { border-width: 1px; border-style: solid solid solid solid; border-color: gray; padding: 2px;}\n"
                             "table.lgd td.noborder { border-style: none; padding: 2px; white-space: nowrap;}\n"
                             "-->\n"
                             "</style></head>\n",
-                            uri->node_name ? " on " : "",
-                            uri->node_name ? uri->node_name : ""
+                            (uri->flags&ST_SHNODE) ? " on " : "",
+                            (uri->flags&ST_SHNODE) ? (uri->node ? uri->node : global.node) : ""
                             );
                } else {
                        print_csv_header(&msg);
@@ -804,16 +808,16 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri)
                        chunk_printf(&msg,
                             "<body><h1><a href=\"" PRODUCT_URL "\" style=\"text-decoration: none;\">"
                             PRODUCT_NAME "%s</a></h1>\n"
-                            "<h2>Statistics Report for pid %d%s%s</h2>\n"
+                            "<h2>Statistics Report for pid %d%s%s%s%s</h2>\n"
                             "<hr width=\"100%%\" class=\"hr\">\n"
                             "<h3>&gt; General process information</h3>\n"
                             "<table border=0 cols=4><tr><td align=\"left\" nowrap width=\"1%%\">\n"
                             "<p><b>pid = </b> %d (process #%d, nbproc = %d)<br>\n"
                             "<b>uptime = </b> %dd %dh%02dm%02ds<br>\n"
-                            "<b>system limits :</b> memmax = %s%s ; ulimit-n = %d<br>\n"
-                            "<b>maxsock = </b> %d ; <b>maxconn = </b> %d ; <b>maxpipes = </b> %d<br>\n"
-                            "current conns = %d ; current pipes = %d/%d<br>\n"
-                            "Running tasks : %d/%d<br>\n"
+                            "<b>system limits:</b> memmax = %s%s; ulimit-n = %d<br>\n"
+                            "<b>maxsock = </b> %d; <b>maxconn = </b> %d; <b>maxpipes = </b> %d<br>\n"
+                            "current conns = %d; current pipes = %d/%d<br>\n"
+                            "Running tasks: %d/%d<br>\n"
                             "</td><td align=\"center\" nowrap>\n"
                             "<table class=\"lgd\"><tr>\n"
                             "<td class=\"active3\">&nbsp;</td><td class=\"noborder\">active UP </td>"
@@ -834,9 +838,9 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri)
                             "<b>Display option:</b><ul style=\"margin-top: 0.25em;\">"
                             "",
                             (uri->flags&ST_HIDEVER)?"":(STATS_VERSION_STRING),
-                            pid, uri->node_name ? " on " : "", uri->node_name ? uri->node_name : "",
-                            pid,
-                            relative_pid, global.nbproc,
+                            pid, (uri->flags&ST_SHNODE) ? " on " : "", (uri->flags&ST_SHNODE) ? (uri->node ? uri->node : global.node) : "",
+                            (uri->flags&ST_SHDESC)? ": " : "", (uri->flags&ST_SHDESC) ? (uri->desc ? uri->desc : global.desc) : "",
+                            pid, relative_pid, global.nbproc,
                             up / 86400, (up % 86400) / 3600,
                             (up % 3600) / 60, (up % 60),
                             global.rlimit_memmax ? ultoa(global.rlimit_memmax) : "unlimited",
@@ -999,11 +1003,13 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) {
                        /* print a new table */
                        chunk_printf(&msg,
-                                    "<table cols=\"29\" class=\"tbl\" width=\"100%%\">\n"
+                                    "<table class=\"tbl\" width=\"100%%\">\n"
                                     "<tr align=\"center\" class=\"titre\">"
-                                    "<th colspan=2 class=\"pxname\">%s</th>"
-                                    "<th colspan=27 class=\"empty\"></th>"
+                                    "<th class=\"pxname\" width=\"10%%\">%s</th>"
+                                    "<th class=\"%s\" width=\"90%%\">%s</th>"
                                     "</tr>\n"
+                                    "</table>\n"
+                                    "<table cols=\"29\" class=\"tbl\" width=\"100%%\">\n"
                                     "<tr align=\"center\" class=\"titre\">"
                                     "<th rowspan=2></th>"
                                     "<th colspan=3>Queue</th>"
@@ -1022,7 +1028,8 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                                     "<th>Bck</th><th>Chk</th><th>Dwn</th><th>Dwntme</th>"
                                     "<th>Thrtle</th>\n"
                                     "</tr>",
-                                    px->id);
+                                    px->id,
+                                    px->desc ? "desc" : "empty", px->desc ? px->desc : "");
 
                        if (buffer_write_chunk(rep, &msg) >= 0)
                                return 0;
index d426e671763b63bb11f799bb2e803dd26969c0ec..b5e1dc973d6300601506a9b534e8f70ddc0cd68d 100644 (file)
@@ -677,6 +677,9 @@ void init(int argc, char **argv)
                printf("Using %s() as the polling mechanism.\n", cur_poller.name);
        }
 
+       if (!global.node)
+               global.node = strdup(hostname);
+
 }
 
 void deinit(void)
@@ -843,6 +846,8 @@ void deinit(void)
 
                free(uap->uri_prefix);
                free(uap->auth_realm);
+               free(uap->node);
+               free(uap->desc);
 
                while (uap->users) {
                        user = uap->users;
@@ -857,6 +862,8 @@ void deinit(void)
 
        free(global.chroot);  global.chroot = NULL;
        free(global.pidfile); global.pidfile = NULL;
+       free(global.node);    global.node = NULL;
+       free(global.desc);    global.desc = NULL;
        free(fdtab);          fdtab   = NULL;
        free(oldpids);        oldpids = NULL;
 
index ba029a6ba020e4a00c6420dea4ab9d77ff17af8f..3cfc445263c3f0a38be35f72eb4b7ec1bced81cf 100644 (file)
@@ -110,26 +110,71 @@ struct uri_auth *stats_set_realm(struct uri_auth **root, char *realm)
 }
 
 /*
- * Returns a default uri_auth with <node-name> set as the node name.
+ * Returns a default uri_auth with ST_SHNODE flag enabled and
+ * <node> set as the name if it is not empty.
  * Uses the pointer provided if not NULL and not initialized.
  */
-struct uri_auth *stats_set_node_name(struct uri_auth **root, char *name)
+struct uri_auth *stats_set_node(struct uri_auth **root, char *name)
 {
        struct uri_auth *u;
-       char *name_copy;
+       char *node_copy = NULL;
 
-       if ((name_copy = strdup(name)) == NULL)
-               goto out_realm;
+       if (name && *name) {
+               node_copy = strdup(name);
+               if (node_copy == NULL)
+                       goto out_realm;
+       }
        
        if ((u = stats_check_init_uri_auth(root)) == NULL)
                goto out_u;
+
+       if (!stats_set_flag(root, ST_SHNODE))
+               goto out_u;
+
+       if (node_copy) {        
+               free(u->node);
+               u->node = node_copy;
+       }
+
+       return u;
+
+ out_u:
+       free(node_copy);
+ out_realm:
+       return NULL;
+}
+
+/*
+ * Returns a default uri_auth with ST_SHDESC flag enabled and
+ * <description> set as the desc if it is not empty.
+ * Uses the pointer provided if not NULL and not initialized.
+ */
+struct uri_auth *stats_set_desc(struct uri_auth **root, char *desc)
+{
+       struct uri_auth *u;
+       char *desc_copy = NULL;
+
+       if (desc && *desc) {
+               desc_copy = strdup(desc);
+               if (desc_copy == NULL)
+                       goto out_realm;
+       }
        
-       free(u->node_name);
-       u->node_name = name_copy;
+       if ((u = stats_check_init_uri_auth(root)) == NULL)
+               goto out_u;
+
+       if (!stats_set_flag(root, ST_SHDESC))
+               goto out_u;
+
+       if (desc_copy) {
+               free(u->desc);
+               u->desc = desc_copy;
+       }
+
        return u;
 
  out_u:
-       free(name_copy);
+       free(desc_copy);
  out_realm:
        return NULL;
 }