Beispiel #1
0
/*!
 * \internal
 * \brief Create regular expression matching failure-related attributes
 *
 * \param[out] regex  Where to store created regular expression
 * \param[in]  rsc    Name of resource to clear (or NULL for all)
 * \param[in]  op     Operation to clear if rsc is specified (or NULL for all)
 * \param[in]  interval  Interval of operation to clear if op is specified
 *
 * \return pcmk_ok on success, -EINVAL if arguments are invalid
 *
 * \note The caller is responsible for freeing the result with regfree().
 */
int
attrd_failure_regex(regex_t *regex, const char *rsc, const char *op,
                    int interval)
{
    char *pattern = NULL;
    int rc;

    /* Create a pattern that matches desired attributes */

    if (rsc == NULL) {
        pattern = strdup(ATTRD_RE_CLEAR_ALL);
    } else if (op == NULL) {
        pattern = crm_strdup_printf(ATTRD_RE_CLEAR_ONE, rsc);
    } else {
        pattern = crm_strdup_printf(ATTRD_RE_CLEAR_OP,
                                    rsc, op, interval);
    }

    /* Compile pattern into regular expression */
    crm_trace("Clearing attributes matching %s", pattern);
    rc = regcomp(regex, pattern, REG_EXTENDED|REG_NOSUB);
    free(pattern);

    return (rc == 0)? pcmk_ok : -EINVAL;
}
Beispiel #2
0
/*!
 * \brief Create a new election object
 *
 * Every node that wishes to participate in an election must create an election
 * object. Typically, this should be done once, at start-up. A caller should
 * only create a single election object.
 *
 * \param[in] name       Label for election (for logging)
 * \param[in] uname      Local node's name
 * \param[in] period_ms  How long to wait for all peers to vote
 * \param[in] cb         Function to call if local node wins election
 *
 * \return Newly allocated election object on success, NULL on error
 * \note The caller is responsible for freeing the returned value using
 *       election_fini().
 */
