Mercurial > illumos > illumos-gate
view usr/src/cmd/fm/modules/common/eversholt/eft.c @ 12979:ab9ae749152f
PSARC/2009/617 Software Events Notification Parameters CLI
PSARC/2009/618 snmp-notify: SNMP Notification Daemon for Software Events
PSARC/2009/619 smtp-notify: Email Notification Daemon for Software Events
PSARC/2010/225 fmd for non-global Solaris zones
PSARC/2010/226 Solaris Instance UUID
PSARC/2010/227 nvlist_nvflag(3NVPAIR)
PSARC/2010/228 libfmevent additions
PSARC/2010/257 sysevent_evc_setpropnvl and sysevent_evc_getpropnvl
PSARC/2010/265 FMRI and FMA Event Stabilty, 'ireport' category 1 event class, and the 'sw' FMRI scheme
PSARC/2010/278 FMA/SMF integration: instance state transitions
PSARC/2010/279 Modelling panics within FMA
PSARC/2010/290 logadm.conf upgrade
6392476 fmdump needs to pretty-print
6393375 userland ereport/ireport event generation interfaces
6445732 Add email notification agent for FMA and software events
6804168 RFE: Allow an efficient means to monitor SMF services status changes
6866661 scf_values_destroy(3SCF) will segfault if is passed NULL
6884709 Add snmp notification agent for FMA and software events
6884712 Add private interface to tap into libfmd_msg macro expansion capabilities
6897919 fmd to run in a non-global zone
6897937 fmd use of non-private doors is not safe
6900081 add a UUID to Solaris kernel image for use in crashdump identification
6914884 model panic events as a defect diagnosis in FMA
6944862 fmd_case_open_uuid, fmd_case_uuisresolved, fmd_nvl_create_defect
6944866 log legacy sysevents in fmd
6944867 enumerate svc scheme in topo
6944868 software-diagnosis and software-response fmd modules
6944870 model SMF maintenance state as a defect diagnosis in FMA
6944876 savecore runs in foreground for systems with zfs root and dedicated dump
6965796 Implement notification parameters for SMF state transitions and FMA events
6968287 SUN-FM-MIB.mib needs to be updated to reflect Oracle information
6972331 logadm.conf upgrade PSARC/2010/290
author | Gavin Maltby <gavin.maltby@oracle.com> |
---|---|
date | Fri, 30 Jul 2010 17:04:17 +1000 |
parents | bb6372f778bb |
children |
line wrap: on
line source
/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <unistd.h> #include <stdio.h> #include <string.h> #include <fm/fmd_api.h> #include <libnvpair.h> #include <fm/libtopo.h> #include "out.h" #include "stats.h" #include "alloc.h" #include "stable.h" #include "literals.h" #include "lut.h" #include "esclex.h" #include "tree.h" #include "ipath.h" #include "itree.h" #include "iexpr.h" #include "ptree.h" #include "check.h" #include "version.h" #include "fme.h" #include "eval.h" #include "config.h" #include "platform.h" /* * eversholt diagnosis engine (eft.so) main entry points */ fmd_hdl_t *Hdl; /* handle in global for platform.c */ int Debug = 1; /* turn on here and let fmd_hdl_debug() decide if really on */ hrtime_t Hesitate; /* hesitation time in ns */ char *Serd_Override; /* override for Serd engines */ int Verbose; int Estats; int Warn; /* zero -- eft.so should not issue language warnings */ char **Efts; int Max_fme; /* Maximum number of open FMEs */ /* stuff exported by yacc-generated parsers */ extern void yyparse(void); extern int yydebug; extern struct lut *Dicts; extern void literals_init(void); extern void literals_fini(void); struct eftsubr { const char *prefix; void (*hdlr)(fmd_hdl_t *, fmd_event_t *, nvlist_t *, const char *); } eftsubrs[] = { { "ereport.", fme_receive_external_report }, { "list.repaired", fme_receive_repair_list }, { NULL, NULL } }; /*ARGSUSED*/ static void eft_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class) { struct eftsubr *sp = eftsubrs; while (sp->prefix != NULL) { if (strncmp(class, sp->prefix, strlen(sp->prefix)) == 0) break; sp++; } if (sp->prefix != NULL) { (sp->hdlr)(hdl, ep, nvl, class); } else { out(O_DIE, "eft_recv: event class \"%s\" does not match our " "subscriptions", class); } } /*ARGSUSED*/ static void eft_timeout(fmd_hdl_t *hdl, id_t tid, void *arg) { out(O_ALTFP|O_STAMP, "\neft.so timer %ld fired with arg %p", tid, arg); if (arg == NULL) return; fme_timer_fired(arg, tid); } static void eft_close(fmd_hdl_t *hdl, fmd_case_t *fmcase) { out(O_ALTFP, "eft_close called for case %s", fmd_case_uuid(hdl, fmcase)); fme_close_case(hdl, fmcase); } /* * The "serd_override" property allows the N and T parameters of specified serd * engines to be overridden. The property is a string consisting of one or more * space separated triplets. Each triplet is of the form "name,N,T" where "name" * is the name of the serd engine and N and T are the new paremeters to use. * For example "serd.io.device.nonfatal,5,3h" would set the parameters for the * serd.io.device.nonfatal engine to 5 in 3 hours. */ static const fmd_prop_t eft_props[] = { { "estats", FMD_TYPE_BOOL, "false" }, { "hesitate", FMD_TYPE_INT64, "10000000000" }, { "serd_override", FMD_TYPE_STRING, NULL }, { "verbose", FMD_TYPE_INT32, "0" }, { "warn", FMD_TYPE_BOOL, "false" }, { "status", FMD_TYPE_STRING, NULL }, { "maxfme", FMD_TYPE_INT32, "0" }, { NULL, 0, NULL } }; /*ARGSUSED*/ static void eft_topo_change(fmd_hdl_t *hdl, topo_hdl_t *thp) { fme_receive_topology_change(); } static const fmd_hdl_ops_t eft_ops = { eft_recv, /* fmdo_recv */ eft_timeout, /* fmdo_timeout */ eft_close, /* fmdo_close */ NULL, /* fmdo_stats */ NULL, /* fmdo_gc */ NULL, /* fmdo_send */ eft_topo_change /* fmdo_topo_change */ }; #define xstr(s) str(s) #define str(s) #s static const fmd_hdl_info_t fmd_info = { "eft diagnosis engine", xstr(VERSION_MAJOR) "." xstr(VERSION_MINOR), &eft_ops, eft_props }; /* * ename_strdup -- like strdup but ename comes in and class string goes out */ static char * ename_strdup(struct node *np) { struct node *mynp; int len; char *buf; /* calculate length of buffer required */ len = 0; for (mynp = np; mynp; mynp = mynp->u.name.next) len += strlen(mynp->u.name.s) + 1; /* +1 for dot or NULL */ buf = MALLOC(len); buf[0] = '\0'; /* now build the string */ while (np) { (void) strcat(buf, np->u.name.s); np = np->u.name.next; if (np) (void) strcat(buf, "."); } return (buf); } /*ARGSUSED*/ static void dosubscribe(struct node *lhs, struct node *rhs, void *arg) { char *ename = ename_strdup(lhs); fmd_hdl_subscribe(Hdl, ename); FREE(ename); } /*ARGSUSED*/ static void dodiscardprint(struct node *lhs, struct node *rhs, void *arg) { char *ename = (char *)lhs; out(O_VERB, "allow silent discard_if_config_unknown: \"%s\"", ename); } extern struct stats *Filecount; /* * Call all of the _fini() routines to clean up the exiting DE */ void call_finis(void) { platform_free_eft_files(Efts); Efts = NULL; platform_fini(); fme_fini(); itree_fini(); ipath_fini(); iexpr_fini(); istat_fini(); serd_fini(); lex_free(); check_fini(); tree_fini(); lut_fini(); literals_fini(); stable_fini(); stats_fini(); out_fini(); alloc_fini(); } /*ARGSUSED*/ static void doopendict(const char *lhs, void *rhs, void *arg) { out(O_VERB, "opendict: \"%s\"", lhs); fmd_hdl_opendict(Hdl, lhs); } void _fmd_init(fmd_hdl_t *hdl) { fmd_case_t *casep = NULL; int count; char *fname; (void) fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info); /* keep handle for routines like out() which need it */ Hdl = hdl; /* set up out(O_ALTFP) first things so it is available for debug */ alloc_init(); out_init("eft"); if ((fname = fmd_prop_get_string(hdl, "status")) != NULL) { FILE *fp; if ((fp = fopen(fname, "a")) == NULL) { fmd_prop_free_string(hdl, fname); out(O_DIE|O_SYS, "status property file: %s", fname); } (void) setlinebuf(fp); out_altfp(fp); out(O_DEBUG, "appending status changes to \"%s\"", fname); fmd_prop_free_string(hdl, fname); out(O_ALTFP|O_STAMP, "\neft.so startup"); } Estats = fmd_prop_get_int32(hdl, "estats"); stats_init(Estats); stable_init(0); literals_init(); platform_init(); lut_init(); tree_init(); ipath_init(); iexpr_init(); Efts = platform_get_eft_files(); lex_init(Efts, NULL, 0); check_init(); /* * If we read no .eft files, we can't do any * diagnosing, so we just unload ourselves */ if (stats_counter_value(Filecount) == 0) { (void) lex_fini(); call_finis(); fmd_hdl_debug(hdl, "no fault trees provided."); fmd_hdl_unregister(hdl); return; } yyparse(); (void) lex_fini(); tree_report(); if (count = out_errcount()) out(O_DIE, "%d language error%s encountered, exiting.", OUTS(count)); /* subscribe to events we expect to consume */ lut_walk(Ereportenames, (lut_cb)dosubscribe, NULL); lut_walk(Ereportenames_discard, (lut_cb)dodiscardprint, NULL); /* subscribe to repair events so we can clear state on repair */ fmd_hdl_subscribe(hdl, "list.repaired"); /* open dictionaries referenced by all .eft files */ lut_walk(Dicts, (lut_cb)doopendict, (void *)0); Verbose = fmd_prop_get_int32(hdl, "verbose"); Warn = fmd_prop_get_int32(hdl, "warn"); Hesitate = fmd_prop_get_int64(hdl, "hesitate"); Serd_Override = fmd_prop_get_string(hdl, "serd_override"); Max_fme = fmd_prop_get_int32(hdl, "maxfme"); out(O_DEBUG, "initialized, verbose %d warn %d maxfme %d", Verbose, Warn, Max_fme); fme_istat_load(hdl); fme_serd_load(hdl); out(O_VERB, "reconstituting any existing fmes"); while ((casep = fmd_case_next(hdl, casep)) != NULL) { fme_restart(hdl, casep); } } /*ARGSUSED*/ void _fmd_fini(fmd_hdl_t *hdl) { call_finis(); }