[libvirt] [PATCHV2] qemu: ask for -enable-fips when FIPS is required
by Eric Blake
On a system that is enforcing FIPS, most libraries honor the
current mode by default. Qemu, on the other hand, refused to
honor FIPS mode unless you add the '-enable-fips' command
line option; worse, this option is not discoverable via QMP,
and is only present on binaries built for Linux. So, if we
detect FIPS mode, then we unconditionally ask for FIPS; either
qemu is new enough to have the option and then correctly
cripple insecure VNC passwords, or it is so old that we are
correctly avoiding a FIPS violation by preventing qemu from
starting. Meanwhile, if we don't detect FIPS mode, then
omitting the argument is safe whether the qemu has the option
(but it would do nothing because FIPS is disabled) or whether
qemu lacks the option (including in the case where we are not
running on Linux).
The testsuite was a bit interesting: we don't want our test
to depend on whether it is being run in FIPS mode, so I had
to tweak things to set the capability bit outside of our
normal interaction with capability parsing.
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=1035474
* src/qemu/qemu_capabilities.h (QEMU_CAPS_ENABLE_FIPS): New bit.
* src/qemu/qemu_capabilities.c (virQEMUCapsInitQMP): Conditionally
set capability according to detection of FIPS mode.
* src/qemu/qemu_command.c (qemuBuildCommandLine): Use it.
* tests/qemucapabilitiestest.c (testQemuCaps): Conditionally set
capability to test expected output.
* tests/qemucapabilitiesdata/caps_1.2.2-1.caps: Update list.
* tests/qemucapabilitiesdata/caps_1.6.0-1.caps: Likewise.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
src/qemu/qemu_capabilities.c | 28 +++++++++++++++++++++++++++-
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 2 ++
tests/qemucapabilitiesdata/caps_1.2.2-1.caps | 1 +
tests/qemucapabilitiesdata/caps_1.6.0-1.caps | 1 +
tests/qemucapabilitiestest.c | 20 +++++++++++++++-----
6 files changed, 47 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 5e9c65e..9470814 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -245,7 +245,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"kvm-pit-lost-tick-policy",
"boot-strict", /* 160 */
- "pvpanic", /* 161 */
+ "pvpanic",
+ "enable-fips",
);
struct _virQEMUCaps {
@@ -2630,6 +2631,31 @@ virQEMUCapsInitQMP(virQEMUCapsPtr qemuCaps,
config.data.nix.path = monpath;
config.data.nix.listen = false;
+ /* Qemu 1.2 and later have a binary flag -enable-fips that must be
+ * used for VNC auth to obey FIPS settings; but the flag only
+ * exists on Linux, and with no way to probe for it via QMP. Our
+ * solution: if FIPS mode is required, then unconditionally use
+ * the flag, regardless of qemu version, for the following matrix:
+ *
+ * old QEMU new QEMU
+ * FIPS enabled doesn't start VNC auth disabled
+ * FIPS disabled/missing VNC auth enabled VNC auth enabled
+ *
+ * Setting the flag here instead of in virQEMUCapsInitQMPMonitor
+ * or virQEMUCapsInitHelp also allows the testsuite to be
+ * independent of FIPS setting.
+ */
+ if (virFileExists("/proc/sys/crypto/fips_enabled")) {
+ char buf[sizeof("1\n")];
+ char *ptr = buf;
+
+ if (virFileReadAll("/proc/sys/crypto/fips_enabled",
+ sizeof(buf), &ptr) < 0)
+ goto cleanup;
+ if (*buf == '1')
+ virQEMUCapsSet(qemuCaps, QEMU_CAPS_ENABLE_FIPS);
+ }
+
VIR_DEBUG("Try to get caps via QMP qemuCaps=%p", qemuCaps);
/*
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index bbf4972..efb3f43 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -200,6 +200,7 @@ enum virQEMUCapsFlags {
QEMU_CAPS_KVM_PIT_TICK_POLICY = 159, /* kvm-pit.lost_tick_policy */
QEMU_CAPS_BOOT_STRICT = 160, /* -boot strict */
QEMU_CAPS_DEVICE_PANIC = 161, /* -device pvpanic */
+ QEMU_CAPS_ENABLE_FIPS = 162, /* -enable-fips */
QEMU_CAPS_LAST, /* this must always be the last item */
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index a80559e..d723dc8 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7747,6 +7747,8 @@ qemuBuildCommandLine(virConnectPtr conn,
}
}
virCommandAddArg(cmd, "-S"); /* freeze CPU */
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_ENABLE_FIPS))
+ virCommandAddArg(cmd, "-enable-fips");
if (qemuBuildMachineArgStr(cmd, def, qemuCaps) < 0)
goto error;
diff --git a/tests/qemucapabilitiesdata/caps_1.2.2-1.caps b/tests/qemucapabilitiesdata/caps_1.2.2-1.caps
index 73a561d..c3ae814 100644
--- a/tests/qemucapabilitiesdata/caps_1.2.2-1.caps
+++ b/tests/qemucapabilitiesdata/caps_1.2.2-1.caps
@@ -112,4 +112,5 @@
<flag name='usb-storage'/>
<flag name='usb-storage.removable'/>
<flag name='kvm-pit-lost-tick-policy'/>
+ <flag name='enable-fips'/>
</qemuCaps>
diff --git a/tests/qemucapabilitiesdata/caps_1.6.0-1.caps b/tests/qemucapabilitiesdata/caps_1.6.0-1.caps
index c7ce591..2d50cf9 100644
--- a/tests/qemucapabilitiesdata/caps_1.6.0-1.caps
+++ b/tests/qemucapabilitiesdata/caps_1.6.0-1.caps
@@ -138,4 +138,5 @@
<flag name='boot-strict'/>
<flag name='pvpanic'/>
<flag name='reboot-timeout'/>
+ <flag name='enable-fips'/>
</qemuCaps>
diff --git a/tests/qemucapabilitiestest.c b/tests/qemucapabilitiestest.c
index d912171..3b34f78 100644
--- a/tests/qemucapabilitiestest.c
+++ b/tests/qemucapabilitiestest.c
@@ -31,6 +31,7 @@ typedef testQemuData *testQemuDataPtr;
struct _testQemuData {
virDomainXMLOptionPtr xmlopt;
const char *base;
+ bool fips;
};
static qemuMonitorTestPtr
@@ -192,6 +193,12 @@ testQemuCaps(const void *opaque)
qemuMonitorTestGetMonitor(mon)) < 0)
goto cleanup;
+ /* So that our test does not depend on the contents of /proc, we
+ * hoisted the setting of ENABLE_FIPS to virQEMUCapsInitQMP. But
+ * we do want to test the effect of that flag. */
+ if (data->fips)
+ virQEMUCapsSet(capsComputed, QEMU_CAPS_ENABLE_FIPS);
+
if (testQemuCapsCompare(capsProvided, capsComputed) < 0)
goto cleanup;
@@ -227,16 +234,19 @@ mymain(void)
data.xmlopt = xmlopt;
-#define DO_TEST(name) \
- data.base = name; \
- if (virtTestRun(name, testQemuCaps, &data) < 0) \
+#define DO_TEST_FULL(name, use_fips) \
+ data.base = name; \
+ data.fips = use_fips; \
+ if (virtTestRun(name, testQemuCaps, &data) < 0) \
ret = -1
- DO_TEST("caps_1.2.2-1");
+#define DO_TEST(name) DO_TEST_FULL(name, false)
+
+ DO_TEST_FULL("caps_1.2.2-1", true);
DO_TEST("caps_1.3.1-1");
DO_TEST("caps_1.4.2-1");
DO_TEST("caps_1.5.3-1");
- DO_TEST("caps_1.6.0-1");
+ DO_TEST_FULL("caps_1.6.0-1", true);
DO_TEST("caps_1.6.50-1");
virObjectUnref(xmlopt);
--
1.8.4.2
10 years, 11 months
[libvirt] [PATCHv2.5] specfile: fix make rpm when with_driver_modules is 1
by Laine Stump
Commit ff76566 moved around things in the specfiles to put
driver-specific files into their appropriate sub-packages (when
with_driver_modules == 1), but accidentally changed things so that the
deamon-driver-network and daemon-config-network files were only
included in a package when with_driver_modules == 0. This broke "make
rpm" on fedora (where with_driver_modules == 1).
This patch follows the pattern (already used for the files in other
sub-modules) of duplicating the files for the main package
(!with_driver_modules) and the sub-package (with_driver_modules).
---
Changes from V1: realized that %{_datadir} is /usr/share, so
%{_datadir}/libvirt/networks/default.xml should be installed as a part
of daemon-driver-network (or the main package, if not building with
driver modules).
libvirt.spec.in | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 849ec80..015e627 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1894,11 +1894,6 @@ exit 0
%endif
%endif # ! %{with_driver_modules}
- %if %{with_network}
-%files daemon-config-network
-%defattr(-, root, root)
- %endif
-
%if %{with_nwfilter}
%files daemon-config-nwfilter
%defattr(-, root, root)
@@ -1915,6 +1910,14 @@ exit 0
%if %{with_network}
%files daemon-driver-network
%defattr(-, root, root)
+%dir %attr(0700, root, root) %{_sysconfdir}/libvirt/qemu/
+%dir %attr(0700, root, root) %{_sysconfdir}/libvirt/qemu/networks/
+%dir %attr(0700, root, root) %{_sysconfdir}/libvirt/qemu/networks/autostart
+%dir %{_datadir}/libvirt/networks/
+%{_datadir}/libvirt/networks/default.xml
+%ghost %dir %{_localstatedir}/run/libvirt/network/
+%dir %attr(0700, root, root) %{_localstatedir}/lib/libvirt/network/
+%dir %attr(0755, root, root) %{_localstatedir}/lib/libvirt/dnsmasq/
%{_libdir}/%{name}/connection-driver/libvirt_driver_network.so
%endif
--
1.8.3.1
10 years, 11 months
[libvirt] hindsight on qcow2v3 format
by Eric Blake
I spent a couple hours today debugging a bug in an older branch of
libvirt (0.10.2) - one where libvirt only knew how to parse version 2
qcow2 images. Alas, that version of libvirt can be coerced into reading
the header of a random file under the assumption that it is qcow2 data,
and where it tries to find the backing format information in the header
extensions without first validating that the file format actually
matches qcow2 (that is, it looks for header extensions starting at
offset 72 without first checking the version field (bytes 4-7) contains 2).
So far, we've been lucky: since libvirt is trying to parse 72-75 as a
version 2 extension header magic number, and the number is stored in big
endian format, we end up reading the first 4 bytes of the version 3
incompatible_features field, which so far are always 0 (we don't have
that many incompatible features yet), and that happens to be the magic
number for end of extension headers; and thus libvirt quit trying to
look for any further extension headers. Furthermore, since libvirt
already refuses to probe backing file format unless explicitly allowed
by user action (since mis-probing a raw file is CVE-worthy if done
automatically), the damage stopped there, and the worst I could do
(without intentionally bypassing the CVE safety valve) was fail a test
in the libvirt testsuite when using version 3 files. But it DOES mean
that libvirt fails to find the backing header format extension of a v3
file, even when one is present, because libvirt fails to start looking
at the right offset.
But it does raise a question: What happens if we eventually DO reach bit
32, so that bytes 72-75 is no longer all 0s and therefore no longer the
end-of-extension marker? It might be possible to write a file that has
one interpretation as a valid qcow2v3, while having a different
interpretation by the older libvirt, such that libvirt tries to treat a
backing file as an incorrect format if it is probing.
Is it worth tweaking docs/specs/qcow2.txt to permanently change the
incompatible_features field to be 4 bytes (76-79) and mandate that bytes
72-75 always be 0, as a conservative way to prevent other misbehavior of
programs like libvirt 0.10.2 that have code paths that don't correctly
validate for version 2 files? And if we ever really did hit a situation
of having 31 or more incompatible features, I could envision using bit
31 as an incompatible_feature witness that tells new enough qemu to look
at some other offset for remaining feature bits (thankfully, the
semantics of the incompatible_feature field mean that older qemu that
honors version 3 formats will reject a file with incompatible_feature
bit 31 set), so this is no real loss in the number of potential
incompatible features being added.
If we had a time machine, I would suggest that we change 72-75 to have
constant contents as a new magic number, and 76-79 encode the length of
the remaining header, and delay the location of incompatible_features
into the remaining header; such that this situation of libvirt looking
for extensions would still find known could have still found the backing
file format extension header. But that ship has sailed - all we can do
now is decide to encode 72-75 as permanent 0s.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
10 years, 11 months
[libvirt] [PATCH v2] Set the 'container_ttys' env variable for LXC consoles
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Systemd specified that any /dev/pts/NNN device on which it
is expected to spawn a agetty login, should be listed in
the 'container_ttys' env variable. It should just contain
the relative paths, eg 'pts/0' not '/dev/pts/0' and should
be space separated.
http://cgit.freedesktop.org/systemd/systemd/commit/?id=1d97ff7dd71902a560...
In v2:
- Rewrite loop with virBufferTrim
- Don't include first pty in env
- Only set env if at least one pty is listed
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/lxc/lxc_container.c | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 51fa1b3..c885782 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -196,10 +196,33 @@ int lxcContainerHasReboot(void)
*
* Returns a virCommandPtr
*/
-static virCommandPtr lxcContainerBuildInitCmd(virDomainDefPtr vmDef)
+static virCommandPtr lxcContainerBuildInitCmd(virDomainDefPtr vmDef,
+ char **ttyPaths,
+ size_t nttyPaths)
{
char uuidstr[VIR_UUID_STRING_BUFLEN];
virCommandPtr cmd;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ size_t i;
+
+ /* 'container_ptys' must exclude the PTY associated with
+ * the /dev/console device, hence start at 1 not 0
+ */
+ for (i = 1; i < nttyPaths; i++) {
+ if (!STRPREFIX(ttyPaths[0], "/dev/")) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Expected a /dev path for '%s'"),
+ ttyPaths[0]);
+ virBufferFreeAndReset(&buf);
+ return NULL;
+ }
+ virBufferAdd(&buf, ttyPaths[i] + 5, -1);
+ virBufferAddChar(&buf, ' ');
+ }
+ virBufferTrim(&buf, NULL, 1);
+
+ if (virBufferError(&buf))
+ return NULL;
virUUIDFormat(vmDef->uuid, uuidstr);
@@ -212,11 +235,14 @@ static virCommandPtr lxcContainerBuildInitCmd(virDomainDefPtr vmDef)
virCommandAddEnvString(cmd, "TERM=linux");
virCommandAddEnvString(cmd, "container=lxc-libvirt");
virCommandAddEnvPair(cmd, "container_uuid", uuidstr);
+ if (nttyPaths > 1)
+ virCommandAddEnvPair(cmd, "container_ttys", virBufferCurrentContent(&buf));
virCommandAddEnvPair(cmd, "LIBVIRT_LXC_UUID", uuidstr);
virCommandAddEnvPair(cmd, "LIBVIRT_LXC_NAME", vmDef->name);
if (vmDef->os.cmdline)
virCommandAddEnvPair(cmd, "LIBVIRT_LXC_CMDLINE", vmDef->os.cmdline);
+ virBufferFreeAndReset(&buf);
return cmd;
}
@@ -1789,7 +1815,9 @@ static int lxcContainerChild(void *data)
if ((hasReboot = lxcContainerHasReboot()) < 0)
goto cleanup;
- cmd = lxcContainerBuildInitCmd(vmDef);
+ cmd = lxcContainerBuildInitCmd(vmDef,
+ argv->ttyPaths,
+ argv->nttyPaths);
virCommandWriteArgLog(cmd, 1);
if (lxcContainerSetID(vmDef) < 0)
--
1.8.3.1
10 years, 11 months
[libvirt] [PATCH] docs: fix address type for disks
by Martin Kletzander
Disks have type='drive', not type='disk'.
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
docs/formatdomain.html.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 0067e8f..2b8bc8f 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -2355,7 +2355,7 @@
address to use for a given device is constrained in part by the
device and the architecture of the guest. For example,
a <code><disk></code> device
- uses <code>type='disk'</code>, while
+ uses <code>type='drive'</code>, while
a <code><console></code> device would
use <code>type='pci'</code> on i686 or x86_64 guests,
or <code>type='spapr-vio'</code> on PowerPC64 pseries guests.
--
1.8.5.1
10 years, 11 months
[libvirt] [PATCH] storage: resize vol against real allocated size
by Michal Privoznik
From: Wang Sen <wangsen(a)linux.vnet.ibm.com>
Currently, 'vol-resize --allocate' allocates new space at the
vol->capacity offset. But the vol->capacity is not necessarily the same
as vol->allocation. For instance:.
[root@localhost ~]# virsh vol-list --pool tmp-pool --details
Name Path Type Capacity Allocation
-------------------------------------------------------------
tmp-vol /root/tmp-pool/tmp-vol file 1.00 GiB 1.00 GiB
[root@localhost ~]# virsh vol-resize tmp-vol --pool tmp-pool 2G
[root@localhost ~]# virsh vol-list --pool tmp-pool --details
Name Path Type Capacity Allocation
-------------------------------------------------------------
tmp-vol /root/tmp-pool/tmp-vol file 2.00 GiB 1.00 GiB
So, if we want to allocate more bytes, so the file is say 3G big, the
real allocated size is 2G actually:
[root@localhost ~]# virsh vol-resize tmp-vol --pool tmp-pool 3G --allocate
[root@localhost ~]# virsh vol-list --pool tmp-pool --details
Name Path Type Capacity Allocation
-------------------------------------------------------------
tmp-vol /root/tmp-pool/tmp-vol file 3.00 GiB 2.00 GiB
This commit uses the correct vol->allocation instead of incorrect
vol->capacity, so the output of the commands above looks like this:
[root@localhost ~]# virsh vol-resize tmp-vol --pool tmp-pool 3G --allocate
[root@localhost ~]# virsh vol-list --pool tmp-pool --details
Name Path Type Capacity Allocation
-------------------------------------------------------------
tmp-vol /root/tmp-pool/tmp-vol file 3.00 GiB 3.00 GiB
Moreover, if the '--alocate' flag was used, we must update the
vol->allocation member in storageVolResize API too, not just
vol->capacity.
Reported-by: Wang Sen <wangsen(a)linux.vnet.ibm.com>
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/storage/storage_backend_fs.c | 2 +-
src/storage/storage_driver.c | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index 11cf2df..95783be 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -1267,7 +1267,7 @@ virStorageBackendFileSystemVolResize(virConnectPtr conn ATTRIBUTE_UNUSED,
if (vol->target.format == VIR_STORAGE_FILE_RAW) {
return virStorageFileResize(vol->target.path, capacity,
- vol->capacity, pre_allocate);
+ vol->allocation, pre_allocate);
} else {
if (pre_allocate) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index f08255e..816efda 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -2029,6 +2029,8 @@ storageVolResize(virStorageVolPtr obj,
goto out;
vol->capacity = abs_capacity;
+ if (flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE)
+ vol->allocation = abs_capacity;
/* Update pool metadata */
pool->def->allocation += (abs_capacity - vol->capacity);
--
1.8.5.1
10 years, 11 months
[libvirt] non trivial question
by Vasiliy Tolstov
Hi all.
I have very special task - i have some vps on kvm, that sometimes
needs external support help (administration). But i can't trust
external workers and need to known what files are changed.
As i understand best of all - create backup before work and after.
After that check it for difference and decide apply this work or not.
Vps need to run all time. (no downtime for work).
How can i do that and what tools i need to use? Is that possible?
Thanks for all answers.
--
Vasiliy Tolstov,
e-mail: v.tolstov(a)selfip.ru
jabber: vase(a)selfip.ru
10 years, 11 months
[libvirt] [PATCH] examples: Resurrect domsuspend example
by Michal Privoznik
This partially reverts 5eb4b04211 and 62774afb6ba8.
Rewrite the domsuspend example from scratch. This time do it right.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
.gitignore | 1 +
Makefile.am | 4 +-
cfg.mk | 2 +-
configure.ac | 1 +
examples/domsuspend/Makefile.am | 27 ++++
examples/domsuspend/suspend.c | 276 ++++++++++++++++++++++++++++++++++++++++
libvirt.spec.in | 3 +-
7 files changed, 310 insertions(+), 4 deletions(-)
create mode 100644 examples/domsuspend/Makefile.am
create mode 100644 examples/domsuspend/suspend.c
diff --git a/.gitignore b/.gitignore
index 2d364dc..fbb2c01 100644
--- a/.gitignore
+++ b/.gitignore
@@ -71,6 +71,7 @@
/docs/todo.html.in
/examples/domain-events/events-c/event-test
/examples/dominfo/info1
+/examples/domsuspend/suspend
/examples/hellolibvirt/hellolibvirt
/examples/openauth/openauth
/gnulib/lib/*
diff --git a/Makefile.am b/Makefile.am
index 2cbf71a..d7ddd9d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,8 +21,8 @@ GENHTML = genhtml
SUBDIRS = . gnulib/lib include src daemon tools docs gnulib/tests \
tests po examples/domain-events/events-c examples/hellolibvirt \
- examples/dominfo examples/apparmor examples/xml/nwfilter \
- examples/openauth examples/systemtap
+ examples/dominfo examples/domsuspend examples/apparmor \
+ examples/xml/nwfilter examples/openauth examples/systemtap
ACLOCAL_AMFLAGS = -I m4
diff --git a/cfg.mk b/cfg.mk
index fe760a9..67fc432 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -1003,7 +1003,7 @@ exclude_file_name_regexp--sc_prohibit_sprintf = \
exclude_file_name_regexp--sc_prohibit_strncpy = ^src/util/virstring\.c$$
exclude_file_name_regexp--sc_prohibit_strtol = \
- ^src/(util/virsexpr|(vbox|xen|xenxs)/.*)\.c$$
+ ^(src/(util/virsexpr|(vbox|xen|xenxs)/.*)\.c)|(examples/domsuspend/suspend.c)$$
exclude_file_name_regexp--sc_prohibit_xmlGetProp = ^src/util/virxml\.c$$
diff --git a/configure.ac b/configure.ac
index bb92349..cc485d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2555,6 +2555,7 @@ AC_CONFIG_FILES([\
tests/Makefile \
examples/apparmor/Makefile \
examples/domain-events/events-c/Makefile \
+ examples/domsuspend/Makefile \
examples/dominfo/Makefile \
examples/openauth/Makefile \
examples/hellolibvirt/Makefile \
diff --git a/examples/domsuspend/Makefile.am b/examples/domsuspend/Makefile.am
new file mode 100644
index 0000000..b8e65f2
--- /dev/null
+++ b/examples/domsuspend/Makefile.am
@@ -0,0 +1,27 @@
+## Process this file with automake to produce Makefile.in
+
+## 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/>.
+
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
+LDADDS = $(STATIC_BINARIES) $(WARN_CFLAGS) $(top_builddir)/src/libvirt.la \
+ $(COVERAGE_LDFLAGS)
+
+noinst_PROGRAMS=suspend
+
+suspend_SOURCES=suspend.c
+suspend_LDFLAGS=
+suspend_LDADD= $(LDADDS)
diff --git a/examples/domsuspend/suspend.c b/examples/domsuspend/suspend.c
new file mode 100644
index 0000000..ba9dd6e
--- /dev/null
+++ b/examples/domsuspend/suspend.c
@@ -0,0 +1,276 @@
+/*
+ * suspend.c: Demo program showing how to suspend a domain
+ *
+ * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * 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: Michal Privoznik <mprivozn(a)redhat.com>
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <libvirt/libvirt.h>
+#include <libvirt/virterror.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int debug = 0;
+
+#define ERROR(...) \
+do { \
+ fprintf(stderr, "ERROR %s:%d : ", __FUNCTION__, __LINE__); \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+} while (0)
+
+#define DEBUG(...) \
+do { \
+ if (!debug) \
+ break; \
+ fprintf(stderr, "DEBUG %s:%d : ", __FUNCTION__, __LINE__); \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+} while (0)
+
+static void
+print_usage(const char *progname)
+{
+ const char *unified_progname;
+
+ if (!(unified_progname = strrchr(progname, '/')))
+ unified_progname = progname;
+ else
+ unified_progname++;
+
+ printf("\n%s [options] [domain name]\n\n"
+ " options:\n"
+ " -d | --debug enable debug printings\n"
+ " -h | --help print this help\n"
+ " -c | --connect=URI hypervisor connection URI\n"
+ " -s | --seconds=X suspend domain for X seconds (default 1)\n",
+ unified_progname);
+}
+
+static int
+parse_argv(int argc, char *argv[],
+ const char **uri,
+ const char **dom_name,
+ unsigned int *seconds)
+{
+ int ret = -1;
+ int arg;
+ unsigned long val;
+ char *p;
+ struct option opt[] = {
+ {"debug", no_argument, NULL, 'd'},
+ {"help", no_argument, NULL, 'h'},
+ {"connect", required_argument, NULL, 'c'},
+ {"seconds", required_argument, NULL, 's'},
+ {NULL, 0, NULL, 0}
+ };
+
+ while ((arg = getopt_long(argc, argv, "+:dhc:s:", opt, NULL)) != -1) {
+ switch (arg) {
+ case 'd':
+ debug = 1;
+ break;
+ case 'h':
+ print_usage(argv[0]);
+ exit(EXIT_SUCCESS);
+ break;
+ case 'c':
+ *uri = optarg;
+ break;
+ case 's':
+ /* strtoul man page suggest clearing errno prior to call */
+ errno = 0;
+ val = strtoul(optarg, &p, 10);
+ if (errno || *p || p == optarg) {
+ ERROR("Invalid number: '%s'", optarg);
+ goto cleanup;
+ }
+ *seconds = val;
+ if (*seconds != val) {
+ ERROR("Integer overflow: %ld", val);
+ goto cleanup;
+ }
+ break;
+ case ':':
+ ERROR("option '-%c' requires an argument", optopt);
+ exit(EXIT_FAILURE);
+ case '?':
+ if (optopt)
+ ERROR("unsupported option '-%c'. See --help.", optopt);
+ else
+ ERROR("unsupported option '%s'. See --help.", argv[optind - 1]);
+ exit(EXIT_FAILURE);
+ default:
+ ERROR("unknown option");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (argc > optind)
+ *dom_name = argv[optind];
+
+ ret = 0;
+cleanup:
+ return ret;
+}
+
+static int
+fetch_domains(virConnectPtr conn)
+{
+ int num_domains, ret = -1;
+ virDomainPtr *domains = NULL;
+ size_t i;
+ const int list_flags = VIR_CONNECT_LIST_DOMAINS_ACTIVE;
+
+ DEBUG("Fetching list of running domains");
+ num_domains = virConnectListAllDomains(conn, &domains, list_flags);
+
+ DEBUG("num_domains=%d", num_domains);
+ if (num_domains < 0) {
+ ERROR("Unable to fetch list of running domains");
+ goto cleanup;
+ }
+
+ printf("Running domains:\n");
+ printf("----------------\n");
+ for (i = 0; i < num_domains; i++) {
+ virDomainPtr dom = domains[i];
+ const char *dom_name = virDomainGetName(dom);
+ printf("%s\n", dom_name);
+ virDomainFree(dom);
+ }
+
+ ret = 0;
+cleanup:
+ free(domains);
+ return ret;
+}
+
+static int
+suspend_and_resume(virConnectPtr conn,
+ const char *dom_name,
+ unsigned int seconds)
+{
+ int ret = -1;
+ virDomainPtr dom;
+ virDomainInfo dom_info;
+
+ if (!(dom = virDomainLookupByName(conn, dom_name))) {
+ ERROR("Unable to find domain '%s'", dom_name);
+ goto cleanup;
+ }
+
+ if (virDomainGetInfo(dom, &dom_info) < 0) {
+ ERROR("Unable to get domain info");
+ goto cleanup;
+ }
+
+ DEBUG("Domain state %d", dom_info.state);
+
+ switch (dom_info.state) {
+ case VIR_DOMAIN_NOSTATE:
+ case VIR_DOMAIN_RUNNING:
+ case VIR_DOMAIN_BLOCKED:
+ /* In these states the domain can be suspended */
+ DEBUG("Suspending domain");
+ if (virDomainSuspend(dom) < 0) {
+ ERROR("Unable to suspend domain");
+ goto cleanup;
+ }
+
+ DEBUG("Domain suspended. Entering sleep for %u seconds.", seconds);
+ sleep(seconds);
+ DEBUG("Sleeping done. Resuming the domain.");
+
+ if (virDomainResume(dom) < 0) {
+ ERROR("Unable to resume domain");
+ goto cleanup;
+ }
+ break;
+
+ default:
+ /* In all other states domain can't be suspended */
+ ERROR("Domain is not state where it can be suspended: %d",
+ dom_info.state);
+ goto cleanup;
+ }
+
+ ret = 0;
+cleanup:
+ if (dom)
+ virDomainFree(dom);
+ return ret;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ret = EXIT_FAILURE;
+ virConnectPtr conn = NULL;
+ const char *uri = NULL;
+ const char *dom_name = NULL;
+ unsigned int seconds = 1; /* Suspend domain for this long */
+ const int connect_flags = 0; /* No connect flags for now */
+
+ if (parse_argv(argc, argv, &uri, &dom_name, &seconds) < 0)
+ goto cleanup;
+
+ DEBUG("Proceeding with uri=%s dom_name=%s seconds=%u",
+ uri, dom_name, seconds);
+
+ if (!(conn = virConnectOpenAuth(uri,
+ virConnectAuthPtrDefault,
+ connect_flags))) {
+ ERROR("Failed to connect to hypervisor");
+ goto cleanup;
+ }
+
+ DEBUG("Successfully connected");
+
+ if (!dom_name) {
+ if (fetch_domains(conn) == 0)
+ ret = EXIT_SUCCESS;
+ goto cleanup;
+ }
+
+ if (suspend_and_resume(conn, dom_name, seconds) < 0)
+ goto cleanup;
+
+ ret = EXIT_SUCCESS;
+cleanup:
+ if (conn) {
+ int tmp;
+ tmp = virConnectClose(conn);
+ if (tmp < 0) {
+ ERROR("Failed to disconnect from the hypervisor");
+ ret = EXIT_FAILURE;
+ } else if (tmp > 0) {
+ ERROR("One or more references were leaked after "
+ "disconnect from the hypervisor");
+ ret = EXIT_FAILURE;
+ } else {
+ DEBUG("Connection successfully closed");
+ }
+ }
+ return ret;
+}
diff --git a/libvirt.spec.in b/libvirt.spec.in
index f615c62..8867ebc 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1430,7 +1430,7 @@ rm -fr %{buildroot}
# on RHEL 5, thus we need to expand it here.
make install DESTDIR=%{?buildroot} SYSTEMD_UNIT_DIR=%{_unitdir}
-for i in domain-events/events-c dominfo hellolibvirt openauth xml/nwfilter systemtap
+for i in domain-events/events-c dominfo domsuspend hellolibvirt openauth xml/nwfilter systemtap
do
(cd examples/$i ; make clean ; rm -rf .deps .libs Makefile Makefile.in)
done
@@ -2134,6 +2134,7 @@ exit 0
%doc examples/hellolibvirt
%doc examples/domain-events/events-c
%doc examples/dominfo
+%doc examples/domsuspend
%doc examples/openauth
%doc examples/xml
%doc examples/systemtap
--
1.8.5.1
10 years, 11 months
[libvirt] [PATCH 1/1] storage: resize vol against real allocated size when --allocate is specified
by Wang Sen
Currently, vol-resize allocates more bytes against vol->capacity, but
vol->capacity may be different from the real allocated size because --allocate
may not be specified. e.g.
[root@localhost ~]# virsh vol-list --pool tmp-pool --details
name path type Capacity allocated
-------------------------------------------------------------
tmp-vol /root/tmp-pool/tmp-vol file 1.00 GiB 1.00 GiB
[root@localhost ~]# virsh vol-resize tmp-vol --pool tmp-pool 2G
[root@localhost ~]# virsh vol-list --pool tmp-pool --details
name path type Capacity allocated
-------------------------------------------------------------
tmp-vol /root/tmp-pool/tmp-vol file 2.00 GiB 1.00 GiB
So, if we want to allocate more bytes to 3G, the real allocated size is 2G
actually.
[root@localhost ~]# virsh vol-resize tmp-vol --pool tmp-pool 3G --allocate
[root@localhost ~]# virsh vol-list --pool tmp-pool --details
name path type Capacity allocated
-------------------------------------------------------------
tmp-vol /root/tmp-pool/tmp-vol file 3.00 GiB 2.00 GiB
This patch enable resize vol against the real allocated size. After this patch
is applied, the result of the last resize command become 3G.
[root@localhost ~]# virsh vol-resize tmp-vol --pool tmp-pool 3G --allocate
[root@localhost ~]# virsh vol-list --pool tmp-pool --details
name path type Capacity allocated
-------------------------------------------------------------
tmp-vol /root/tmp-pool/tmp-vol file 3.00 GiB 3.00 GiB
Signed-off-by: Wang Sen <wangsen(a)linux.vnet.ibm.com>
---
src/storage/storage_backend_fs.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index 11cf2df..e75c57b 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -1261,13 +1261,28 @@ virStorageBackendFileSystemVolResize(virConnectPtr conn ATTRIBUTE_UNUSED,
unsigned long long capacity,
unsigned int flags)
{
+ int fd = -1;
virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE, -1);
+ unsigned long long orig_capacity;
+ virStorageFileMetadataPtr meta = NULL;
+
+ if ((fd = open(vol->target.path, O_RDWR)) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Can not open file"));
+ }
+
+ if (!(meta = virStorageFileGetMetadataFromFD(vol->target.path, fd, \
+ vol->target.format))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Get meta data error!"));
+ }
+ orig_capacity = meta->capacity;
+ virStorageFileFreeMetadata(meta);
+ close(fd);
bool pre_allocate = flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE;
if (vol->target.format == VIR_STORAGE_FILE_RAW) {
return virStorageFileResize(vol->target.path, capacity,
- vol->capacity, pre_allocate);
+ orig_capacity, pre_allocate);
} else {
if (pre_allocate) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
--
1.8.3.1
10 years, 11 months
[libvirt] [PATCH 0/2] Fix interface state transitions logic
by Michal Privoznik
Right now it's possible to start an interface that is already running, or
destroy an interface multiple times. Such state transitions are not allowed and
we check for such cases explicitly in other areas like qemu driver.
Michal Privoznik (2):
interface: Introduce netcfInterfaceObjIsActive
interface: Take interface status into account when starting and
destroying
src/interface/interface_backend_netcf.c | 77 +++++++++++++++++++++++----------
1 file changed, 53 insertions(+), 24 deletions(-)
--
1.8.5.1
10 years, 11 months