Example #1
0
/* Returns FALSE if 'op' should be free'd by the caller */
gboolean
operation_finalize(svc_action_t * op)
{
    int recurring = 0;

    if (op->interval) {
        if (op->cancel) {
            op->status = PCMK_LRM_OP_CANCELLED;
            cancel_recurring_action(op);
        } else {
            recurring = 1;
            op->opaque->repeat_timer = g_timeout_add(op->interval,
                                                     recurring_action_timer, (void *)op);
        }
    }

    if (op->opaque->callback) {
        op->opaque->callback(op);
    }

    op->pid = 0;

    if (!recurring && op->synchronous == FALSE) {
        /*
         * If this is a recurring action, do not free explicitly.
         * It will get freed whenever the action gets cancelled.
         */
        services_action_free(op);
        return TRUE;
    }

    services_action_cleanup(op);
    return FALSE;
}
Example #2
0
gboolean
services_action_cancel(const char *name, const char *action, int interval)
{
    svc_action_t *op = NULL;
    char id[512];

    snprintf(id, sizeof(id), "%s_%s_%d", name, action, interval);

    if (!(op = g_hash_table_lookup(recurring_actions, id))) {
        return FALSE;
    }

    if (op->pid == 0) {
        cancel_recurring_action(op);
        op->status = PCMK_LRM_OP_CANCELLED;
        if (op->opaque->callback) {
            op->opaque->callback(op);
        }
        services_action_free(op);
    } else {
        crm_info("Cancelling op: %s will occur once operation completes", id);
        op->cancel = 1;
    }

    return TRUE;
}
Example #3
0
/* add new recurring operation, check for duplicates. 
 * - if duplicate found, return TRUE, immediately reschedule op.
 * - if no dup, return FALSE, inserve into recurring op list.*/
