Beispiel #1
0
static void test_class_ref(void)
{
    {
        ClassRef ref = ClassRefParse("class");
        assert_true(ref.ns == NULL);
        assert_string_equal("class", ref.name);
        char *expr = ClassRefToString(ref.ns, ref.name);
        assert_string_equal("class", expr);
        free(expr);
        ClassRefDestroy(ref);
    }

    {
        ClassRef ref = ClassRefParse("default:class");
        assert_string_equal("default", ref.ns);
        assert_string_equal("class", ref.name);
        char *expr = ClassRefToString(ref.ns, ref.name);
        assert_string_equal("class", expr);
        free(expr);
        ClassRefDestroy(ref);
    }

    {
        ClassRef ref = ClassRefParse("ns:class");
        assert_string_equal("ns", ref.ns);
        assert_string_equal("class", ref.name);
        char *expr = ClassRefToString(ref.ns, ref.name);
        assert_string_equal("ns:class", expr);
        free(expr);
        ClassRefDestroy(ref);
    }
}
Beispiel #2
0
static bool MethodsParseTreeCheck(const Promise *pp, Seq *errors)
{
    bool success = true;

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

        // ensure: if call and callee are resolved, then they have matching arity
        if (StringSafeEqual(cp->lval, "usebundle"))
        {
            if (cp->rval.type == RVAL_TYPE_FNCALL)
            {
                // HACK: exploiting the fact that class-references and call-references are similar
                FnCall *call = RvalFnCallValue(cp->rval);
                ClassRef ref = ClassRefParse(call->name);
                if (!ClassRefIsQualified(ref))
                {
                    ClassRefQualify(&ref, PromiseGetNamespace(pp));
                }

                const Bundle *callee = PolicyGetBundle(PolicyFromPromise(pp), ref.ns, "agent", ref.name);
                if (!callee)
                {
                    callee = PolicyGetBundle(PolicyFromPromise(pp), ref.ns, "common", ref.name);
                }

                ClassRefDestroy(ref);

                if (callee)
                {
                    if (RlistLen(call->args) != RlistLen(callee->args))
                    {
                        SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, cp,
                                                         POLICY_ERROR_METHODS_BUNDLE_ARITY,
                                                         call->name, RlistLen(callee->args), RlistLen(call->args)));
                        success = false;
                    }
                }
            }
        }
    }
    return success;
}
Beispiel #3
0
static PromiseResult VerifyProcessOp(EvalContext *ctx, Item *procdata, Attributes a, const Promise *pp)
{
    bool do_signals = true;
    int out_of_range;
    int killed = 0;
    bool need_to_restart = true;
    Item *killlist = NULL;

    int matches = FindPidMatches(procdata, &killlist, a, pp->promiser);

/* promise based on number of matches */

    PromiseResult result = PROMISE_RESULT_NOOP;
    if (a.process_count.min_range != CF_NOINT)  /* if a range is specified */
    {
        if ((matches < a.process_count.min_range) || (matches > a.process_count.max_range))
        {
            cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Process count for '%s' was out of promised range (%d found)", pp->promiser, matches);
            result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE);
            for (const Rlist *rp = a.process_count.out_of_range_define; rp != NULL; rp = rp->next)
            {
                ClassRef ref = ClassRefParse(RlistScalarValue(rp));
                EvalContextClassPutSoft(ctx, RlistScalarValue(rp), CONTEXT_SCOPE_NAMESPACE, "source=promise");
                ClassRefDestroy(ref);
            }
            out_of_range = true;
        }
        else
        {
            for (const Rlist *rp = a.process_count.in_range_define; rp != NULL; rp = rp->next)
            {
                ClassRef ref = ClassRefParse(RlistScalarValue(rp));
                EvalContextClassPutSoft(ctx, RlistScalarValue(rp), CONTEXT_SCOPE_NAMESPACE, "source=promise");
                ClassRefDestroy(ref);
            }
            cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Process promise for '%s' is kept", pp->promiser);
            out_of_range = false;
        }
    }
    else
    {
        out_of_range = true;
    }

    if (!out_of_range)
    {
        DeleteItemList(killlist);
        return result;
    }

    if (a.transaction.action == cfa_warn)
    {
        do_signals = false;
        result = PromiseResultUpdate(result, PROMISE_RESULT_WARN);
    }
    else
    {
        do_signals = true;
    }

/* signal/kill promises for existing matches */

    if (do_signals && (matches > 0))
    {
        if (a.process_stop != NULL)
        {
            if (DONTDO)
            {
                cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a,
                     "Need to keep process-stop promise for '%s', but only a warning is promised", pp->promiser);
                result = PromiseResultUpdate(result, PROMISE_RESULT_WARN);
            }
            else
            {
                if (IsExecutable(CommandArg0(a.process_stop)))
                {
                    ShellCommandReturnsZero(a.process_stop, SHELL_TYPE_NONE);
                }
                else
                {
                    cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a,
                         "Process promise to stop '%s' could not be kept because '%s' the stop operator failed",
                         pp->promiser, a.process_stop);
                    result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
                    DeleteItemList(killlist);
                    return result;
                }
            }
        }

        killed = DoAllSignals(ctx, killlist, a, pp, &result);
    }

