[libvirt] [PATCH REPOST 0/4] Couple of random and crypto adjustments
by John Ferlan
Originally posted :
http://www.redhat.com/archives/libvir-list/2016-May/msg01650.html
Updated to current head and reposted.
John Ferlan (4):
util: Add range parameters to virRandomBytes
storage: Use virRandomBytes for virStorageGenerateQcowPassphrase
util: Alter virCryptoEncryptData for non GNUTLS builds
util: Adjust virCryptoEncryptData code to use macros
src/storage/storage_backend.c | 10 +++--
src/util/vircrypto.c | 88 +++++++++++++++++++++++++----------------
src/util/virrandom.c | 13 ++++--
src/util/virrandom.h | 3 +-
src/util/virstorageencryption.c | 42 +++++++-------------
src/util/virstorageencryption.h | 4 +-
src/util/viruuid.c | 2 +-
tests/qemuxml2argvmock.c | 2 +-
tests/vircryptotest.c | 4 +-
tests/virrandommock.c | 10 +++--
tests/virrandomtest.c | 32 +++++++++++----
11 files changed, 124 insertions(+), 86 deletions(-)
--
2.5.5
8 years, 4 months
[libvirt] [PATCH v2 0/3] Adjust qemu-img switches and checks
by John Ferlan
v1:http://www.redhat.com/archives/libvir-list/2016-June/msg00081.html
(patches 4, 6, and 7)
Patch 4 is now patch 1
Patch 6 was reviewed, but this patch alters it not need backingType
Patch 7 reworked to accommodate patch 1 changes
John Ferlan (3):
storage: Adjust qemu-img switches check
storage: Create helper to set backing for CreateQemuImg code
storage: Create helper to set options for CreateQemuImg code
src/storage/storage_backend.c | 223 ++++++++++-----------
tests/storagevolxml2argvdata/qcow2-flag.argv | 2 -
.../qcow2-nobacking-convert-flag.argv | 2 -
.../qcow2-nobacking-convert-none.argv | 2 -
.../qcow2-nobacking-flag.argv | 1 -
.../qcow2-nobacking-none.argv | 1 -
tests/storagevolxml2argvdata/qcow2-none.argv | 1 -
tests/storagevolxml2argvtest.c | 22 +-
8 files changed, 107 insertions(+), 147 deletions(-)
delete mode 100644 tests/storagevolxml2argvdata/qcow2-flag.argv
delete mode 100644 tests/storagevolxml2argvdata/qcow2-nobacking-convert-flag.argv
delete mode 100644 tests/storagevolxml2argvdata/qcow2-nobacking-convert-none.argv
delete mode 100644 tests/storagevolxml2argvdata/qcow2-nobacking-flag.argv
delete mode 100644 tests/storagevolxml2argvdata/qcow2-nobacking-none.argv
delete mode 100644 tests/storagevolxml2argvdata/qcow2-none.argv
--
2.5.5
8 years, 4 months
[libvirt] [PATCH v2 00/10] Add domain config validation infrastructure
by Peter Krempa
Similarly to post parse callbacks let's add infrastructure that will allow us
to introduce checks that will reject configrations that were previously valid.
This is achieved by flagging all the entry points to the config parser that need
to ignore invadid configurations and adding a callback infrastructure for
driver specific checks.
Peter Krempa (10):
conf: Rename VIR_DOMAIN_DEF_PARSE_VALIDATE to
VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA
conf: Add infrastructure for adding configuration validation
conf: drop 'def' from struct virDomainDefPostParseDeviceIteratorData
conf: Add device def validation callback
qemu: process: Unexport qemuProcessStartValidate
qemu: process: Convert multiple boolean args to a single flag
qemu: process: Call the domain config validator when starting a new VM
conf: Move disk info validator to the domain conf validator
conf: Move validation of disk LUN device to the appropriate place
qemu: Move check that validates 'min_guarantee' to
qemuDomainDefValidate
src/bhyve/bhyve_driver.c | 4 +-
src/conf/domain_conf.c | 225 ++++++++++++++++++++++++++++++++++--------
src/conf/domain_conf.h | 31 +++++-
src/conf/snapshot_conf.c | 3 +-
src/conf/virdomainobjlist.c | 6 +-
src/esx/esx_driver.c | 2 +-
src/libvirt_private.syms | 2 +-
src/libxl/libxl_domain.c | 3 +-
src/libxl/libxl_driver.c | 10 +-
src/libxl/libxl_migration.c | 6 +-
src/lxc/lxc_driver.c | 7 +-
src/openvz/openvz_driver.c | 7 +-
src/phyp/phyp_driver.c | 2 +-
src/qemu/qemu_domain.c | 20 +++-
src/qemu/qemu_driver.c | 15 +--
src/qemu/qemu_migration.c | 14 ++-
src/qemu/qemu_process.c | 42 ++++----
src/qemu/qemu_process.h | 9 +-
src/security/virt-aa-helper.c | 3 +-
src/test/test_driver.c | 4 +-
src/uml/uml_driver.c | 7 +-
src/vbox/vbox_common.c | 5 +-
src/vmware/vmware_driver.c | 4 +-
src/vz/vz_driver.c | 6 +-
src/xen/xen_driver.c | 4 +-
src/xen/xend_internal.c | 3 +-
src/xen/xm_internal.c | 3 +-
src/xenapi/xenapi_driver.c | 4 +-
tests/qemuxml2argvtest.c | 6 +-
29 files changed, 325 insertions(+), 132 deletions(-)
--
2.8.3
8 years, 4 months
[libvirt] [PATCH v2] systemd: directly notify systemd instead of using sd_notify
by Daniel P. Berrange
The sd_notify method is used to tell systemd when libvirtd
has finished starting up. All it does is send a datagram
containing the string parameter to systemd on a UNIX socket
named in the NOTIFY_SOCKET environment variable. Rather than
pulling in the systemd libraries for this, just code the
notification directly in libvirt as this is a stable ABI
from systemd's POV which explicitly allows independant
implementations:
See "Reimplementable Independently" column in the
"$NOTIFY_SOCKET Daemon Notifications" row:
https://www.freedesktop.org/wiki/Software/systemd/InterfacePortabilityAnd...
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
configure.ac | 2 --
libvirt.spec.in | 12 -----------
m4/virt-systemd-daemon.m4 | 34 ------------------------------
src/Makefile.am | 4 ++--
src/util/virsystemd.c | 53 ++++++++++++++++++++++++++++++++++++++++++-----
5 files changed, 50 insertions(+), 55 deletions(-)
delete mode 100644 m4/virt-systemd-daemon.m4
diff --git a/configure.ac b/configure.ac
index 74c33b3..a63b912 100644
--- a/configure.ac
+++ b/configure.ac
@@ -256,7 +256,6 @@ LIBVIRT_CHECK_SANLOCK
LIBVIRT_CHECK_SASL
LIBVIRT_CHECK_SELINUX
LIBVIRT_CHECK_SSH2
-LIBVIRT_CHECK_SYSTEMD_DAEMON
LIBVIRT_CHECK_UDEV
LIBVIRT_CHECK_WIRESHARK
LIBVIRT_CHECK_NSS
@@ -2787,7 +2786,6 @@ LIBVIRT_RESULT_SANLOCK
LIBVIRT_RESULT_SASL
LIBVIRT_RESULT_SELINUX
LIBVIRT_RESULT_SSH2
-LIBVIRT_RESULT_SYSTEMD_DAEMON
LIBVIRT_RESULT_UDEV
LIBVIRT_RESULT_WIRESHARK
LIBVIRT_RESULT_NSS
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 8b88eef..b93a53c 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -79,7 +79,6 @@
%define with_firewalld 0%{!?_without_firewalld:0}
%define with_libssh2 0%{!?_without_libssh2:0}
%define with_wireshark 0%{!?_without_wireshark:0}
-%define with_systemd_daemon 0%{!?_without_systemd_daemon:0}
%define with_pm_utils 1
# Finally set the OS / architecture specific special cases
@@ -133,7 +132,6 @@
# Fedora has systemd, libvirt still used sysvinit there.
%if 0%{?fedora} || 0%{?rhel} >= 7
%define with_systemd 1
- %define with_systemd_daemon 1
%define with_pm_utils 0
%endif
@@ -268,9 +266,6 @@ BuildRequires: python
%if %{with_systemd}
BuildRequires: systemd-units
%endif
-%if %{with_systemd_daemon}
-BuildRequires: systemd-devel
-%endif
%if %{with_xen} || %{with_libxl}
BuildRequires: xen-devel
%endif
@@ -1061,12 +1056,6 @@ rm -rf .git
%define arg_wireshark --without-wireshark-dissector
%endif
-%if %{with_systemd_daemon}
- %define arg_systemd_daemon --with-systemd-daemon
-%else
- %define arg_systemd_daemon --without-systemd-daemon
-%endif
-
%if %{with_pm_utils}
%define arg_pm_utils --with-pm-utils
%else
@@ -1157,7 +1146,6 @@ rm -f po/stamp-po
--with-driver-modules \
%{?arg_firewalld} \
%{?arg_wireshark} \
- %{?arg_systemd_daemon} \
%{?arg_pm_utils} \
--with-nss-plugin \
%{arg_packager} \
diff --git a/m4/virt-systemd-daemon.m4 b/m4/virt-systemd-daemon.m4
deleted file mode 100644
index 8516e41..0000000
--- a/m4/virt-systemd-daemon.m4
+++ /dev/null
@@ -1,34 +0,0 @@
-dnl The libsystemd-daemon.so library
-dnl
-dnl Copyright (C) 2012-2013 Red Hat, Inc.
-dnl
-dnl This library is free software; you can redistribute it and/or
-dnl modify it under the terms of the GNU Lesser General Public
-dnl License as published by the Free Software Foundation; either
-dnl version 2.1 of the License, or (at your option) any later version.
-dnl
-dnl This library is distributed in the hope that it will be useful,
-dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
-dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-dnl Lesser General Public License for more details.
-dnl
-dnl You should have received a copy of the GNU Lesser General Public
-dnl License along with this library. If not, see
-dnl <http://www.gnu.org/licenses/>.
-dnl
-
-AC_DEFUN([LIBVIRT_CHECK_SYSTEMD_DAEMON],[
- LIBVIRT_CHECK_PKG([SYSTEMD_DAEMON], [libsystemd-daemon], [0.27.1])
-
- old_CFLAGS="$CFLAGS"
- old_LIBS="$LIBS"
- CFLAGS="$CFLAGS $SYSTEMD_DAEMON_CFLAGS"
- LIBS="$LIBS $SYSTEMD_DAEMON_LIBS"
- AC_CHECK_FUNCS([sd_notify])
- CFLAGS="$old_CFLAGS"
- LIBS="$old_LIBS"
-])
-
-AC_DEFUN([LIBVIRT_RESULT_SYSTEMD_DAEMON],[
- LIBVIRT_RESULT_LIB([SYSTEMD_DAEMON])
-])
diff --git a/src/Makefile.am b/src/Makefile.am
index 12b66c2..11c79df 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1106,12 +1106,12 @@ libvirt_util_la_SOURCES = \
libvirt_util_la_CFLAGS = $(CAPNG_CFLAGS) $(YAJL_CFLAGS) $(LIBNL_CFLAGS) \
$(AM_CFLAGS) $(AUDIT_CFLAGS) $(DEVMAPPER_CFLAGS) \
$(DBUS_CFLAGS) $(LDEXP_LIBM) $(NUMACTL_CFLAGS) \
- $(SYSTEMD_DAEMON_CFLAGS) $(POLKIT_CFLAGS) $(GNUTLS_CFLAGS) \
+ $(POLKIT_CFLAGS) $(GNUTLS_CFLAGS) \
-I$(srcdir)/conf
libvirt_util_la_LIBADD = $(CAPNG_LIBS) $(YAJL_LIBS) $(LIBNL_LIBS) \
$(THREAD_LIBS) $(AUDIT_LIBS) $(DEVMAPPER_LIBS) \
$(LIB_CLOCK_GETTIME) $(DBUS_LIBS) $(MSCOM_LIBS) $(LIBXML_LIBS) \
- $(SECDRIVER_LIBS) $(NUMACTL_LIBS) $(SYSTEMD_DAEMON_LIBS) \
+ $(SECDRIVER_LIBS) $(NUMACTL_LIBS) \
$(POLKIT_LIBS)
diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c
index 4883f94..871db7e 100644
--- a/src/util/virsystemd.c
+++ b/src/util/virsystemd.c
@@ -21,8 +21,9 @@
#include <config.h>
-#ifdef WITH_SYSTEMD_DAEMON
-# include <systemd/sd-daemon.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
#endif
#include "virsystemd.h"
@@ -34,6 +35,7 @@
#include "virutil.h"
#include "virlog.h"
#include "virerror.h"
+#include "virfile.h"
#define VIR_FROM_THIS VIR_FROM_SYSTEMD
@@ -480,9 +482,50 @@ int virSystemdTerminateMachine(const char *name)
void
virSystemdNotifyStartup(void)
{
-#ifdef WITH_SYSTEMD_DAEMON
- sd_notify(0, "READY=1");
-#endif
+#ifdef HAVE_SYS_UN_H
+ const char *path;
+ const char *msg = "READY=1";
+ int fd;
+ struct sockaddr_un un = {
+ .sun_family = AF_UNIX,
+ };
+ struct iovec iov = {
+ .iov_base = (char *)msg,
+ .iov_len = strlen(msg),
+ };
+ struct msghdr mh = {
+ .msg_name = &un,
+ .msg_namelen = sizeof(un),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+
+ if (!(path = virGetEnvBlockSUID("NOTIFY_SOCKET"))) {
+ VIR_DEBUG("Skipping systemd notify, not requested");
+ return;
+ }
+
+ /* NB sun_path field is *not* NUL-terminated, hence >, not >= */
+ if (strlen(path) > sizeof(un.sun_path)) {
+ VIR_WARN("Systemd notify socket path '%s' too long", path);
+ return;
+ }
+
+ memcpy(un.sun_path, path, strlen(path));
+ if (un.sun_path[0] == '@')
+ un.sun_path[0] = '\0';
+
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ VIR_WARN("Unable to create socket FD");
+ return;
+ }
+
+ if (sendmsg(fd, &mh, MSG_NOSIGNAL) < 0)
+ VIR_WARN("Failed to notify systemd");
+
+ VIR_FORCE_CLOSE(fd);
+#endif /* HAVE_SYS_UN_H */
}
static int
--
2.5.5
8 years, 4 months
[libvirt] [PATCH 0/7] Cleanup with storageencryption/qemu-img
by John Ferlan
The first 4 patches were already posted:
http://www.redhat.com/archives/libvir-list/2016-May/msg01984.htm
http://www.redhat.com/archives/libvir-list/2016-May/msg02147.html
There was only one small change in a comment to any of those patches.
The last 3 patches are new - just trying to make it easier to use the
qemu-img code for creating a luks volume.
John Ferlan (7):
util: Clean up code formatting in virstorageencryption
storage: Split out setting default secret for encryption
storage: Split out a helper for encryption checks
storage: Adjust qemu-img switches check
storage: Create helper to set input for CreateQemuImg code
storage: Create helper to set backing for CreateQemuImg code
storage: Create helper to set options for CreateQemuImg code
src/storage/storage_backend.c | 367 ++++++++++++++++++++++-----------------
src/storage/storage_backend_fs.c | 79 +++++----
src/util/virstorageencryption.c | 58 +++----
3 files changed, 282 insertions(+), 222 deletions(-)
--
2.5.5
8 years, 4 months
[libvirt] [PATCH] systemd: directly notify systemd instead of using sd_notify
by Daniel P. Berrange
The sd_notify method is used to tell systemd when libvirtd
has finished starting up. All it does is send a datagram
containing the string parameter to systemd on a UNIX socket
named in the NOTIFY_SOCKET environment variable. Rather than
pulling in the systemd libraries for this, just code the
notification directly in libvirt as this is a stable ABI
from systemd's POV which explicitly allows independant
implementations:
See "Reimplementable Independently" column in the
"$NOTIFY_SOCKET Daemon Notifications" row:
https://www.freedesktop.org/wiki/Software/systemd/InterfacePortabilityAnd...
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
configure.ac | 2 --
libvirt.spec.in | 12 -----------
m4/virt-systemd-daemon.m4 | 34 -------------------------------
src/Makefile.am | 4 ++--
src/util/virsystemd.c | 52 ++++++++++++++++++++++++++++++++++++++++++-----
5 files changed, 49 insertions(+), 55 deletions(-)
delete mode 100644 m4/virt-systemd-daemon.m4
diff --git a/configure.ac b/configure.ac
index 74c33b3..a63b912 100644
--- a/configure.ac
+++ b/configure.ac
@@ -256,7 +256,6 @@ LIBVIRT_CHECK_SANLOCK
LIBVIRT_CHECK_SASL
LIBVIRT_CHECK_SELINUX
LIBVIRT_CHECK_SSH2
-LIBVIRT_CHECK_SYSTEMD_DAEMON
LIBVIRT_CHECK_UDEV
LIBVIRT_CHECK_WIRESHARK
LIBVIRT_CHECK_NSS
@@ -2787,7 +2786,6 @@ LIBVIRT_RESULT_SANLOCK
LIBVIRT_RESULT_SASL
LIBVIRT_RESULT_SELINUX
LIBVIRT_RESULT_SSH2
-LIBVIRT_RESULT_SYSTEMD_DAEMON
LIBVIRT_RESULT_UDEV
LIBVIRT_RESULT_WIRESHARK
LIBVIRT_RESULT_NSS
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 8b88eef..b93a53c 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -79,7 +79,6 @@
%define with_firewalld 0%{!?_without_firewalld:0}
%define with_libssh2 0%{!?_without_libssh2:0}
%define with_wireshark 0%{!?_without_wireshark:0}
-%define with_systemd_daemon 0%{!?_without_systemd_daemon:0}
%define with_pm_utils 1
# Finally set the OS / architecture specific special cases
@@ -133,7 +132,6 @@
# Fedora has systemd, libvirt still used sysvinit there.
%if 0%{?fedora} || 0%{?rhel} >= 7
%define with_systemd 1
- %define with_systemd_daemon 1
%define with_pm_utils 0
%endif
@@ -268,9 +266,6 @@ BuildRequires: python
%if %{with_systemd}
BuildRequires: systemd-units
%endif
-%if %{with_systemd_daemon}
-BuildRequires: systemd-devel
-%endif
%if %{with_xen} || %{with_libxl}
BuildRequires: xen-devel
%endif
@@ -1061,12 +1056,6 @@ rm -rf .git
%define arg_wireshark --without-wireshark-dissector
%endif
-%if %{with_systemd_daemon}
- %define arg_systemd_daemon --with-systemd-daemon
-%else
- %define arg_systemd_daemon --without-systemd-daemon
-%endif
-
%if %{with_pm_utils}
%define arg_pm_utils --with-pm-utils
%else
@@ -1157,7 +1146,6 @@ rm -f po/stamp-po
--with-driver-modules \
%{?arg_firewalld} \
%{?arg_wireshark} \
- %{?arg_systemd_daemon} \
%{?arg_pm_utils} \
--with-nss-plugin \
%{arg_packager} \
diff --git a/m4/virt-systemd-daemon.m4 b/m4/virt-systemd-daemon.m4
deleted file mode 100644
index 8516e41..0000000
--- a/m4/virt-systemd-daemon.m4
+++ /dev/null
@@ -1,34 +0,0 @@
-dnl The libsystemd-daemon.so library
-dnl
-dnl Copyright (C) 2012-2013 Red Hat, Inc.
-dnl
-dnl This library is free software; you can redistribute it and/or
-dnl modify it under the terms of the GNU Lesser General Public
-dnl License as published by the Free Software Foundation; either
-dnl version 2.1 of the License, or (at your option) any later version.
-dnl
-dnl This library is distributed in the hope that it will be useful,
-dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
-dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-dnl Lesser General Public License for more details.
-dnl
-dnl You should have received a copy of the GNU Lesser General Public
-dnl License along with this library. If not, see
-dnl <http://www.gnu.org/licenses/>.
-dnl
-
-AC_DEFUN([LIBVIRT_CHECK_SYSTEMD_DAEMON],[
- LIBVIRT_CHECK_PKG([SYSTEMD_DAEMON], [libsystemd-daemon], [0.27.1])
-
- old_CFLAGS="$CFLAGS"
- old_LIBS="$LIBS"
- CFLAGS="$CFLAGS $SYSTEMD_DAEMON_CFLAGS"
- LIBS="$LIBS $SYSTEMD_DAEMON_LIBS"
- AC_CHECK_FUNCS([sd_notify])
- CFLAGS="$old_CFLAGS"
- LIBS="$old_LIBS"
-])
-
-AC_DEFUN([LIBVIRT_RESULT_SYSTEMD_DAEMON],[
- LIBVIRT_RESULT_LIB([SYSTEMD_DAEMON])
-])
diff --git a/src/Makefile.am b/src/Makefile.am
index 12b66c2..11c79df 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1106,12 +1106,12 @@ libvirt_util_la_SOURCES = \
libvirt_util_la_CFLAGS = $(CAPNG_CFLAGS) $(YAJL_CFLAGS) $(LIBNL_CFLAGS) \
$(AM_CFLAGS) $(AUDIT_CFLAGS) $(DEVMAPPER_CFLAGS) \
$(DBUS_CFLAGS) $(LDEXP_LIBM) $(NUMACTL_CFLAGS) \
- $(SYSTEMD_DAEMON_CFLAGS) $(POLKIT_CFLAGS) $(GNUTLS_CFLAGS) \
+ $(POLKIT_CFLAGS) $(GNUTLS_CFLAGS) \
-I$(srcdir)/conf
libvirt_util_la_LIBADD = $(CAPNG_LIBS) $(YAJL_LIBS) $(LIBNL_LIBS) \
$(THREAD_LIBS) $(AUDIT_LIBS) $(DEVMAPPER_LIBS) \
$(LIB_CLOCK_GETTIME) $(DBUS_LIBS) $(MSCOM_LIBS) $(LIBXML_LIBS) \
- $(SECDRIVER_LIBS) $(NUMACTL_LIBS) $(SYSTEMD_DAEMON_LIBS) \
+ $(SECDRIVER_LIBS) $(NUMACTL_LIBS) \
$(POLKIT_LIBS)
diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c
index 4883f94..71b8f33 100644
--- a/src/util/virsystemd.c
+++ b/src/util/virsystemd.c
@@ -21,8 +21,9 @@
#include <config.h>
-#ifdef WITH_SYSTEMD_DAEMON
-# include <systemd/sd-daemon.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
#endif
#include "virsystemd.h"
@@ -34,6 +35,7 @@
#include "virutil.h"
#include "virlog.h"
#include "virerror.h"
+#include "virfile.h"
#define VIR_FROM_THIS VIR_FROM_SYSTEMD
@@ -480,9 +482,49 @@ int virSystemdTerminateMachine(const char *name)
void
virSystemdNotifyStartup(void)
{
-#ifdef WITH_SYSTEMD_DAEMON
- sd_notify(0, "READY=1");
-#endif
+#ifdef HAVE_SYS_UN_H
+ const char *path;
+ const char *msg = "READY=1";
+ int fd;
+ struct sockaddr_un un = {
+ .sun_family = AF_UNIX,
+ };
+ struct iovec iov = {
+ .iov_base = (char *)msg,
+ .iov_len = strlen(msg),
+ };
+ struct msghdr mh = {
+ .msg_name = &un,
+ .msg_namelen = sizeof(un),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+
+ if (!(path = virGetEnvBlockSUID("NOTIFY_SOCKET"))) {
+ VIR_DEBUG("Skipping systemd notify, not requested");
+ return;
+ }
+
+ if (strlen(path) > sizeof(un.sun_path)) {
+ VIR_WARN("Systemd notify socket path '%s' too long", path);
+ return;
+ }
+
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ VIR_WARN("Unable to create socket FD");
+ return;
+ }
+
+ ignore_value(virStrcpy(un.sun_path, path, sizeof(un.sun_path)));
+ if (un.sun_path[0] == '@')
+ un.sun_path[0] = '\0';
+
+ if (sendmsg(fd, &mh, MSG_NOSIGNAL) < 0)
+ VIR_WARN("Failed to notify systemd");
+
+ VIR_FORCE_CLOSE(fd);
+#endif /* HAVE_SYS_UN_H */
}
static int
--
2.5.5
8 years, 4 months
[libvirt] [PATCH] docs: Document our event loop
by Michal Privoznik
I was asked the other day what's event loop and how libvirt uses
it. Well, I haven't found any good sources on the Internet so I
thought of writing the documentation on my own.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
NB, when I will push this, the images will go to our
libvirt-media repo among with the original SVGs that PNGs were
rendered from. I'm sending them here for easier review.
docs/internals.html.in | 1 +
docs/internals/event_loop_simple.png | Bin 0 -> 16043 bytes
docs/internals/event_loop_worker.png | Bin 0 -> 29696 bytes
docs/internals/eventloop.html.in | 106 +++++++++++++++++++++++++++++++++++
docs/sitemap.html.in | 4 ++
5 files changed, 111 insertions(+)
create mode 100644 docs/internals/event_loop_simple.png
create mode 100644 docs/internals/event_loop_worker.png
create mode 100644 docs/internals/eventloop.html.in
diff --git a/docs/internals.html.in b/docs/internals.html.in
index c30f52f..fcc0758 100644
--- a/docs/internals.html.in
+++ b/docs/internals.html.in
@@ -14,6 +14,7 @@
<li>Introduction to basic rules and guidelines for
<a href="hacking.html">hacking</a> on libvirt code</li>
<li>Guide to adding <a href="api_extension.html">public APIs</a></li>
+ <li>Insight into libvirt <a href="internals/eventloop.html">event loop and worker pool</a></li>
<li>Approach for <a href="internals/command.html">spawning commands</a>
from libvirt driver code</li>
<li>The libvirt <a href="internals/rpc.html">RPC infrastructure</a></li>
diff --git a/docs/internals/event_loop_simple.png b/docs/internals/event_loop_simple.png
new file mode 100644
index 0000000000000000000000000000000000000000..daf4338a16bc1051aca0ca1c7ea13baa4e7179f1
GIT binary patch
literal 16043
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
Mp@LL_gu%=I0mPN)82|tP
literal 0
HcmV?d00001
diff --git a/docs/internals/event_loop_worker.png b/docs/internals/event_loop_worker.png
new file mode 100644
index 0000000000000000000000000000000000000000..1bec1ea598b2806fea24ab25dc825c9055c76ee6
GIT binary patch
literal 29696
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
literal 0
HcmV?d00001
diff --git a/docs/internals/eventloop.html.in b/docs/internals/eventloop.html.in
new file mode 100644
index 0000000..93d9e8d
--- /dev/null
+++ b/docs/internals/eventloop.html.in
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <body>
+ <h1>Libvirt's event loop</h1>
+
+ <ul id="toc"></ul>
+
+ <p>
+ This page describes the event loop approach used in
+ libvirt. Both server and client.
+ </p>
+
+ <h2><a name="event_loop">Event driven programming</a></h2>
+
+ <p>Traditionally, a program simply ran once, then terminated.
+ This type of program was very common in the early days of
+ computing, and lacked any form of user interactivity. This is
+ still used frequently, particularly in small one purpose
+ programs.</p>
+
+ <p>However, that approach is not suitable for all the types
+ of applications. For instance graphical applications spend
+ most of their run time waiting for an input from user. Only
+ after it happened (in our example a button was clicked, a key
+ pressed, etc.) an event is generated to which they respond
+ by executing desired function. If generalized, this is how
+ many long running programs (daemons) work. Even those who are
+ not waiting for direct user input and have no graphical
+ interface. Such as Libvirt.</p>
+
+ <img alt="event loop" src="event_loop_simple.png"/>
+
+ <p>In Libvirt this approach is used in combination with
+ <code>poll(2)</code> as all the communication with its
+ clients (and domains it manages too) happens through sockets.
+ Therefore whenever new client connects, it is given exclusive
+ file descriptor which is then watched for incoming events,
+ e.g. messages. </p>
+
+ <h2><a name="api">The event loop API</a></h2>
+
+ <p>To work with event loop from our code we have plenty of
+ APIs.</p>
+
+ <ul>
+ <li><code>virEventAddHandle</code>: Registers a
+ callback for monitoring file handle events.</li>
+ <li><code>virEventUpdateHandle</code>: Change set of events
+ monitored file handle is being watched for.</li>
+ <li><code>virEventRemoveHandle</code>: Unregisters
+ previously registered file handle so that it is no
+ longer monitored for any events.</li>
+ <li><code>virEventAddTimeout</code>: Registers a
+ callback for timer event.</li>
+ <li><code>virEventUpdateTimeout</code>: Changes frequency
+ for a timer.</li>
+ <li><code>virEventRemoveTimeout</code>: Unregisters
+ a timer.</li>
+ </ul>
+
+ <p>For more information on these APIs continue reading <a
+ href="../html/libvirt-libvirt-event.html">here</a>.</p>
+
+ <h2><a name="worker_pool">Worker pool</a></h2>
+
+ <p>Looking back at the image above we can see one big
+ limitation. While processing a message event loop is blocked
+ and for an outside observer unresponsive. This is not
+ acceptable for Libvirt. Therefore we have came up with the
+ following solution.</p>
+
+ <img alt="event loop" src="event_loop_worker.png"/>
+
+ <p>The event loop does only necessary minimum and hand over
+ message processing to another thread. In fact, there can be
+ as many processing threads as configured increasing
+ processing power.</p>
+
+ <p>To break this high level description into smaller pieces,
+ here is what happens when user calls an API:</p>
+ <ol>
+ <li>User (or management application) calls a Libvirt API.
+ Depending on the connection URI, this may or may not
+ involve server. Well, for the sake of our
+ demonstration we assume the former.</li>
+ <li>Remote driver encodes the API among it's arguments
+ into an <a href="rpc.html">RPC message</a> and sends
+ it to the server.</li>
+ <li>Here, server is waiting in <code>poll(2)</code> for
+ an event, like incoming message.</li>
+ <li>As soon as the first bytes of message are received,
+ even loop wakes up and server starts reading the
+ whole message.</li>
+ <li>Once fully read, the event loop notifies threads
+ known as worker threads from which one picks the incoming
+ message, decodes and process it.</li>
+ <li>As soon as API execution is finished, a reply is sent
+ to the client.</li>
+ </ol>
+
+ <p>In case that there's no free worker to process an incoming
+ message in step 5, message is placed at the end of a message
+ queue and is processed in next iteration.</p>
+ </body>
+</html>
diff --git a/docs/sitemap.html.in b/docs/sitemap.html.in
index d5cf723..757d5aa 100644
--- a/docs/sitemap.html.in
+++ b/docs/sitemap.html.in
@@ -397,6 +397,10 @@
<span>Adding new public libvirt APIs</span>
</li>
<li>
+ <a href="internals/eventloop.html">Event loop and worker pool</a>
+ <span>Libvirt's event loop and worker pool mode</span>
+ </li>
+ <li>
<a href="internals/command.html">Spawning commands</a>
<span>Spawning commands from libvirt driver code</span>
</li>
--
2.8.3
8 years, 4 months
[libvirt] [PATCH 00/32] node_device_udev: cleanups
by Ján Tomko
Mostly style changes and refactors.
Ján Tomko (32):
Initialize ret to -1 in nodeStateInitialize
Split out pciaccess (de)initialization
node_device_udev: initialize libpciaccess after the driver lock
Reformat nodeStateCleanup
Do not call nodeStateCleanup on early initialization error
Assign node device driver private data earlier
udevGetDMIData: remove unused variable
udevProcessSCSIHost: use STRSKIP
Rewrite usage of StrToLong_ui in udevProcess{PCI,SCSI}
Remove udevStrToLong_ull
Remove udevStrToLong_ui
Remove udevStrToLong_i
Do not VIR_STRDUP the string in udevGetDeviceProperty
Move udevHasDeviceProperty earlier
udevProcessFloppy; remove unnecessary allocation
Fix the return value in udevKludgeStorageType
Rewrite disk type checking in udevProcessStorage
Only return two values in udevGetStringProperty
Only return two values in udevGetUintProperty
Remove extra allocation in udevGetDeviceSysfsAttr
Only return two values in udevGetStringSysfsAttr
Only return two values in udevGetIntSysfsAttr
Only return two values in udevGetUintSysfsAttr
Remove PROPERTY_* constants
node_device_udev: switch to using virReportError
udevProcessStorage: trim all whitespace from model and vendor
Reformat udevProcessRemoveableMedia
udevSetupSystemDev: return if allocation fails
node_device_udev: remove yoda condition
node_device_udev: remove unnecessary ret variables
node_device_udev: rename labels to cleanup
Add nomatch filters when enumerating udev devices
src/node_device/node_device_udev.c | 1156 ++++++++++++++----------------------
src/node_device/node_device_udev.h | 3 -
2 files changed, 437 insertions(+), 722 deletions(-)
--
2.7.3
8 years, 4 months
[libvirt] [PATCH 0/3] Fix 'make rpm' failure with systemd 230
by Andrea Bolognani
Turns out the libsystemd-daemon library, which we've been
using for the sd_notify() feature, has been deprecated for
a long time and has finally been removed as of systemd 230.
This means 'make rpm' no longer works on Fedora rawhide,
and that other distributions such as Debian sid are silently
disabling the sd_notify() feature.
Switch from libsystemd-daemon to libsystemd.
Andrea Bolognani (3):
maint: Use libsystemd instead of libsystemd-daemon
spec: Enable libsystemd on Fedora >= 21, RHEL >= 7
systemd: Guard the call to sd_notify() properly
configure.ac | 4 ++--
libvirt.spec.in | 18 +++++++++++-------
m4/{virt-systemd-daemon.m4 => virt-libsystemd.m4} | 14 +++++++-------
src/Makefile.am | 4 ++--
src/util/virsystemd.c | 4 ++--
5 files changed, 24 insertions(+), 20 deletions(-)
rename m4/{virt-systemd-daemon.m4 => virt-libsystemd.m4} (73%)
--
2.5.5
8 years, 4 months