static gboolean
handle_duplicate_recurring(svc_action_t * op, void (*action_callback) (svc_action_t *))
{
    svc_action_t * dup = NULL;

    if (recurring_actions == NULL) {
        recurring_actions = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
        return FALSE;
    }

    /* check for duplicates */
    dup = g_hash_table_lookup(recurring_actions, op->id);

    if (dup && (dup != op)) {
        /* update user data */
        if (op->opaque->callback) {
            dup->opaque->callback = op->opaque->callback;
            dup->cb_data = op->cb_data;
            op->cb_data = NULL;
        }
        /* immediately execute the next interval */
        if (dup->pid != 0) {
            if (op->opaque->repeat_timer) {
                g_source_remove(op->opaque->repeat_timer);
            }
            recurring_action_timer(dup);
        }
        /* free the dup.  */
        services_action_free(op);
        return TRUE;
    }

    return FALSE;
}
Example #4
0
gboolean
services_action_cancel(const char *name, const char *action, int interval)
{
    svc_action_t *op = NULL;
    char id[512];

    snprintf(id, sizeof(id), "%s_%s_%d", name, action, interval);

    if (!(op = g_hash_table_lookup(recurring_actions, id))) {
        return FALSE;
    }

    if (op->pid == 0) {
        cancel_recurring_action(op);
        op->status = PCMK_LRM_OP_CANCELLED;
        if (op->opaque->callback) {
            op->opaque->callback(op);
        }
        services_action_free(op);
    } else {
        crm_info("Cancelling in-flight op: performing early termination of %s", id);
        op->cancel = 1;
        if (mainloop_child_kill(op->pid) == FALSE) {
            /* even though the early termination failed,
             * the op will be marked as cancelled once it completes. */
            crm_err("Termination of %s failed", id);
        }
    }

    return TRUE;
}
Example #5
0
gboolean
Resources_invoke(Matahari *matahari, const char *name, const char *standard,
                 const char *provider, const char *agent, const char *action,
                 unsigned int interval, GHashTable *parameters,
                 unsigned int timeout, unsigned int expected_rc,
                 const char *userdata_in, DBusGMethodInvocation *context)
{
    GError* error = NULL;
    svc_action_t *op = NULL;
    GList *standards;
    struct invoke_cb_data *data;

    if (!check_authorization(RESOURCES_INTERFACE_NAME ".invoke",
                             &error, context)) {
        dbus_g_method_return_error(context, error);
        g_error_free(error);
        return FALSE;
    }

    // Check if standard is valid
    standards = resources_list_standards();

    if (g_list_find_custom(standards, standard, (GCompareFunc) strcasecmp) == NULL) {
        mh_err("%s is not a known resource standard", standard);
        error = g_error_new(MATAHARI_ERROR, MH_RES_NOT_IMPLEMENTED,
                            "%s is not a known resource standard", standard);
        dbus_g_method_return_error(context, error);
        g_error_free(error);
        g_list_free_full(standards, free);
        return FALSE;
    }
    g_list_free_full(standards, free);

    op = resources_action_create(name, standard, provider, agent, action,
                                 0, timeout, g_hash_table_ref(parameters));
    op->expected_rc = expected_rc;

    if (!(data = malloc(1 * sizeof(struct invoke_cb_data)))) {
        services_action_free(op);
        return FALSE;
    }

    data->context = context;
    data->userdata = strdup(userdata_in);
    op->cb_data = data;

    services_action_async(op, invoke_cb);
    return FALSE;
}
Example #6
0
gboolean
Services_disable(Matahari *matahari, const char *name,
                 DBusGMethodInvocation *context)
{
    GError* error = NULL;
    svc_action_t *op;
    gboolean res;

    if (!check_authorization(SERVICES_BUS_NAME ".disable", &error, context)) {
        dbus_g_method_return_error(context, error);
        return FALSE;
    }
    op = services_action_create(name, "disable", 0, TIMEOUT_MS);
    res = services_action_sync(op);
    services_action_free(op);
    dbus_g_method_return(context, res);
    return res;
}
Example #7
0
gboolean
Services_status(Matahari *matahari, const char *name, unsigned int interval,
                unsigned int timeout, DBusGMethodInvocation *context)
{
    GError* error = NULL;
    svc_action_t *op;
    int rc;

    if (!check_authorization(SERVICES_BUS_NAME ".status", &error, context)) {
        dbus_g_method_return_error(context, error);
        return FALSE;
    }
    op = services_action_create(name, "status", interval, timeout);
    services_action_sync(op);
    rc = op->rc;
    services_action_free(op);
    dbus_g_method_return(context, rc);
    return TRUE;
}
Example #8
0
gboolean
services_action_cancel(const char *name, const char *action, int interval)
{
    svc_action_t* op = NULL;
    char id[512];

    snprintf(id, sizeof(id), "%s_%s_%d", name, action, interval);

    if (!(op = g_hash_table_lookup(recurring_actions, id))) {
        return FALSE;
    }

    op->opaque->cancel = TRUE;
    mh_debug("Removing %s", op->id);
    if (op->opaque->repeat_timer) {
        g_source_remove(op->opaque->repeat_timer);
    }
    services_action_free(op);

    return TRUE;
}
Example #9
0
svc_action_t *resources_action_create(
    const char *name, const char *standard, const char *provider, const char *agent,
    const char *action, int interval, int timeout, GHashTable *params)
{
    svc_action_t *op;

    op = calloc(1, sizeof(svc_action_t));
    op->opaque = calloc(1, sizeof(svc_action_private_t));
    op->rsc = strdup(name);
    op->action = strdup(action);
    op->interval = interval;
    op->timeout = timeout;
    op->standard = strdup(standard);
    op->agent = strdup(agent);
    op->sequence = ++operations;
    asprintf(&op->id, "%s_%s_%d", name, action, interval);

    if(strcmp(standard, "ocf") == 0) {
	op->provider = strdup(provider);
	op->params = params;

	asprintf(&op->opaque->exec, "%s/resource.d/%s/%s",
		 OCF_ROOT, provider, agent);
	op->opaque->args[0] = strdup(op->opaque->exec);
	op->opaque->args[1] = strdup(action);

    } else if(strcmp(standard, "lsb") == 0 || strcmp(standard, "windows") == 0) {
	services_os_set_exec(op);

    } else {
	mh_err("Unknown resource standard: %s", standard);
	services_action_free(op);
	op = NULL;
    }
    
    return op;
}
Example #10
0
svc_action_t *
resources_action_create(const char *name, const char *standard, const char *provider,
                        const char *agent, const char *action, int interval, int timeout,
                        GHashTable * params)
{
    svc_action_t *op = NULL;

    /*
     * Do some up front sanity checks before we go off and
     * build the svc_action_t instance.
     */

    if (crm_strlen_zero(name)) {
        crm_err("A service or resource action must have a name.");
        goto return_error;
    }

    if (crm_strlen_zero(standard)) {
        crm_err("A service action must have a valid standard.");
        goto return_error;
    }

    if (!strcasecmp(standard, "ocf") && crm_strlen_zero(provider)) {
        crm_err("An OCF resource action must have a provider.");
        goto return_error;
    }

    if (crm_strlen_zero(agent)) {
        crm_err("A service or resource action must have an agent.");
        goto return_error;
    }

    if (crm_strlen_zero(action)) {
        crm_err("A service or resource action must specify an action.");
        goto return_error;
    }

    if (safe_str_eq(action, "monitor")
        && (safe_str_eq(standard, "lsb") || safe_str_eq(standard, "service"))) {
        action = "status";
    }

    /*
     * Sanity checks passed, proceed!
     */

    op = calloc(1, sizeof(svc_action_t));
    op->opaque = calloc(1, sizeof(svc_action_private_t));
    op->rsc = strdup(name);
    op->action = strdup(action);
    op->interval = interval;
    op->timeout = timeout;
    op->standard = strdup(standard);
    op->agent = strdup(agent);
    op->sequence = ++operations;
    if (asprintf(&op->id, "%s_%s_%d", name, action, interval) == -1) {
        goto return_error;
    }

    if (strcasecmp(op->standard, "service") == 0) {
        const char *expanded = resources_find_service_class(op->agent);

        if(expanded) {
            crm_debug("Found a %s agent for %s/%s", expanded, op->rsc, op->agent);
            free(op->standard);
            op->standard = strdup(expanded);

        } else {
            crm_info("Cannot determine the standard for %s (%s)", op->rsc, op->agent);
            free(op->standard);
            op->standard = strdup("lsb");
        }
    }

    if (strcasecmp(op->standard, "ocf") == 0) {
        op->provider = strdup(provider);
        op->params = params;
        params = NULL;

        if (asprintf(&op->opaque->exec, "%s/resource.d/%s/%s", OCF_ROOT_DIR, provider, agent) == -1) {
            crm_err("Internal error: cannot create agent path");
            goto return_error;
        }
        op->opaque->args[0] = strdup(op->opaque->exec);
        op->opaque->args[1] = strdup(action);

    } else if (strcasecmp(op->standard, "lsb") == 0) {
        if (op->agent[0] == '/') {
            /* if given an absolute path, use that instead
             * of tacking on the LSB_ROOT_DIR path to the front */
            op->opaque->exec = strdup(op->agent);
        } else if (asprintf(&op->opaque->exec, "%s/%s", LSB_ROOT_DIR, op->agent) == -1) {
            crm_err("Internal error: cannot create agent path");
            goto return_error;
        }
        op->opaque->args[0] = strdup(op->opaque->exec);
        op->opaque->args[1] = strdup(op->action);
        op->opaque->args[2] = NULL;

#if SUPPORT_SYSTEMD
    } else if (strcasecmp(op->standard, "systemd") == 0) {
        op->opaque->exec = strdup("systemd-dbus");
#endif
#if SUPPORT_UPSTART
    } else if (strcasecmp(op->standard, "upstart") == 0) {
        op->opaque->exec = strdup("upstart-dbus");
#endif
    } else if (strcasecmp(op->standard, "service") == 0) {
        op->opaque->exec = strdup(SERVICE_SCRIPT);
        op->opaque->args[0] = strdup(SERVICE_SCRIPT);
        op->opaque->args[1] = strdup(agent);
        op->opaque->args[2] = strdup(action);

#if SUPPORT_NAGIOS
    } else if (strcasecmp(op->standard, "nagios") == 0) {
        int index = 0;

        if (op->agent[0] == '/') {
            /* if given an absolute path, use that instead
             * of tacking on the NAGIOS_PLUGIN_DIR path to the front */
            op->opaque->exec = strdup(op->agent);

        } else if (asprintf(&op->opaque->exec, "%s/%s", NAGIOS_PLUGIN_DIR, op->agent) == -1) {
            crm_err("Internal error: cannot create agent path");
            goto return_error;
        }

        op->opaque->args[0] = strdup(op->opaque->exec);
        index = 1;

        if (safe_str_eq(op->action, "monitor") && op->interval == 0) {
            /* Invoke --version for a nagios probe */
            op->opaque->args[index] = strdup("--version");
            index++;

        } else if (params) {
            GHashTableIter iter;
            char *key = NULL;
            char *value = NULL;
            static int args_size = sizeof(op->opaque->args) / sizeof(char *);

            g_hash_table_iter_init(&iter, params);

            while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value) &&
                   index <= args_size - 3) {
                int len = 3;
                char *long_opt = NULL;

                if (safe_str_eq(key, XML_ATTR_CRM_VERSION) || strstr(key, CRM_META "_")) {
                    continue;
                }

                len += strlen(key);
                long_opt = calloc(1, len);
                sprintf(long_opt, "--%s", key);
                long_opt[len - 1] = 0;

                op->opaque->args[index] = long_opt;
                op->opaque->args[index + 1] = strdup(value);
                index += 2;
            }
        }
        op->opaque->args[index] = NULL;
