Print this page
    
OS-1840 fmdump shall emit JSON
Reviewed by: Robert Mustacchi <rm@joyent.com>
    
      
        | Split | Close | 
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/fm/fmdump/common/fault.c
          +++ new/usr/src/cmd/fm/fmdump/common/fault.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  
    | ↓ open down ↓ | 12 lines elided | ↑ open up ↑ | 
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
       23 + * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  23   24   */
  24   25  
  25   26  #include <fmdump.h>
  26   27  #include <stdio.h>
  27   28  #include <strings.h>
  28   29  
  29   30  /*ARGSUSED*/
  30   31  static int
  31   32  flt_short(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
  32   33  {
  33   34          char buf[32], str[32];
  34   35          char *class = NULL, *uuid = "-", *code = "-";
  35   36  
  36   37          static const struct {
  37   38                  const char *class;
  38   39                  const char *tag;
  39   40          } tags[] = {
  40   41                  { FM_LIST_SUSPECT_CLASS,        "Diagnosed" },
  41   42                  { FM_LIST_REPAIRED_CLASS,       "Repaired" },
  42   43                  { FM_LIST_RESOLVED_CLASS,       "Resolved" },
  43   44                  { FM_LIST_UPDATED_CLASS,        "Updated" },
  44   45                  { FM_LIST_ISOLATED_CLASS,       "Isolated" },
  45   46          };
  46   47  
  47   48          (void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_UUID, &uuid);
  48   49          (void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_DIAG_CODE, &code);
  49   50  
  50   51          (void) nvlist_lookup_string(rp->rec_nvl, FM_CLASS, &class);
  51   52          if (class != NULL) {
  52   53                  int i;
  53   54  
  54   55                  for (i = 0; i < sizeof (tags) / sizeof (tags[0]); i++) {
  55   56                          if (strcmp(class, tags[i].class) == 0) {
  56   57                                  (void) snprintf(str, sizeof (str), "%s %s",
  57   58                                      code, tags[i].tag);
  58   59                                  code = str;
  59   60                                  break;
  60   61                          }
  61   62                  }
  62   63          }
  63   64  
  64   65          fmdump_printf(fp, "%-20s %-32s %s\n",
  65   66              fmdump_date(buf, sizeof (buf), rp), uuid, code);
  66   67  
  67   68          return (0);
  68   69  }
  69   70  
  70   71  static int
  71   72  flt_verb1(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
  72   73  {
  73   74          uint_t i, size = 0;
  74   75          nvlist_t **nva;
  75   76          uint8_t *ba;
  76   77  
  77   78          (void) flt_short(lp, rp, fp);
  78   79          (void) nvlist_lookup_uint32(rp->rec_nvl, FM_SUSPECT_FAULT_SZ, &size);
  79   80  
  80   81          if (size != 0) {
  81   82                  (void) nvlist_lookup_nvlist_array(rp->rec_nvl,
  82   83                      FM_SUSPECT_FAULT_LIST, &nva, &size);
  83   84                  (void) nvlist_lookup_uint8_array(rp->rec_nvl,
  84   85                      FM_SUSPECT_FAULT_STATUS, &ba, &size);
  85   86          }
  86   87  
  87   88          for (i = 0; i < size; i++) {
  88   89                  char *class = NULL, *rname = NULL, *aname = NULL, *fname = NULL;
  89   90                  char *loc = NULL;
  90   91                  nvlist_t *fru, *asru, *rsrc;
  91   92                  uint8_t pct = 0;
  92   93  
  93   94                  (void) nvlist_lookup_uint8(nva[i], FM_FAULT_CERTAINTY, &pct);
  94   95                  (void) nvlist_lookup_string(nva[i], FM_CLASS, &class);
  95   96  
  96   97                  if (nvlist_lookup_nvlist(nva[i], FM_FAULT_FRU, &fru) == 0)
  97   98                          fname = fmdump_nvl2str(fru);
  98   99  
  99  100                  if (nvlist_lookup_nvlist(nva[i], FM_FAULT_ASRU, &asru) == 0)
 100  101                          aname = fmdump_nvl2str(asru);
 101  102  
 102  103                  if (nvlist_lookup_nvlist(nva[i], FM_FAULT_RESOURCE, &rsrc) == 0)
 103  104                          rname = fmdump_nvl2str(rsrc);
 104  105  
 105  106                  if (nvlist_lookup_string(nva[i], FM_FAULT_LOCATION, &loc)
 106  107                      == 0) {
 107  108                          if (fname && strncmp(fname, FM_FMRI_LEGACY_HC_PREFIX,
 108  109                              sizeof (FM_FMRI_LEGACY_HC_PREFIX)) == 0)
 109  110                                  loc = fname + sizeof (FM_FMRI_LEGACY_HC_PREFIX);
 110  111                  }
 111  112  
 112  113  
 113  114                  fmdump_printf(fp, "  %3u%%  %s",
 114  115                      pct, class ? class : "-");
 115  116  
 116  117                  if (ba[i] & FM_SUSPECT_FAULTY)
 117  118                          fmdump_printf(fp, "\n\n");
 118  119                  else if (ba[i] & FM_SUSPECT_NOT_PRESENT)
 119  120                          fmdump_printf(fp, "\tRemoved\n\n");
 120  121                  else if (ba[i] & FM_SUSPECT_REPLACED)
 121  122                          fmdump_printf(fp, "\tReplaced\n\n");
 122  123                  else if (ba[i] & FM_SUSPECT_REPAIRED)
 123  124                          fmdump_printf(fp, "\tRepair Attempted\n\n");
 124  125                  else if (ba[i] & FM_SUSPECT_ACQUITTED)
 125  126                          fmdump_printf(fp, "\tAcquitted\n\n");
 126  127                  else
 127  128                          fmdump_printf(fp, "\n\n");
 128  129  
 129  130                  fmdump_printf(fp, "        Problem in: %s\n",
 130  131                      rname ? rname : "-");
 131  132  
 132  133                  fmdump_printf(fp, "           Affects: %s\n",
 133  134                      aname ? aname : "-");
 134  135  
 135  136                  fmdump_printf(fp, "               FRU: %s\n",
 136  137                      fname ? fname : "-");
 137  138  
 138  139                  fmdump_printf(fp, "          Location: %s\n\n",
 139  140                      loc ? loc : "-");
 140  141  
 141  142                  free(fname);
 142  143                  free(aname);
 143  144                  free(rname);
 144  145          }
 145  146  
 146  147          return (0);
 147  148  }
 148  149  
 149  150  static int
 150  151  flt_verb23_cmn(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp,
 151  152      nvlist_prtctl_t pctl)
 152  153  {
 153  154          const struct fmdump_fmt *efp = &fmdump_err_ops.do_formats[FMDUMP_VERB1];
 154  155          const struct fmdump_fmt *ffp = &fmdump_flt_ops.do_formats[FMDUMP_VERB2];
 155  156          uint_t i;
 156  157          char buf[32], str[32];
 157  158          char *class = NULL, *uuid = "-", *code = "-";
 158  159  
 159  160          (void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_UUID, &uuid);
 160  161          (void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_DIAG_CODE, &code);
 161  162  
 162  163          (void) nvlist_lookup_string(rp->rec_nvl, FM_CLASS, &class);
 163  164          if (class != NULL && strcmp(class, FM_LIST_REPAIRED_CLASS) == 0) {
 164  165                  (void) snprintf(str, sizeof (str), "%s %s", code, "Repaired");
 165  166                  code = str;
 166  167          }
 167  168          if (class != NULL && strcmp(class, FM_LIST_RESOLVED_CLASS) == 0) {
 168  169                  (void) snprintf(str, sizeof (str), "%s %s", code, "Resolved");
 169  170                  code = str;
 170  171          }
 171  172          if (class != NULL && strcmp(class, FM_LIST_UPDATED_CLASS) == 0) {
 172  173                  (void) snprintf(str, sizeof (str), "%s %s", code, "Updated");
 173  174                  code = str;
 174  175          }
 175  176  
 176  177          fmdump_printf(fp, "%s\n", ffp->do_hdr);
 177  178          fmdump_printf(fp, "%-20s.%9.9llu %-32s %s\n",
 178  179              fmdump_year(buf, sizeof (buf), rp), rp->rec_nsec, uuid, code);
 179  180  
 180  181          if (rp->rec_nrefs != 0)
 181  182                  fmdump_printf(fp, "\n  %s\n", efp->do_hdr);
 182  183  
 183  184          for (i = 0; i < rp->rec_nrefs; i++) {
 184  185                  fmdump_printf(fp, "  ");
 185  186                  efp->do_func(lp, &rp->rec_xrefs[i], fp);
 186  187          }
 187  188  
 188  189          fmdump_printf(fp, "\n");
 189  190          if (pctl)
 190  191                  nvlist_prt(rp->rec_nvl, pctl);
 191  192          else
 192  193                  nvlist_print(fp, rp->rec_nvl);
 193  194          fmdump_printf(fp, "\n");
 194  195  
 195  196          return (0);
 196  197  }
 197  198  
 198  199  static int
 199  200  flt_verb2(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
 200  201  {
 201  202          return (flt_verb23_cmn(lp, rp, fp, NULL));
 202  203  }
 203  204  
 204  205  
 205  206  static int
 206  207  flt_pretty(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
 207  208  {
 208  209          nvlist_prtctl_t pctl;
 209  210          int rc;
 210  211  
 211  212          if ((pctl = nvlist_prtctl_alloc()) != NULL) {
 212  213                  nvlist_prtctl_setdest(pctl, fp);
 213  214                  nvlist_prtctlop_nvlist(pctl, fmdump_render_nvlist, NULL);
 214  215          }
 215  216  
 216  217          rc = flt_verb23_cmn(lp, rp, fp, pctl);
 217  218  
 218  219          nvlist_prtctl_free(pctl);
 219  220          return (rc);
 220  221  }
 221  222  
 222  223  /*
 223  224   * There is a lack of uniformity in how the various entries in our diagnosis
 224  225   * are terminated.  Some end with one newline, others with two.  This makes the
 225  226   * output of fmdump -m look a bit ugly.  Therefore we postprocess the message
 226  227   * before printing it, removing consecutive occurences of newlines.
 227  228   */
 228  229  static void
 229  230  postprocess_msg(char *msg)
 230  231  {
 231  232          int i = 0, j = 0;
 232  233          char *buf;
 233  234  
 234  235          if ((buf = malloc(strlen(msg) + 1)) == NULL)
 235  236                  return;
 236  237  
 237  238          buf[j++] = msg[i++];
 238  239          for (i = 1; i < strlen(msg); i++) {
 239  240                  if (!(msg[i] == '\n' && msg[i - 1] == '\n'))
 240  241                          buf[j++] = msg[i];
 241  242          }
 242  243          buf[j] = '\0';
 243  244          (void) strncpy(msg, buf, j+1);
 244  245          free(buf);
 245  246  }
 246  247  
 247  248  /*ARGSUSED*/
 248  249  static int
 249  250  flt_msg(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
 250  251  {
 251  252          char *msg;
 252  253  
 253  254          if ((msg = fmd_msg_gettext_nv(g_msg, NULL, rp->rec_nvl)) == NULL) {
 254  255                  (void) fprintf(stderr, "%s: failed to format message: %s\n",
 255  256                      g_pname, strerror(errno));
 256  257                  g_errs++;
 257  258                  return (-1);
 258  259          } else {
 259  260                  postprocess_msg(msg);
 260  261                  fmdump_printf(fp, "%s\n", msg);
 261  262                  free(msg);
 262  263          }
 263  264  
 264  265          return (0);
 265  266  }
 266  267  
 267  268  const fmdump_ops_t fmdump_flt_ops = {
 268  269  "fault", {
 269  270  {
 270  271  "TIME                 UUID                                 SUNW-MSG-ID "
 271  272                                                                  "EVENT",
 272  273  (fmd_log_rec_f *)flt_short
 273  274  }, {
 274  275  "TIME                 UUID                                 SUNW-MSG-ID "
 275  276                                                                  "EVENT",
 276  277  (fmd_log_rec_f *)flt_verb1
 277  278  }, {
  
    | ↓ open down ↓ | 245 lines elided | ↑ open up ↑ | 
 278  279  "TIME                           UUID"
 279  280  "                                 SUNW-MSG-ID",
 280  281  (fmd_log_rec_f *)flt_verb2
 281  282  }, {
 282  283  "TIME                           UUID"
 283  284  "                                 SUNW-MSG-ID",
 284  285  (fmd_log_rec_f *)flt_pretty
 285  286  }, {
 286  287  NULL,
 287  288  (fmd_log_rec_f *)flt_msg
      289 +}, {
      290 +NULL,
      291 +(fmd_log_rec_f *)fmdump_print_json
 288  292  } }
 289  293  };
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX