From 2d5dc6512e10924ab68e6a139081d7121bc3f7d6 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Mon, 22 Feb 2016 09:42:03 -0600 Subject: [PATCH] dbus: add notification from commands When a command modifies a PV or VG, or changes the activation state of an LV, it will send a dbus notification when the command is finished. This can be enabled/disabled with a config setting. --- WHATS_NEW | 1 + configure.in | 23 ++++++++ include/.symlinks.in | 1 + lib/Makefile.in | 2 + lib/commands/toolcontext.c | 2 + lib/commands/toolcontext.h | 3 + lib/config/config_settings.h | 7 ++- lib/config/defaults.h | 1 + lib/log/log.h | 2 + lib/metadata/metadata.c | 5 ++ lib/notify/lvmnotify.c | 109 +++++++++++++++++++++++++++++++++++ lib/notify/lvmnotify.h | 20 +++++++ tools/lvmcmdline.c | 3 + tools/pvchange.c | 2 + tools/pvresize.c | 2 + tools/toollib.c | 4 ++ tools/tools.h | 1 + 17 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 lib/notify/lvmnotify.c create mode 100644 lib/notify/lvmnotify.h diff --git a/WHATS_NEW b/WHATS_NEW index f29250e76..e2e946295 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.146 - ================================= + Add dbus notification from commands after a PV/VG/LV changes state. Version 2.02.145 - 4th March 2016 ================================= diff --git a/configure.in b/configure.in index e8723f4da..33cd0fece 100644 --- a/configure.in +++ b/configure.in @@ -1268,6 +1268,28 @@ fi AC_DEFINE_UNQUOTED(DEFAULT_USE_LVMPOLLD, [$DEFAULT_USE_LVMPOLLD], [Use lvmpolld by default.]) +################################################################################ +dnl -- Build notifydbus +AC_MSG_CHECKING(whether to build notifydbus) +AC_ARG_ENABLE(notify-dbus, + AC_HELP_STRING([--enable-notify-dbus], + [enable LVM notification using dbus]), + NOTIFYDBUS=$enableval) +AC_MSG_RESULT($NOTIFYDBUS) + +BUILD_NOTIFYDBUS=$NOTIFYDBUS + +if test "$BUILD_NOTIFYDBUS" = yes; then + AC_DEFINE([NOTIFYDBUS_SUPPORT], 1, [Define to 1 to include code that uses dbus notification.]) + LIBS="-lsystemd $LIBS" +fi + +################################################################################ +dnl -- Look for dbus libraries +if test "$BUILD_NOTIFYDBUS" = yes; then + PKG_CHECK_MODULES(NOTIFY_DBUS, systemd >= 221, [HAVE_NOTIFY_DBUS=yes], $bailout) +fi + ################################################################################ dnl -- Enable blkid wiping functionality @@ -1965,6 +1987,7 @@ AC_SUBST(BUILD_LVMPOLLD) AC_SUBST(BUILD_LVMLOCKD) AC_SUBST(BUILD_LOCKDSANLOCK) AC_SUBST(BUILD_LOCKDDLM) +AC_SUBST(BUILD_NOTIFYDBUS) AC_SUBST(CACHE) AC_SUBST(CFLAGS) AC_SUBST(CFLOW_CMD) diff --git a/include/.symlinks.in b/include/.symlinks.in index 98d680483..d1cc8268f 100644 --- a/include/.symlinks.in +++ b/include/.symlinks.in @@ -58,6 +58,7 @@ @top_srcdir@/lib/misc/util.h @top_srcdir@/lib/mm/memlock.h @top_srcdir@/lib/mm/xlate.h +@top_srcdir@/lib/notify/lvmnotify.h @top_srcdir@/lib/properties/prop_common.h @top_srcdir@/lib/report/properties.h @top_srcdir@/lib/report/report.h diff --git a/lib/Makefile.in b/lib/Makefile.in index ece9b1068..467ef9077 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -116,6 +116,7 @@ SOURCES =\ misc/lvm-wrappers.c \ misc/lvm-percent.c \ mm/memlock.c \ + notify/lvmnotify.c \ properties/prop_common.c \ report/properties.c \ report/report.c \ @@ -215,6 +216,7 @@ ifeq ($(MAKECMDGOALS),distclean) format_pool \ snapshot \ mirror \ + notify \ raid \ replicator \ thin \ diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index 7f6eee447..08e857c2f 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -278,6 +278,8 @@ static int _parse_debug_classes(struct cmd_context *cmd) debug_classes |= LOG_CLASS_LOCKING; else if (!strcasecmp(cv->v.str, "lvmpolld")) debug_classes |= LOG_CLASS_LVMPOLLD; + else if (!strcasecmp(cv->v.str, "dbus")) + debug_classes |= LOG_CLASS_DBUS; else log_verbose("Unrecognised value for log/debug_classes: %s", cv->v.str); } diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h index 6a6267d1d..c3b9b2ea5 100644 --- a/lib/commands/toolcontext.h +++ b/lib/commands/toolcontext.h @@ -141,6 +141,9 @@ struct cmd_context { unsigned lockd_vg_rescan:1; unsigned lockd_vg_default_sh:1; unsigned lockd_vg_enforce_sh:1; + unsigned vg_notify:1; + unsigned lv_notify:1; + unsigned pv_notify:1; /* * Filtering. diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h index 12911091c..d58b7a4aa 100644 --- a/lib/config/config_settings.h +++ b/lib/config/config_settings.h @@ -581,7 +581,7 @@ cfg(log_activation_CFG, "activation", log_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn( cfg(log_activate_file_CFG, "activate_file", log_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_UNSUPPORTED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL, NULL) -cfg_array(log_debug_classes_CFG, "debug_classes", log_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#Smemory#Sdevices#Sactivation#Sallocation#Slvmetad#Smetadata#Scache#Slocking#Slvmpolld", vsn(2, 2, 99), NULL, 0, NULL, +cfg_array(log_debug_classes_CFG, "debug_classes", log_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#Smemory#Sdevices#Sactivation#Sallocation#Slvmetad#Smetadata#Scache#Slocking#Slvmpolld#Sdbus", vsn(2, 2, 99), NULL, 0, NULL, "Select log messages by class.\n" "Some debugging messages are assigned to a class and only appear in\n" "debug output if the class is listed here. Classes currently\n" @@ -995,6 +995,11 @@ cfg(global_use_lvmpolld_CFG, "use_lvmpolld", global_CFG_SECTION, 0, CFG_TYPE_BOO "and to use its own control group. When this option is disabled, LVM\n" "commands will supervise long running operations by forking themselves.\n") +cfg(global_notify_dbus_CFG, "notify_dbus", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_NOTIFY_DBUS, vsn(2, 2, 145), NULL, 0, NULL, + "Enable D-Bus notification from LVM commands.\n" + "When enabled, an LVM command that changes PVs, changes VG metadata,\n" + "or changes the activation state of an LV will send a notification.\n") + cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_UDEV_SYNC, vsn(2, 2, 51), NULL, 0, NULL, "Use udev notifications to synchronize udev and LVM.\n" "The --nodevsync option overrides this setting.\n" diff --git a/lib/config/defaults.h b/lib/config/defaults.h index fd7986c35..51fd01d5b 100644 --- a/lib/config/defaults.h +++ b/lib/config/defaults.h @@ -138,6 +138,7 @@ #define DEFAULT_READ_AHEAD "auto" #define DEFAULT_UDEV_RULES 1 #define DEFAULT_UDEV_SYNC 1 +#define DEFAULT_NOTIFY_DBUS 1 #define DEFAULT_VERIFY_UDEV_OPERATIONS 0 #define DEFAULT_RETRY_DEACTIVATION 1 #define DEFAULT_ACTIVATION_CHECKS 0 diff --git a/lib/log/log.h b/lib/log/log.h index b7ba044fa..222a1adba 100644 --- a/lib/log/log.h +++ b/lib/log/log.h @@ -66,6 +66,7 @@ #define LOG_CLASS_CACHE 0x0040 /* "cache" */ #define LOG_CLASS_LOCKING 0x0080 /* "locking" */ #define LOG_CLASS_LVMPOLLD 0x0100 /* "lvmpolld" */ +#define LOG_CLASS_DBUS 0x0200 /* "dbus" */ #define log_debug(x...) LOG_LINE(_LOG_DEBUG, x) #define log_debug_mem(x...) LOG_LINE_WITH_CLASS(_LOG_DEBUG, LOG_CLASS_MEM, x) @@ -77,6 +78,7 @@ #define log_debug_cache(x...) LOG_LINE_WITH_CLASS(_LOG_DEBUG, LOG_CLASS_CACHE, x) #define log_debug_locking(x...) LOG_LINE_WITH_CLASS(_LOG_DEBUG, LOG_CLASS_LOCKING, x) #define log_debug_lvmpolld(x...) LOG_LINE_WITH_CLASS(_LOG_DEBUG, LOG_CLASS_LVMPOLLD, x) +#define log_debug_dbus(x...) LOG_LINE_WITH_CLASS(_LOG_DEBUG, LOG_CLASS_DBUS, x) #define log_info(x...) LOG_LINE(_LOG_INFO, x) #define log_notice(x...) LOG_LINE(_LOG_NOTICE, x) diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 9700e7324..1330cc019 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -33,6 +33,7 @@ #include "defaults.h" #include "lvmlockd.h" #include "time.h" +#include "lvmnotify.h" #include #include @@ -604,6 +605,8 @@ int vg_remove_direct(struct volume_group *vg) lockd_vg_update(vg); + set_vg_notify(vg->cmd); + if (!backup_remove(vg->cmd, vg->name)) stack; @@ -3591,6 +3594,8 @@ int vg_commit(struct volume_group *vg) cache_updated = _vg_commit_mdas(vg); + set_vg_notify(vg->cmd); + if (cache_updated) { /* Instruct remote nodes to upgrade cached metadata. */ if (!remote_commit_cached_metadata(vg)) diff --git a/lib/notify/lvmnotify.c b/lib/notify/lvmnotify.c new file mode 100644 index 000000000..0b04ee4ba --- /dev/null +++ b/lib/notify/lvmnotify.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * This file is part of LVM2. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License v.2.1. + */ + +#include "lib.h" +#include "toolcontext.h" +#include "metadata.h" +#include "lvmnotify.h" + +#define LVM_DBUS_DESTINATION "com.redhat.lvmdbus1" +#define LVM_DBUS_PATH "/com/redhat/lvmdbus1/Manager" +#define LVM_DBUS_INTERFACE "com.redhat.lvmdbus1.Manager" + +#ifdef NOTIFYDBUS_SUPPORT +#include + +void lvmnotify_send(struct cmd_context *cmd) +{ + sd_bus *bus = NULL; + sd_bus_message *m = NULL; + sd_bus_error error = SD_BUS_ERROR_NULL; + const char *cmd_name; + int ret; + int result = 0; + + if (!cmd->vg_notify && !cmd->lv_notify && !cmd->pv_notify) + return; + + cmd->vg_notify = 0; + cmd->lv_notify = 0; + cmd->pv_notify = 0; + + cmd_name = get_cmd_name(); + + ret = sd_bus_open_system(&bus); + if (ret < 0) { + log_debug_dbus("Failed to connect to dbus: %d", ret); + return; + } + + log_debug_dbus("Nofify dbus at %s.", LVM_DBUS_DESTINATION); + + ret = sd_bus_call_method(bus, + LVM_DBUS_DESTINATION, + LVM_DBUS_PATH, + LVM_DBUS_INTERFACE, + "ExternalEvent", + &error, + &m, + "s", + cmd_name); + + if (ret < 0) { + log_warn("WARNING: D-Bus notification failed: %s", error.message); + goto out; + } + + ret = sd_bus_message_read(m, "i", &result); + if (ret < 0) + log_debug_dbus("Failed to parse dbus response message: %d", ret); + if (result) + log_debug_dbus("Bad return value from dbus service: %d", result); +out: + sd_bus_error_free(&error); + sd_bus_message_unref(m); + sd_bus_unref(bus); +} + +void set_vg_notify(struct cmd_context *cmd) +{ + cmd->vg_notify = 1; +} + +void set_lv_notify(struct cmd_context *cmd) +{ + cmd->lv_notify = 1; +} + +void set_pv_notify(struct cmd_context *cmd) +{ + cmd->pv_notify = 1; +} + +#else + +void lvmnotify_send(struct cmd_context *cmd) +{ +} + +void set_vg_notify(struct cmd_context *cmd) +{ +} + +void set_lv_notify(struct cmd_context *cmd) +{ +} + +void set_pv_notify(struct cmd_context *cmd) +{ +} + +#endif + diff --git a/lib/notify/lvmnotify.h b/lib/notify/lvmnotify.h new file mode 100644 index 000000000..43fffd0da --- /dev/null +++ b/lib/notify/lvmnotify.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * This file is part of LVM2. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License v.2.1. + */ + +#ifndef _LVMNOTIFY_H +#define _LVMNOTIFY_H + +void lvmnotify_send(struct cmd_context *cmd); +void set_vg_notify(struct cmd_context *cmd); +void set_lv_notify(struct cmd_context *cmd); +void set_pv_notify(struct cmd_context *cmd); + +#endif + diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index 72570f7df..2ee54e8ff 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -1660,6 +1660,9 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) lvmlockd_disconnect(); fin_locking(); + if (!_cmd_no_meta_proc(cmd) && find_config_tree_bool(cmd, global_notify_dbus_CFG, NULL)) + lvmnotify_send(cmd); + out: if (test_mode()) { log_verbose("Test mode: Wiping internal cache"); diff --git a/tools/pvchange.c b/tools/pvchange.c index 86c4ac4f0..5f9901687 100644 --- a/tools/pvchange.c +++ b/tools/pvchange.c @@ -228,6 +228,8 @@ int pvchange(struct cmd_context *cmd, int argc, char **argv) } } + set_pv_notify(cmd); + ret = process_each_pv(cmd, argc, argv, NULL, 0, READ_FOR_UPDATE, handle, _pvchange_single); if (!argc) diff --git a/tools/pvresize.c b/tools/pvresize.c index b79098ca9..13122907e 100644 --- a/tools/pvresize.c +++ b/tools/pvresize.c @@ -79,6 +79,8 @@ int pvresize(struct cmd_context *cmd, int argc, char **argv) params.done = 0; params.total = 0; + set_pv_notify(cmd); + if (!(handle = init_processing_handle(cmd))) { log_error("Failed to initialize processing handle."); ret = ECMD_FAILED; diff --git a/tools/toollib.c b/tools/toollib.c index 9e866d6f4..14aca1503 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -1069,6 +1069,8 @@ int lv_change_activate(struct cmd_context *cmd, struct logical_volume *lv, if (!lv_active_change(cmd, lv, activate, 0)) return_0; + set_lv_notify(lv->vg->cmd); + return r; } @@ -4179,6 +4181,8 @@ int pvcreate_each_device(struct cmd_context *cmd, int found; int i; + set_pv_notify(cmd); + dm_list_init(&arg_sort); handle->custom_handle = pp; diff --git a/tools/tools.h b/tools/tools.h index 5875376ba..3762e8eed 100644 --- a/tools/tools.h +++ b/tools/tools.h @@ -42,6 +42,7 @@ #include "str_list.h" #include "toolcontext.h" #include "toollib.h" +#include "lvmnotify.h" #include #include