[libvirt] [PATCH] add nocow feature option to vol-create
by Chunyan Liu
Btrfs has terrible performance when hosting VM images, even more when the guest
in those VM are also using btrfs as file system. One way to mitigate this bad
performance is to turn off COW attributes on VM files (since having copy on
write for this kind of data is not useful).
According to 'chattr' manpage, NOCOW could be set to new or empty file only on
btrfs, so this patch tries to add nocow feature option in volume xml and handle
it in vol-create, so that users could have a chance to set NOCOW to a new
volume if that happens on a btrfs like file system.
Signed-off-by: Chunyan Liu <cyliu(a)suse.com>
---
This is a revised version to:
http://www.redhat.com/archives/libvir-list/2013-December/msg00303.html
Changes:
* fix Daniel's comments
---
docs/formatstorage.html.in | 12 +++++---
docs/schemas/storagefilefeatures.rng | 3 ++
src/conf/storage_conf.c | 9 ++++--
src/storage/storage_backend.c | 4 +-
src/storage/storage_backend_fs.c | 48 ++++++++++++++++++++++++++++++++++
src/util/virstoragefile.c | 1 +
src/util/virstoragefile.h | 1 +
7 files changed, 69 insertions(+), 9 deletions(-)
diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in
index a089a31..3de1a2b 100644
--- a/docs/formatstorage.html.in
+++ b/docs/formatstorage.html.in
@@ -385,6 +385,7 @@
<compat>1.1</compat>
<features>
<lazy_refcounts/>
+ <nocow/>
</features>
</target></pre>
@@ -423,11 +424,14 @@
<span class="since">Since 1.1.0</span>
</dd>
<dt><code>features</code></dt>
- <dd>Format-specific features. Only used for <code>qcow2</code> now.
- Valid sub-elements are:
- <ul>
+ <dd>Format-specific features. Valid sub-elements are:
+ <ul>
<li><code><lazy_refcounts/></code> - allow delayed reference
- counter updates. <span class="since">Since 1.1.0</span></li>
+ counter updates. Only used for <code>qcow2</code> now.
+ <span class="since">Since 1.1.0</span></li>
+ <li><code><nocow/></code> - turn off copy-on-write. Only valid
+ to volume on <code>btrfs</code>, can improve performance.
+ <span class="since">Since 1.2.2</span></li>
</ul>
</dd>
</dl>
diff --git a/docs/schemas/storagefilefeatures.rng b/docs/schemas/storagefilefeatures.rng
index 424b4e2..0cf3513 100644
--- a/docs/schemas/storagefilefeatures.rng
+++ b/docs/schemas/storagefilefeatures.rng
@@ -17,6 +17,9 @@
<element name='lazy_refcounts'>
<empty/>
</element>
+ <element name='nocow'>
+ <empty/>
+ </element>
</optional>
</interleave>
</element>
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 22e38c1..b6409a6 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -1398,9 +1398,6 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
if ((n = virXPathNodeSet("./target/features/*", ctxt, &nodes)) < 0)
goto error;
- if (!ret->target.compat && VIR_STRDUP(ret->target.compat, "1.1") < 0)
- goto error;
-
if (!(ret->target.features = virBitmapNew(VIR_STORAGE_FILE_FEATURE_LAST)))
goto error;
@@ -1412,6 +1409,12 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
(const char*)nodes[i]->name);
goto error;
}
+
+ if (f == VIR_STORAGE_FILE_FEATURE_LAZY_REFCOUNTS) {
+ if (!ret->target.compat && VIR_STRDUP(ret->target.compat, "1.1") < 0)
+ goto error;
+ }
+
ignore_value(virBitmapSetBit(ret->target.features, f));
}
VIR_FREE(nodes);
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index b08d646..b4ab866 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -423,7 +423,7 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
operation_flags |= VIR_FILE_OPEN_FORK;
if ((fd = virFileOpenAs(vol->target.path,
- O_RDWR | O_CREAT | O_EXCL,
+ O_RDWR | O_CREAT,
vol->target.perms.mode,
vol->target.perms.uid,
vol->target.perms.gid,
@@ -729,7 +729,7 @@ virStorageBackendCreateQemuImgOpts(char **opts,
break;
/* coverity[dead_error_begin] */
- case VIR_STORAGE_FILE_FEATURE_LAST:
+ default:
;
}
virBufferAsprintf(&buf, "%s,",
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index 95783be..dc26f6d 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -51,6 +51,13 @@
#include "virfile.h"
#include "virlog.h"
#include "virstring.h"
+#ifdef __linux__
+# include <sys/ioctl.h>
+# include <linux/fs.h>
+#ifndef FS_NOCOW_FL
+#define FS_NOCOW_FL 0x00800000 /* Do not cow file */
+#endif
+#endif
#define VIR_FROM_THIS VIR_FROM_STORAGE
@@ -1061,6 +1068,7 @@ _virStorageBackendFileSystemVolBuild(virConnectPtr conn,
{
virStorageBackendBuildVolFrom create_func;
int tool_type;
+ bool nocow;
if (inputvol) {
if (vol->target.encryption != NULL) {
@@ -1090,6 +1098,46 @@ _virStorageBackendFileSystemVolBuild(virConnectPtr conn,
return -1;
}
+ if (vol->target.features)
+ ignore_value(virBitmapGetBit(vol->target.features,
+ VIR_STORAGE_FILE_FEATURE_NOCOW, &nocow));
+ if (nocow) {
+#ifdef __linux__
+ /* create an empty file and set nocow flag.
+ * This could optimize performance on file system like btrfs.
+ */
+ int attr, fd;
+ int operation_flags = VIR_FILE_OPEN_FORCE_MODE | VIR_FILE_OPEN_FORCE_OWNER;
+ if (pool->def->type == VIR_STORAGE_POOL_NETFS)
+ operation_flags |= VIR_FILE_OPEN_FORK;
+
+ if ((fd = virFileOpenAs(vol->target.path,
+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
+ vol->target.perms.mode,
+ vol->target.perms.uid,
+ vol->target.perms.gid,
+ operation_flags)) < 0) {
+ virReportSystemError(-fd,
+ _("Failed to create file '%s'"),
+ vol->target.path);
+ return -1;
+ }
+
+ /* This is an optimisation. The FS_IOC_SETFLAGS ioctl return value will
+ * be ignored since any failure of this operation should not block the
+ * left work.
+ */
+ if (ioctl(fd, FS_IOC_GETFLAGS, &attr) == 0) {
+ attr |= FS_NOCOW_FL;
+ ioctl(fd, FS_IOC_SETFLAGS, &attr);
+ }
+
+ VIR_FORCE_CLOSE(fd);
+#endif
+ if (virBitmapClearBit(vol->target.features, VIR_STORAGE_FILE_FEATURE_NOCOW) < 0)
+ return -1;
+ }
+
if (create_func(conn, pool, vol, inputvol, flags) < 0)
return -1;
return 0;
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index e45236f..6e34e4c 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -62,6 +62,7 @@ VIR_ENUM_IMPL(virStorageFileFormat,
VIR_ENUM_IMPL(virStorageFileFeature,
VIR_STORAGE_FILE_FEATURE_LAST,
"lazy_refcounts",
+ "nocow",
)
enum lv_endian {
diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
index 7bd2fe0..f45743a 100644
--- a/src/util/virstoragefile.h
+++ b/src/util/virstoragefile.h
@@ -62,6 +62,7 @@ VIR_ENUM_DECL(virStorageFileFormat);
enum virStorageFileFeature {
VIR_STORAGE_FILE_FEATURE_LAZY_REFCOUNTS = 0,
+ VIR_STORAGE_FILE_FEATURE_NOCOW = 1,
VIR_STORAGE_FILE_FEATURE_LAST
};
--
1.6.0.2
10 years, 10 months
[libvirt] [RFC PATCH 0/7] Adding 'config' driver
by Adam Walters
This patchset adds a driver named 'config' that allows access to configuration data, such as secret and storage definitions. This is a pre-requisite for my next patchset which resolves the race condition on libvirtd startup and the circular dependencies between QEMU and the storage driver.
The basic rationale behind this idea is that there exist circumstances under which a driver may need to access things such as secrets during a time at which there is no active connection to a hypervisor. Without a connection, the data can't be accessed currently. I felt that this was a much simpler solution to the problem that building new APIs that do not require a connection to operate.
This driver is technically what one may call a hypervisor driver, but it does not implement any domain operations. It simply exists to handle requests by drivers for access to informatino that would otherwise require a connection. The URI used for this driver is 'config:///' and has been tested working on 4 different machines of mine, running three different distributions of Linux (Archlinux, Gentoo, and CentOS). Being a very simple driver, I would expect it to work pretty much anywhere.
I would love to hear any comments and suggestions you may have about this driver. At the very least this plus my next patchset resolves the startup race condition on my machine. If a more robust setup (likely a new internal API) is in the works, this driver could act as a band-aid to allow access to this type of data in the interim if a better resolution is a ways off.
Adam Walters (7):
config: Adding source for the config driver
config: Adding header for the config driver
virterror: Adding a new VIR_FROM_ define
libvirtd: Add config driver hooks
po: Add config_driver.c to POTFILES.in
configure: Add config driver to configure script
Makefile: Add config driver to src/Makefile.am
configure.ac | 10 ++
daemon/libvirtd.c | 21 ++--
include/libvirt/virterror.h | 2 +
po/POTFILES.in | 1 +
src/Makefile.am | 25 +++++
src/config/config_driver.c | 237 ++++++++++++++++++++++++++++++++++++++++++++
src/config/config_driver.h | 44 ++++++++
src/util/virerror.c | 2 +
8 files changed, 336 insertions(+), 6 deletions(-)
create mode 100644 src/config/config_driver.c
create mode 100644 src/config/config_driver.h
--
1.8.5.2
10 years, 10 months
[libvirt] [PATCH v2] virtlockd: make re-exec more robust
by Michael Chapman
- Use $XDG_RUNTIME_DIR for re-exec state file when running unprivileged.
- argv[0] may not contain a full path to the binary, however it should
contain something that can be looked up in the PATH. Use execvp() to
do path lookup on re-exec.
- As per list discussion [1], ignore --daemon on re-exec.
[1] https://www.redhat.com/archives/libvir-list/2013-December/msg00514.html
Signed-off-by: Michael Chapman <mike(a)very.puzzling.org>
---
src/locking/lock_daemon.c | 128 ++++++++++++++++++++++++++++++++++------------
1 file changed, 94 insertions(+), 34 deletions(-)
diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c
index a6be43c..b405e3a 100644
--- a/src/locking/lock_daemon.c
+++ b/src/locking/lock_daemon.c
@@ -925,7 +925,41 @@ error:
}
-#define VIR_LOCK_DAEMON_RESTART_EXEC_FILE LOCALSTATEDIR "/run/virtlockd-restart-exec.json"
+static int
+virLockDaemonExecRestartStatePath(bool privileged,
+ char **state_file)
+{
+ if (privileged) {
+ if (VIR_STRDUP(*state_file, LOCALSTATEDIR "/run/virtlockd-restart-exec.json") < 0)
+ goto error;
+ } else {
+ char *rundir = NULL;
+ mode_t old_umask;
+
+ if (!(rundir = virGetUserRuntimeDirectory()))
+ goto error;
+
+ old_umask = umask(077);
+ if (virFileMakePath(rundir) < 0) {
+ umask(old_umask);
+ goto error;
+ }
+ umask(old_umask);
+
+ if (virAsprintf(state_file, "%s/virtlockd-restart-exec.json", rundir) < 0) {
+ VIR_FREE(rundir);
+ goto error;
+ }
+
+ VIR_FREE(rundir);
+ }
+
+ return 0;
+
+error:
+ return -1;
+}
+
static char *
virLockDaemonGetExecRestartMagic(void)
@@ -938,7 +972,10 @@ virLockDaemonGetExecRestartMagic(void)
static int
-virLockDaemonPostExecRestart(bool privileged)
+virLockDaemonPostExecRestart(const char *state_file,
+ const char *pid_file,
+ int *pid_file_fd,
+ bool privileged)
{
const char *gotmagic;
char *wantmagic = NULL;
@@ -948,14 +985,14 @@ virLockDaemonPostExecRestart(bool privileged)
VIR_DEBUG("Running post-restart exec");
- if (!virFileExists(VIR_LOCK_DAEMON_RESTART_EXEC_FILE)) {
- VIR_DEBUG("No restart file %s present",
- VIR_LOCK_DAEMON_RESTART_EXEC_FILE);
+ if (!virFileExists(state_file)) {
+ VIR_DEBUG("No restart state file %s present",
+ state_file);
ret = 0;
goto cleanup;
}
- if (virFileReadAll(VIR_LOCK_DAEMON_RESTART_EXEC_FILE,
+ if (virFileReadAll(state_file,
1024 * 1024 * 10, /* 10 MB */
&state) < 0)
goto cleanup;
@@ -982,13 +1019,18 @@ virLockDaemonPostExecRestart(bool privileged)
goto cleanup;
}
+ /* Re-claim PID file now as we will not be daemonizing */
+ if (pid_file &&
+ (*pid_file_fd = virPidFileAcquirePath(pid_file, getpid())) < 0)
+ goto cleanup;
+
if (!(lockDaemon = virLockDaemonNewPostExecRestart(object, privileged)))
goto cleanup;
ret = 1;
cleanup:
- unlink(VIR_LOCK_DAEMON_RESTART_EXEC_FILE);
+ unlink(state_file);
VIR_FREE(wantmagic);
VIR_FREE(state);
virJSONValueFree(object);
@@ -997,7 +1039,8 @@ cleanup:
static int
-virLockDaemonPreExecRestart(virNetServerPtr srv,
+virLockDaemonPreExecRestart(const char *state_file,
+ virNetServerPtr srv,
char **argv)
{
virJSONValuePtr child;
@@ -1065,15 +1108,15 @@ virLockDaemonPreExecRestart(virNetServerPtr srv,
VIR_DEBUG("Saving state %s", state);
- if (virFileWriteStr(VIR_LOCK_DAEMON_RESTART_EXEC_FILE,
+ if (virFileWriteStr(state_file,
state, 0700) < 0) {
virReportSystemError(errno,
_("Unable to save state file %s"),
- VIR_LOCK_DAEMON_RESTART_EXEC_FILE);
+ state_file);
goto cleanup;
}
- if (execv(argv[0], argv) < 0) {
+ if (execvp(argv[0], argv) < 0) {
virReportSystemError(errno, "%s",
_("Unable to restart self"));
goto cleanup;
@@ -1153,6 +1196,7 @@ int main(int argc, char **argv) {
char *pid_file = NULL;
int pid_file_fd = -1;
char *sock_file = NULL;
+ char *state_file = NULL;
bool implicit_conf = false;
mode_t old_umask;
bool privileged = false;
@@ -1276,21 +1320,13 @@ int main(int argc, char **argv) {
VIR_DEBUG("Decided on socket paths '%s'",
sock_file);
- if (godaemon) {
- char ebuf[1024];
-
- if (chdir("/") < 0) {
- VIR_ERROR(_("cannot change to root directory: %s"),
- virStrerror(errno, ebuf, sizeof(ebuf)));
- goto cleanup;
- }
-
- if ((statuswrite = virLockDaemonForkIntoBackground(argv[0])) < 0) {
- VIR_ERROR(_("Failed to fork as daemon: %s"),
- virStrerror(errno, ebuf, sizeof(ebuf)));
- goto cleanup;
- }
+ if (virLockDaemonExecRestartStatePath(privileged,
+ &state_file) < 0) {
+ VIR_ERROR(_("Can't determine restart state file path"));
+ exit(EXIT_FAILURE);
}
+ VIR_DEBUG("Decided on restart state file path '%s'",
+ state_file);
/* Ensure the rundir exists (on tmpfs on some systems) */
if (privileged) {
@@ -1317,20 +1353,41 @@ int main(int argc, char **argv) {
}
umask(old_umask);
- /* If we have a pidfile set, claim it now, exiting if already taken */
- if ((pid_file_fd = virPidFileAcquirePath(pid_file, getpid())) < 0) {
- ret = VIR_LOCK_DAEMON_ERR_PIDFILE;
- goto cleanup;
- }
-
- if ((rv = virLockDaemonPostExecRestart(privileged)) < 0) {
+ if ((rv = virLockDaemonPostExecRestart(state_file,
+ pid_file,
+ &pid_file_fd,
+ privileged)) < 0) {
ret = VIR_LOCK_DAEMON_ERR_INIT;
goto cleanup;
}
/* rv == 1, means we setup everything from saved state,
- * so we only setup stuff from scratch if rv == 0 */
+ * so only (possibly) daemonize and setup stuff from
+ * scratch if rv == 0
+ */
if (rv == 0) {
+ if (godaemon) {
+ char ebuf[1024];
+
+ if (chdir("/") < 0) {
+ VIR_ERROR(_("cannot change to root directory: %s"),
+ virStrerror(errno, ebuf, sizeof(ebuf)));
+ goto cleanup;
+ }
+
+ if ((statuswrite = virLockDaemonForkIntoBackground(argv[0])) < 0) {
+ VIR_ERROR(_("Failed to fork as daemon: %s"),
+ virStrerror(errno, ebuf, sizeof(ebuf)));
+ goto cleanup;
+ }
+ }
+
+ /* If we have a pidfile set, claim it now, exiting if already taken */
+ if ((pid_file_fd = virPidFileAcquirePath(pid_file, getpid())) < 0) {
+ ret = VIR_LOCK_DAEMON_ERR_PIDFILE;
+ goto cleanup;
+ }
+
if (!(lockDaemon = virLockDaemonNew(config, privileged))) {
ret = VIR_LOCK_DAEMON_ERR_INIT;
goto cleanup;
@@ -1388,7 +1445,9 @@ int main(int argc, char **argv) {
virNetServerRun(lockDaemon->srv);
if (execRestart &&
- virLockDaemonPreExecRestart(lockDaemon->srv, argv) < 0)
+ virLockDaemonPreExecRestart(state_file,
+ lockDaemon->srv,
+ argv) < 0)
ret = VIR_LOCK_DAEMON_ERR_REEXEC;
else
ret = 0;
@@ -1410,6 +1469,7 @@ cleanup:
virPidFileReleasePath(pid_file, pid_file_fd);
VIR_FREE(pid_file);
VIR_FREE(sock_file);
+ VIR_FREE(state_file);
VIR_FREE(run_dir);
return ret;
--
1.8.4.2
10 years, 10 months
[libvirt] [PATCH v2 0/8] Add throttle blkio cgroup support for libvirt
by Gao feng
Right now, libvirt only supports the cfq based blkio cgorup,
this means if the block devices doesn't use cfq scheduler, the
blkio cgroup will loss effect.
This patchset adds the throttle blkio cgroup support for libvirt,
introduces four elements for domain configuration and extend the
virsh command blkiotune.
This patchset is a new version of Guan Qiang's patchset
://www.redhat.com/archives/libvir-list/2013-October/msg01066.html
Change from v1:
1, rearrange the order of patches
2, change the options/elements of throttle blkio cgroup to consist
with disk iotune.
3, fix complie error when cgroup is unavailable.
4, remove virCgroupSetBlkioDevice, split virCgroupSetBlkioDeviceBps
and virCgroupSetBlkioDeviceIops
Change from Guan Qiang's patchset:
1, split to 8 patches, make logic more clear
2, change the type of read/write iops form unsigned long long to unsigned int,
trying to set read/write iops to the value which bigger than max number of
unsigned int will fail.
3, fix some logic shortage.
Gao feng (8):
rename virDomainBlkioDeviceWeightParseXML to
virDomainBlkioDeviceParseXML
rename virBlkioDeviceWeightArrayClear to virBlkioDeviceArrayClear
rename virBlkioDeviceWeightPtr to virBlkioDevicePtr
domain: introduce xml elements for throttle blkio cgroup
blkio: Setting throttle blkio cgroup for domain
virsh: add setting throttle blkio cgroup option to blkiotune
qemu: allow to setup throttle blkio cgroup through virsh
lxc: allow to setup throttle blkio cgroup through virsh
docs/schemas/domaincommon.rng | 28 +-
include/libvirt/libvirt.h.in | 45 ++
src/conf/domain_conf.c | 113 +++-
src/conf/domain_conf.h | 16 +-
src/libvirt_private.syms | 6 +-
src/lxc/lxc_cgroup.c | 29 +-
src/lxc/lxc_driver.c | 649 ++++++++++++++++++++-
src/qemu/qemu_cgroup.c | 29 +-
src/qemu/qemu_driver.c | 443 ++++++++++++--
src/util/vircgroup.c | 224 ++++++-
src/util/vircgroup.h | 16 +
.../qemuxml2argv-blkiotune-device.xml | 8 +
tools/virsh-domain.c | 64 ++
tools/virsh.pod | 36 +-
14 files changed, 1583 insertions(+), 123 deletions(-)
--
1.8.3.1
10 years, 10 months
[libvirt] [RFC PATCH 0/3] Implement two-tier driver loading
by Adam Walters
This patchset implements a two-tier driver loading system. I split the hypervisor drivers out into their own tier, which is loaded after the other drivers. This has the net effect of ensuring that things like secrets, networks, etc., are initialized and auto-started before any hypervisors, such as qemu, lxc, etc., are touched. This resolves the race condition present when starting libvirtd while domains are running, which happens when restarting libvirtd after having started at least one domain.
This patch will work without my config driver patchset, but does prevent RBD storage pools from auto-starting. It may also affect other pool types, but I only have file and RBD to test with, personally. The RBD storage pool is only affected because it requires a hypervisor connection (prior to this patchset, that connection was hardcoded to be a connection to qemu on localhost) in order to look up secrets. Any pool type that does not use/need data outside of the base storage pool definition should continue to auto-start (file backed pools definitely still work) and also no longer be part of the restart race condition.
For anyone who is not familiar with the race condition I mentioned above, the basic description is the upon restarting libvirtd, any running QEMU domains using storage pool backed disks are killed (randomly) due to their storage pool not being online. This is due to storage pool auto-start not having finished before QEMU initalization runs.
I would appreciate any comments and suggestions about this patchset. It works for me on 4 machines running three different distros of Linux (Archlinux, Gentoo, and CentOS), so I would imagine it should work most anywhere.
Adam Walters (3):
driver: Implement new state driver field
storage: Fix hardcoded qemu connection
libvirt: Implement two-tier driver loading
src/config/config_driver.c | 1 +
src/driver.h | 6 ++++
src/interface/interface_backend_netcf.c | 1 +
src/libvirt.c | 57 ++++++++++++++++++++++++++++-----
src/libxl/libxl_driver.c | 1 +
src/lxc/lxc_driver.c | 1 +
src/network/bridge_driver.c | 1 +
src/node_device/node_device_hal.c | 1 +
src/node_device/node_device_udev.c | 1 +
src/nwfilter/nwfilter_driver.c | 1 +
src/qemu/qemu_driver.c | 1 +
src/remote/remote_driver.c | 1 +
src/secret/secret_driver.c | 1 +
src/storage/storage_driver.c | 13 ++++----
src/uml/uml_driver.c | 1 +
src/xen/xen_driver.c | 1 +
16 files changed, 75 insertions(+), 14 deletions(-)
--
1.8.5.2
10 years, 10 months
[libvirt] Add GVirConfigDomainDiskDriver
by Christophe Fergeau
Hey,
I wanted to add support in libvirt-gconfig for the 'discard' attribute of
the disk driver node. If I follow the way the API is currently done, it
would be an additional method to GVirConfigDomainDisk. However, there are
quite a few attributes attached to the disk driver node, so I felt it was
preferrable to have a dedicated GVirConfigDomainDiskDriver class. This also
matches better other places of libvirt-gconfig API.
I've implemented support for most of the attributes of the disk driver node,
as a result the corresponding methods in GVirConfigDomainDisk have been deprecated.
Christophe
10 years, 10 months
[libvirt] [libvirt-glib] config: Fix typo preventing clock removal from a domain
by Christophe Fergeau
Commit 1c8ce29 added a way to unset a GVirConfigDomainClock set on a
GVirConfigDomain by calling gvir_config_domain_set_clock() with a NULL
argument.
However, a typo in a g_return_if_fail precondition prevents this code from
ever being called: g_return_if_fail(clock != NULL) is used while it should
have been g_return_if_fail(clock == NULL) as in all other preconditions in
1c8ce29.
---
libvirt-gconfig/libvirt-gconfig-domain.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libvirt-gconfig/libvirt-gconfig-domain.c b/libvirt-gconfig/libvirt-gconfig-domain.c
index 3c28a4a..6cd2f86 100644
--- a/libvirt-gconfig/libvirt-gconfig-domain.c
+++ b/libvirt-gconfig/libvirt-gconfig-domain.c
@@ -552,7 +552,7 @@ void gvir_config_domain_set_clock(GVirConfigDomain *domain,
GVirConfigDomainClock *klock)
{
g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
- g_return_if_fail(klock != NULL || GVIR_CONFIG_IS_DOMAIN_CLOCK(klock));
+ g_return_if_fail(klock == NULL || GVIR_CONFIG_IS_DOMAIN_CLOCK(klock));
gvir_config_object_attach_replace(GVIR_CONFIG_OBJECT(domain),
"clock",
--
1.8.4.2
10 years, 10 months
[libvirt] [PATCH] Add helper program to create custom leases
by Nehal J Wani
Introduce helper program to catch events from dnsmasq and maintain a custom
lease file per network. It supports dhcpv4 and dhcpv6. The file is saved as
"<interface-name>.status".
The format of each lease is:
<expiry-time (epoch time)> <mac> <iaid> <ip-address> <hostname> <clientid>
Example of custom leases file content:
1385245780 52:54:00:2f:ba:76 * 192.168.150.153 * *
1385245781 52:54:00:2f:ba:76 3127926 2001:db8:ca2:2:1::6c * 00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec
1385245964 52:54:00:44:7c:d7 * 192.168.150.219 iiit-ad885e4aa1 01:52:54:00:44:7c:d7
1385245964 52:54:00:44:7c:d7 * 192.168.150.219 * 01:52:54:00:44:7c:d7
1385246016 52:54:00:5d:99:92 * 192.168.150.212 iiit-ad885e4aa1 01:52:54:00:5d:99:92
1385246041 52:54:00:3b:16:e0 * 192.168.150.207 * *
1385246081 52:54:00:db:dd:98 * 192.168.150.234 * *
1385246088 52:54:00:db:dd:98 14409112 2001:db8:ca2:2:1::6d * 00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec
---
src/util/leaseshelper.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 232 insertions(+)
create mode 100644 src/util/leaseshelper.c
diff --git a/src/util/leaseshelper.c b/src/util/leaseshelper.c
new file mode 100644
index 0000000..9ed22a6
--- /dev/null
+++ b/src/util/leaseshelper.c
@@ -0,0 +1,232 @@
+/*
+ * leasehelper.c: Helper program to create custom leases file
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Nehal J Wani <nehaljw.kkd1(a)gmail.com>
+ *
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "virutil.h"
+#include "virthread.h"
+#include "virfile.h"
+#include "virbuffer.h"
+#include "virstring.h"
+#include "virerror.h"
+#include "viralloc.h"
+#include "configmake.h"
+
+#define VIR_FROM_THIS VIR_FROM_NETWORK
+
+/**
+ * VIR_NETWORK_DHCP_LEASE_FIELDS:
+ *
+ * Macro providing the maximum number of fields in an entry in
+ * the leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FIELDS 6
+/**
+ * VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX:
+ *
+ * Macro providing the upper limit on the size of leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX 2097152
+
+/*
+ * Use this when passing possibly-NULL strings to printf-a-likes.
+ */
+# define EMPTY_STR(s) ((s) ? (s) : "*")
+
+int
+main(int argc, char **argv) {
+
+ FILE *g = fopen("/tmp/wtf", "a");
+ int j;
+ for (j = 0; j < argc; j++)
+ fprintf(g, "called :: : %s, ", argv[j]);
+ fprintf(g, "\n");
+ fclose(g);
+
+ /* Doesn't hurt to check */
+ if (argc < 4) {
+ /* Refer man page of dnsmasq --dhcp-script for more details */
+ fprintf(stderr, "Usage: $program $action ${mac|clientid} $ip\n");
+ return -1;
+ }
+
+ const char *program_name = argv[0];
+ const char *action = argv[1];
+ const char *interface = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_INTERFACE"));
+ const char *expirytime = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_LEASE_EXPIRES"));
+ const char *mac = argv[2];
+ const char *ip = argv[3];
+ const char *iaid = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_IAID"));
+ const char *hostname = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_SUPPLIED_HOSTNAME"));
+ const char *clientid = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_CLIENT_ID"));
+ const char *leases_str = NULL;
+ char *lease_file = NULL;
+ char *lease_entries = NULL;
+ char *lease_entry = NULL;
+ char **lease_fields = NULL;
+ bool delete = false;
+ bool add = false;
+ int rv = -1;
+ int lease_file_len = 0;
+ FILE *fp = NULL;
+ long long expirytime_tmp = 0;
+ virBuffer buf_new_lease = VIR_BUFFER_INITIALIZER;
+ virBuffer buf_all_leases = VIR_BUFFER_INITIALIZER;
+
+ if (setlocale(LC_ALL, "") == NULL ||
+ bindtextdomain(PACKAGE, LOCALEDIR) == NULL ||
+ textdomain(PACKAGE) == NULL) {
+ fprintf(stderr, _("%s: initialization failed\n"), program_name);
+ exit(EXIT_FAILURE);
+ }
+
+ if (virThreadInitialize() < 0 ||
+ virErrorInitialize() < 0) {
+ fprintf(stderr, _("%s: initialization failed\n"), program_name);
+ exit(EXIT_FAILURE);
+ }
+
+ if (virAsprintf(&lease_file, "%s/%s.status", LOCALSTATEDIR
+ "/lib/libvirt/dnsmasq/", interface) < 0)
+ goto cleanup;
+
+ if (virGetEnvAllowSUID("DNSMASQ_IAID")) {
+ mac = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_MAC"));
+ clientid = argv[2];
+ }
+
+ /* Make sure dnsmasq knows the interface, otherwise something is wrong */
+ if (STREQ(interface, "*"))
+ goto cleanup;
+
+ /* Make sure the file exists. If not, 'touch' it */
+ if (virFileTouch(lease_file, 0644) < 0)
+ goto cleanup;
+
+ /* Read entire contents */
+ if ((lease_file_len = virFileReadAll(lease_file,
+ VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX,
+ &lease_entries)) < 0) {
+ goto cleanup;
+ }
+
+ if (STREQ(action, "add") || STREQ(action, "old") || STREQ(action, "del")) {
+ if (mac || STREQ(action, "del")) {
+ /* Delete the corresponding lease */
+ delete = true;
+ if (STREQ(action, "add") || STREQ(action, "old")) {
+ fprintf(stderr, "add|old\n");
+ add = true;
+ /* Enter new lease */
+ virBufferAsprintf(&buf_new_lease, "%s %s %s %s %s %s\n",
+ expirytime, mac, iaid, ip, hostname, clientid);
+
+ if (virBufferError(&buf_new_lease)) {
+ virBufferFreeAndReset(&buf_new_lease);
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+ }
+ }
+
+ lease_entry = lease_entries[0] == '\0' ? NULL : lease_entries;
+
+ while (lease_entry) {
+ int nfields = 0;
+
+ char *eol = strchr(lease_entry, '\n');
+ *eol = '\0';
+
+ /* Split the lease line */
+ if (!(lease_fields = virStringSplit(lease_entry, " ",
+ VIR_NETWORK_DHCP_LEASE_FIELDS)))
+ goto cleanup;
+
+ nfields = virStringListLength(lease_fields);
+
+ /* Forward lease_entry to the next lease */
+ lease_entry = strchr(lease_entry, '\0');
+ if (lease_entry - lease_entries + 1 < lease_file_len)
+ lease_entry++;
+ else
+ lease_entry = NULL;
+
+ if (nfields != VIR_NETWORK_DHCP_LEASE_FIELDS)
+ goto cleanup;
+
+ if (virStrToLong_ll(lease_fields[0], NULL, 10, &expirytime_tmp) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to convert lease expiry time to integer: %s"),
+ lease_fields[0]);
+ goto cleanup;
+ }
+
+ /* Check whether lease has expired or not */
+ if (expirytime_tmp < (long long) time(NULL))
+ continue;
+ else if (delete && STREQ(lease_fields[3], ip))
+ continue;
+ else {
+ virBufferAsprintf(&buf_all_leases, "%s %s %s %s %s %s\n",
+ lease_fields[0], lease_fields[1], lease_fields[2],
+ lease_fields[3], lease_fields[4], lease_fields[5]);
+
+ if (virBufferError(&buf_all_leases)) {
+ virBufferFreeAndReset(&buf_all_leases);
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+ }
+
+ if (add) {
+ virBufferAsprintf(&buf_all_leases, "%s", virBufferContentAndReset(&buf_new_lease));
+
+ if (virBufferError(&buf_all_leases)) {
+ virBufferFreeAndReset(&buf_all_leases);
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ rv = 0;
+
+ /* Write to file */
+ leases_str = virBufferContentAndReset(&buf_all_leases);
+ if (!leases_str)
+ leases_str = "";
+
+ if (virFileWriteStr(lease_file, leases_str, 0) < 0)
+ rv = -1;
+
+cleanup:
+ VIR_FREE(lease_file);
+ VIR_FREE(lease_entries);
+ if (lease_fields)
+ virStringFreeList(lease_fields);
+ return rv;
+}
--
1.8.1.4
10 years, 10 months
[libvirt] [PATCH] vbox: add support for v4.2.20+ and v4.3.4+
by Jean-Baptiste Rouault
While working on adding virDomain*Stats support to the vbox driver, we
found bugs in the VirtualBox API C bindings. These bugs have been fixed
in versions 4.2.20 and 4.3.4.
However, the changes in the C bindings are incompatible with the vbox_CAPI_v4_2.h
and vbox_CAPI_v4_3.h files which are bundled in libvirt source code. This is why the
following patch adds vbox_CAPI_v4_2_20.h and vbox_CAPI_v4_3_4.h.
We tried to keep compatibility with older VirtualBox 4.2.x and 4.3.x releases so we
added a "SPECIAL_VERSION" identifier to conditionnaly include the right header.
I'm not really pleased with this "SPECIAL_VERSION" identifier, maybe we could instead
increase the precision of "VBOX_API_VERSION", for example 4002 would become 4002000.
This would permit us to select the right header based on the VBOX_API_VERSION only, what
do you think ?
Jean-Baptiste Rouault (1):
vbox: add support for v4.2.20+ and v4.3.4+
src/Makefile.am | 4 +-
src/vbox/vbox_CAPI_v4_2_20.h | 9001 +++++++++++++++++++++++++++++++++++
src/vbox/vbox_CAPI_v4_3_4.h | 10321 +++++++++++++++++++++++++++++++++++++++++
src/vbox/vbox_V2_2.c | 1 +
src/vbox/vbox_V3_0.c | 1 +
src/vbox/vbox_V3_1.c | 1 +
src/vbox/vbox_V3_2.c | 1 +
src/vbox/vbox_V4_0.c | 1 +
src/vbox/vbox_V4_1.c | 1 +
src/vbox/vbox_V4_2.c | 1 +
src/vbox/vbox_V4_2_20.c | 14 +
src/vbox/vbox_V4_3.c | 1 +
src/vbox/vbox_V4_3_4.c | 14 +
src/vbox/vbox_driver.c | 20 +-
src/vbox/vbox_tmpl.c | 12 +-
15 files changed, 19389 insertions(+), 5 deletions(-)
create mode 100644 src/vbox/vbox_CAPI_v4_2_20.h
create mode 100644 src/vbox/vbox_CAPI_v4_3_4.h
create mode 100644 src/vbox/vbox_V4_2_20.c
create mode 100644 src/vbox/vbox_V4_3_4.c
--
1.8.5.1
10 years, 10 months