[libvirt] [PATCH 00/14] Add a virtlockd lock manager daemon
by Daniel P. Berrange
The lock manager infrastructure we recently added to QEMU only has
two possible drivers at this time, 'nop' and 'sanlock'. The former
does absolutely nothing, while the latter requires a 3rd party
package installed and is a little heavy on disk I/O and storage
requirements.
This series adds a new daemon 'virtlockd' which is intended to be
enabled by default on all hosts running 'libvirtd'. This daemon
provides a service for disk locking based on the traditional
fcntl() lock primitives. There is a new libvirt manager plugin
which talks to this daemon over RPC. The reason for doing the
locks in a separate process is that we want the locks to remain
active, even if libvirtd crashes, or is restarted. The virtlockd
daemon has this one single job so should be pretty reliable and
selfcontained. This patch series really benefits from the new RPC
APIs, requiring minimal code for the new daemon / client
At this time, virtlockd does not lock the actual disk files, but
instead creates a lockspace & leases under /var/lib/libvirt/lockd.
The lockspace we use for disks is named org.libvirt.lockd.files,
and lease names are based on a SHA256 checksum of the fully
qualified disk name. eg
/var/lib/libvirt/lockd/org.libvirt.lockd.files/adf94fc33a24da1abff7dd7374a9919bb51efee646da8c3ac464c10cd59750bd
These leases are all zero-bytes long and no I/O is ever performed
on them, only fcntl() is used. So there is material overhead.
Whenever creating or deleting leases, we first acquire a lock on
/var/lib/libvirt/lockd/org.libvirt.lockd.files/org.libvirt.lockd.index
A non-root virtlockd will instead use $HOME/.libvirt/lockd
By default we gain protection out of the box against
- Starting two guests on the same host with the same disk image
not marked with <shareable/>
- libvirtd getting confused and forgetting a guest, allowing it
to be started for a 2nd time
If the admin mounts a shared filesytem (eg NFS) on /var/lib/libvirt/lockd
then this protection is extended across all hosts sharing that
mount volume.
As part of this series, I also introduce support for systemd
services for libvirtd and libvir-guests.
12 years, 11 months
[libvirt] [PATCH 00/10] Console coruption with two or more clients series
by Peter Krempa
This series fixes anoying console corruption if two clients try to connect
at same time to the console. The current state of this is, that two/more
of libvirt iohelpers are spawned on the same time that compete for data
from the pty. This causes that each of the consoles get scrambled and
unusable.
Patches
fdstream: Emit stream abort callback even if poll() doesnt.
virnetclientstream: Propagate stream error messages to callback
daemon: Subscribe the stream event callback for error events.
add the ability to abort a stream from the daemon side.
fdstream: Add internal function to check if a fdstream is open
This patch adds a helper function that checks internally if a fdstream
is open and working.
virsh: fix console stream error reporting
Add flags for virDomainOpenConsole
virsh: add support for VIR_DOMAIN_CONSOLE_FORCE flag
This patches add instrumentation to virsh that supports the new ability to
abort streams from the daemon side and adapts the console callback to handle
this. These patches also add a new flag set for virDomainOpenConsole API
call that allow users to control the if the existing console connection should
be left in place or killed in favor of the new one
qemu: Add ability to abort existing console while creating new one
lxc: Add ability to abort existing console when creating a new one
uml: Add ability to abort existing console when creating a new one
These patches modify the hypervisor drivers so that they are aware of existing
console connections and refuse to create a new one (or kill the old).
The xen driver also supports console in a similar way like the previously
mentioned drivers, but lacks the means to store a stream reference
permanently. I'll look in if it's possible to modify this driver to support
this new functionality.
For convinience, to review these patches:
git checkout -b console_corruption 33b55fd85ae5435bda53c3cfcbe1385074befd01
git pull git://aeon.pipo.sk/libvirt.git console_corruption
Peter
Peter Krempa (10):
fdstream: Emit stream abort callback even if poll() doesnt.
virnetclientstream: Propagate stream error messages to callback
daemon: Subscribe the stream event callback for error events.
fdstream: Add internal function to check if a fdstream is open
virsh: fix console stream error reporting
Add flags for virDomainOpenConsole
virsh: add support for VIR_DOMAIN_CONSOLE_FORCE flag
qemu: Add ability to abort existing console while creating new one
lxc: Add ability to abort existing console when creating a new one
uml: Add ability to abort existing console when creating a new one
daemon/stream.c | 2 +-
include/libvirt/libvirt.h.in | 12 +++++++-
src/fdstream.c | 61 ++++++++++++++++++++++++++++++++++++++---
src/fdstream.h | 2 +
src/libvirt_private.syms | 1 +
src/lxc/lxc_driver.c | 28 ++++++++++++++++++-
src/qemu/qemu_domain.c | 3 ++
src/qemu/qemu_domain.h | 2 +
src/qemu/qemu_driver.c | 23 +++++++++++++++-
src/rpc/virnetclientstream.c | 12 +++++---
src/uml/uml_driver.c | 28 ++++++++++++++++++-
tools/console.c | 27 ++++++++++++------
tools/console.h | 2 +-
tools/virsh.c | 18 +++++++++---
14 files changed, 192 insertions(+), 29 deletions(-)
--
1.7.3.4
12 years, 11 months
[libvirt] [RFC PATCH 0/5] Support online resizing of block devices.
by Osier Yang
This patch series introduce new API "virDomainBlockResize" to expose
qemu monitor command "block_size", which is for resizing the a block
device while the domain is running.
The prototype for the new API is:
int
virDomainBlockResize (virDomainPtr dom,
const char *path,
unsigned long long size,
unsigned int flags)
* "@path" is the absolute path of the block device, which can be
extraced from domain xml.
* The units for "@size" is kilobytes, which might be not quite properly.
(qemu HMP uses Megabytes as the default units, QMP uses Bytes as the
default units, so it means we need to divice "@size" by 1024 for HMP,
and multiply "@size" by 1024 for QMP. On the other hand, we need to
check the overflowing). Any ideas on this is welcomed.
* "@flags" is unused currently.
[PATCH 1/5] block_resize: Define the new API
[PATCH 2/5] block_resize: Wire up the remote protocol
[PATCH 3/5] block_resize: Implement qemu monitor functions
[PATCH 4/5] block_resize: Implement qemu driver method
[PATCH 5/5] block_resize: Expose the new API to virsh
12 years, 12 months
[libvirt] [PATCH v4 00/13] Implement keepalive protocol for libvirt RPC
by Jiri Denemark
This patchset can also be found at
https://gitorious.org/~jirka/libvirt/jirka-staging/commits/keepalive
This allows us to detect broken connections between server and client without
waiting for TCP timeout and dead deamon/client. By default a connection is
considered broken after about 30 seconds of no messages received from remote
party. After that period, the connection is automatically closed.
The main reason for implementing this is that peer-to-peer migration can now be
canceled when a connection between source and target breaks. Although this will
really work only after qemu fixes migrate_cancel command so that it doesn't
block when outgoing TCP buffers are full.
Version 4 addresses comments from Daniel and Matthias. Although most of the
patches were already (conditionally) acked, I'm sending all of them to provide
a complete picture of the change. Patches that were already acked are
explicitly marked so in the Notes section so anyone can just skip them if they
like.
Jiri Denemark (13):
Define keepalive protocol
Implement common keepalive handling
Introduce virConnectSetKeepAlive
virsh: Always run event loop
Implement keepalive protocol in libvirt daemon
Add support for non-blocking calls in client RPC
Add support for async close of client RPC socket
Implement keepalive protocol in remote driver
Introduce virConnectIsAlive API
Implement virConnectIsAlive in all drivers
Add keepalive support into domain-events examples
qemu: Add support for keepalive messages during p2p migration
qemu: Cancel p2p migration when connection breaks
.gitignore | 1 +
daemon/libvirtd.aug | 5 +
daemon/libvirtd.c | 15 +
daemon/libvirtd.conf | 25 ++
daemon/libvirtd.h | 1 +
daemon/remote.c | 48 ++-
examples/domain-events/events-c/event-test.c | 9 +-
examples/domain-events/events-python/event-test.py | 4 +-
include/libvirt/libvirt.h.in | 5 +
po/POTFILES.in | 1 +
src/Makefile.am | 20 +-
src/driver.h | 8 +
src/esx/esx_driver.c | 18 +
src/hyperv/hyperv_driver.c | 18 +
src/libvirt.c | 93 ++++
src/libvirt_internal.h | 10 +-
src/libvirt_private.syms | 2 +
src/libvirt_public.syms | 2 +
src/libxl/libxl_driver.c | 8 +
src/lxc/lxc_driver.c | 7 +
src/openvz/openvz_driver.c | 7 +
src/phyp/phyp_driver.c | 18 +
src/probes.d | 12 +
src/qemu/libvirtd_qemu.aug | 2 +
src/qemu/qemu.conf | 22 +
src/qemu/qemu_conf.c | 11 +
src/qemu/qemu_conf.h | 3 +
src/qemu/qemu_driver.c | 6 +
src/qemu/qemu_migration.c | 43 ++-
src/qemu/test_libvirtd_qemu.aug | 6 +
src/remote/remote_driver.c | 70 +++
src/remote/remote_protocol.x | 2 +-
src/rpc/virkeepalive.c | 448 ++++++++++++++++++++
src/rpc/virkeepalive.h | 56 +++
src/rpc/virkeepaliveprotocol.x | 7 +
src/rpc/virnetclient.c | 428 ++++++++++++++++---
src/rpc/virnetclient.h | 6 +
src/rpc/virnetserver.c | 22 +
src/rpc/virnetserver.h | 5 +
src/rpc/virnetserverclient.c | 143 ++++++-
src/rpc/virnetserverclient.h | 7 +
src/test/test_driver.c | 6 +
src/uml/uml_driver.c | 7 +
src/util/event.c | 6 +-
src/vbox/vbox_tmpl.c | 6 +
src/vmware/vmware_driver.c | 7 +
src/xen/xen_driver.c | 8 +
src/xenapi/xenapi_driver.c | 12 +
tools/console.c | 17 +-
tools/virsh.c | 31 ++
50 files changed, 1621 insertions(+), 103 deletions(-)
create mode 100644 src/rpc/virkeepalive.c
create mode 100644 src/rpc/virkeepalive.h
create mode 100644 src/rpc/virkeepaliveprotocol.x
--
1.7.7.1
13 years
[libvirt] [PATCH V1 0/9] NWFilter: Filter more protocols and other extensions
by Stefan Berger
This patch series adds:
- filtering support for VLAN traffic
- support for a 'mac' chain
- filtering support for STP (spanning tree protocol)
- new filters that enable filtering of multiple IP addresses per interface
- better error reporting if ebtables/ip(6)table commands fail
Regards,
Stefan
13 years
[libvirt] bug: try to take disk snapshot for LVM2 Volume
by MATSUDA, Daiki
I tried the new snapshot function implemented by Eric Blake.
It works very well for QCOW2 disk image system.
But I often use LVM2 volume for QEMU virtual machines and tried to take
disk snapshot by virsh command ( snapshot-create DOMNAME --disk-only).
So, finally qemu monitor command 'snapshot_blkdev' accepts the LVM2
volume and create QCOW2 snapshot image. In addition, domain's
configuration file is replaced to use snapshot disk image instead of
LVM2 volume.
configuration file
from
....
<disk type='block' device='disk>
<driver name='qemu' type='raw' cache='none'/>
<source dev='dev/VG1/LVM2_dom'/>
....
to
<disk type='block' device='disk>
<driver name='qemu' type='qcow2' cache='none'/>
<source dev='dev/VG1/LVM2_dom.1317357844'/>
After then, the domain runs well till it is shutdowned. I started the
domain, but it does not with following error
virtsh # start LVM2_dom
error: Failed to start domain LVM2_dom
error: 内部エラー Process exited while reading console log output: char
device redirected to /dev/pts/7
qemu: could not open disk image /dev/VG1/LVM2_dom.1317357844: Invalid
argument.
I think that if the volume but qcow2 is given libvirt should be refuse,
e.g. in qemuDomainSnapshotCreateDiskActive() with voulme driver type.
But currently the structures concerning with snapshot or disk has no
member to hold such a volume driver information. In addition, as we want
to add the LVM2 and other volume snapshot function, we hope you add its
information and fix.
Regards
MATSUDA Daiki
13 years
[libvirt] [PATCH V5 0/4] Support for multiple IP addresses using lists
by Stefan Berger
This patch series builds on the previously posted patch series
https://www.redhat.com/archives/libvir-list/2011-October/msg00912.html
and introduces the capability to assign a list to a variable and
have multiple rules instantiated, one for each item in the list.
This means, that if for example a variable like IP has been assigned
a list of values
IP = [1.2.3.4, 5.6.7.8, 10.0.0.1]
it will instantiate 3 rules, which in turn allows us to build filters
that can evaluate multiple possible values per field, i.e., allow
the filtering for multiple IP addresses (per interface).
v5:
- addressing Eric Blake's comments
v4:
- addressing Daniel Berrange's comments
- changed (default) behavior of iterator
v3:
- following Daniel Berrange's comment regarding how a list of items
should be represented in the XML
v2:
- reimplementation of iterator
- other nits
Regards,
Stefan
13 years
[libvirt] [PATCH V4 00/10] Make inner workings of nwfilters more flexible + extensions
by Stefan Berger
The following series of patches re-does some of the inner workings
of nwfilters with the goal to enable users to write filters that have other
than the system-known chains supported right now ('root','arp','rarp','ipv4'
and 'ipv6'). Ideally users should be able to provide a chain name in the
chains XML attribute and either be able to jump to it as an 'action' or
have the chain created automatically as it is the case right now for those
chains enumerated before. The latter is now added in this patch series
as well.
I am first introducing internal priorities for the chains mentioned above so
that their creation can be made more flexible -- currently their creation and
the order in which they are accessed is hardcoded. This largely does away
with the hardcoded stuff. All assigned priorities have negative values.
Later on the priorities for the chains are made accessible via an XML
attribute.
Further, filters will be automatically accessed from the (ebtables)
interface 'root' chain using the prefix of the name of the chain. As an
example, the following filter will be accessed from the root chain for 'arp'
packets since its name 'arp-xyz' has the prefix 'arp'.
<filter name='test-arp-xyz' chain='arp-xyz' priority='-650'>
<uuid>94abeecc-c956-0ac8-1f49-a06ee8995688</uuid>
<rule action='accept' direction='out' priority='100'>
<arp opcode='Request_Reverse' arpsrcmacaddr='$MAC' arpdstmacaddr='$MAC'
arpsrcipaddr='0.0.0.0' arpdstipaddr='0.0.0.0'/>
</rule>
<rule action='accept' direction='inout' priority='500'/>
</filter>
In another step the priorities of rules is extended to also allow negativ
values. This then allows the creation of rules and chains in the interface
'root' chain to be mixed so that the following layout becomes possible:
Bridge chain: libvirt-I-vnet0, entries: 6, policy: ACCEPT
-p IPv4 -j I-vnet0-ipv4
-p ARP -j I-vnet0-arp
-p ARP -j ACCEPT
-p 0x8035 -j I-vnet0-rarp
-p 0x835 -j ACCEPT
-j DROP
In the above list of rules the '-p ARP -j ACCEPT' can now be found in
between the 'jumps' to protocol-specific chains, which allows for more
efficient rule evaluation.
I did testing with the test cases in libvirt-tck as well as those in
the tests/ directory and did not see any regressions.
v4:
- assign priority to chain according to name prefix
- change default (internal) priorities of chains (by +200)
- fix memory leak
Regards,
Stefan
13 years
Re: [libvirt] [RFC PATCH v3 4/4] qemu/rbd: improve rbd device specification
by Daniel P. Berrange
On Thu, Oct 20, 2011 at 11:01:27AM -0700, Josh Durgin wrote:
> From: Sage Weil <sage(a)newdream.net>
>
> This improves the support for qemu rbd devices by adding support for a few
> key features (e.g., authentication) and cleaning up the way in which
> rbd configuration options are passed to qemu.
>
> And <auth> member of the disk source xml specifies how librbd should
> authenticate. The username attribute is the Ceph/RBD user to authenticate as.
> The usage or uuid attributes specify which secret to use. Usage is an
> arbitrary identifier local to libvirt.
>
> The old RBD support relied on setting an environment variable to
> communicate information to qemu/librbd. Instead, pass those options
> explicitly to qemu. Update the qemu argument parsing and tests
> accordingly.
>
> Signed-off-by: Sage Weil <sage(a)newdream.net>
> Signed-off-by: Josh Durgin <josh.durgin(a)dreamhost.com>
> ---
> src/qemu/qemu_command.c | 284 ++++++++++++--------
> .../qemuxml2argv-disk-drive-network-rbd-auth.args | 6 +
> .../qemuxml2argv-disk-drive-network-rbd-auth.xml | 37 +++
> .../qemuxml2argv-disk-drive-network-rbd.args | 6 +-
> tests/qemuxml2argvtest.c | 52 ++++
> 5 files changed, 268 insertions(+), 117 deletions(-)
> create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd-auth.args
> create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd-auth.xml
>
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 4dfce88..b2c0eee 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -38,6 +38,7 @@
> #include "domain_audit.h"
> #include "domain_conf.h"
> #include "network/bridge_driver.h"
> +#include "base64.h"
>
> #include <sys/utsname.h>
> #include <sys/stat.h>
> @@ -1489,6 +1490,159 @@ qemuSafeSerialParamValue(const char *value)
> return 0;
> }
>
> +static int buildRBDString(virConnectPtr conn,
> + virDomainDiskDefPtr disk,
> + virBufferPtr opt)
For style reasons, s/buildRBDString/qemuBuildRBDString/
> +{
> + int i;
> + virSecretPtr sec = NULL;
> + char *secret = NULL;
> + size_t secret_size;
> +
> + virBufferAsprintf(opt, "rbd:%s", disk->src);
> + if (disk->auth.username) {
> + virBufferEscape(opt, ":", ":id=%s", disk->auth.username);
> + /* look up secret */
> + switch (disk->auth.secretType) {
> + case VIR_DOMAIN_DISK_SECRET_TYPE_UUID:
> + sec = virSecretLookupByUUID(conn,
> + disk->auth.secret.uuid);
> + break;
> + case VIR_DOMAIN_DISK_SECRET_TYPE_USAGE:
> + sec = virSecretLookupByUsage(conn,
> + VIR_SECRET_USAGE_TYPE_CEPH,
> + disk->auth.secret.usage);
> + break;
> + }
> +
> + if (sec) {
> + char *base64;
> +
> + secret = (char *)conn->secretDriver->getValue(sec, &secret_size, 0,
> + VIR_SECRET_GET_VALUE_INTERNAL_CALL);
> + if (secret == NULL) {
> + qemuReportError(VIR_ERR_INTERNAL_ERROR,
> + _("could not get the value of the secret for username %s"),
> + disk->auth.username);
> + return -1;
> + }
> + /* qemu/librbd wants it base64 encoded */
> + base64_encode_alloc(secret, secret_size, &base64);
> + virBufferEscape(opt, ":", ":key=%s:auth_supported=cephx\\;none",
> + base64);
> + VIR_FREE(base64);
> + VIR_FREE(secret);
> + virUnrefSecret(sec);
> + } else {
> + qemuReportError(VIR_ERR_INTERNAL_ERROR,
> + _("rbd username '%s' specified but secret not found"),
> + disk->auth.username);
> + return -1;
> + }
> + }
> +
> + if (disk->nhosts > 0) {
> + virBufferStrcat(opt, ":mon_host=", NULL);
> + for (i = 0; i < disk->nhosts; ++i) {
> + if (i) {
> + virBufferStrcat(opt, "\\;", NULL);
> + }
> + if (disk->hosts[i].port) {
> + virBufferAsprintf(opt, "%s\\:%s",
> + disk->hosts[i].name,
> + disk->hosts[i].port);
> + } else {
> + virBufferAsprintf(opt, "%s", disk->hosts[i].name);
> + }
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int addRBDHost(virDomainDiskDefPtr disk, char *hostport)
s/add/qemuAdd/
> +{
> + char *port;
> + int ret;
> +
> + disk->nhosts++;
> + ret = VIR_REALLOC_N(disk->hosts, disk->nhosts);
> + if (ret < 0) {
> + virReportOOMError();
> + return -1;
> + }
> +
> + port = strstr(hostport, "\\:");
> + if (port) {
> + *port = '\0';
> + port += 2;
> + disk->hosts[disk->nhosts-1].port = strdup(port);
> + } else {
> + disk->hosts[disk->nhosts-1].port = strdup("6789");
> + }
> + disk->hosts[disk->nhosts-1].name = strdup(hostport);
> + return 0;
> +}
> +
> +/* disk->src initially has everything after the rbd: prefix */
> +static int parseRBDString(virDomainDiskDefPtr disk)
s/parse/qemuParse/
> +{
> + char *options = NULL;
> + char *p, *e, *next;
> +
> + p = strchr(disk->src, ':');
> + if (p) {
> + options = strdup(p + 1);
> + *p = '\0';
> + }
> +
> + /* options */
> + if (!options)
> + return 0; /* all done */
> +
> + p = options;
> + while (*p) {
> + /* find : delimiter or end of string */
> + for (e = p; *e && *e != ':'; ++e) {
> + if (*e == '\\') {
> + e++;
> + if (*e == '\0')
> + break;
> + }
> + }
> + if (*e == '\0') {
> + next = e; /* last kv pair */
> + } else {
> + next = e + 1;
> + *e = '\0';
> + }
> +
> + if (STRPREFIX(p, "id=")) {
> + disk->auth.username = strdup(p + strlen("id="));
> + }
> + if (STRPREFIX(p, "mon_host=")) {
> + char *h, *sep;
> +
> + h = p + strlen("mon_host=");
> + while (h < e) {
> + for (sep = h; sep < e; ++sep) {
> + if (*sep == '\\' && (sep[1] == ',' ||
> + sep[1] == ';' ||
> + sep[1] == ' ')) {
> + *sep = '\0';
> + sep += 2;
> + break;
> + }
> + }
> + addRBDHost(disk, h);
> + h = sep;
> + }
> + }
> +
> + p = next;
> + }
> + return 0;
> +}
>
> char *
> qemuBuildDriveStr(virConnectPtr conn,
> @@ -1608,8 +1762,10 @@ qemuBuildDriveStr(virConnectPtr conn,
> disk->hosts->name, disk->hosts->port);
> break;
> case VIR_DOMAIN_DISK_PROTOCOL_RBD:
> - /* TODO: set monitor hostnames */
> - virBufferAsprintf(&opt, "file=rbd:%s,", disk->src);
> + virBufferStrcat(&opt, "file=", NULL);
> + if (buildRBDString(conn, disk, &opt) < 0)
> + goto error;
> + virBufferStrcat(&opt, ",", NULL);
> break;
> case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
> if (disk->nhosts == 0)
> @@ -3278,8 +3434,6 @@ qemuBuildCommandLine(virConnectPtr conn,
> int last_good_net = -1;
> bool hasHwVirt = false;
> virCommandPtr cmd;
> - bool has_rbd_hosts = false;
> - virBuffer rbd_hosts = VIR_BUFFER_INITIALIZER;
> bool emitBootindex = false;
> int usbcontroller = 0;
> bool usblegacy = false;
> @@ -3861,7 +4015,6 @@ qemuBuildCommandLine(virConnectPtr conn,
> virDomainDiskDefPtr disk = def->disks[i];
> int withDeviceArg = 0;
> bool deviceFlagMasked = false;
> - int j;
>
> /* Unless we have -device, then USB disks need special
> handling */
> @@ -3919,26 +4072,6 @@ qemuBuildCommandLine(virConnectPtr conn,
> virCommandAddArg(cmd, optstr);
> VIR_FREE(optstr);
>
> - if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK &&
> - disk->protocol == VIR_DOMAIN_DISK_PROTOCOL_RBD) {
> - for (j = 0 ; j < disk->nhosts ; j++) {
> - if (!has_rbd_hosts) {
> - virBufferAddLit(&rbd_hosts, "CEPH_ARGS=-m ");
> - has_rbd_hosts = true;
> - } else {
> - virBufferAddLit(&rbd_hosts, ",");
> - }
> - virDomainDiskHostDefPtr host = &disk->hosts[j];
> - if (host->port) {
> - virBufferAsprintf(&rbd_hosts, "%s:%s",
> - host->name,
> - host->port);
> - } else {
> - virBufferAdd(&rbd_hosts, host->name, -1);
> - }
> - }
> - }
> -
> if (!emitBootindex)
> bootindex = 0;
> else if (disk->bootIndex)
> @@ -3976,7 +4109,6 @@ qemuBuildCommandLine(virConnectPtr conn,
> char *file;
> const char *fmt;
> virDomainDiskDefPtr disk = def->disks[i];
> - int j;
>
> if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
> if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
> @@ -4045,24 +4177,15 @@ qemuBuildCommandLine(virConnectPtr conn,
> }
> break;
> case VIR_DOMAIN_DISK_PROTOCOL_RBD:
> - if (virAsprintf(&file, "rbd:%s,", disk->src) < 0) {
> - goto no_memory;
> - }
> - for (j = 0 ; j < disk->nhosts ; j++) {
> - if (!has_rbd_hosts) {
> - virBufferAddLit(&rbd_hosts, "CEPH_ARGS=-m ");
> - has_rbd_hosts = true;
> - } else {
> - virBufferAddLit(&rbd_hosts, ",");
> - }
> - virDomainDiskHostDefPtr host = &disk->hosts[j];
> - if (host->port) {
> - virBufferAsprintf(&rbd_hosts, "%s:%s",
> - host->name,
> - host->port);
> - } else {
> - virBufferAdd(&rbd_hosts, host->name, -1);
> + {
> + virBuffer opt = VIR_BUFFER_INITIALIZER;
> + if (buildRBDString(conn, disk, &opt) < 0)
> + goto error;
> + if (virBufferError(&opt)) {
> + virReportOOMError();
> + goto error;
> }
> + file = virBufferContentAndReset(&opt);
> }
> break;
> case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
> @@ -4091,9 +4214,6 @@ qemuBuildCommandLine(virConnectPtr conn,
> }
> }
>
> - if (has_rbd_hosts)
> - virCommandAddEnvBuffer(cmd, &rbd_hosts);
> -
> if (qemuCapsGet(qemuCaps, QEMU_CAPS_FSDEV)) {
> for (i = 0 ; i < def->nfss ; i++) {
> char *optstr;
> @@ -5263,7 +5383,6 @@ qemuBuildCommandLine(virConnectPtr conn,
> networkReleaseActualDevice(def->nets[i]);
> for (i = 0; i <= last_good_net; i++)
> virDomainConfNWFilterTeardown(def->nets[i]);
> - virBufferFreeAndReset(&rbd_hosts);
> virCommandFree(cmd);
> return NULL;
> }
> @@ -5295,10 +5414,6 @@ static int qemuStringToArgvEnv(const char *args,
> const char *next;
>
> start = curr;
> - /* accept a space in CEPH_ARGS */
> - if (STRPREFIX(curr, "CEPH_ARGS=-m ")) {
> - start += strlen("CEPH_ARGS=-m ");
> - }
> if (*start == '\'') {
> if (start == curr)
> curr++;
> @@ -5577,6 +5692,8 @@ qemuParseCommandLineDisk(virCapsPtr caps,
> virReportOOMError();
> goto cleanup;
> }
> + if (parseRBDString(def) < 0)
> + goto cleanup;
>
> VIR_FREE(p);
> } else if (STRPREFIX(def->src, "sheepdog:")) {
> @@ -6696,7 +6813,8 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
> disk->src = NULL;
> break;
> case VIR_DOMAIN_DISK_PROTOCOL_RBD:
> - /* handled later since the hosts for all disks are in CEPH_ARGS */
> + if (parseRBDString(disk) < 0)
> + goto error;
> break;
> case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
> /* disk->src must be [vdiname] or [host]:[port]:[vdiname] */
> @@ -7035,68 +7153,6 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
> }
>
> #undef WANT_VALUE
> - if (def->ndisks > 0) {
> - const char *ceph_args = qemuFindEnv(progenv, "CEPH_ARGS");
> - if (ceph_args) {
> - char *hosts, *port, *saveptr = NULL, *token;
> - virDomainDiskDefPtr first_rbd_disk = NULL;
> - for (i = 0 ; i < def->ndisks ; i++) {
> - if (def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_NETWORK &&
> - def->disks[i]->protocol == VIR_DOMAIN_DISK_PROTOCOL_RBD) {
> - first_rbd_disk = def->disks[i];
> - break;
> - }
> - }
> -
> - if (!first_rbd_disk) {
> - qemuReportError(VIR_ERR_INTERNAL_ERROR,
> - _("CEPH_ARGS was set without an rbd disk"));
> - goto error;
> - }
> -
> - /* CEPH_ARGS should be: -m host1[:port1][,host2[:port2]]... */
> - if (!STRPREFIX(ceph_args, "-m ")) {
> - qemuReportError(VIR_ERR_INTERNAL_ERROR,
> - _("could not parse CEPH_ARGS '%s'"), ceph_args);
> - goto error;
> - }
> - hosts = strdup(strchr(ceph_args, ' ') + 1);
> - if (!hosts)
> - goto no_memory;
> - first_rbd_disk->nhosts = 0;
> - token = strtok_r(hosts, ",", &saveptr);
> - while (token != NULL) {
> - if (VIR_REALLOC_N(first_rbd_disk->hosts, first_rbd_disk->nhosts + 1) < 0) {
> - VIR_FREE(hosts);
> - goto no_memory;
> - }
> - port = strchr(token, ':');
> - if (port) {
> - *port++ = '\0';
> - port = strdup(port);
> - if (!port) {
> - VIR_FREE(hosts);
> - goto no_memory;
> - }
> - }
> - first_rbd_disk->hosts[first_rbd_disk->nhosts].port = port;
> - first_rbd_disk->hosts[first_rbd_disk->nhosts].name = strdup(token);
> - if (!first_rbd_disk->hosts[first_rbd_disk->nhosts].name) {
> - VIR_FREE(hosts);
> - goto no_memory;
> - }
> - first_rbd_disk->nhosts++;
> - token = strtok_r(NULL, ",", &saveptr);
> - }
> - VIR_FREE(hosts);
> -
> - if (first_rbd_disk->nhosts == 0) {
> - qemuReportError(VIR_ERR_INTERNAL_ERROR,
> - _("found no rbd hosts in CEPH_ARGS '%s'"), ceph_args);
> - goto error;
> - }
> - }
> - }
>
> if (!nographics && def->ngraphics == 0) {
> virDomainGraphicsDefPtr sdl;
> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
> index a7ae925..31bd928 100644
> --- a/tests/qemuxml2argvtest.c
> +++ b/tests/qemuxml2argvtest.c
> @@ -23,6 +23,55 @@
> static const char *abs_top_srcdir;
> static struct qemud_driver driver;
>
> +static unsigned char *
> +fakeSecretGetValue(virSecretPtr obj ATTRIBUTE_UNUSED,
> + size_t *value_size,
> + unsigned int fakeflags ATTRIBUTE_UNUSED,
> + unsigned int internalFlags ATTRIBUTE_UNUSED)
> +{
> + char *secret = strdup("AQCVn5hO6HzFAhAAq0NCv8jtJcIcE+HOBlMQ1A");
> + *value_size = strlen(secret);
> + return (unsigned char *) secret;
> +}
> +
> +static virSecretPtr
> +fakeSecretLookupByUsage(virConnectPtr conn,
> + int usageType ATTRIBUTE_UNUSED,
> + const char *usageID)
> +{
> + virSecretPtr ret = NULL;
> + if (strcmp(usageID, "mycluster_myname"))
s/strcmp/STRNEQ/
> + return ret;
> + ret = malloc(sizeof(virSecret));
Need to use VIR_ALLOC for this.
> + ret->magic = VIR_SECRET_MAGIC;
> + ret->conn = conn;
> + conn->refs++;
> + ret->refs = 1;
> + ret->usageID = strdup(usageID);
> + return ret;
> +}
> +
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
13 years
[libvirt] [libvirt-glib 00/24] libvirt-gconfig patches
by Christophe Fergeau
Hi,
Here is a set of patches which start to implement functionality to
libvirt-gconfig. The end result is that the "name", "memory" and
"features" properties are implemented for the Domain class. Most of
the work is about reworking the low-level plumbing to make the
implementation as easy as possible.
I chose to remove the xmlDocPtr and the xml string that were stored
in GVirConfigObject objects and to replace this with a xmlNodePtr.
This is useful when creating children objects (eg devices) when
parsing a domain XML because the xmlNodePtr will point at the
right position in the XML document. One caveat with that approach
is that we need to refcount the xmlDocPtr associated with the
xmlNodePtr to know when to free it, but this is not implemented
yet (though gupnp seems to have code doing exactly this).
Then most of the work is adding properties and helpers to make
the code easier to write. And thinking about what API we want to
expose to clients :) The two test programs should show how the API
can be used as it is now.
While writing this, I realized we had to do some "useless" work to
return strings from libxml2 to glib, ie I g_strdup the string and
xmlFree the source so that the caller can free it with g_free.
While writing this code, there were at least 2 questions that arose,
some input would be welcome :)
* I don't know how to handle XMLs where the same node appears multiple
times (eg "name"). If it's the latest name that wins, what do we do when
changing the name on such an XML document? only modify the last name node?
Drop all the redundant name nodes?
* I'm also not sure how to make it possible to check whether a given
property is set or not. For strings, this is easy, NULL means that the
property was not set, but for integers, this is less obvious. Any thoughts on
that?
Next I'll have to start looking at more complicated properties :) More API
questions on the way I guess...
Christophe
Christophe Fergeau (23):
Add helpers in libvirt-gconfig-helpers.[ch]
gvir_config_object_parse: don't parse empty documents
Add getters for GVirConfig xmlNode and xmlDoc
Add GVirConfigObject::node property
Add GVir::Config::Domain::name property
Rename gvir_config_domain_new
Add gvir_config_domain_new to create an empty domain
Implement gvir_config_domain_set_name
Make the GVirConfigDomain::name property writable
Add gvir_config_object_to_xml
Use gvir_config_object_to_xml
Add domain creation/parsing test
Remove GVirConfigObject::docHandle
Remove xml parsing from gvir_config_*_new functions
Only do XML parsing when creating config objects
Remove GError argument from GVirConfigObject::node getter
Remove GVirConfigObject::doc
Add gvir_config_object_get_node_content
Add gvir_config_object_set_node_content
Add test-domain-duplicate.xml which currently fails
Validate document in parsing test
Add GVirConfigDomain::memory
Add GVirConfigDomain::features
configure.ac | 1 +
examples/Makefile.am | 1 +
libvirt-gconfig/Makefile.am | 4 +
libvirt-gconfig/libvirt-gconfig-capabilities.c | 10 +-
libvirt-gconfig/libvirt-gconfig-capabilities.h | 2 +-
libvirt-gconfig/libvirt-gconfig-domain-snapshot.c | 9 +-
libvirt-gconfig/libvirt-gconfig-domain-snapshot.h | 2 +-
libvirt-gconfig/libvirt-gconfig-domain.c | 186 ++++++++++++++++-
libvirt-gconfig/libvirt-gconfig-domain.h | 12 +-
libvirt-gconfig/libvirt-gconfig-helpers.c | 179 +++++++++++++++
libvirt-gconfig/libvirt-gconfig-helpers.h | 48 ++++
libvirt-gconfig/libvirt-gconfig-interface.c | 12 +-
libvirt-gconfig/libvirt-gconfig-interface.h | 2 +-
libvirt-gconfig/libvirt-gconfig-network-filter.c | 8 +-
libvirt-gconfig/libvirt-gconfig-network-filter.h | 2 +-
libvirt-gconfig/libvirt-gconfig-network.c | 8 +-
libvirt-gconfig/libvirt-gconfig-network.h | 2 +-
libvirt-gconfig/libvirt-gconfig-node-device.c | 9 +-
libvirt-gconfig/libvirt-gconfig-node-device.h | 2 +-
libvirt-gconfig/libvirt-gconfig-object.c | 244 ++++++++++++---------
libvirt-gconfig/libvirt-gconfig-object.h | 17 ++-
libvirt-gconfig/libvirt-gconfig-secret.c | 8 +-
libvirt-gconfig/libvirt-gconfig-secret.h | 2 +-
libvirt-gconfig/libvirt-gconfig-storage-pool.c | 8 +-
libvirt-gconfig/libvirt-gconfig-storage-pool.h | 2 +-
libvirt-gconfig/libvirt-gconfig-storage-vol.c | 12 +-
libvirt-gconfig/libvirt-gconfig-storage-vol.h | 2 +-
libvirt-gconfig/libvirt-gconfig.h | 2 +
libvirt-gconfig/libvirt-gconfig.sym | 11 +-
libvirt-gconfig/tests/Makefile.am | 16 ++
libvirt-gconfig/tests/test-domain-create.c | 68 ++++++
libvirt-gconfig/tests/test-domain-duplicate.xml | 7 +
libvirt-gconfig/tests/test-domain-invalid.xml | 6 +
libvirt-gconfig/tests/test-domain-noname.xml | 4 +
libvirt-gconfig/tests/test-domain-parse.c | 87 ++++++++
libvirt-gconfig/tests/test-domain.xml | 7 +
libvirt-gobject/Makefile.am | 2 +
libvirt-gobject/libvirt-gobject-connection.c | 2 +-
libvirt-gobject/libvirt-gobject-domain-snapshot.c | 3 +
libvirt-gobject/libvirt-gobject-domain.c | 6 +-
libvirt-gobject/libvirt-gobject-interface.c | 3 +
libvirt-gobject/libvirt-gobject-network-filter.c | 3 +
libvirt-gobject/libvirt-gobject-network.c | 3 +
libvirt-gobject/libvirt-gobject-node-device.c | 4 +
libvirt-gobject/libvirt-gobject-secret.c | 4 +
libvirt-gobject/libvirt-gobject-storage-pool.c | 5 +-
libvirt-gobject/libvirt-gobject-storage-vol.c | 3 +
47 files changed, 895 insertions(+), 145 deletions(-)
create mode 100644 libvirt-gconfig/libvirt-gconfig-helpers.c
create mode 100644 libvirt-gconfig/libvirt-gconfig-helpers.h
create mode 100644 libvirt-gconfig/tests/Makefile.am
create mode 100644 libvirt-gconfig/tests/test-domain-create.c
create mode 100644 libvirt-gconfig/tests/test-domain-duplicate.xml
create mode 100644 libvirt-gconfig/tests/test-domain-invalid.xml
create mode 100644 libvirt-gconfig/tests/test-domain-noname.xml
create mode 100644 libvirt-gconfig/tests/test-domain-parse.c
create mode 100644 libvirt-gconfig/tests/test-domain.xml
--
1.7.6.4
13 years