Ejemplo n.º 1
0
/*!
 * \internal
 * \brief Send a method to systemd without arguments, and wait for reply
 *
 * \param[in] method  Method to send
 *
 * \return Systemd reply on success, NULL (and error will be logged) otherwise
 *
 * \note The caller must call dbus_message_unref() on the reply after
 *       handling it.
 */
static DBusMessage *
systemd_call_simple_method(const char *method)
{
    DBusMessage *msg = systemd_new_method(method);
    DBusMessage *reply = NULL;
    DBusError error;

    /* Don't call systemd_init() here, because that calls this */
    CRM_CHECK(systemd_proxy, return NULL);

    if (msg == NULL) {
        crm_err("Could not create message to send %s to systemd", method);
        return NULL;
    }

    dbus_error_init(&error);
    reply = systemd_send_recv(msg, &error, DBUS_TIMEOUT_USE_DEFAULT);
    dbus_message_unref(msg);

    if (dbus_error_is_set(&error)) {
        crm_err("Could not send %s to systemd: %s (%s)",
                method, error.message, error.name);
        dbus_error_free(&error);
        return NULL;

    } else if (reply == NULL) {
        crm_err("Could not send %s to systemd: no reply received", method);
        return NULL;
    }

    return reply;
}
Ejemplo n.º 2
0
static char *
systemd_unit_by_name(const gchar * arg_name, svc_action_t *op)
{
    DBusMessage *msg;
    DBusMessage *reply = NULL;
    DBusPendingCall* pending = NULL;
    char *name = NULL;

/*
  Equivalent to GetUnit if its already loaded
  <method name="LoadUnit">
   <arg name="name" type="s" direction="in"/>
   <arg name="unit" type="o" direction="out"/>
  </method>
 */

    if (systemd_init() == FALSE) {
        return FALSE;
    }

    msg = systemd_new_method(BUS_NAME".Manager", "LoadUnit");
    CRM_ASSERT(msg != NULL);

    name = systemd_service_name(arg_name);
    CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID));
    free(name);

    if(op == NULL || op->synchronous) {
        const char *unit = NULL;
        char *munit = NULL;
        DBusError error;

        dbus_error_init(&error);
        reply = pcmk_dbus_send_recv(msg, systemd_proxy, &error, op? op->timeout : DBUS_TIMEOUT_USE_DEFAULT);
        dbus_message_unref(msg);

        unit = systemd_loadunit_result(reply, op);
        if(unit) {
            munit = strdup(unit);
        }
        if(reply) {
            dbus_message_unref(reply);
        }
        return munit;
    }

    pending = pcmk_dbus_send(msg, systemd_proxy, systemd_loadunit_cb, op, op->timeout);
    if(pending) {
        services_set_op_pending(op, pending);
    }

    dbus_message_unref(msg);
    return NULL;
}
Ejemplo n.º 3
0
static bool
systemd_daemon_reload(int timeout)
{
    static unsigned int reload_count = 0;
    DBusMessage *msg = systemd_new_method("Reload");

    reload_count++;
    CRM_ASSERT(msg != NULL);
    systemd_send(msg, systemd_daemon_reload_complete,
                 GUINT_TO_POINTER(reload_count), timeout);
    dbus_message_unref(msg);

    return TRUE;
}
Ejemplo n.º 4
0
static bool
systemd_daemon_reload(void)
{
    /* TODO: Make this asynchronous */
    const char *method = "Reload";
    DBusMessage *reply = NULL;
    DBusMessage *msg = systemd_new_method(BUS_NAME".Manager", method);

    CRM_ASSERT(msg != NULL);
    reply = pcmk_dbus_send_recv(msg, systemd_proxy, NULL);
    dbus_message_unref(msg);
    if(reply) {
        dbus_message_unref(reply);
    }
    return TRUE;
}
Ejemplo n.º 5
0
static bool
systemd_daemon_reload(int timeout)
{
    static unsigned int reload_count = 0;
    const char *method = "Reload";


    reload_count++;
    if(reload_count % 10 == 0) {
        DBusMessage *msg = systemd_new_method(BUS_NAME".Manager", method);

        CRM_ASSERT(msg != NULL);
        pcmk_dbus_send(msg, systemd_proxy, systemd_daemon_reload_complete, GUINT_TO_POINTER(reload_count), timeout);
        dbus_message_unref(msg);
    }
    return TRUE;
}
Ejemplo n.º 6
0
GList *
systemd_unit_listall(void)
{
    int lpc = 0;
    GList *units = NULL;
    DBusMessageIter args;
    DBusMessageIter unit;
    DBusMessageIter elem;
    DBusMessage *msg = NULL;
    DBusMessage *reply = NULL;
    const char *method = "ListUnits";
    DBusError error;

    if (systemd_init() == FALSE) {
        return NULL;
    }

/*
        "  <method name=\"ListUnits\">\n"                               \
        "   <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
        "  </method>\n"                                                 \
*/

    dbus_error_init(&error);
    msg = systemd_new_method(BUS_NAME".Manager", method);
    CRM_ASSERT(msg != NULL);

    reply = pcmk_dbus_send_recv(msg, systemd_proxy, &error, DBUS_TIMEOUT_USE_DEFAULT);
    dbus_message_unref(msg);

    if(error.name) {
        crm_err("Call to %s failed: %s", method, error.name);
        return NULL;

    } else if (reply == NULL) {
        crm_err("Call to %s failed: Message has no reply", method);
        return NULL;

    } else if (!dbus_message_iter_init(reply, &args)) {
        crm_err("Call to %s failed: Message has no arguments", method);
        dbus_message_unref(reply);
        return NULL;
    }

    if(!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_ARRAY, __FUNCTION__, __LINE__)) {
        crm_err("Call to %s failed: Message has invalid arguments", method);
        dbus_message_unref(reply);
        return NULL;
    }

    dbus_message_iter_recurse(&args, &unit);
    while (dbus_message_iter_get_arg_type (&unit) != DBUS_TYPE_INVALID) {
        DBusBasicValue value;

        if(!pcmk_dbus_type_check(reply, &unit, DBUS_TYPE_STRUCT, __FUNCTION__, __LINE__)) {
            continue;
        }

        dbus_message_iter_recurse(&unit, &elem);
        if(!pcmk_dbus_type_check(reply, &elem, DBUS_TYPE_STRING, __FUNCTION__, __LINE__)) {
            continue;
        }

        dbus_message_iter_get_basic(&elem, &value);
        crm_trace("Got: %s", value.str);
        if(value.str) {
            char *match = strstr(value.str, ".service");

            if (match) {
                lpc++;
                match[0] = 0;

                units = g_list_append(units, strdup(value.str));
            }
        }
        dbus_message_iter_next (&unit);
    }

    dbus_message_unref(reply);

    crm_trace("Found %d systemd services", lpc);
    return units;
}
Ejemplo n.º 7
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 (unit == NULL) {
        crm_debug("Could not obtain unit named '%s'", op->agent);
        op->rc = PCMK_OCF_NOT_INSTALLED;
        op->status = PCMK_LRM_OP_NOT_INSTALLED;
        goto cleanup;
    }

    if (safe_str_eq(op->action, "monitor") || safe_str_eq(method, "status")) {
        char *state = pcmk_dbus_get_property(systemd_proxy, BUS_NAME, unit, BUS_NAME ".Unit", "ActiveState",
                                             op->synchronous?NULL:systemd_unit_check, op);
        if (op->synchronous) {
            systemd_unit_check("ActiveState", state, op);
            free(state);
            return op->rc == PCMK_OCF_OK;
        }
        return TRUE;

    } else if (g_strcmp0(method, "start") == 0) {
        FILE *file_strm = NULL;
        char *override_dir = g_strdup_printf("%s/%s", SYSTEMD_OVERRIDE_ROOT, unit);
        char *override_file = g_strdup_printf("%s/%s/50-pacemaker.conf", SYSTEMD_OVERRIDE_ROOT, unit);

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

        file_strm = fopen(override_file, "w");
        if (file_strm != NULL) {
            int rc = fprintf(file_strm, "[Service]\nRestart=no");
            if (rc < 0) {
                crm_perror(LOG_ERR, "Cannot write to systemd override file %s", override_file);
            }

        } else {
            crm_err("Cannot open systemd override file %s for writing", override_file);
        }

        if (file_strm != NULL) {
            fflush(file_strm);
            fclose(file_strm);
        }
        systemd_daemon_reload();
        free(override_file);
        free(override_dir);

    } else if (g_strcmp0(method, "stop") == 0) {
        char *override_file = g_strdup_printf("%s/%s/50-pacemaker.conf", SYSTEMD_OVERRIDE_ROOT, unit);

        method = "StopUnit";
        unlink(override_file);
        free(override_file);
        systemd_daemon_reload();

    } else if (g_strcmp0(method, "restart") == 0) {
        method = "RestartUnit";

    } else {
        op->rc = PCMK_OCF_UNIMPLEMENT_FEATURE;
        goto cleanup;
    }

    crm_debug("Calling %s for %s: %s", method, op->rsc, unit);

    msg = systemd_new_method(BUS_NAME".Manager", method);
    CRM_ASSERT(msg != NULL);

    /* (ss) */
    {
        const char *replace_s = "replace";
        char *name = systemd_service_name(op->agent);

        CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID));
        CRM_LOG_ASSERT(dbus_message_append_args(msg, DBUS_TYPE_STRING, &replace_s, DBUS_TYPE_INVALID));

        free(name);
    }

    if (op->synchronous == FALSE) {
        return pcmk_dbus_send(msg, systemd_proxy, systemd_async_dispatch, op);

    } else {
        DBusError error;

        reply = pcmk_dbus_send_recv(msg, systemd_proxy, &error);
        systemd_exec_result(reply, op);
        if(reply) {
            dbus_message_unref(reply);
        }
    }

    if(msg) {
        dbus_message_unref(msg);
    }

  cleanup:
    if (op->synchronous == FALSE) {
        operation_finalize(op);
        return TRUE;
    }

    return op->rc == PCMK_OCF_OK;
}