#endif

    } else {
        crm_err("Unknown resource standard: %s", op->standard);
        services_action_free(op);
        op = NULL;
    }

    if(params) {
        g_hash_table_destroy(params);
    }
    return op;

  return_error:
    if(params) {
        g_hash_table_destroy(params);
    }
    services_action_free(op);

    return NULL;
}
Example #11
0
svc_action_t *
resources_action_create(const char *name, const char *standard,
                        const char *provider, const char *agent,
                        const char *action, guint interval_ms, int timeout,
                        GHashTable *params, enum svc_action_flags flags)
{
    svc_action_t *op = NULL;
    uint32_t ra_caps = 0;

    /*
     * Do some up front sanity checks before we go off and
     * build the svc_action_t instance.
     */

    if (crm_strlen_zero(name)) {
        crm_err("Cannot create operation without resource name");
        goto return_error;
    }

    if (crm_strlen_zero(standard)) {
        crm_err("Cannot create operation for %s without resource class", name);
        goto return_error;
    }
    ra_caps = pcmk_get_ra_caps(standard);

    if (is_set(ra_caps, pcmk_ra_cap_provider) && crm_strlen_zero(provider)) {
        crm_err("Cannot create operation for %s without provider", name);
        goto return_error;
    }

    if (crm_strlen_zero(agent)) {
        crm_err("Cannot create operation for %s without agent name", name);
        goto return_error;
    }

    if (crm_strlen_zero(action)) {
        crm_err("Cannot create operation for %s without operation name", name);
        goto return_error;
    }

    /*
     * Sanity checks passed, proceed!
     */

    op = calloc(1, sizeof(svc_action_t));
    op->opaque = calloc(1, sizeof(svc_action_private_t));
    op->rsc = strdup(name);
    op->interval_ms = interval_ms;
    op->timeout = timeout;
    op->standard = expand_resource_class(name, standard, agent);
    op->agent = strdup(agent);
    op->sequence = ++operations;
    op->flags = flags;
    op->id = generate_op_key(name, action, interval_ms);

    if (is_set(ra_caps, pcmk_ra_cap_status) && safe_str_eq(action, "monitor")) {
        op->action = strdup("status");
    } else {
        op->action = strdup(action);
    }

    if (is_set(ra_caps, pcmk_ra_cap_provider)) {
        op->provider = strdup(provider);
    }

    if (is_set(ra_caps, pcmk_ra_cap_params)) {
        op->params = params;
        params = NULL; // so we don't free them in this function
    }

    if (strcasecmp(op->standard, PCMK_RESOURCE_CLASS_OCF) == 0) {
        op->opaque->exec = crm_strdup_printf("%s/resource.d/%s/%s",
                                             OCF_ROOT_DIR, provider, agent);
        op->opaque->args[0] = strdup(op->opaque->exec);
        op->opaque->args[1] = strdup(op->action);

    } else if (strcasecmp(op->standard, PCMK_RESOURCE_CLASS_LSB) == 0) {
        op->opaque->exec = services__lsb_agent_path(op->agent);
        op->opaque->args[0] = strdup(op->opaque->exec);
        op->opaque->args[1] = strdup(op->action);

#if SUPPORT_SYSTEMD
    } else if (strcasecmp(op->standard, PCMK_RESOURCE_CLASS_SYSTEMD) == 0) {
        op->opaque->exec = strdup("systemd-dbus");
#endif
#if SUPPORT_UPSTART
    } else if (strcasecmp(op->standard, PCMK_RESOURCE_CLASS_UPSTART) == 0) {
        op->opaque->exec = strdup("upstart-dbus");
#endif
#if SUPPORT_NAGIOS
    } else if (strcasecmp(op->standard, PCMK_RESOURCE_CLASS_NAGIOS) == 0) {
        op->opaque->exec = dup_file_path(op->agent, NAGIOS_PLUGIN_DIR);
        op->opaque->args[0] = strdup(op->opaque->exec);

        if (safe_str_eq(op->action, "monitor") && (op->interval_ms == 0)) {
            /* Invoke --version for a nagios probe */
            op->opaque->args[1] = strdup("--version");

        } else if (op->params) {
            GHashTableIter iter;
            char *key = NULL;
            char *value = NULL;
            int index = 1;
            static int args_size = sizeof(op->opaque->args) / sizeof(char *);

            g_hash_table_iter_init(&iter, op->params);

            while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value) &&
                   index <= args_size - 3) {

                if (safe_str_eq(key, XML_ATTR_CRM_VERSION) || strstr(key, CRM_META "_")) {
                    continue;
                }
                op->opaque->args[index++] = crm_strdup_printf("--%s", key);
                op->opaque->args[index++] = strdup(value);
            }
        }

        // Nagios actions don't need to keep the parameters
        if (op->params != NULL) {
            g_hash_table_destroy(op->params);
            op->params = NULL;
        }