election_t *
election_init(const char *name, const char *uname, guint period_ms, GSourceFunc cb)
{
    election_t *e = NULL;

    static guint count = 0;

    CRM_CHECK(uname != NULL, return NULL);

    e = calloc(1, sizeof(election_t));
    if (e == NULL) {
        crm_perror(LOG_CRIT, "Cannot create election");
        return NULL;
    }

    e->uname = strdup(uname);
    if (e->uname == NULL) {
        crm_perror(LOG_CRIT, "Cannot create election");
        free(e);
        return NULL;
    }

    e->name = name? crm_strdup_printf("election-%s", name)
                  : crm_strdup_printf("election-%u", count++);
    e->cb = cb;
    e->timeout = mainloop_timer_add(e->name, period_ms, FALSE,
                                    election_timer_cb, e);
    crm_trace("Created %s", e->name);
    return e;
}
Beispiel #3
0
gboolean
systemd_unit_exec_with_unit(svc_action_t * op, const char *unit)
{
    const char *method = op->action;
    DBusMessage *msg = NULL;
    DBusMessage *reply = NULL;

    CRM_ASSERT(unit);

    if (safe_str_eq(op->action, "monitor") || safe_str_eq(method, "status")) {
        DBusPendingCall *pending = NULL;
        char *state;

        state = pcmk_dbus_get_property(systemd_proxy, BUS_NAME, unit,
                                       BUS_NAME ".Unit", "ActiveState",
                                       op->synchronous?NULL:systemd_unit_check,
                                       op, op->synchronous?NULL:&pending, op->timeout);
        if (op->synchronous) {
            systemd_unit_check("ActiveState", state, op);
            free(state);
            return op->rc == PCMK_OCF_OK;
        } else if (pending) {
            services_set_op_pending(op, pending);
            return TRUE;

        } else {
            return operation_finalize(op);
        }

    } else if (g_strcmp0(method, "start") == 0) {
        FILE *file_strm = NULL;
        char *override_dir = crm_strdup_printf("%s/%s.service.d", SYSTEMD_OVERRIDE_ROOT, op->agent);
        char *override_file = crm_strdup_printf("%s/%s.service.d/50-pacemaker.conf", SYSTEMD_OVERRIDE_ROOT, op->agent);

        method = "StartUnit";
        crm_build_path(override_dir, 0755);

        file_strm = fopen(override_file, "w");
        if (file_strm != NULL) {
            /* TODO: Insert the start timeout in too */
            char *override = crm_strdup_printf(
                "[Unit]\n"
                "Description=Cluster Controlled %s\n"
                "Before=pacemaker.service\n"
                "\n"
                "[Service]\n"
                "Restart=no\n",
                op->agent);

            int rc = fprintf(file_strm, "%s\n", override);

            free(override);
            if (rc < 0) {
                crm_perror(LOG_ERR, "Cannot write to systemd override file %s", override_file);
            }

        } else {
Beispiel #4
0
/*!
 * \internal
 * \brief Respond to client clear-failure request
 *
 * \param[in] xml         Request XML
 */
void
attrd_client_clear_failure(xmlNode *xml)
{
#if 0
    /* @TODO Track the minimum supported protocol version across all nodes,
     * then enable this more-efficient code.
     */
    if (compare_version("2", minimum_protocol_version) <= 0) {
        /* Propagate to all peers (including ourselves).
         * This ends up at attrd_peer_message().
         */
        send_attrd_message(NULL, xml);
        return;
    }
#endif

    const char *rsc = crm_element_value(xml, F_ATTRD_RESOURCE);
    const char *op = crm_element_value(xml, F_ATTRD_OPERATION);
    const char *interval_spec = crm_element_value(xml, F_ATTRD_INTERVAL);

    /* Map this to an update */
    crm_xml_add(xml, F_ATTRD_TASK, ATTRD_OP_UPDATE);

    /* Add regular expression matching desired attributes */

    if (rsc) {
        char *pattern;

        if (op == NULL) {
            pattern = crm_strdup_printf(ATTRD_RE_CLEAR_ONE, rsc);

        } else {
            guint interval_ms = crm_parse_interval_spec(interval_spec);

            pattern = crm_strdup_printf(ATTRD_RE_CLEAR_OP,
                                        rsc, op, interval_ms);
        }

        crm_xml_add(xml, F_ATTRD_REGEX, pattern);
        free(pattern);

    } else {
        crm_xml_add(xml, F_ATTRD_REGEX, ATTRD_RE_CLEAR_ALL);
    }

    /* Make sure attribute and value are not set, so we delete via regex */
    if (crm_element_value(xml, F_ATTRD_ATTRIBUTE)) {
        crm_xml_replace(xml, F_ATTRD_ATTRIBUTE, NULL);
    }
    if (crm_element_value(xml, F_ATTRD_VALUE)) {
        crm_xml_replace(xml, F_ATTRD_VALUE, NULL);
    }

    attrd_client_update(xml);
}
Beispiel #5
0
static void
build_update_element(xmlNode *parent, attribute_t *a, const char *nodeid, const char *value)
{
    char *set = NULL;
    char *uuid = NULL;
    xmlNode *xml_obj = NULL;

    if(a->set) {
        set = strdup(a->set);
    } else {
        set = crm_strdup_printf("%s-%s", XML_CIB_TAG_STATUS, nodeid);
    }

    if(a->uuid) {
        uuid = strdup(a->uuid);
    } else {
        int lpc;
        uuid = crm_strdup_printf("%s-%s", set, a->id);

        /* Minimal attempt at sanitizing automatic IDs */
        for (lpc = 0; uuid[lpc] != 0; lpc++) {
            switch (uuid[lpc]) {
                case ':':
                    uuid[lpc] = '.';
            }
        }
    }

    xml_obj = create_xml_node(parent, XML_CIB_TAG_STATE);
    crm_xml_add(xml_obj, XML_ATTR_ID, nodeid);

    xml_obj = create_xml_node(xml_obj, XML_TAG_TRANSIENT_NODEATTRS);
    crm_xml_add(xml_obj, XML_ATTR_ID, nodeid);

    xml_obj = create_xml_node(xml_obj, XML_TAG_ATTR_SETS);
    crm_xml_add(xml_obj, XML_ATTR_ID, set);

    xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_NVPAIR);
    crm_xml_add(xml_obj, XML_ATTR_ID, uuid);
    crm_xml_add(xml_obj, XML_NVPAIR_ATTR_NAME, a->id);

    if(value) {
        crm_xml_add(xml_obj, XML_NVPAIR_ATTR_VALUE, value);

    } else {
        crm_xml_add(xml_obj, XML_NVPAIR_ATTR_VALUE, "");
        crm_xml_add(xml_obj, "__delete__", XML_NVPAIR_ATTR_VALUE);
    }

    free(uuid);
    free(set);
}
Beispiel #6
0
static int32_t
attrd_ipc_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
{
    uint32_t id = 0;
    uint32_t flags = 0;
    crm_client_t *client = crm_client_get(c);
    xmlNode *xml = crm_ipcs_recv(client, data, size, &id, &flags);
    const char *op;

    if (xml == NULL) {
        crm_debug("No msg from %d (%p)", crm_ipcs_client_pid(c), c);
        return 0;
    }
#if ENABLE_ACL
    CRM_ASSERT(client->user != NULL);
    crm_acl_get_set_user(xml, F_ATTRD_USER, client->user);
#endif

    crm_trace("Processing msg from %d (%p)", crm_ipcs_client_pid(c), c);
    crm_log_xml_trace(xml, __FUNCTION__);

    op = crm_element_value(xml, F_ATTRD_TASK);

    if (client->name == NULL) {
        const char *value = crm_element_value(xml, F_ORIG);
        client->name = crm_strdup_printf("%s.%d", value?value:"unknown", client->pid);
    }

    if (safe_str_eq(op, ATTRD_OP_PEER_REMOVE)) {
        attrd_send_ack(client, id, flags);
        attrd_client_peer_remove(client->name, xml);

    } else if (safe_str_eq(op, ATTRD_OP_UPDATE)) {
        attrd_send_ack(client, id, flags);
        attrd_client_update(xml);

    } else if (safe_str_eq(op, ATTRD_OP_UPDATE_BOTH)) {
        attrd_send_ack(client, id, flags);
        attrd_client_update(xml);

    } else if (safe_str_eq(op, ATTRD_OP_UPDATE_DELAY)) {
        attrd_send_ack(client, id, flags);
        attrd_client_update(xml);
  
    } else if (safe_str_eq(op, ATTRD_OP_REFRESH)) {
        attrd_send_ack(client, id, flags);
        attrd_client_refresh();

    } else if (safe_str_eq(op, ATTRD_OP_QUERY)) {
        /* queries will get reply, so no ack is necessary */
        attrd_client_query(client, id, flags, xml);

    } else {
        crm_info("Ignoring request from client %s with unknown operation %s",
                 client->name, op);
    }

    free_xml(xml);
    return 0;
}
Beispiel #7
0
int
query_node_uuid(cib_t * the_cib, const char *uname, char **uuid, int *is_remote_node)
{
    int rc = pcmk_ok;
    char *xpath_string;
    xmlNode *xml_search = NULL;

    CRM_ASSERT(uname != NULL);

    if (uuid) {
        *uuid = NULL;
    }
    if (is_remote_node) {
        *is_remote_node = FALSE;
    }

    xpath_string = crm_strdup_printf(XPATH_NODE, uname, uname, uname, uname);
    if (cib_internal_op(the_cib, CIB_OP_QUERY, NULL, xpath_string, NULL,
                        &xml_search, cib_sync_call|cib_scope_local|cib_xpath,
                        NULL) == pcmk_ok) {
        rc = get_uuid_from_result(xml_search, uuid, is_remote_node);
    } else {
        rc = -ENXIO;
    }
    free(xpath_string);
    free_xml(xml_search);

    if (rc != pcmk_ok) {
        crm_debug("Could not map node name '%s' to a UUID: %s",
                  uname, pcmk_strerror(rc));
    } else {
        crm_info("Mapped node name '%s' to UUID %s", uname, (uuid? *uuid : ""));
    }
    return rc;
}
Beispiel #8
0
/*!
 * \brief Generate an operation key
 *
 * \param[in] rsc_id       ID of resource being operated on
 * \param[in] op_type      Operation name
 * \param[in] interval_ms  Operation interval
 *
 * \return Newly allocated memory containing operation key as string
 *
 * \note It is the caller's responsibility to free() the result.
 */
char *
generate_op_key(const char *rsc_id, const char *op_type, guint interval_ms)
{
    CRM_ASSERT(rsc_id != NULL);
    CRM_ASSERT(op_type != NULL);
    return crm_strdup_printf(CRM_OP_FMT, rsc_id, op_type, interval_ms);
}
Beispiel #9
0
char *
crm_concat(const char *prefix, const char *suffix, char join)
{
    CRM_ASSERT(prefix != NULL);
    CRM_ASSERT(suffix != NULL);
    return crm_strdup_printf("%s%c%s", prefix, join, suffix);
}
Beispiel #10
0
/*!
 * \brief Generate an operation key
 *
 * \param[in] rsc_id    ID of resource being operated on
 * \param[in] op_type   Operation name
 * \param[in] interval  Operation interval
 *
 * \return Newly allocated memory containing operation key as string
 *
 * \note It is the caller's responsibility to free() the result.
 */
char *
generate_op_key(const char *rsc_id, const char *op_type, int interval)
{
    CRM_ASSERT(rsc_id != NULL);
    CRM_ASSERT(op_type != NULL);
    CRM_ASSERT(interval >= 0);
    return crm_strdup_printf("%s_%s_%d", rsc_id, op_type, interval);
}
Beispiel #11
0
/*!
 * \brief Create an XML attribute with specified name and unsigned value
 *
 * This is like \c crm_xml_add() but taking a guint value.
 *
 * \param[in,out] node   XML node to modify
 * \param[in]     name   Attribute name to set
 * \param[in]     ms     Attribute value to set
 *
 * \return New value as string on success, \c NULL otherwise
 * \note This does nothing if node or name are \c NULL or empty.
 */
const char *
crm_xml_add_ms(xmlNode *node, const char *name, guint ms)
{
    char *number = crm_strdup_printf("%u", ms);
    const char *added = crm_xml_add(node, name, number);

    free(number);
    return added;
}
election_t *
election_init(const char *name, const char *uname, guint period_ms, GSourceFunc cb)
{
    static guint count = 0;
    election_t *e = calloc(1, sizeof(election_t));

    if(e != NULL) {
        if(name) {
            e->name = crm_strdup_printf("election-%s", name);
        } else {
            e->name = crm_strdup_printf("election-%u", count++);
        }

        e->cb = cb;
        e->uname = strdup(uname);
        e->timeout = mainloop_timer_add(e->name, period_ms, FALSE, election_timer_cb, e);
        crm_trace("Created %s %p", e->name, e);
    }
    return e;
}
Beispiel #13
0
/*!
 * \internal
 * \brief Read and return sequence number stored in a file series' .last file
 *
 * \param[in] directory Directory that contains the file series
 * \param[in] series Start of file name
 *
 * \return The last sequence number, or 0 on error
 */
int
get_last_sequence(const char *directory, const char *series)
{
    FILE *file_strm = NULL;
    int start = 0, length = 0, read_len = 0;
    char *series_file = NULL;
    char *buffer = NULL;
    int seq = 0;

    CRM_CHECK(directory != NULL, return 0);
    CRM_CHECK(series != NULL, return 0);

    series_file = crm_strdup_printf("%s/%s.last", directory, series);
    file_strm = fopen(series_file, "r");
    if (file_strm == NULL) {
        crm_debug("Series file %s does not exist", series_file);
        free(series_file);
        return 0;
    }

    /* see how big the file is */
    start = ftell(file_strm);
    fseek(file_strm, 0L, SEEK_END);
    length = ftell(file_strm);
    fseek(file_strm, 0L, start);

    CRM_ASSERT(length >= 0);
    CRM_ASSERT(start == ftell(file_strm));

    if (length <= 0) {
        crm_info("%s was not valid", series_file);
        free(buffer);
        buffer = NULL;

    } else {
        crm_trace("Reading %d bytes from file", length);
        buffer = calloc(1, (length + 1));
        read_len = fread(buffer, 1, length, file_strm);
        if (read_len != length) {
            crm_err("Calculated and read bytes differ: %d vs. %d", length, read_len);
            free(buffer);
            buffer = NULL;
        }
    }

    seq = crm_parse_int(buffer, "0");
    fclose(file_strm);

    crm_trace("Found %d in %s", seq, series_file);

    free(series_file);
    free(buffer);
    return seq;
}
Beispiel #14
0
mainloop_timer_t *
mainloop_timer_add(const char *name, guint period_ms, bool repeat, GSourceFunc cb, void *userdata)
{
    mainloop_timer_t *t = calloc(1, sizeof(mainloop_timer_t));

    if(t) {
        if(name) {
            t->name = crm_strdup_printf("%s-%u-%d", name, period_ms, repeat);
        } else {
            t->name = crm_strdup_printf("%p-%u-%d", t, period_ms, repeat);
        }
        t->id = 0;
        t->period_ms = period_ms;
        t->repeat = repeat;
        t->cb = cb;
        t->userdata = userdata;
        crm_trace("Created timer %s with %p %p", t->name, userdata, t->userdata);
    }
    return t;
}
Beispiel #15
0
static void
force_local_option(xmlNode *xml, const char *attr_name, const char *attr_value)
{
    int max = 0;
    int lpc = 0;
    char *xpath_string = NULL;
    xmlXPathObjectPtr xpathObj = NULL;

    xpath_string = crm_strdup_printf("%.128s//%s//nvpair[@name='%.128s']",
                                     get_object_path(XML_CIB_TAG_CRMCONFIG),
                                     XML_CIB_TAG_PROPSET, attr_name);
    xpathObj = xpath_search(xml, xpath_string);
    max = numXpathResults(xpathObj);
    free(xpath_string);

    for (lpc = 0; lpc < max; lpc++) {
        xmlNode *match = getXpathResult(xpathObj, lpc);
        crm_trace("Forcing %s/%s = %s", ID(match), attr_name, attr_value);
        crm_xml_add(match, XML_NVPAIR_ATTR_VALUE, attr_value);
    }

    if(max == 0) {
        xmlNode *configuration = NULL;
        xmlNode *crm_config = NULL;
        xmlNode *cluster_property_set = NULL;

        crm_trace("Creating %s-%s for %s=%s",
                  CIB_OPTIONS_FIRST, attr_name, attr_name, attr_value);

        configuration = find_entity(xml, XML_CIB_TAG_CONFIGURATION, NULL);
        if (configuration == NULL) {
            configuration = create_xml_node(xml, XML_CIB_TAG_CONFIGURATION);
        }

        crm_config = find_entity(configuration, XML_CIB_TAG_CRMCONFIG, NULL);
        if (crm_config == NULL) {
            crm_config = create_xml_node(configuration, XML_CIB_TAG_CRMCONFIG);
        }

        cluster_property_set = find_entity(crm_config, XML_CIB_TAG_PROPSET, NULL);
        if (cluster_property_set == NULL) {
            cluster_property_set = create_xml_node(crm_config, XML_CIB_TAG_PROPSET);
            crm_xml_add(cluster_property_set, XML_ATTR_ID, CIB_OPTIONS_FIRST);
        }

        xml = create_xml_node(cluster_property_set, XML_CIB_TAG_NVPAIR);

        crm_xml_set_id(xml, "%s-%s", CIB_OPTIONS_FIRST, attr_name);
        crm_xml_add(xml, XML_NVPAIR_ATTR_NAME, attr_name);
        crm_xml_add(xml, XML_NVPAIR_ATTR_VALUE, attr_value);
    }
    freeXpathObject(xpathObj);
}
Beispiel #16
0
static char *
systemd_service_name(const char *name)
{
    if (name == NULL) {
        return NULL;

    } else if (strstr(name, ".service")) {
        return strdup(name);
    }

    return crm_strdup_printf("%s.service", name);
}
Beispiel #17
0
char *
get_corosync_uuid(crm_node_t *node)
{
    if (node && is_corosync_cluster()) {
        if (node->id > 0) {
            return crm_strdup_printf("%u", node->id);
        } else {
            crm_info("Node %s is not yet known by corosync", node->uname);
        }
    }
    return NULL;
}
Beispiel #18
0
static void
xml_end_list(pcmk__output_t *out) {
    char *buf = NULL;
    xml_private_t *priv = out->priv;
    xmlNodePtr node;

    CRM_ASSERT(priv != NULL);

    node = g_queue_pop_tail(priv->parent_q);
    buf = crm_strdup_printf("%lu", xmlChildElementCount(node));
    xmlSetProp(node, (pcmkXmlStr) "count", (pcmkXmlStr) buf);
    free(buf);
}
Beispiel #19
0
char *
crm_generate_ra_key(const char *standard, const char *provider,
                    const char *type)
{
    if (!standard && !provider && !type) {
        return NULL;
    }

    return crm_strdup_printf("%s%s%s:%s",
                             (standard? standard : ""),
                             (provider? ":" : ""), (provider? provider : ""),
                             (type? type : ""));
}
Beispiel #20
0
static char *
systemd_service_name(const char *name)
{
    if (name == NULL) {
        return NULL;
    }

    if (systemd_unit_extension(name)) {
        return strdup(name);
    }

    return crm_strdup_printf("%s.service", name);
}
Beispiel #21
0
static char *
systemd_unit_metadata(const char *name, int timeout)
{
    char *meta = NULL;
    char *desc = NULL;
    char *path = systemd_unit_by_name(name, NULL);

    if (path) {
        /* TODO: Worth a making blocking call for? Probably not. Possibly if cached. */
        desc = pcmk_dbus_get_property(systemd_proxy, BUS_NAME, path, BUS_NAME ".Unit", "Description", NULL, NULL, NULL, timeout);
    } else {
        desc = crm_strdup_printf("Systemd unit file for %s", name);
    }

    meta = crm_strdup_printf("<?xml version=\"1.0\"?>\n"
                           "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
                           "<resource-agent name=\"%s\" version=\"0.1\">\n"
                           "  <version>1.0</version>\n"
                           "  <longdesc lang=\"en\">\n"
                           "    %s\n"
                           "  </longdesc>\n"
                           "  <shortdesc lang=\"en\">systemd unit file for %s</shortdesc>\n"
                           "  <parameters>\n"
                           "  </parameters>\n"
                           "  <actions>\n"
                           "    <action name=\"start\"   timeout=\"15\" />\n"
                           "    <action name=\"stop\"    timeout=\"15\" />\n"
                           "    <action name=\"status\"  timeout=\"15\" />\n"
                           "    <action name=\"restart\"  timeout=\"15\" />\n"
                           "    <action name=\"monitor\" timeout=\"15\" interval=\"15\" start-delay=\"15\" />\n"
                           "    <action name=\"meta-data\"  timeout=\"5\" />\n"
                           "  </actions>\n"
                           "  <special tag=\"systemd\">\n"
                           "  </special>\n" "</resource-agent>\n", name, desc, name);
    free(desc);
    free(path);
    return meta;
}
Beispiel #22
0
pid_t
pcmk_locate_sbd(void)
{
    char *pidfile = NULL;
    char *sbd_path = NULL;

    if(sbd_pid > 1) {
        return sbd_pid;
    }

    /* Look for the pid file */
    pidfile = crm_strdup_printf("%s/sbd.pid", HA_STATE_DIR);
    sbd_path = crm_strdup_printf("%s/sbd", SBIN_DIR);

    /* Read the pid file */
    CRM_ASSERT(pidfile);

    sbd_pid = crm_pidfile_inuse(pidfile, 0, sbd_path);
    if(sbd_pid > 0) {
        crm_trace("SBD detected at pid=%d (file)", sbd_pid);

    } else {
        /* Fall back to /proc for systems that support it */
        sbd_pid = crm_procfs_pid_of("sbd");
        crm_trace("SBD detected at pid=%d (proc)", sbd_pid);
    }

    if(sbd_pid < 0) {
        sbd_pid = 0;
        crm_trace("SBD not detected");
    }

    free(pidfile);
    free(sbd_path);

    return sbd_pid;
}
Beispiel #23
0
/*!
 * \internal
 * \brief Change the owner and group of a file series' .last file
 *
 * \param[in] dir Directory that contains series
 * \param[in] uid Uid of desired file owner
 * \param[in] gid Gid of desired file group
 *
 * \return 0 on success, -1 on error (in which case errno will be set)
 * \note The caller must have the appropriate privileges.
 */
int
crm_chown_last_sequence(const char *directory, const char *series, uid_t uid, gid_t gid)
{
    char *series_file = NULL;
    int rc;

    CRM_CHECK((directory != NULL) && (series != NULL), errno = EINVAL; return -1);

    series_file = crm_strdup_printf("%s/%s.last", directory, series);
    CRM_CHECK(series_file != NULL, return -1);

    rc = chown(series_file, uid, gid);
    free(series_file);
    return rc;
}
Beispiel #24
0
/*!
 * \internal
 * \brief Wipe all transient attributes for this node from the CIB
 *
 * Clear any previous transient node attributes from the CIB. This is
 * normally done by the DC's controller when this node leaves the cluster, but
 * this handles the case where the node restarted so quickly that the
 * cluster layer didn't notice.
 *
 * \todo If pacemaker-attrd respawns after crashing (see PCMK_respawned),
 *       ideally we'd skip this and sync our attributes from the writer.
 *       However, currently we reject any values for us that the writer has, in
 *       attrd_peer_update().
 */
static void
attrd_erase_attrs()
{
    int call_id;
    char *xpath = crm_strdup_printf(XPATH_TRANSIENT, attrd_cluster->uname);

    crm_info("Clearing transient attributes from CIB " CRM_XS " xpath=%s",
             xpath);

    call_id = the_cib->cmds->remove(the_cib, xpath, NULL,
                                    cib_quorum_override | cib_xpath);
    the_cib->cmds->register_callback_full(the_cib, call_id, 120, FALSE, xpath,
                                          "attrd_erase_cb", attrd_erase_cb,
                                          free);
}
Beispiel #25
0
int
set_standby(cib_t * the_cib, const char *uuid, const char *scope, const char *standby_value)
{
    int rc = pcmk_ok;
    char *attr_id = NULL;

    CRM_CHECK(uuid != NULL, return -EINVAL);
    CRM_CHECK(standby_value != NULL, return -EINVAL);

    if (safe_str_eq(scope, "reboot") || safe_str_eq(scope, XML_CIB_TAG_STATUS)) {
        scope = XML_CIB_TAG_STATUS;
        attr_id = crm_strdup_printf("transient-standby-%.256s", uuid);

    } else {
        scope = XML_CIB_TAG_NODES;
        attr_id = crm_strdup_printf("standby-%.256s", uuid);
    }

    rc = update_attr_delegate(the_cib, cib_sync_call, scope, uuid, NULL, NULL,
                              attr_id, "standby", standby_value, TRUE, NULL, NULL);

    free(attr_id);
    return rc;
}
Beispiel #26
0
/*!
 * \internal
 * \brief Allocate and create a file path using a sequence number
 *
 * \param[in] directory Directory that contains the file series
 * \param[in] series Start of file name
 * \param[in] sequence Sequence number (MUST be less than 33 digits)
 * \param[in] bzip Whether to use ".bz2" instead of ".raw" as extension
 *
 * \return Newly allocated file path, or NULL on error
 * \note Caller is responsible for freeing the returned memory
 */
char *
generate_series_filename(const char *directory, const char *series, int sequence, gboolean bzip)
{
    const char *ext = "raw";

    CRM_CHECK(directory != NULL, return NULL);
    CRM_CHECK(series != NULL, return NULL);

#if !HAVE_BZLIB_H
    bzip = FALSE;
#endif

    if (bzip) {
        ext = "bz2";
    }
    return crm_strdup_printf("%s/%s-%d.%s", directory, series, sequence, ext);
}
/* Nodes can be specified two different ways in the CIB, so we have two different
 * functions to try clearing out any constraints on them:
 *
 * (1) The node could be given by attribute=/value= in an expression XML node.
 * That's what resource_clear_node_in_expr handles.  That XML looks like this:
 *
 * <rsc_location id="cli-prefer-dummy" rsc="dummy" role="Started">
 *   <rule id="cli-prefer-rule-dummy" score="INFINITY" boolean-op="and">
 *     <expression id="cli-prefer-expr-dummy" attribute="#uname" operation="eq" value="test02" type="string"/>
 *     <date_expression id="cli-prefer-lifetime-end-dummy" operation="lt" end="2018-12-12 14:05:37 -05:00"/>
 *   </rule>
 * </rsc_location>
 *
 * (2) The mode could be given by node= in an rsc_location XML node.  That's
 * what resource_clear_node_in_location handles.  That XML looks like this:
 *
 * <rsc_location id="cli-prefer-dummy" rsc="dummy" role="Started" node="node1" score="INFINITY"/>
 */
static int
resource_clear_node_in_expr(const char *rsc_id, const char *host, cib_t * cib_conn)
{
    int rc = pcmk_ok;
    char *xpath_string = NULL;

    xpath_string = crm_strdup_printf("//rsc_location[@id='cli-prefer-%s'][rule[@id='cli-prefer-rule-%s']/expression[@attribute='#uname' and @value='%s']]",
                                     rsc_id, rsc_id, host);

    rc = cib_conn->cmds->remove(cib_conn, xpath_string, NULL, cib_xpath | cib_options);
    if (rc == -ENXIO) {
        rc = pcmk_ok;
    }

    free(xpath_string);
    return rc;
}
Beispiel #28
0
/*!
 * \internal
 * \brief Save CIB query result to file, raising FSA error
 *
 * \param[in] msg        Ignored
 * \param[in] call_id    Call ID of CIB query
 * \param[in] rc         Return code of CIB query
 * \param[in] output     Result of CIB query
 * \param[in] user_data  Unique identifier for filename (will be freed)
 *
 * \note This is intended to be called after a scheduler connection fails.
 */
static void
save_cib_contents(xmlNode *msg, int call_id, int rc, xmlNode *output,
                  void *user_data)
{
    char *id = user_data;

    register_fsa_error_adv(C_FSA_INTERNAL, I_ERROR, NULL, NULL, __FUNCTION__);
    CRM_CHECK(id != NULL, return);

    if (rc == pcmk_ok) {
        char *filename = crm_strdup_printf(PE_STATE_DIR "/pe-core-%s.bz2", id);

        if (write_xml_file(output, filename, TRUE) < 0) {
            crm_err("Could not save Cluster Information Base to %s after scheduler crash",
                    filename);
        } else {
            crm_notice("Saved Cluster Information Base to %s after scheduler crash",
                       filename);
        }
        free(filename);
    }
}
Beispiel #29
0
/*!
 * \internal
 * \brief Write sequence number to a file series' .last file
 *
 * \param[in] directory Directory that contains the file series
 * \param[in] series Start of file name
 * \param[in] sequence Sequence number to write
 * \param[in] max Maximum sequence value, after which sequence is reset to 0
 *
 * \note This function logs some errors but does not return any to the caller
 */
void
write_last_sequence(const char *directory, const char *series, int sequence, int max)
{
    int rc = 0;
    FILE *file_strm = NULL;
    char *series_file = NULL;

    CRM_CHECK(directory != NULL, return);
    CRM_CHECK(series != NULL, return);

    if (max == 0) {
        return;
    }
    if (max > 0 && sequence >= max) {
        sequence = 0;
    }

    series_file = crm_strdup_printf("%s/%s.last", directory, series);
    file_strm = fopen(series_file, "w");
    if (file_strm != NULL) {
        rc = fprintf(file_strm, "%d", sequence);
        if (rc < 0) {
            crm_perror(LOG_ERR, "Cannot write to series file %s", series_file);
        }

    } else {
        crm_err("Cannot open series file %s for writing", series_file);
    }

    if (file_strm != NULL) {
        fflush(file_strm);
        fclose(file_strm);
    }

    crm_trace("Wrote %d to %s", sequence, series_file);
    free(series_file);
}
Beispiel #30
0
static char *
upstart_job_metadata(const char *name)
{
    return crm_strdup_printf("<?xml version=\"1.0\"?>\n"
                           "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
                           "<resource-agent name=\"%s\" version=\"0.1\">\n"
                           "  <version>1.0</version>\n"
                           "  <longdesc lang=\"en\">\n"
                           "    Upstart agent for controlling the system %s service\n"
                           "  </longdesc>\n"
                           "  <shortdesc lang=\"en\">%s upstart agent</shortdesc>\n"
                           "  <parameters>\n"
                           "  </parameters>\n"
                           "  <actions>\n"
                           "    <action name=\"start\"   timeout=\"15\" />\n"
                           "    <action name=\"stop\"    timeout=\"15\" />\n"
                           "    <action name=\"status\"  timeout=\"15\" />\n"
                           "    <action name=\"restart\"  timeout=\"15\" />\n"
                           "    <action name=\"monitor\" timeout=\"15\" interval=\"15\" start-delay=\"15\" />\n"
                           "    <action name=\"meta-data\"  timeout=\"5\" />\n"
                           "  </actions>\n"
                           "  <special tag=\"upstart\">\n"
                           "  </special>\n" "</resource-agent>\n", name, name, name);
}