Esempio n. 1
0
PromiseResult VerifyMeasurementPromise(EvalContext *ctx, double *measurement, const Promise *pp)
{
    if (EvalContextPromiseIsDone(ctx, pp))
    {
        if (pp->comment)
        {
            Log(LOG_LEVEL_VERBOSE, "Skipping static observation '%s' (comment: %s), already done", pp->promiser, pp->comment);
        }
        else
        {
            Log(LOG_LEVEL_VERBOSE, "Skipping static observation '%s', already done", pp->promiser);
        }

        return PROMISE_RESULT_NOOP;
    }

    PromiseBanner(pp);

    Attributes a = GetMeasurementAttributes(ctx, pp);

    if (!CheckMeasureSanity(a.measure, pp))
    {
        cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Measurement promise is not valid");
        return PROMISE_RESULT_INTERRUPTED;
    }

    return VerifyMeasurement(ctx, measurement, a, pp);
}
Esempio n. 2
0
void VerifyDatabasePromises(EvalContext *ctx, Promise *pp)
{
    Attributes a = { {0} };

    if (EvalContextPromiseIsDone(ctx, pp))
    {
        return;
    }

    PromiseBanner(pp);

    a = GetDatabaseAttributes(ctx, pp);

    if (!CheckDatabaseSanity(a, pp))
    {
        return;
    }

    if (strcmp(a.database.type, "sql") == 0)
    {
        VerifySQLPromise(ctx, a, pp);
        return;
    }

    if (strcmp(a.database.type, "ms_registry") == 0)
    {
#if defined(__MINGW32__)
        VerifyRegistryPromise(ctx, a, pp);
#endif
        return;
    }
}
Esempio n. 3
0
static int EvalClassExpression(EvalContext *ctx, Constraint *cp, Promise *pp)
{
    int result_and = true;
    int result_or = false;
    int result_xor = 0;
    int result = 0, total = 0;
    char buffer[CF_MAXVARSIZE];
    Rlist *rp;
    FnCall *fp;
    Rval rval;

    if (cp == NULL)
    {
        Log(LOG_LEVEL_ERR, "EvalClassExpression internal diagnostic discovered an ill-formed condition");
    }

    if (!IsDefinedClass(ctx, pp->classes, PromiseGetNamespace(pp)))
    {
        return false;
    }

    if (EvalContextPromiseIsDone(ctx, pp))
    {
        return false;
    }

    if (IsDefinedClass(ctx, pp->promiser, PromiseGetNamespace(pp)))
    {
        if (PromiseGetConstraintAsInt(ctx, "persistence", pp) == 0)
        {
            Log(LOG_LEVEL_VERBOSE, " ?> Cancelling cached persistent class %s", pp->promiser);
            EvalContextHeapPersistentRemove(pp->promiser);
        }
        return false;
    }

    switch (cp->rval.type)
    {
    case RVAL_TYPE_FNCALL:

        fp = (FnCall *) cp->rval.item;  /* Special expansion of functions for control, best effort only */
        FnCallResult res = FnCallEvaluate(ctx, fp, pp);

        FnCallDestroy(fp);
        cp->rval = res.rval;
        break;

    case RVAL_TYPE_LIST:
        for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next)
        {
            rval = EvaluateFinalRval(ctx, "this", (Rval) {rp->item, rp->type}, true, pp);
            RvalDestroy((Rval) {rp->item, rp->type});
            rp->item = rval.item;
            rp->type = rval.type;
        }
        break;

    default:

        rval = ExpandPrivateRval(ctx, "this", cp->rval);
        RvalDestroy(cp->rval);
        cp->rval = rval;
        break;
    }

    if (strcmp(cp->lval, "expression") == 0)
    {
        if (cp->rval.type != RVAL_TYPE_SCALAR)
        {
            return false;
        }

        if (IsDefinedClass(ctx, (char *) cp->rval.item, PromiseGetNamespace(pp)))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    if (strcmp(cp->lval, "not") == 0)
    {
        if (cp->rval.type != RVAL_TYPE_SCALAR)
        {
            return false;
        }

        if (IsDefinedClass(ctx, (char *) cp->rval.item, PromiseGetNamespace(pp)))
        {
            return false;
        }
        else
        {
            return true;
        }
    }

// Class selection

    if (strcmp(cp->lval, "select_class") == 0)
    {
        char splay[CF_MAXVARSIZE];
        int i, n;
        double hash;

        total = 0;

        for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next)
        {
            total++;
        }

        if (total == 0)
        {
            Log(LOG_LEVEL_ERR, "No classes to select on RHS");
            PromiseRef(LOG_LEVEL_ERR, pp);
            return false;
        }

        snprintf(splay, CF_MAXVARSIZE, "%s+%s+%ju", VFQNAME, VIPADDRESS, (uintmax_t)getuid());
        hash = (double) OatHash(splay, CF_HASHTABLESIZE);
        n = (int) (total * hash / (double) CF_HASHTABLESIZE);

        for (rp = (Rlist *) cp->rval.item, i = 0; rp != NULL; rp = rp->next, i++)
        {
            if (i == n)
            {
                EvalContextHeapAddSoft(ctx, rp->item, PromiseGetNamespace(pp));
                return true;
            }
        }
    }