#endif
    } else {
        crm_err("Unknown resource standard: %s", op->standard);
        goto return_error;
    }

    if(params) {
        g_hash_table_destroy(params);
    }
    return op;

  return_error:
    if(params) {
        g_hash_table_destroy(params);
    }
    services_action_free(op);

    return NULL;
}
Example #12
0
svc_action_t *resources_action_create(
    const char *name, const char *standard, const char *provider, const char *agent,
    const char *action, int interval, int timeout, GHashTable *params)
{
    svc_action_t *op;

    /*
     * Do some up front sanity checks before we go off and
     * build the svc_action_t instance.
     */

    if (crm_strlen_zero(name)) {
        crm_err("A service or resource action must have a name.");
        return NULL;
    }

    if (crm_strlen_zero(standard)) {
        crm_err("A service action must have a valid standard.");
        return NULL;
    }

    if (!strcasecmp(standard, "ocf") && crm_strlen_zero(provider)) {
        crm_err("An OCF resource action must have a provider.");
        return NULL;
    }

    if (crm_strlen_zero(agent)) {
        crm_err("A service or resource action must have an agent.");
        return NULL;
    }

    if (crm_strlen_zero(action)) {
        crm_err("A service or resource action must specify an action.");
        return NULL;
    }

    if (safe_str_eq(action, "monitor") && (safe_str_eq(standard, "lsb") || safe_str_eq(standard, "service"))) {
        action = "status";
    }

    /*
     * Sanity checks passed, proceed!
     */

    op = calloc(1, sizeof(svc_action_t));
    op->opaque = calloc(1, sizeof(svc_action_private_t));
    op->rsc = strdup(name);
    op->action = strdup(action);
    op->interval = interval;
    op->timeout = timeout;
    op->standard = strdup(standard);
    op->agent = strdup(agent);
    op->sequence = ++operations;
    if (asprintf(&op->id, "%s_%s_%d", name, action, interval) == -1) {
        goto return_error;
    }

    if(strcasecmp(op->standard, "service") == 0) {
        /* Work it out and then fall into the if-else block below.
         * Priority is:
         * - lsb
         * - systemd
         * - upstart
         */
        int rc = 0;
        struct stat st;
        char *path = NULL;

#ifdef LSB_ROOT_DIR
        rc = asprintf(&path, "%s/%s", LSB_ROOT_DIR, op->agent);
        if(rc > 0 && stat(path, &st) == 0) {
            crm_debug("Found an lsb agent for %s/% the", op->rsc, op->agent);
            free(path);
            free(op->standard);
            op->standard = strdup("lsb");
            goto expanded;
        }
        free(path);
#endif

#if SUPPORT_SYSTEMD
        if(systemd_unit_exists(op->agent)) {
            crm_debug("Found a systemd agent for %s/%s", op->rsc, op->agent);
            free(op->standard);
            op->standard = strdup("systemd");
            goto expanded;
        }
#endif

#if SUPPORT_UPSTART
        if(upstart_job_exists(op->agent)) {
            crm_debug("Found an upstart agent for %s/%s", op->rsc, op->agent);
            free(op->standard);
            op->standard = strdup("upstart");
            goto expanded;
        }
#endif

        crm_info("Cannot determine the standard for %s (%s)", op->rsc, op->agent);
    }

expanded:
    if(strcasecmp(op->standard, "ocf") == 0) {
        op->provider = strdup(provider);
        op->params = params;

        if (asprintf(&op->opaque->exec, "%s/resource.d/%s/%s",
                     OCF_ROOT_DIR, provider, agent) == -1) {
            goto return_error;
        }
        op->opaque->args[0] = strdup(op->opaque->exec);
        op->opaque->args[1] = strdup(action);

    } else if(strcasecmp(op->standard, "lsb") == 0) {
        if (op->agent[0] == '/') {
            /* if given an absolute path, use that instead
            * of tacking on the LSB_ROOT_DIR path to the front */
            op->opaque->exec = strdup(op->agent);
        } else if (asprintf(&op->opaque->exec, "%s/%s", LSB_ROOT_DIR, op->agent) == -1) {
            goto return_error;
        }
        op->opaque->args[0] = strdup(op->opaque->exec);
        op->opaque->args[1] = strdup(op->action);
        op->opaque->args[2] = NULL;

#if SUPPORT_SYSTEMD
    } else if(strcasecmp(op->standard, "systemd") == 0) {
        op->opaque->exec = strdup("systemd-dbus");
#endif
#if SUPPORT_UPSTART
    } else if(strcasecmp(op->standard, "upstart") == 0) {
        op->opaque->exec = strdup("upstart-dbus");
#endif
    } else if(strcasecmp(op->standard, "service") == 0) {
        op->opaque->exec = strdup(SERVICE_SCRIPT);
        op->opaque->args[0] = strdup(SERVICE_SCRIPT);
        op->opaque->args[1] = strdup(agent);
        op->opaque->args[2] = strdup(action);

    } else {
        crm_err("Unknown resource standard: %s", op->standard);
        services_action_free(op);
        op = NULL;
    }

    return op;

return_error:
    services_action_free(op);

    return NULL;
}