summaryrefslogtreecommitdiffstats
path: root/src/service-dbus
diff options
context:
space:
mode:
authorVitezslav Crhonek <vcrhonek@redhat.com>2013-12-02 16:11:08 +0100
committerVitezslav Crhonek <vcrhonek@redhat.com>2013-12-02 16:11:08 +0100
commit8e995d10dcf6741960c2ea7633fcd2b5cc252870 (patch)
treefcc9f3341a08dc8e97fdfc6617086701e9b9fc1d /src/service-dbus
parentf47c906dc30690da4fb318107e1c53f53ba648d0 (diff)
downloadopenlmi-providers-8e995d10dcf6741960c2ea7633fcd2b5cc252870.tar.gz
openlmi-providers-8e995d10dcf6741960c2ea7633fcd2b5cc252870.tar.xz
openlmi-providers-8e995d10dcf6741960c2ea7633fcd2b5cc252870.zip
Service: Support indications on instance property modification.
Diffstat (limited to 'src/service-dbus')
-rw-r--r--src/service-dbus/CMakeLists.txt11
-rw-r--r--src/service-dbus/LMI_ServiceInstanceModificationIndicationProvider.c140
-rw-r--r--src/service-dbus/util/serviceutil.c193
-rw-r--r--src/service-dbus/util/serviceutil.h20
4 files changed, 361 insertions, 3 deletions
diff --git a/src/service-dbus/CMakeLists.txt b/src/service-dbus/CMakeLists.txt
index 3cc2082..4ba3231 100644
--- a/src/service-dbus/CMakeLists.txt
+++ b/src/service-dbus/CMakeLists.txt
@@ -23,8 +23,15 @@ add_library(${LIBRARY_NAME} SHARED
# Require libgio
pkg_check_modules(GIO REQUIRED gio-2.0)
-include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMPI_INCLUDE_DIR} ${GIO_INCLUDE_DIRS})
-target_link_libraries(${LIBRARY_NAME} openlmicommon ${KONKRETCMPI_LIBRARIES} ${GIO_LIBRARIES})
+include_directories(${CMAKE_CURRENT_BINARY_DIR}
+ ${CMPI_INCLUDE_DIR}
+ ${GIO_INCLUDE_DIRS}
+ ${CMAKE_SOURCE_DIR}/src/indmanager)
+target_link_libraries(${LIBRARY_NAME}
+ openlmicommon
+ openlmiindmanager
+ ${KONKRETCMPI_LIBRARIES}
+ ${GIO_LIBRARIES})
# Create registration file
cim_registration(${PROVIDER_NAME} ${LIBRARY_NAME} ${MOF} share/openlmi-providers)
diff --git a/src/service-dbus/LMI_ServiceInstanceModificationIndicationProvider.c b/src/service-dbus/LMI_ServiceInstanceModificationIndicationProvider.c
new file mode 100644
index 0000000..1b0edf4
--- /dev/null
+++ b/src/service-dbus/LMI_ServiceInstanceModificationIndicationProvider.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Vitezslav Crhonek <vcrhonek@redhat.com>
+*/
+
+#include <konkret/konkret.h>
+#include "LMI_ServiceInstanceModificationIndication.h"
+
+#include "ind_manager.h"
+#include "util/serviceutil.h"
+
+static const CMPIBroker* _cb = NULL;
+
+static const char* service_allowed_classes[] = {
+ LMI_Service_ClassName,
+ NULL};
+
+static IMManager *im = NULL;
+static IMError im_err = IM_ERR_OK;
+static ServiceIndication si;
+
+static void LMI_ServiceInstanceModificationIndicationInitialize()
+{
+ im = im_create_manager(NULL, NULL, true, ind_watcher,
+ IM_IND_MODIFICATION, _cb, &im_err);
+ im_register_filter_classes(im, &service_allowed_classes[0], &im_err);
+}
+
+static CMPIStatus LMI_ServiceInstanceModificationIndicationIndicationCleanup(
+ CMPIIndicationMI* mi,
+ const CMPIContext* cc,
+ CMPIBoolean term)
+{
+ if (!im_destroy_manager(im, cc, &im_err))
+ CMReturn(CMPI_RC_ERR_FAILED);
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_ServiceInstanceModificationIndicationAuthorizeFilter(
+ CMPIIndicationMI* mi,
+ const CMPIContext* cc,
+ const CMPISelectExp* se,
+ const char* ns,
+ const CMPIObjectPath* op,
+ const char* user)
+{
+ if (!im_verify_filter(im, se, cc, &im_err) )
+ CMReturn(CMPI_RC_ERR_INVALID_QUERY);
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_ServiceInstanceModificationIndicationMustPoll(
+ CMPIIndicationMI* mi,
+ const CMPIContext* cc,
+ const CMPISelectExp* se,
+ const char* ns,
+ const CMPIObjectPath* op)
+{
+ CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+}
+
+static CMPIStatus LMI_ServiceInstanceModificationIndicationActivateFilter(
+ CMPIIndicationMI* mi,
+ const CMPIContext* cc,
+ const CMPISelectExp* se,
+ const char* ns,
+ const CMPIObjectPath* op,
+ CMPIBoolean firstActivation)
+{
+ if (!im_verify_filter(im, se, cc, &im_err))
+ CMReturn(CMPI_RC_ERR_INVALID_QUERY);
+ if (!im_add_filter(im, (CMPISelectExp*)se, cc, &im_err))
+ CMReturn(CMPI_RC_ERR_FAILED);
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_ServiceInstanceModificationIndicationDeActivateFilter(
+ CMPIIndicationMI* mi,
+ const CMPIContext* cc,
+ const CMPISelectExp* se,
+ const char* ns,
+ const CMPIObjectPath* op,
+ CMPIBoolean lastActivation)
+{
+ if (!im_remove_filter(im, se, cc, &im_err))
+ CMReturn(CMPI_RC_ERR_FAILED);
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_ServiceInstanceModificationIndicationEnableIndications(
+ CMPIIndicationMI* mi,
+ const CMPIContext* cc)
+{
+ char output[1024];
+
+ if (ind_init(&si, output, sizeof(output)) != 0) {
+ lmi_debug("ind_init failed: %s", output);
+ CMReturn(CMPI_RC_ERR_FAILED);
+ }
+ if (!im_start_ind(im, cc, &im_err))
+ CMReturn(CMPI_RC_ERR_FAILED);
+ CMReturn(CMPI_RC_OK);
+}
+
+static CMPIStatus LMI_ServiceInstanceModificationIndicationDisableIndications(
+ CMPIIndicationMI* mi,
+ const CMPIContext* cc)
+{
+ if (!im_stop_ind(im, cc, &im_err))
+ CMReturn(CMPI_RC_ERR_FAILED);
+ ind_destroy(&si);
+ CMReturn(CMPI_RC_OK);
+}
+
+CMIndicationMIStub(
+ LMI_ServiceInstanceModificationIndication,
+ LMI_ServiceInstanceModificationIndication,
+ _cb,
+ LMI_ServiceInstanceModificationIndicationInitialize())
+
+KONKRET_REGISTRATION(
+ "root/cimv2",
+ "LMI_ServiceInstanceModificationIndication",
+ "LMI_ServiceInstanceModificationIndication",
+ "indication")
diff --git a/src/service-dbus/util/serviceutil.c b/src/service-dbus/util/serviceutil.c
index 50b18b9..eed0ad8 100644
--- a/src/service-dbus/util/serviceutil.c
+++ b/src/service-dbus/util/serviceutil.c
@@ -26,7 +26,6 @@
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
-#include <gio/gio.h>
#include "serviceutil.h"
@@ -346,3 +345,195 @@ unsigned int service_operation(
g_object_unref(manager_proxy);
return 0;
}
+
+/* Indications */
+
+pthread_mutex_t m;
+pthread_cond_t c;
+
+void *loop_thread(
+ void *arg)
+{
+ ServiceIndication *si = (ServiceIndication *) arg;
+
+ lmi_debug("loop_thread enter");
+
+ g_main_loop_run(si->loop);
+
+ lmi_debug("loop_thread exit");
+
+ return NULL;
+}
+
+static void on_signal(
+ GDBusProxy *proxy,
+ gchar *sender_name,
+ gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ lmi_debug("on_signal enter, object_path: %s", g_dbus_proxy_get_object_path(proxy));
+
+ pthread_mutex_lock(&m);
+ pthread_cond_signal(&c);
+ pthread_mutex_unlock(&m);
+
+ lmi_debug("on_signal exit");
+}
+
+int ind_init(ServiceIndication *si, char *output, int output_len)
+{
+ GVariant *result = NULL;
+ GError *error = NULL;
+ gchar *tmps = NULL;
+ int i = 0;
+
+ lmi_debug("ind_init enter");
+
+ si->context = g_main_context_new();
+ g_main_context_push_thread_default(si->context);
+
+ si->loop = NULL;
+
+ si->slist = service_find_all(output, output_len);
+ if (si->slist == NULL) {
+ g_main_context_unref(si->context);
+ return -1;
+ }
+
+ si->manager_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
+ NULL, MANAGER_NAME, MANAGER_OP, MANAGER_INTERFACE, NULL, &error);
+ if (!si->manager_proxy) {
+ strncpy(output, error->message, output_len);
+ g_error_free(error);
+ g_main_context_unref(si->context);
+ service_free_slist(si->slist);
+ return -1;
+ }
+
+ si->signal_proxy = malloc(si->slist->cnt * sizeof(GDBusProxy *));
+ if (!si->signal_proxy) {
+ strncpy(output, "Insufficient memory", output_len);
+ g_main_context_unref(si->context);
+ service_free_slist(si->slist);
+ return -1;
+ }
+
+ for (i = 0; i < si->slist->cnt; i++) {
+ result = g_dbus_proxy_call_sync(si->manager_proxy, "LoadUnit", g_variant_new("(s)", si->slist->name[i]),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) {
+ strncpy(output, error->message, output_len);
+ g_error_free(error);
+ ind_destroy(si);
+ return -1;
+ }
+ g_variant_get(result, "(&o)", &tmps);
+
+ error = NULL;
+ si->signal_proxy[i] = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
+ NULL, MANAGER_NAME, tmps, PROPERTY_INTERFACE, NULL, &error);
+ g_variant_unref(result);
+ if (si->signal_proxy[i] == NULL)
+ {
+ strncpy(output, error->message, output_len);
+ g_error_free(error);
+ ind_destroy(si);
+ return -1;
+ }
+ g_signal_connect(si->signal_proxy[i], "g-signal", G_CALLBACK(on_signal), NULL);
+ }
+
+ error = NULL;
+ g_dbus_proxy_call_sync(si->manager_proxy, "Subscribe", NULL,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) {
+ strncpy(output, error->message, output_len);
+ g_error_free(error);
+ ind_destroy(si);
+ return -1;
+ }
+
+ g_main_context_pop_thread_default(si->context);
+
+ si->loop = g_main_loop_new(si->context, FALSE);
+
+ if (pthread_create(&si->p, NULL, loop_thread, si) != 0) {
+ ind_destroy(si);
+ return -1;
+ }
+
+ if (pthread_mutex_init(&m, NULL) != 0) {
+ strncpy(output, "pthread_mutex_init error", output_len);
+ return -1;
+ }
+ if (pthread_cond_init(&c, NULL) != 0) {
+ strncpy(output, "pthread_cond_init error", output_len);
+ return -1;
+ }
+
+ lmi_debug("ind_init exit");
+
+ return 0;
+}
+
+bool ind_watcher(
+ void **data)
+{
+ lmi_debug("ind_watcher enter");
+
+ pthread_mutex_lock(&m);
+ pthread_cond_wait(&c, &m);
+ pthread_mutex_unlock(&m);
+
+ lmi_debug("ind_watcher exit");
+
+ return true;
+}
+
+void ind_destroy(ServiceIndication *si)
+{
+ int i;
+ GError *error = NULL;
+
+ lmi_debug("ind_destroy enter");
+
+ if (si->loop) {
+ g_main_loop_quit(si->loop);
+ if (pthread_join(si->p, NULL) != 0) {
+ lmi_debug("pthread_join error");
+ }
+ g_main_loop_unref(si->loop);
+ }
+
+ if (pthread_cond_destroy(&c) != 0) {
+ lmi_debug("pthread_cond_destroy error");
+ }
+ if (pthread_mutex_destroy(&m) != 0) {
+ lmi_debug("pthread_mutex_destroy error");
+ }
+
+ g_main_context_unref(si->context);
+
+ for (i = 0; i < si->slist->cnt; i++) {
+ if (si->signal_proxy[i]) {
+ g_object_unref(si->signal_proxy[i]);
+ }
+ }
+ free(si->signal_proxy);
+
+ g_dbus_proxy_call_sync(si->manager_proxy, "Unsubscribe", NULL,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) {
+ lmi_debug("Unsubscribe error: %s", error->message);
+ g_error_free(error);
+ }
+
+ g_object_unref(si->manager_proxy);
+
+ service_free_slist(si->slist);
+
+ lmi_debug("ind_destroy exit");
+
+ return;
+}
diff --git a/src/service-dbus/util/serviceutil.h b/src/service-dbus/util/serviceutil.h
index fbdadad..9bb565c 100644
--- a/src/service-dbus/util/serviceutil.h
+++ b/src/service-dbus/util/serviceutil.h
@@ -23,7 +23,10 @@
#define SERVICEUTIL_H
#include <stdio.h>
+#include <gio/gio.h>
+#include <pthread.h>
#include "openlmi.h"
+#include "LMI_Service.h"
#define ARRAY_SIZE(name) (sizeof(name) / sizeof(name[0]))
@@ -62,4 +65,21 @@ int service_get_properties(Service *svc, const char *service, char *output, int
unsigned int service_operation(const char *service, const char *method, char *output, int output_len);
+/* Indications */
+
+struct _ServiceIndication {
+ SList *slist;
+ GDBusProxy *manager_proxy;
+ GDBusProxy **signal_proxy;
+ GMainContext *context;
+ GMainLoop *loop;
+ pthread_t p;
+};
+
+typedef struct _ServiceIndication ServiceIndication;
+
+int ind_init(ServiceIndication *si, char *output, int output_len);
+bool ind_watcher(void **data);
+void ind_destroy(ServiceIndication *si);
+
#endif