/* delegated promise to restart killed or non-existent entries */

    need_to_restart = (a.restart_class != NULL) && (killed || (matches == 0));

    DeleteItemList(killlist);

    if (!need_to_restart)
    {
        cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No restart promised for %s", pp->promiser);
        return result;
    }
    else
    {
        if (a.transaction.action == cfa_warn)
        {
            cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a,
                 "Need to keep restart promise for '%s', but only a warning is promised", pp->promiser);
            result = PromiseResultUpdate(result, PROMISE_RESULT_WARN);
        }
        else
        {
            cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Making a one-time restart promise for '%s'", pp->promiser);
            result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE);
            EvalContextClassPutSoft(ctx, a.restart_class, CONTEXT_SCOPE_NAMESPACE, "source=promise");
        }
    }

    return result;
}
Beispiel #4
0
static PromiseResult VerifyEnvironments(EvalContext *ctx, Attributes a, const Promise *pp)
{
    char hyper_uri[CF_MAXVARSIZE];
    enum cfhypervisors envtype = cfv_none;

    switch (Str2Hypervisors(a.env.type))
    {
    case cfv_virt_xen:
    case cfv_virt_xen_net:
        snprintf(hyper_uri, CF_MAXVARSIZE - 1, "xen:///");
        envtype = cfv_virt_xen;
        break;

    case cfv_virt_kvm:
    case cfv_virt_kvm_net:
        snprintf(hyper_uri, CF_MAXVARSIZE - 1, "qemu:///session");
        envtype = cfv_virt_kvm;
        break;
    case cfv_virt_esx:
    case cfv_virt_esx_net:
        snprintf(hyper_uri, CF_MAXVARSIZE - 1, "esx://127.0.0.1");
        envtype = cfv_virt_esx;
        break;

    case cfv_virt_test:
    case cfv_virt_test_net:
        snprintf(hyper_uri, CF_MAXVARSIZE - 1, "test:///default");
        envtype = cfv_virt_test;
        break;

    case cfv_virt_vbox:
        snprintf(hyper_uri, CF_MAXVARSIZE - 1, "vbox:///session");
        envtype = cfv_virt_vbox;
        break;

    case cfv_zone:
        snprintf(hyper_uri, CF_MAXVARSIZE - 1, "solaris_zone");
        envtype = cfv_zone;
        break;

    default:
        Log(LOG_LEVEL_ERR, "Environment type '%s' not currently supported", a.env.type);
        return PROMISE_RESULT_NOOP;
        break;
    }

    Log(LOG_LEVEL_VERBOSE, "Selecting environment type '%s' '%s'", a.env.type, hyper_uri);

    ClassRef environment_host_ref = ClassRefParse(a.env.host);
    if (!EvalContextClassGet(ctx, environment_host_ref.ns, environment_host_ref.name))
    {
        switch (a.env.state)
        {
        case ENVIRONMENT_STATE_CREATE:
        case ENVIRONMENT_STATE_RUNNING:
            Log(LOG_LEVEL_VERBOSE,
                "This host ''%s' is not the promised host for the environment '%s', so setting its intended state to 'down'",
                  VFQNAME, a.env.host);
            a.env.state = ENVIRONMENT_STATE_DOWN;
            break;
        default:
            Log(LOG_LEVEL_VERBOSE,
                  "This is not the promised host for the environment, but it does not promise a run state, so take promise as valid");
        }
    }
    ClassRefDestroy(environment_host_ref);

    virInitialize();

    PromiseResult result = PROMISE_RESULT_NOOP;
#if defined(__linux__)
    switch (Str2Hypervisors(a.env.type))
    {
    case cfv_virt_xen:
    case cfv_virt_kvm:
    case cfv_virt_esx:
    case cfv_virt_vbox:
    case cfv_virt_test:
        result = PromiseResultUpdate(result, VerifyVirtDomain(ctx, hyper_uri, envtype, a, pp));
        break;
    case cfv_virt_xen_net:
    case cfv_virt_kvm_net:
    case cfv_virt_esx_net:
    case cfv_virt_test_net:
        result = PromiseResultUpdate(result, VerifyVirtNetwork(ctx, hyper_uri, envtype, a, pp));
        break;
    case cfv_ec2:
        break;
    case cfv_eucalyptus:
        break;
    default:
        break;
    }
#elif defined(__APPLE__)
    switch (Str2Hypervisors(a.env.type))
    {
    case cfv_virt_vbox:
    case cfv_virt_test:
        result = PromiseResultUpdate(result, VerifyVirtDomain(ctx, hyper_uri, envtype, a, pp));
        break;
    case cfv_virt_xen_net:
    case cfv_virt_kvm_net:
    case cfv_virt_esx_net:
    case cfv_virt_test_net:
        result = PromiseResultUpdate(result, VerifyVirtNetwork(ctx, hyper_uri, envtype, a, pp));
        break;
    default:
        break;
    }
#elif defined(__sun)
    switch (Str2Hypervisors(a.env.type))
    {
    case cfv_zone:
        result = PromiseResultUpdate(result, VerifyZone(a, pp));
        break;
    default:
        break;
    }
#else
    Log(LOG_LEVEL_VERBOSE, "Unable to resolve an environment supervisor/monitor for this platform, aborting");
#endif
    return result;
}