/* If we get here, anything remaining on the RHS must be a clist */

    if (cp->rval.type != RVAL_TYPE_LIST)
    {
        Log(LOG_LEVEL_ERR, "RHS of promise body attribute '%s' is not a list", cp->lval);
        PromiseRef(LOG_LEVEL_ERR, pp);
        return true;
    }

// Class distributions

    if (strcmp(cp->lval, "dist") == 0)
    {
        for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next)
        {
            result = IntFromString(rp->item);

            if (result < 0)
            {
                Log(LOG_LEVEL_ERR, "Non-positive integer in class distribution");
                PromiseRef(LOG_LEVEL_ERR, pp);
                return false;
            }

            total += result;
        }

        if (total == 0)
        {
            Log(LOG_LEVEL_ERR, "An empty distribution was specified on RHS");
            PromiseRef(LOG_LEVEL_ERR, pp);
            return false;
        }

        double fluct = drand48();
        double cum = 0.0;

        for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next)
        {
            double prob = ((double) IntFromString(rp->item)) / ((double) total);
            cum += prob;

            if (fluct < cum)
            {
                break;
            }
        }

        snprintf(buffer, CF_MAXVARSIZE - 1, "%s_%s", pp->promiser, (char *) rp->item);
        /* FIXME: figure why explicit mark and get rid of it */
        EvalContextMarkPromiseDone(ctx, pp);

        if (strcmp(PromiseGetBundle(pp)->type, "common") == 0)
        {
            EvalContextHeapAddSoft(ctx, buffer, PromiseGetNamespace(pp));
        }
        else
        {
            EvalContextStackFrameAddSoft(ctx, buffer);
        }

        return true;
    }

    /* and/or/xor expressions */

    for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next)
    {
        if (rp->type != RVAL_TYPE_SCALAR)
        {
            return false;
        }

        result = IsDefinedClass(ctx, (char *) (rp->item), PromiseGetNamespace(pp));

        result_and = result_and && result;
        result_or = result_or || result;
        result_xor ^= result;
    }

// Class combinations

    if (strcmp(cp->lval, "or") == 0)
    {
        return result_or;
    }

    if (strcmp(cp->lval, "xor") == 0)
    {
        return (result_xor == 1) ? true : false;
    }

    if (strcmp(cp->lval, "and") == 0)
    {
        return result_and;
    }

    return false;
}
Esempio n. 4
0
/**
 * @brief Collects variable constraints controlling how the promise should be converged
 */
static ConvergeVariableOptions CollectConvergeVariableOptions(EvalContext *ctx, const Promise *pp, bool allow_redefine)
{
    ConvergeVariableOptions opts = { 0 };
    opts.should_converge = false;
    opts.drop_undefined = false;
    opts.ok_redefine = allow_redefine;
    opts.cp_save = NULL;

    if (EvalContextPromiseIsDone(ctx, pp))
    {
        return opts;
    }

    if (!IsDefinedClass(ctx, pp->classes))
    {
        return opts;
    }

    int num_values = 0;
    for (size_t i = 0; i < SeqLength(pp->conlist); i++)
    {
        Constraint *cp = SeqAt(pp->conlist, i);

        if (strcmp(cp->lval, "comment") == 0)
        {
            continue;
        }

        if (cp->rval.item == NULL)
        {
            continue;
        }

        if (strcmp(cp->lval, "ifvarclass") == 0)
        {
            switch (cp->rval.type)
            {
            case RVAL_TYPE_SCALAR:
                if (!IsDefinedClass(ctx, cp->rval.item))
                {
                    return opts;
                }

                break;

            case RVAL_TYPE_FNCALL:
                {
                    bool excluded = false;

                    /* eval it: e.g. ifvarclass => not("a_class") */

                    Rval res = FnCallEvaluate(ctx, PromiseGetPolicy(pp), cp->rval.item, pp).rval;

                    /* Don't continue unless function was evaluated properly */
                    if (res.type != RVAL_TYPE_SCALAR)
                    {
                        RvalDestroy(res);
                        return opts;
                    }

                    excluded = !IsDefinedClass(ctx, res.item);

                    RvalDestroy(res);

                    if (excluded)
                    {
                        return opts;
                    }
                }
                break;

            default:
                Log(LOG_LEVEL_ERR, "Invalid ifvarclass type '%c': should be string or function", cp->rval.type);
                continue;
            }

            continue;
        }

        if (strcmp(cp->lval, "policy") == 0)
        {
            if (strcmp(cp->rval.item, "ifdefined") == 0)
            {
                opts.drop_undefined = true;
                opts.ok_redefine = false;
            }
            else if (strcmp(cp->rval.item, "constant") == 0)
            {
                opts.ok_redefine = false;
            }
            else
            {
                opts.ok_redefine |= true;
            }

            opts.ok_redefine &= allow_redefine;
        }
        else if (DataTypeFromString(cp->lval) != CF_DATA_TYPE_NONE)
        {
            num_values++;
            opts.cp_save = cp;
        }
    }

    if (opts.cp_save == NULL)
    {
        Log(LOG_LEVEL_WARNING, "Variable body for '%s' seems incomplete", pp->promiser);
        PromiseRef(LOG_LEVEL_INFO, pp);
        return opts;
    }

    if (num_values > 2)
    {
        Log(LOG_LEVEL_ERR, "Variable '%s' breaks its own promise with multiple values (code %d)", pp->promiser, num_values);
        PromiseRef(LOG_LEVEL_ERR, pp);
        return opts;
    }

    opts.should_converge = true;
    return opts;
}