"Fossies" - the Fresh Open Source Software Archive

Member "cfengine-3.15.4/cf-monitord/cf-monitord.c" (7 Jun 2021, 10566 Bytes) of package /linux/misc/cfengine-3.15.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2   Copyright 2019 Northern.tech AS
    3 
    4   This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
    5 
    6   This program is free software; you can redistribute it and/or modify it
    7   under the terms of the GNU General Public License as published by the
    8   Free Software Foundation; version 3.
    9 
   10   This program is distributed in the hope that it will be useful,
   11   but WITHOUT ANY WARRANTY; without even the implied warranty of
   12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13   GNU General Public License for more details.
   14 
   15   You should have received a copy of the GNU General Public License
   16   along with this program; if not, write to the Free Software
   17   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
   18 
   19   To the extent this program is licensed as part of the Enterprise
   20   versions of CFEngine, the applicable Commercial Open Source License
   21   (COSL) may apply to this file if you as a licensee so wish it. See
   22   included file COSL.txt.
   23 */
   24 
   25 #include <generic_agent.h>
   26 #include <mon.h>
   27 
   28 #include <eval_context.h>
   29 #include <env_monitor.h>
   30 #include <conversion.h>
   31 #include <vars.h>
   32 #include <signals.h>
   33 #include <scope.h>
   34 #include <known_dirs.h>
   35 #include <man.h>
   36 #include <bootstrap.h>
   37 #include <timeout.h>
   38 #include <time_classes.h>
   39 #include <loading.h>
   40 #include <cleanup.h>
   41 #include <file_lib.h>           /* FILE_SEPARATOR */
   42 
   43 typedef enum
   44 {
   45     MONITOR_CONTROL_FORGET_RATE,
   46     MONITOR_CONTROL_MONITOR_FACILITY,
   47     MONITOR_CONTROL_HISTOGRAMS,
   48     MONITOR_CONTROL_TCP_DUMP,
   49     MONITOR_CONTROL_NONE
   50 } MonitorControl;
   51 
   52 static void ThisAgentInit(EvalContext *ctx);
   53 static GenericAgentConfig *CheckOpts(int argc, char **argv);
   54 static void KeepPromises(EvalContext *ctx, const Policy *policy);
   55 
   56 /*****************************************************************************/
   57 /* Globals                                                                   */
   58 /*****************************************************************************/
   59 
   60 extern int NO_FORK;
   61 
   62 extern const ConstraintSyntax CFM_CONTROLBODY[];
   63 
   64 /*******************************************************************/
   65 /* Command line options                                            */
   66 /*******************************************************************/
   67 
   68 static const char *const CF_MONITORD_SHORT_DESCRIPTION =
   69     "monitoring daemon for CFEngine";
   70 
   71 static const char *const CF_MONITORD_MANPAGE_LONG_DESCRIPTION =
   72     "cf-monitord is the monitoring daemon for CFEngine. It samples probes defined in policy code and attempts to learn the "
   73     "normal system state based on current and past observations. Current estimates are made available as "
   74     "special variables (e.g. $(mon.av_cpu)) to cf-agent, which may use them to inform policy decisions.";
   75 
   76 static const struct option OPTIONS[] =
   77 {
   78     {"help", no_argument, 0, 'h'},
   79     {"debug", no_argument, 0, 'd'},
   80     {"verbose", no_argument, 0, 'v'},
   81     {"dry-run", no_argument, 0, 'n'},
   82     {"version", no_argument, 0, 'V'},
   83     {"no-lock", no_argument, 0, 'K'},
   84     {"file", required_argument, 0, 'f'},
   85     {"log-level", required_argument, 0, 'g'},
   86     {"inform", no_argument, 0, 'I'},
   87     {"diagnostic", no_argument, 0, 'x'},
   88     {"no-fork", no_argument, 0, 'F'},
   89     {"histograms", no_argument, 0, 'H'},
   90     {"tcpdump", no_argument, 0, 'T'},
   91     {"color", optional_argument, 0, 'C'},
   92     {"timestamp", no_argument, 0, 'l'},
   93     {NULL, 0, 0, '\0'}
   94 };
   95 
   96 static const char *const HINTS[] =
   97 {
   98     "Print the help message",
   99     "Enable debugging output",
  100     "Output verbose information about the behaviour of cf-monitord",
  101     "All talk and no action mode - make no changes, only inform of promises not kept",
  102     "Output the version of the software",
  103     "Ignore system lock",
  104     "Specify an alternative input file than the default. This option is overridden by FILE if supplied as argument.",
  105     "Specify how detailed logs should be. Possible values: 'error', 'warning', 'notice', 'info', 'verbose', 'debug'",
  106     "Print basic information about changes made to the system, i.e. promises repaired",
  107     "Activate internal diagnostics (developers only)",
  108     "Run process in foreground, not as a daemon",
  109     "Ignored for backward compatibility",
  110     "Interface with tcpdump if available to collect data about network",
  111     "Enable colorized output. Possible values: 'always', 'auto', 'never'. If option is used, the default value is 'auto'",
  112     "Log timestamps on each line of log output",
  113     NULL
  114 };
  115 
  116 /*****************************************************************************/
  117 
  118 int main(int argc, char *argv[])
  119 {
  120     GenericAgentConfig *config = CheckOpts(argc, argv);
  121     EvalContext *ctx = EvalContextNew();
  122     GenericAgentConfigApply(ctx, config);
  123 
  124     const char *program_invocation_name = argv[0];
  125     const char *last_dir_sep = strrchr(program_invocation_name, FILE_SEPARATOR);
  126     const char *program_name = (last_dir_sep != NULL ? last_dir_sep + 1 : program_invocation_name);
  127     GenericAgentDiscoverContext(ctx, config, program_name);
  128 
  129     Policy *policy = LoadPolicy(ctx, config);
  130 
  131     GenericAgentPostLoadInit(ctx);
  132     ThisAgentInit(ctx);
  133 
  134     KeepPromises(ctx, policy);
  135 
  136     MonitorStartServer(ctx, policy);
  137 
  138     PolicyDestroy(policy);
  139     GenericAgentFinalize(ctx, config);
  140     CallCleanupFunctions();
  141     return 0;
  142 }
  143 
  144 /*******************************************************************/
  145 
  146 static GenericAgentConfig *CheckOpts(int argc, char **argv)
  147 {
  148     extern char *optarg;
  149     int c;
  150     GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_MONITOR, GetTTYInteractive());
  151 
  152     while ((c = getopt_long(argc, argv, "dvnIf:g:VSxHTKMFhC::l",
  153                             OPTIONS, NULL)) != -1)
  154     {
  155         switch (c)
  156         {
  157         case 'f':
  158             GenericAgentConfigSetInputFile(config, GetInputDir(), optarg);
  159             MINUSF = true;
  160             break;
  161 
  162         case 'd':
  163             LogSetGlobalLevel(LOG_LEVEL_DEBUG);
  164             NO_FORK = true;
  165             break;
  166 
  167         case 'K':
  168             config->ignore_locks = true;
  169             break;
  170 
  171         case 'I':
  172             LogSetGlobalLevel(LOG_LEVEL_INFO);
  173             break;
  174 
  175         case 'v':
  176             LogSetGlobalLevel(LOG_LEVEL_VERBOSE);
  177             NO_FORK = true;
  178             break;
  179 
  180         case 'g':
  181             LogSetGlobalLevelArgOrExit(optarg);
  182             break;
  183 
  184         case 'F':
  185             NO_FORK = true;
  186             break;
  187 
  188         case 'H':              /* Keep accepting this option for compatibility -- no longer used */
  189             break;
  190 
  191         case 'T':
  192             MonNetworkSnifferEnable(true);
  193             break;
  194 
  195         case 'V':
  196         {
  197             Writer *w = FileWriter(stdout);
  198             GenericAgentWriteVersion(w);
  199             FileWriterDetach(w);
  200         }
  201         DoCleanupAndExit(EXIT_SUCCESS);
  202 
  203         case 'h':
  204         {
  205             Writer *w = FileWriter(stdout);
  206             WriterWriteHelp(w, "cf-monitord", OPTIONS, HINTS, NULL, false, true);
  207             FileWriterDetach(w);
  208         }
  209         DoCleanupAndExit(EXIT_SUCCESS);
  210 
  211         case 'M':
  212         {
  213             Writer *out = FileWriter(stdout);
  214             ManPageWrite(out, "cf-monitord", time(NULL),
  215                          CF_MONITORD_SHORT_DESCRIPTION,
  216                          CF_MONITORD_MANPAGE_LONG_DESCRIPTION,
  217                          OPTIONS, HINTS,
  218                          NULL, false,
  219                          true);
  220             FileWriterDetach(out);
  221             DoCleanupAndExit(EXIT_SUCCESS);
  222         }
  223 
  224         case 'x':
  225             Log(LOG_LEVEL_ERR, "Self-diagnostic functionality is retired.");
  226             DoCleanupAndExit(EXIT_SUCCESS);
  227 
  228         case 'C':
  229             if (!GenericAgentConfigParseColor(config, optarg))
  230             {
  231                 DoCleanupAndExit(EXIT_FAILURE);
  232             }
  233             break;
  234 
  235         case 'l':
  236             LoggingEnableTimestamps(true);
  237             break;
  238 
  239         default:
  240         {
  241             Writer *w = FileWriter(stdout);
  242             WriterWriteHelp(w, "cf-monitord", OPTIONS, HINTS, NULL, false, true);
  243             FileWriterDetach(w);
  244         }
  245         DoCleanupAndExit(EXIT_FAILURE);
  246         }
  247     }
  248 
  249     if (!GenericAgentConfigParseArguments(config, argc - optind, argv + optind))
  250     {
  251         Log(LOG_LEVEL_ERR, "Too many arguments");
  252         DoCleanupAndExit(EXIT_FAILURE);
  253     }
  254 
  255     return config;
  256 }
  257 
  258 /*****************************************************************************/
  259 
  260 static void KeepPromises(EvalContext *ctx, const Policy *policy)
  261 {
  262     Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_MONITOR);
  263     if (constraints)
  264     {
  265         for (size_t i = 0; i < SeqLength(constraints); i++)
  266         {
  267             Constraint *cp = SeqAt(constraints, i);
  268 
  269             if (!IsDefinedClass(ctx, cp->classes))
  270             {
  271                 continue;
  272             }
  273 
  274             VarRef *ref = VarRefParseFromScope(cp->lval, "control_monitor");
  275             const void *value = EvalContextVariableGet(ctx, ref, NULL);
  276             VarRefDestroy(ref);
  277             if (!value)
  278             {
  279                 Log(LOG_LEVEL_ERR, "Unknown lval '%s' in monitor control body", cp->lval);
  280                 continue;
  281             }
  282 
  283             if (strcmp(cp->lval, CFM_CONTROLBODY[MONITOR_CONTROL_HISTOGRAMS].lval) == 0)
  284             {
  285                 /* Keep accepting this option for backward compatibility. */
  286             }
  287 
  288             if (strcmp(cp->lval, CFM_CONTROLBODY[MONITOR_CONTROL_TCP_DUMP].lval) == 0)
  289             {
  290                 MonNetworkSnifferEnable(BooleanFromString(value));
  291             }
  292 
  293             if (strcmp(cp->lval, CFM_CONTROLBODY[MONITOR_CONTROL_FORGET_RATE].lval) == 0)
  294             {
  295                 sscanf(value, "%lf", &FORGETRATE);
  296                 Log(LOG_LEVEL_DEBUG, "forget rate %f", FORGETRATE);
  297             }
  298         }
  299     }
  300 }
  301 
  302 /*****************************************************************************/
  303 /* Level 1                                                                   */
  304 /*****************************************************************************/
  305 
  306 static void ThisAgentInit(EvalContext *ctx)
  307 {
  308     umask(077);
  309     strcpy(VPREFIX, "cf-monitord");
  310 
  311     time_t t = SetReferenceTime();
  312     UpdateTimeClasses(ctx, t);
  313 
  314     signal(SIGINT, HandleSignalsForDaemon);
  315     signal(SIGTERM, HandleSignalsForDaemon);
  316     signal(SIGBUS, HandleSignalsForDaemon);
  317     signal(SIGHUP, SIG_IGN);
  318     signal(SIGPIPE, SIG_IGN);
  319     signal(SIGUSR1, HandleSignalsForDaemon);
  320     signal(SIGUSR2, HandleSignalsForDaemon);
  321 
  322     FORGETRATE = 0.6;
  323 
  324     MonitorInitialize();
  325 }