[libvirt] [PATCH 0/2] Allow using custom tap and vhost devices
by Ján Tomko
This allows usage of alternative tun/tap/vhost backends implemented
in userspace via cuse.
Ján Tomko (2):
conf: add backend element to interfaces
Wire up the interface backend options
docs/formatdomain.html.in | 20 +++++++++
docs/schemas/domaincommon.rng | 10 +++++
src/bhyve/bhyve_command.c | 2 +-
src/bhyve/bhyve_process.c | 2 +-
src/conf/domain_conf.c | 11 +++++
src/conf/domain_conf.h | 4 ++
src/network/bridge_driver.c | 6 +--
src/qemu/qemu_command.c | 22 +++++++---
src/qemu/qemu_process.c | 2 +-
src/uml/uml_conf.c | 2 +-
src/uml/uml_driver.c | 3 +-
src/util/virnetdevtap.c | 37 +++++++++++-----
src/util/virnetdevtap.h | 5 ++-
tests/qemuxml2argvdata/qemuxml2argv-tap-vhost.xml | 52 +++++++++++++++++++++++
tests/qemuxml2xmltest.c | 2 +
15 files changed, 154 insertions(+), 26 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-tap-vhost.xml
--
1.8.5.5
10 years, 3 months
[libvirt] RFC: exposing backing store allocation in domain xml
by Eric Blake
Adam Litke has been asking if I can expose watermark information from
qemu when doing block commit. Qemu still doesn't expose that
information when doing 'virsh blockcopy' (QMP drive-mirror), but DOES
expose it for regular and active 'virsh blockcommit'. The idea is that
when you are writing to more than one file at a time, management needs
to know if the file is nearing a watermark for usage that necessitates
growing the storage volume before hitting an ENOSPC error. In
particular, Adam's use is running qcow2 format on top of block devices,
where it is easy to enlarge the block device.
The current libvirt API virDomainBlockInfo() can only get watermark
information for the active image in a disk chain. It shows three numbers:
capacity: the disk size seen by the guest (can be grown via
virt-resize) - usually larger than the host block device if the guest
has not used the complete disk, but can also be smaller than the host
block device due to overhead of qcow2 and the disk is mostly in use
allocation: the known usage of the host file/block device, should never
be larger than the physical size (other than rounding up to file sector
sizing). For sparse files, this number is smaller than total size based
by the amount of holes in the file. For block devices with qcow2 format,
this number is reported by qemu as the maximum offset in use by the
qcow2 file (without regards to whether earlier offsets are holes that
could be reused). Compare this to what 'du' would report.
physical: the total size of the host file/block device. Compare this to
what 'ls' would report.
Also, the libvirt API virStorageVolGetXMLDesc reports two of those
numbers for a top-level image: <capacity> and <allocation> are listed as
siblings of <target>. But it is not present for a <backingStore>; you
have to use the API twice.
Now that we have a common virStorageSourcePtr type in the C code, we
could do a better job of exposing full information for the entire chain
in a single API call.
I've got a couple ideas of where we can extend existing APIs (and the
extensions do not involve bumping the .so versioning, so it can also be
backported, although it gets MUCH harder to backport without
virStorageSourcePtr).
First, I think the virStorageVolGetXMLDesc should show all three
numbers, by adding a <physical unit='bytes'>...</physical> element
alongside the existing <capacity> and <allocation> elements. Also, I
think it might be nice if we could enhance the API to do a full chain
recursion (probably requires an explicit flag to turn on) where it shows
details on the full backing chain, rather than just partial details on
the immediate backing file; in doing that, the <backingStore> element
would gain recursive <backingStore> (similar to what we recently did in
<domain> XML). In that mode, each layer of <backingStore> would also
report <capacity>, <allocation>, and <physical>. Something like:
# virsh vol-dumpxml --pool default f20.snap2
<volume type='file'>
<name>f20.snap2</name>
<key>/var/lib/libvirt/images/f20.snap2</key>
<source>
</source>
<capacity unit='bytes'>12884901888</capacity>
<allocation unit='bytes'>2503548928</allocation>
<physical unit='bytes'>2503548928</allocation>
<target>
<path>/var/lib/libvirt/images/f20.snap2</path>
<format type='qcow2'/>
<permissions>
<mode>0600</mode>
<owner>0</owner>
<group>0</group>
<label>system_u:object_r:virt_image_t:s0</label>
</permissions>
<timestamps>
<atime>1407295598.583411967</atime>
<mtime>1403064822.622766566</mtime>
<ctime>1404318525.899951254</ctime>
</timestamps>
<compat>1.1</compat>
<features/>
</target>
<backingStore>
<path>/var/lib/libvirt/images/f20.snap1</path>
<capacity unit='bytes'>12884901888</capacity>
<allocation unit='bytes'>2503548928</allocation>
<physical unit='bytes'>2503548928</allocation>
<format type='qcow2'/>
<permissions>
<mode>0600</mode>
<owner>107</owner>
<group>107</group>
<label>system_u:object_r:virt_content_t:s0</label>
</permissions>
<timestamps>
<atime>1407295598.623411816</atime>
<mtime>1402005765.810488875</mtime>
<ctime>1404318523.313955796</ctime>
</timestamps>
<compat>1.1</compat>
<features/>
<backingStore>
<path>/var/lib/libvirt/images/f20.base</path>
<capacity unit='bytes'>10737418240</capacity>
<allocation unit='bytes'>2503548928</allocation>
<physical unit='bytes'>10737418240</allocation>
<format type='raw'/>
<permissions>
<mode>0600</mode>
<owner>107</owner>
<group>107</group>
<label>system_u:object_r:virt_content_t:s0</label>
</permissions>
<timestamps>
<atime>1407295598.623411816</atime>
<mtime>1402005765.810488875</mtime>
<ctime>1404318523.313955796</ctime>
</timestamps>
<backingStore/>
</backingStore>
</backingStore>
</volume>
Also, the current storage volume API is rather hard-coded to assume that
backing elements are in the same storage pool, which is not always true.
It may be time to introduce <backingStore type='file'> or <backingStore
type='network'> to allow better details of cross-pool backing elements,
while leaving plain <backingStore> as a back-compat synonym for
<backingStore type='volume'> for the current hard-coded layout that
assumes the backing element is in the same storage pool.
The other idea I've had is to expand the <domain> XML to expose more
information about backing chains, including to make it expose details
that are redundant with virDomainBlockInfo() for the top level, or maybe
even what virDomainBlockStatsFlags() reports. Here, we have a bit of a
choice - storage volume XML was inconsistent on which attributes were
siblings to <target> (such as <capacity>) vs. children (such as
<timestamps>); it might be nicer to stick all per-file elements at the
same level in <disk> XML (probably as siblings to <source>). On the
other hand, I strongly feel that <compat> is a feature of the <format>,
so it should have been a child rather than a sibling. So, as an example
of what the XML might look like:
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'>
<compat>1.1</compat>
<features/>
</driver>
<source file='/tmp/snap2.img'/>
<capacity unit='bytes'>12884901888</capacity>
<allocation unit='bytes'>2503548928</allocation>
<physical unit='bytes'>2503548928</allocation>
<permissions>
<mode>0600</mode>
<owner>107</owner>
<group>107</group>
<label>system_u:object_r:virt_content_t:s0</label>
</permissions>
<timestamps>
<atime>1407295598.623411816</atime>
<mtime>1402005765.810488875</mtime>
<ctime>1404318523.313955796</ctime>
</timestamps>
<backingStore type='file' index='1'>
<format type='qcow2'>
<compat>1.1</compat>
<features/>
</format>
<source file='/tmp/snap1.img'/>
<capacity unit='bytes'>12884901888</capacity>
<allocation unit='bytes'>2503548928</allocation>
<physical unit='bytes'>2503548928</allocation>
<permissions>
<mode>0600</mode>
<owner>0</owner>
<group>0</group>
<label>system_u:object_r:virt_image_t:s0</label>
</permissions>
<timestamps>
<atime>1407295598.583411967</atime>
<mtime>1403064822.622766566</mtime>
<ctime>1404318525.899951254</ctime>
</timestamps>
<backingStore type='file' index='2'>
<format type='raw'/>
<capacity unit='bytes'>10737418240</capacity>
<allocation unit='bytes'>2503548928</allocation>
<physical unit='bytes'>10737418240</allocation>
<source file='/tmp/base.img'/>
<permissions>
<mode>0600</mode>
<owner>107</owner>
<group>107</group>
<label>system_u:object_r:virt_content_t:s0</label>
</permissions>
<timestamps>
<atime>1407295598.623411816</atime>
<mtime>1402005765.810488875</mtime>
<ctime>1404318523.313955796</ctime>
</timestamps>
<backingStore/>
</backingStore>
</backingStore>
<target dev='vda' bus='virtio'/>
<alias name='virtio-disk0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03'
function='0x0'/>
</disk>
Again, this is a lot of new information, so it may be wise to add a new
flag that must be turned on to request the information. But adding this
information would allow watermark tracking for a blockcommit operation -
when collapsing 'base <- snap1 <- snap2' into 'base <- snap2' by
committing snap1 into base, the <allocation> sublement of the
appropriate <backingStore> level will do live tracking of the qemu
values as more data is being written into base, and thus be usable to
determine if the block device behind base needs to be externally
expanded before hitting an ENOSPC situation.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
10 years, 3 months
[libvirt] [PATCH 0/3] Fixes for issues caused by IOThreads
by John Ferlan
Well I guess it happens to everyone - hopefully only once though...
The IOThreads code really messed up a few things - git bisection for
the build is broken as of 5f6ad32c733a3bd158938aecabb0508a434ece95,
but that's resolved by 938fb12fad6d15c9fdb73f998c4e0ec1e278721f
which adds the 'niothreadspin && iothreadspin' definitions.
Secondarily it seems things got worse, because guests weren't able to
be started because of a very bad logic error (<= 0 vs. < 0 and specific
check that 0 is "OK" (meaning no IOThreads).
How that got by own self testing I'm still not quite sure, but it did
and it's a mea culpa for that.
Anyway, patch 1 fixes the running issue... Patch 2 fixes some spacing
issues that Eric pointed out privately (prefer "i + 1" vs. "i+1").
Patch 3 just makes sure to use the right cgroup setup/init parameters
since there is no "iothread0"
John Ferlan (3):
qemu: Fix iothreads issue
qemu_cgroup: Adjust spacing around incrementor
qemu: Fix call in qemuDomainSetNumaParamsLive for virCgroupNewIOThread
src/qemu/qemu_cgroup.c | 7 ++++---
src/qemu/qemu_driver.c | 3 ++-
src/qemu/qemu_process.c | 6 +++++-
3 files changed, 11 insertions(+), 5 deletions(-)
--
1.9.3
10 years, 3 months
[libvirt] [PATCH 0/5] Fix problems caused by FD passing to session daemon
by Martin Kletzander
There were various problems introduced by the series on FD passing.
The path for the socket was not created, the socket was not removed
before binding it, etc. Let's see if it's any better this time.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=927369
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1138604
Martin Kletzander (5):
rpc: reformat the flow to make a bit more sense
remove redundant pidfile path constructions
util: fix potential leak in error codepath
util: get rid of unnecessary umask() call
rpc: make daemon spawning a bit more intelligent
daemon/libvirtd.c | 41 ++------------
src/libvirt_private.syms | 1 +
src/locking/lock_daemon.c | 42 ++-------------
src/rpc/virnetsocket.c | 133 +++++++++++++++++++++++++++++++---------------
src/util/virpidfile.c | 48 ++++++++++++++++-
src/util/virpidfile.h | 7 ++-
6 files changed, 151 insertions(+), 121 deletions(-)
--
2.1.0
10 years, 3 months
[libvirt] [PATCHv2] network: check negative values in bridge queues
by Erik Skultety
We already are checking for negative value, reporting an error, but
using wrong function and the check only succeeds when a value that
cannot be converted to number successfully is encountered. This patch
provides just a minor change in call of the right version
of function virStrToLong.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1138539
---
src/conf/domain_conf.c | 2 +-
.../qemuxml2argv-vhost_queues-invalid.xml | 32 ++++++++++++++++++++++
tests/qemuxml2argvtest.c | 1 +
3 files changed, 34 insertions(+), 1 deletion(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-vhost_queues-invalid.xml
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9cb3ebd..694c6cb 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -7377,7 +7377,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
}
if (queues) {
unsigned int q;
- if (virStrToLong_ui(queues, NULL, 10, &q) < 0) {
+ if (virStrToLong_uip(queues, NULL, 10, &q) < 0) {
virReportError(VIR_ERR_XML_DETAIL,
_("'queues' attribute must be positive number: %s"),
queues);
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-vhost_queues-invalid.xml b/tests/qemuxml2argvdata/qemuxml2argv-vhost_queues-invalid.xml
new file mode 100644
index 0000000..300695a
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-vhost_queues-invalid.xml
@@ -0,0 +1,32 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>bba65c0e-c049-934f-b6aa-4e2c0582acdf</uuid>
+ <memory unit='KiB'>1048576</memory>
+ <currentMemory unit='KiB'>1048576</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='file' device='disk'>
+ <source file='/dev/HostVG/QEMUGuest1'/>
+ <target dev='vda' bus='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <interface type='user'>
+ <mac address='52:54:00:e5:48:58'/>
+ <model type='virtio'/>
+ <driver name='vhost' queues='-5'/>
+ </interface>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 5c28253..0a0c8ec 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -954,6 +954,7 @@ mymain(void)
DO_TEST_FAILURE("misc-enable-s4", NONE);
DO_TEST("misc-no-reboot", NONE);
DO_TEST("misc-uuid", QEMU_CAPS_NAME, QEMU_CAPS_UUID);
+ DO_TEST_PARSE_ERROR("vhost_queues-invalid", NONE);
DO_TEST("net-vhostuser", QEMU_CAPS_DEVICE, QEMU_CAPS_NETDEV);
DO_TEST("net-user", NONE);
DO_TEST("net-virtio", NONE);
--
1.9.3
10 years, 3 months
[libvirt] [PATCH] openvz: fixed two memory leaks on migration code
by Hongbin Lu
---
src/openvz/openvz_driver.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index 57b3c22..3147311 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -2364,7 +2364,10 @@ openvzDomainMigratePrepare3Params(virConnectPtr dconn,
}
done:
- virURIFree(uri);
+ if (!uri_in)
+ VIR_FREE(hostname);
+ else
+ virURIFree(uri);
if (vm)
virObjectUnlock(vm);
return ret;
@@ -2385,7 +2388,7 @@ openvzDomainMigratePerform3Params(virDomainPtr domain,
virDomainObjPtr vm = NULL;
const char *uri_str = NULL;
virURIPtr uri = NULL;
- virCommandPtr cmd = virCommandNew(VZMIGRATE);
+ virCommandPtr cmd = NULL;
int ret = -1;
virCheckFlags(OPENVZ_MIGRATION_FLAGS, -1);
@@ -2412,6 +2415,7 @@ openvzDomainMigratePerform3Params(virDomainPtr domain,
if (uri == NULL || uri->server == NULL)
goto cleanup;
+ cmd = virCommandNew(VZMIGRATE);
if (flags & VIR_MIGRATE_LIVE)
virCommandAddArg(cmd, "--live");
virCommandAddArg(cmd, uri->server);
--
1.7.1
10 years, 3 months
[libvirt] [PATCH] network: check negative values in bridge queues
by Erik Skultety
We already are checking for negative value, reporting an error, but
using wrong function, so the check never succeeds. This patch provides
just a minor change in call of the right version of function virStrToLong.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1138539
---
src/conf/domain_conf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a2a7d92..42b8973 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -7374,7 +7374,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
}
if (queues) {
unsigned int q;
- if (virStrToLong_ui(queues, NULL, 10, &q) < 0) {
+ if (virStrToLong_uip(queues, NULL, 10, &q) < 0) {
virReportError(VIR_ERR_XML_DETAIL,
_("'queues' attribute must be positive number: %s"),
queues);
--
1.9.3
10 years, 3 months
[libvirt] [PATCH] virprocess: Extend list of platforms for setns wrapper
by Michal Privoznik
Currently, the setns() wrapper is supported only for x86_64 and i686
which leaves us failing to build on other platforms like arm, aarch64
and so on. This means, that the wrapper needs to be extended to those
platforms and make to fail on runtime not compile time.
The syscall numbers for other platforms was fetched using this
command:
kernel.git $ git grep "define.*__NR_setns" | grep -e arm -e powerpc -e s390
arch/arm/include/uapi/asm/unistd.h:#define __NR_setns (__NR_SYSCALL_BASE+375)
arch/arm64/include/asm/unistd32.h:#define __NR_setns 375
arch/powerpc/include/uapi/asm/unistd.h:#define __NR_setns 350
arch/s390/include/uapi/asm/unistd.h:#define __NR_setns 339
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/util/virprocess.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 3dae1bd..eac49f5 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -71,27 +71,33 @@ VIR_LOG_INIT("util.process");
# define __NR_setns 308
# elif defined(__i386__)
# define __NR_setns 346
-# else
-# error "__NR_setns is not defined"
+# elif defined(__arm__)
+# define __NR_setns 375
+# elif defined(__aarch64__)
+# define __NR_setns 375
+# elif defined(__powerpc__)
+# define __NR_setns 350
+# elif defined(__s390__)
+# define __NR_setns 339
# endif
#endif
#ifndef HAVE_SETNS
-# ifndef WIN32
+# ifdef __NR_setns
# include <sys/syscall.h>
static inline int setns(int fd, int nstype)
{
return syscall(__NR_setns, fd, nstype);
}
-# else
+# else /* __NR_setns */
static inline int setns(int fd ATTRIBUTE_UNUSED, int nstype ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s",
- _("Namespaces are not supported on windows."));
+ _("Namespaces are not supported on this platform."));
return -1;
}
-# endif /* WIN32 */
+# endif /* __NR_setns */
#endif /* HAVE_SETNS */
/**
--
1.8.5.5
10 years, 3 months
[libvirt] [PATCH] util: storage: Fix qcow(2) header parser according to docs
by Peter Krempa
The backing store string location offset 0 determines that the file
isn't present. The string size shouldn't be then checked:
from qemu.git/docs/specs/qcow2.txt
== Header ==
The first cluster of a qcow2 image contains the file header:
Byte 0 - 3: magic
QCOW magic string ("QFI\xfb")
4 - 7: version
Version number (valid values are 2 and 3)
8 - 15: backing_file_offset
Offset into the image file at which the backing file name
is stored (NB: The string is not null terminated). 0 if the
image doesn't have a backing file.
16 - 19: backing_file_size
Length of the backing file name in bytes. Must not be
longer than 1023 bytes. Undefined if the image doesn't have
a backing file. ^^^^^^^^^
This patch intentionally leaves the backing file string size check in
place in case a malformatted file would be presented to libvirt. Also
according to the docs the string size is maximum 1023 bytes, thus this
patch adds a check to verify that.
I was also able to verify that the check was done the same way in the
legacy qcow fromat (in qemu's code).
---
src/util/virstoragefile.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index 5db9184..13056a7 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -385,15 +385,22 @@ qcowXGetBackingStore(char **res,
offset = virReadBufInt64BE(buf + QCOWX_HDR_BACKING_FILE_OFFSET);
if (offset > buf_size)
return BACKING_STORE_INVALID;
+
+ if (offset == 0) {
+ if (format)
+ *format = VIR_STORAGE_FILE_NONE;
+ return BACKING_STORE_OK;
+ }
+
size = virReadBufInt32BE(buf + QCOWX_HDR_BACKING_FILE_SIZE);
if (size == 0) {
if (format)
*format = VIR_STORAGE_FILE_NONE;
return BACKING_STORE_OK;
}
- if (offset + size > buf_size || offset + size < offset)
+ if (size > 1023)
return BACKING_STORE_INVALID;
- if (size + 1 == 0)
+ if (offset + size > buf_size || offset + size < offset)
return BACKING_STORE_INVALID;
if (VIR_ALLOC_N(*res, size + 1) < 0)
return BACKING_STORE_ERROR;
--
2.1.0
10 years, 3 months
[libvirt] [PATCH] add migration support for OpenVZ driver
by Hongbin Lu
This patch adds initial migration support to the OpenVZ driver,
using the VIR_DRV_FEATURE_MIGRATION_PARAMS family of migration
functions.
---
src/openvz/openvz_conf.h | 5 +-
src/openvz/openvz_driver.c | 348 ++++++++++++++++++++++++++++++++++++++++++++
src/openvz/openvz_driver.h | 10 ++
3 files changed, 361 insertions(+), 2 deletions(-)
diff --git a/src/openvz/openvz_conf.h b/src/openvz/openvz_conf.h
index a7de7d2..33998d6 100644
--- a/src/openvz/openvz_conf.h
+++ b/src/openvz/openvz_conf.h
@@ -35,8 +35,9 @@
/* OpenVZ commands - Replace with wrapper scripts later? */
-# define VZLIST "/usr/sbin/vzlist"
-# define VZCTL "/usr/sbin/vzctl"
+# define VZLIST "/usr/sbin/vzlist"
+# define VZCTL "/usr/sbin/vzctl"
+# define VZMIGRATE "/usr/sbin/vzmigrate"
# define VZ_CONF_FILE "/etc/vz/vz.conf"
# define VZCTL_BRIDGE_MIN_VERSION ((3 * 1000 * 1000) + (0 * 1000) + 22 + 1)
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index 851ed30..57b3c22 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -2207,6 +2207,348 @@ openvzNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
}
+static int
+openvzConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
+{
+ switch (feature) {
+ case VIR_DRV_FEATURE_MIGRATION_PARAMS:
+ case VIR_DRV_FEATURE_MIGRATION_V3:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
+static char *
+openvzDomainMigrateBegin3Params(virDomainPtr domain,
+ virTypedParameterPtr params,
+ int nparams,
+ char **cookieout ATTRIBUTE_UNUSED,
+ int *cookieoutlen ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ virDomainObjPtr vm = NULL;
+ struct openvz_driver *driver = domain->conn->privateData;
+ char *xml = NULL;
+ int status;
+
+ virCheckFlags(OPENVZ_MIGRATION_FLAGS, NULL);
+ if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)
+ return NULL;
+
+ openvzDriverLock(driver);
+ vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
+ openvzDriverUnlock(driver);
+
+ if (!vm) {
+ virReportError(VIR_ERR_NO_DOMAIN, "%s",
+ _("no domain with matching uuid"));
+ goto cleanup;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ goto cleanup;
+ }
+
+ if (openvzGetVEStatus(vm, &status, NULL) == -1)
+ goto cleanup;
+
+ if (status != VIR_DOMAIN_RUNNING) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("domain is not in running state"));
+ goto cleanup;
+ }
+
+ xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);
+
+ cleanup:
+ if (vm)
+ virObjectUnlock(vm);
+ return xml;
+}
+
+static int
+openvzDomainMigratePrepare3Params(virConnectPtr dconn,
+ virTypedParameterPtr params,
+ int nparams,
+ const char *cookiein ATTRIBUTE_UNUSED,
+ int cookieinlen ATTRIBUTE_UNUSED,
+ char **cookieout ATTRIBUTE_UNUSED,
+ int *cookieoutlen ATTRIBUTE_UNUSED,
+ char **uri_out,
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ struct openvz_driver *driver = dconn->privateData;
+ const char *dom_xml = NULL;
+ const char *uri_in = NULL;
+ virDomainDefPtr def = NULL;
+ virDomainObjPtr vm = NULL;
+ char *hostname = NULL;
+ virURIPtr uri = NULL;
+ int ret = -1;
+
+ if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)
+ goto error;
+
+ if (virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_DEST_XML,
+ &dom_xml) < 0 ||
+ virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_URI,
+ &uri_in) < 0)
+ goto error;
+
+ if (!dom_xml) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("no domain XML passed"));
+ goto error;
+ }
+
+ if (!(def = virDomainDefParseString(dom_xml, driver->caps, driver->xmlopt,
+ 1 << VIR_DOMAIN_VIRT_OPENVZ,
+ VIR_DOMAIN_XML_INACTIVE)))
+ goto error;
+
+ if (!(vm = virDomainObjListAdd(driver->domains, def,
+ driver->xmlopt,
+ VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
+ VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
+ NULL)))
+ goto error;
+ def = NULL;
+
+ if (!uri_in) {
+ if ((hostname = virGetHostname()) == NULL)
+ goto error;
+
+ if (STRPREFIX(hostname, "localhost")) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("hostname on destination resolved to localhost,"
+ " but migration requires an FQDN"));
+ goto error;
+ }
+ } else {
+ uri = virURIParse(uri_in);
+
+ if (uri == NULL) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("unable to parse URI: %s"),
+ uri_in);
+ goto error;
+ }
+
+ if (uri->server == NULL) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("missing host in migration URI: %s"),
+ uri_in);
+ goto error;
+ } else {
+ hostname = uri->server;
+ }
+ }
+
+ if (virAsprintf(uri_out, "ssh://%s", hostname) < 0)
+ goto error;
+
+ ret = 0;
+ goto done;
+
+ error:
+ virDomainDefFree(def);
+ if (vm) {
+ virDomainObjListRemove(driver->domains, vm);
+ vm = NULL;
+ }
+
+ done:
+ virURIFree(uri);
+ if (vm)
+ virObjectUnlock(vm);
+ return ret;
+}
+
+static int
+openvzDomainMigratePerform3Params(virDomainPtr domain,
+ const char *dconnuri ATTRIBUTE_UNUSED,
+ virTypedParameterPtr params,
+ int nparams,
+ const char *cookiein ATTRIBUTE_UNUSED,
+ int cookieinlen ATTRIBUTE_UNUSED,
+ char **cookieout ATTRIBUTE_UNUSED,
+ int *cookieoutlen ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ struct openvz_driver *driver = domain->conn->privateData;
+ virDomainObjPtr vm = NULL;
+ const char *uri_str = NULL;
+ virURIPtr uri = NULL;
+ virCommandPtr cmd = virCommandNew(VZMIGRATE);
+ int ret = -1;
+
+ virCheckFlags(OPENVZ_MIGRATION_FLAGS, -1);
+ if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)
+ goto cleanup;
+
+ if (virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_URI,
+ &uri_str) < 0)
+ goto cleanup;
+
+ openvzDriverLock(driver);
+ vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
+ openvzDriverUnlock(driver);
+
+ if (!vm) {
+ virReportError(VIR_ERR_NO_DOMAIN, "%s",
+ _("no domain with matching uuid"));
+ goto cleanup;
+ }
+
+ /* parse dst host:port from uri */
+ uri = virURIParse(uri_str);
+ if (uri == NULL || uri->server == NULL)
+ goto cleanup;
+
+ if (flags & VIR_MIGRATE_LIVE)
+ virCommandAddArg(cmd, "--live");
+ virCommandAddArg(cmd, uri->server);
+ virCommandAddArg(cmd, vm->def->name);
+
+ if (virCommandRun(cmd, NULL) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ virCommandFree(cmd);
+ virURIFree(uri);
+ if (vm)
+ virObjectUnlock(vm);
+ return ret;
+}
+
+static virDomainPtr
+openvzDomainMigrateFinish3Params(virConnectPtr dconn,
+ virTypedParameterPtr params,
+ int nparams,
+ const char *cookiein ATTRIBUTE_UNUSED,
+ int cookieinlen ATTRIBUTE_UNUSED,
+ char **cookieout ATTRIBUTE_UNUSED,
+ int *cookieoutlen ATTRIBUTE_UNUSED,
+ unsigned int flags,
+ int cancelled)
+{
+ struct openvz_driver *driver = dconn->privateData;
+ virDomainObjPtr vm = NULL;
+ const char *dname = NULL;
+ virDomainPtr dom = NULL;
+ int status;
+
+ if (cancelled)
+ goto cleanup;
+
+ virCheckFlags(OPENVZ_MIGRATION_FLAGS, NULL);
+ if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)
+ goto cleanup;
+
+ if (virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_DEST_NAME,
+ &dname) < 0)
+ goto cleanup;
+
+ if (!dname ||
+ !(vm = virDomainObjListFindByName(driver->domains, dname))) {
+ /* Migration obviously failed if the domain doesn't exist */
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("Migration failed. No domain on destination host "
+ "with matching name '%s'"),
+ NULLSTR(dname));
+ goto cleanup;
+ }
+
+ if (openvzGetVEStatus(vm, &status, NULL) == -1)
+ goto cleanup;
+
+ if (status != VIR_DOMAIN_RUNNING) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("domain is not running on destination host"));
+ goto cleanup;
+ }
+
+ vm->def->id = strtoI(vm->def->name);
+ virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_MIGRATED);
+
+ dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
+ if (dom)
+ dom->id = vm->def->id;
+
+ cleanup:
+ if (vm)
+ virObjectUnlock(vm);
+ return dom;
+}
+
+static int
+openvzDomainMigrateConfirm3Params(virDomainPtr domain,
+ virTypedParameterPtr params,
+ int nparams,
+ const char *cookiein ATTRIBUTE_UNUSED,
+ int cookieinlen ATTRIBUTE_UNUSED,
+ unsigned int flags,
+ int cancelled)
+{
+ struct openvz_driver *driver = domain->conn->privateData;
+ virDomainObjPtr vm = NULL;
+ int status;
+ int ret = -1;
+
+ virCheckFlags(OPENVZ_MIGRATION_FLAGS, -1);
+ if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)
+ goto cleanup;
+
+ openvzDriverLock(driver);
+ vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
+ openvzDriverUnlock(driver);
+
+ if (!vm) {
+ virReportError(VIR_ERR_NO_DOMAIN, "%s",
+ _("no domain with matching uuid"));
+ goto cleanup;
+ }
+
+ if (cancelled) {
+ if (openvzGetVEStatus(vm, &status, NULL) == -1)
+ goto cleanup;
+
+ if (status == VIR_DOMAIN_RUNNING) {
+ ret = 0;
+ } else {
+ VIR_DEBUG("Domain '%s' does not recover after failed migration",
+ vm->def->name);
+ }
+
+ goto cleanup;
+ }
+
+ vm->def->id = -1;
+
+ VIR_DEBUG("Domain '%s' successfully migrated", vm->def->name);
+
+ virDomainObjListRemove(driver->domains, vm);
+ vm = NULL;
+
+ ret = 0;
+
+ cleanup:
+ if (vm)
+ virObjectUnlock(vm);
+ return ret;
+}
+
+
static virDriver openvzDriver = {
.no = VIR_DRV_OPENVZ,
.name = "OPENVZ",
@@ -2265,6 +2607,12 @@ static virDriver openvzDriver = {
.connectIsAlive = openvzConnectIsAlive, /* 0.9.8 */
.domainUpdateDeviceFlags = openvzDomainUpdateDeviceFlags, /* 0.9.13 */
.domainGetHostname = openvzDomainGetHostname, /* 0.10.0 */
+ .connectSupportsFeature = openvzConnectSupportsFeature, /* 1.2.8 */
+ .domainMigrateBegin3Params = openvzDomainMigrateBegin3Params, /* 1.2.8 */
+ .domainMigratePrepare3Params = openvzDomainMigratePrepare3Params, /* 1.2.8 */
+ .domainMigratePerform3Params = openvzDomainMigratePerform3Params, /* 1.2.8 */
+ .domainMigrateFinish3Params = openvzDomainMigrateFinish3Params, /* 1.2.8 */
+ .domainMigrateConfirm3Params = openvzDomainMigrateConfirm3Params, /* 1.2.8 */
};
int openvzRegister(void)
diff --git a/src/openvz/openvz_driver.h b/src/openvz/openvz_driver.h
index b39e81c..0c7a070 100644
--- a/src/openvz/openvz_driver.h
+++ b/src/openvz/openvz_driver.h
@@ -31,6 +31,16 @@
# include "internal.h"
+# define OPENVZ_MIGRATION_FLAGS \
+ (VIR_MIGRATE_LIVE)
+
+/* All supported migration parameters and their types. */
+# define OPENVZ_MIGRATION_PARAMETERS \
+ VIR_MIGRATE_PARAM_URI, VIR_TYPED_PARAM_STRING, \
+ VIR_MIGRATE_PARAM_DEST_NAME, VIR_TYPED_PARAM_STRING, \
+ VIR_MIGRATE_PARAM_DEST_XML, VIR_TYPED_PARAM_STRING, \
+ NULL
+
int openvzRegister(void);
#endif
--
1.7.1
10 years, 3 months