[libvirt] [RFC PATCHv2 0/4] Adding 'config' driver
by Adam Walters
This patchset adds a driver named 'config' which provides access to
configuration data, such as secret and storage definitions, without
requiring a connection to a hypervisor. This complements my previous
patchset, which resolves the race condition on libvirtd startup.
The rationale behind this idea is that there exist circumstances under which a
driver may require access to things such as secrets during a time at which
there is no active connection to a hypervisor. Currently, that data can not be
accessed. An example of this in libvirt today is that the storage driver
requires a connection in order to access secret data to auto-start an RBD
storage pool that uses CephX authentication. My previous patchset breaks the
ability to auto-start that type of storage pool, and this patchset fixes it
again.
This driver is technically what one may call a hypervisor driver, but it does
not implement any domain operations. It simply exists to handle requests by
drivers for access to information that would otherwise by unattainable. The
URI provided by this driver is 'config:///' and has been tested working on four
different machines of mine, running three different Linux distributions
(Archlinux, Gentoo, and CentOS). Being a very simple driver, I would expect it
to work pretty much anywhere.
I welcome comments and suggestions related to this driver. At the very least,
this patchset combined with my previous patchset resolves the current race
condition present on startup of libvirtd without any loss of functionality.
Adam Walters (4):
config: Adding config driver
configure: Implement config driver
libvirtd: Reorder load of secrets driver
storage: Change hardcoded QEMU connection to use config driver
configure.ac | 11 ++
daemon/libvirtd.c | 21 ++--
include/libvirt/virterror.h | 2 +
po/POTFILES.in | 1 +
src/Makefile.am | 25 +++++
src/config/config_driver.c | 238 +++++++++++++++++++++++++++++++++++++++++++
src/config/config_driver.h | 44 ++++++++
src/storage/storage_driver.c | 13 +--
src/util/virerror.c | 2 +
9 files changed, 345 insertions(+), 12 deletions(-)
create mode 100644 src/config/config_driver.c
create mode 100644 src/config/config_driver.h
--
1.8.5.2
10 years, 11 months
[libvirt] [PATCHv2 0/9] Snapshots on gluster
by Peter Krempa
Peter Krempa (9):
storage: Add new argument for createVol backend API
storage: gluster: Introduce dummy functions for creating a volume
storage: Add internal API to create temporary storage pools and vols
snapshot: Add support for specifying snapshot disk backing type
snapshot: Test snapshot disk type specification
storage: Implement ephemeral storage APIs in the generic storage
driver
storage: gluster: Support conversion of gluster volumes to temp
volumes
qemu: snapshot: Switch snapshot file deletion to the new storage API
qemu: snapshot: Add support for external active snapshots on gluster
docs/formatsnapshot.html.in | 15 +
docs/hvsupport.pl | 3 +
docs/schemas/domainsnapshot.rng | 76 +++-
src/Makefile.am | 3 +-
src/check-aclrules.pl | 3 +
src/check-drivername.pl | 1 +
src/conf/snapshot_conf.c | 42 ++-
src/conf/snapshot_conf.h | 15 +-
src/driver.h | 13 +
src/libvirt_internal.c | 70 ++++
src/libvirt_internal.h | 22 ++
src/libvirt_private.syms | 3 +
src/qemu/qemu_command.c | 2 +-
src/qemu/qemu_command.h | 9 +
src/qemu/qemu_conf.c | 3 -
src/qemu/qemu_driver.c | 227 ++++++++++--
src/storage/storage_backend.h | 3 +-
src/storage/storage_backend_disk.c | 3 +-
src/storage/storage_backend_fs.c | 30 +-
src/storage/storage_backend_gluster.c | 119 +++++-
src/storage/storage_backend_logical.c | 6 +-
src/storage/storage_backend_rbd.c | 3 +-
src/storage/storage_backend_sheepdog.c | 3 +-
src/storage/storage_driver.c | 405 ++++++++++++++++++++-
tests/domainsnapshotxml2xmlin/disk_snapshot.xml | 18 +
.../disk_driver_name_null.xml | 2 +-
tests/domainsnapshotxml2xmlout/disk_snapshot.xml | 22 +-
.../disk_snapshot_redefine.xml | 6 +-
28 files changed, 1007 insertions(+), 120 deletions(-)
create mode 100644 src/libvirt_internal.c
--
1.8.5.2
10 years, 11 months
[libvirt] [PATCH] Honor blacklist for modprobe command
by John Ferlan
https://bugzilla.redhat.com/show_bug.cgi?id=1045124
When loading modules, libvirt does not honor the modprobe blacklist.
By adding a "-b" to the modprobe command libvirt will fail to load a
module if it's on the blacklist
Check if the failure to load a driver was due to it being on the blacklist
using the output of a "modprobe -c" searching for "blacklist <driver_Name>"
where driver_Name is possibly a modified string of the input driver changing
all '-' into '_' since that's what modprobe does.
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/util/virpci.c | 48 ++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 42 insertions(+), 6 deletions(-)
diff --git a/src/util/virpci.c b/src/util/virpci.c
index e2d222e..18b85f2 100644
--- a/src/util/virpci.c
+++ b/src/util/virpci.c
@@ -979,6 +979,10 @@ virPCIProbeStubDriver(const char *driver)
{
char *drvpath = NULL;
bool probed = false;
+ size_t i;
+ char *drvblklst = NULL;
+ char *outbuf = NULL;
+ virCommandPtr cmd = NULL;
recheck:
if (virPCIDriverDir(&drvpath, driver) == 0 && virFileExists(drvpath)) {
@@ -990,18 +994,49 @@ recheck:
VIR_FREE(drvpath);
if (!probed) {
- const char *const probecmd[] = { MODPROBE, driver, NULL };
+ cmd = virCommandNewArgList(MODPROBE, "-b", driver, NULL);
probed = true;
- if (virRun(probecmd, NULL) < 0) {
+ if (virCommandRun(cmd, NULL) < 0) {
char ebuf[1024];
VIR_WARN("failed to load driver %s: %s", driver,
virStrerror(errno, ebuf, sizeof(ebuf)));
- return -1;
+ goto cleanup;
}
+ virCommandFree(cmd);
+ cmd = NULL;
goto recheck;
}
+ /* All error path code - purpose is to determine whether the failure
+ * occurs because device is on blacklist in order to add an error
+ * message to help detect why load failed
+ */
+ if (virAsprintfQuiet(&drvblklst, "blacklist %s", driver) < 0)
+ goto cleanup;
+
+ /* Although driver may have dash, 'modprobe -c' adjusts to use underscore */
+ for (i = 0; i < drvblklst[i]; i++)
+ if (drvblklst[i] == '-')
+ drvblklst[i] = '_';
+
+ cmd = virCommandNewArgList(MODPROBE, "-c", NULL);
+ virCommandSetOutputBuffer(cmd, &outbuf);
+ if (virCommandRun(cmd, NULL) < 0)
+ goto cleanup;
+
+ /* Find driver on blacklist? */
+ if (strstr(outbuf, drvblklst)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to load PCI stub module %s: "
+ "administratively prohibited"),
+ driver);
+ }
+
+cleanup:
+ virCommandFree(cmd);
+ VIR_FREE(drvblklst);
+ VIR_FREE(outbuf);
return -1;
}
@@ -1313,9 +1348,10 @@ virPCIDeviceDetach(virPCIDevicePtr dev,
virPCIDeviceList *inactiveDevs)
{
if (virPCIProbeStubDriver(dev->stubDriver) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Failed to load PCI stub module %s"),
- dev->stubDriver);
+ if (virGetLastError() == NULL)
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to load PCI stub module %s"),
+ dev->stubDriver);
return -1;
}
--
1.8.4.2
10 years, 11 months
[libvirt] [PATCHv2 0/6] Add BlkIO and CPU/mem stat API implementations for lxc
by Thorsten Behrens
This patch set adds block io, memory and domain cpu statistics API
slot implementations to the LXC driver, in order to get linux
container monitoring and accounting a bit closer to qemu standards.
The last patch is a tad quirky (happy to hear suggestions on
alternative ways), in that it widens the permissible value set
at the .domainBlockStats slot: for lxc guests, it is relatively
likely to have zero disk devices, since host filesystems can be
used via passthrough bind mounts. Therefore, passing the zero-length
string as device path, is interpreted as 'return summary stats for
the entire domains's block io'.
Thorsten Behrens (6):
Add util virCgroupGetBlkioIo*Serviced methods.
Implement domainMemoryStats API slot for LXC driver.
Make qemuGetDomainTotalCPUStats a virCgroup function.
Implement domainGetCPUStats for lxc driver.
Implemet lxcDomainBlockStats for lxc driver
Widening API change - accept empty path for virDomainBlockStats
src/libvirt.c | 8 +-
src/libvirt_private.syms | 3 +
src/lxc/lxc_driver.c | 239 +++++++++++++++++++++++++++++++++++
src/qemu/qemu_driver.c | 54 +-------
src/util/vircgroup.c | 291 +++++++++++++++++++++++++++++++++++++++++++
src/util/vircgroup.h | 17 +++
tools/virsh-domain-monitor.c | 11 +-
tools/virsh.pod | 5 +-
8 files changed, 569 insertions(+), 59 deletions(-)
--
1.8.4
10 years, 11 months
[libvirt] [PATCH v3 0/2] Enhance virnetdevbandwidthtest
by Michal Privoznik
yet another version - this time with virBuffer approach.
Michal Privoznik (2):
virCommand: Introduce virCommandSetDryRun
virnetdevbandwidthtest: Introduce testVirNetDevBandwidthSet
src/libvirt_private.syms | 1 +
src/util/vircommand.c | 57 +++++++++++++++++++++++++++++--
src/util/vircommand.h | 2 ++
tests/virnetdevbandwidthtest.c | 76 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 134 insertions(+), 2 deletions(-)
--
1.8.5.2
10 years, 11 months
Re: [libvirt] [Qemu-devel] [PATCH v4 4/5] qmp: full introspection support for QMP
by Amos Kong
CC Libvirt-list
Original discussion:
http://marc.info/?l=qemu-devel&m=139048842504757&w=2
[Qemu-devel] [PATCH v4 0/5] QMP full introspection
On Fri, Jan 24, 2014 at 06:48:31PM +0800, Fam Zheng wrote:
> On Thu, 01/23 22:46, Amos Kong wrote:
> > This patch introduces a new monitor command to query QMP schema
> > information, the return data is a range of schema structs, which
> > contains the useful metadata to help management to check supported
> > features, QMP commands detail, etc.
> >
> > We use qapi-introspect.py to parse all json definition in
> > qapi-schema.json, and generate a range of dictionaries with metadata.
> > The query command will visit the dictionaries and fill the data
> > to allocated struct tree. Then QMP infrastructure will convert
> > the tree to json string and return to QMP client.
> >
> > TODO:
> > Wenchao Xia is working to convert QMP events to qapi-schema.json,
> > then event can also be queried by this interface.
> >
> > I will introduce another command 'query-qga-schema' to query QGA
> > schema information, it's easy to add this support based on this
> > patch.
> >
> > Signed-off-by: Amos Kong <akong(a)redhat.com>
> > ---
> > qapi-schema.json | 11 +++
> > qmp-commands.hx | 42 +++++++++++
> > qmp.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 268 insertions(+)
> >
> > diff --git a/qapi-schema.json b/qapi-schema.json
> > index c63f0ca..6033383 100644
> > --- a/qapi-schema.json
> > +++ b/qapi-schema.json
> > @@ -4411,3 +4411,14 @@
> > 'reference-type': 'String',
> > 'type': 'DataObjectType',
> > 'unionobj': 'DataObjectUnion' } }
> > +
> > +##
> > +# @query-qmp-schema
> > +#
> > +# Query QMP schema information
> > +#
> > +# @returns: list of @DataObject
> > +#
> > +# Since: 1.8
> > +##
> > +{ 'command': 'query-qmp-schema', 'returns': ['DataObject'] }
> > diff --git a/qmp-commands.hx b/qmp-commands.hx
> > index 02cc815..b83762d 100644
> > --- a/qmp-commands.hx
> > +++ b/qmp-commands.hx
> > @@ -3291,6 +3291,48 @@ Example:
> > }
> >
> > EQMP
> > + {
> > + .name = "query-qmp-schema",
> > + .args_type = "",
> > + .mhandler.cmd_new = qmp_marshal_input_query_qmp_schema,
> > + },
> > +
> > +
> > +SQMP
> > +query-qmp-schema
> > +----------------
> > +
> > +query qmp schema information
> > +
> > +Return a json-object with the following information:
> > +
> > +- "name": qmp schema name (json-string)
> > +- "type": qmp schema type, it can be 'comand', 'type', 'enum', 'union'
> > +- "returns": return data of qmp command (json-object, optional)
> > +
> > +Example:
> > +
> > +-> { "execute": "query-qmp-schema" }
> > +-> { "return": [
> > + {
> > + "name": "query-name",
> > + "type": "command",
> > + "returns": {
> > + "name": "NameInfo",
> > + "type": "type",
> > + "data": [
> > + {
> > + "name": "name",
> > + "optional": true,
> > + "recursive": false,
> > + "type": "str"
> > + }
> > + ]
> > + }
> > + }
> > + }
> > +
> > +EQMP
> >
> > {
> > .name = "blockdev-add",
> > diff --git a/qmp.c b/qmp.c
> > index 0f46171..a64ae6d 100644
> > --- a/qmp.c
> > +++ b/qmp.c
> > @@ -27,6 +27,8 @@
> > #include "qapi/qmp/qobject.h"
> > #include "qapi/qmp-input-visitor.h"
> > #include "hw/boards.h"
> > +#include "qapi/qmp/qjson.h"
> > +#include "qapi-introspect.h"
> >
> > NameInfo *qmp_query_name(Error **errp)
> > {
> > @@ -488,6 +490,219 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
> > return arch_query_cpu_definitions(errp);
> > }
> >
> > +static strList *qobject_to_strlist(QObject *data)
> > +{
> > + strList *list = NULL;
> > + strList **plist = &list;
> > + QList *qlist;
> > + const QListEntry *lent;
> > +
> > + qlist = qobject_to_qlist(data);
> > + for (lent = qlist_first(qlist); lent; lent = qlist_next(lent)) {
> > + strList *entry = g_malloc0(sizeof(strList));
> > + entry->value = g_strdup(qobject_get_str(lent->value));
> > + *plist = entry;
> > + plist = &entry->next;
> > + }
> > +
> > + return list;
> > +}
> > +
> > +static DataObject *qobject_to_dataobj(QObject *data);
> > +
> > +static DataObjectMember *qobject_to_dataobjmem(QObject *data)
> > +{
> > +
> > + DataObjectMember *member = g_malloc0(sizeof(DataObjectMember));
> > +
> > + member->type = g_malloc0(sizeof(DataObjectMemberType));
> > + if (data->type->code == QTYPE_QDICT) {
> > + member->type->kind = DATA_OBJECT_MEMBER_TYPE_KIND_EXTEND;
> > + member->type->extend = qobject_to_dataobj(data);
> > + } else {
> > + member->type->kind = DATA_OBJECT_MEMBER_TYPE_KIND_REFERENCE;
> > + member->type->reference = g_strdup(qobject_get_str(data));
> > + }
> > +
> > + return member;
> > +}
> > +
> > +static DataObjectMemberList *qobject_to_dict_memlist(QObject *data)
> > +{
> > + DataObjectMemberList *list = NULL;
> > + DataObjectMemberList **plist = &list;
> > + QDict *qdict = qobject_to_qdict(data);
> > + const QDictEntry *dent;
> > +
> > + for (dent = qdict_first(qdict); dent; dent = qdict_next(qdict, dent)) {
> > + DataObjectMemberList *entry = g_malloc0(sizeof(DataObjectMemberList));
> > + entry->value = qobject_to_dataobjmem(dent->value);
> > +
> > + entry->value->has_optional = true;
> > + entry->value->has_name = true;
> > + if (dent->key[0] == '*') {
> > + entry->value->optional = true;
> > + entry->value->name = g_strdup(dent->key + 1);
> > + } else {
> > + entry->value->name = g_strdup(dent->key);
> > + }
> > + *plist = entry;
> > + plist = &entry->next;
> > + }
> > +
> > + return list;
> > +}
> > +
> > +static DataObjectMemberList *qobject_to_list_memlist(QObject *data)
> > +{
> > + const QListEntry *lent;
> > + DataObjectMemberList *list = NULL;
> > + DataObjectMemberList **plist = &list;
> > + QList *qlist = qobject_to_qlist(data);
> > +
> > + for (lent = qlist_first(qlist); lent; lent = qlist_next(lent)) {
> > + DataObjectMemberList *entry = g_malloc0(sizeof(DataObjectMemberList));
> > + entry->value = qobject_to_dataobjmem(lent->value);
> > + entry->value->has_optional = true;
> > + entry->value->has_name = true;
> > + *plist = entry;
> > + plist = &entry->next;
> > + }
> > +
> > + return list;
> > +}
> > +
> > +static DataObjectMemberList *qobject_to_memlist(QObject *data)
>
> This whole converting is cumbersome. You already did all the traversing through
> the type jungle in python when generating this, it's not necessary to do the
> similar thing again here.
We can parse raw schemas and generate json string table, we can't
directly return the string / qobject to monitor, C code has to convert
the json to qobject, we have to revisit the qobject and convert them
to DataObject/DataObjectMember/DataObject... structs.
> Alternatively, I think we have a good reason to extend QMP framework as
> necessary here, as we are doing "QMP introspection", which is a part of the
> framework:
>
> * Define final output into qmp_schema_table[], no need to box it like:
>
> "{'_obj_member': 'False', '_obj_type': 'enum', '_obj_name':
> 'ErrorClass', '_obj_data': {'data': ...
>
> just put it content of "qmp-introspection.output.txt" as a long string in
> the header,
> like you would generate in qobject_to_memlist:
>
> const char *qmp_schema_table =
> "{ 'name': 'ErrorClass', 'type': 'enumeration', 'data': [...]},"
> "{ 'name': '...', ...},"
The keys are used for metadata might be 'recursive', 'optional', etc.
It might exists problem in namespace, let's use '_obj_' or '_' prefix
for the metadata keys.
I used a nested dictionary to describe a DataObject, because we can
store the metadata and definition to different level, it's helpful
in parse the output by Libvirt.
example:
"{ 'type': 'NameInfo', 'data': {'*name': 'str', '*job': 'str'} }"
It's good to store _type, _name, data to same level, but the metadata
of items of data's value dictionary can't be appended to same level.
"{ '_name': 'NameInfo', '_type': 'type',
'data': {
'name': 'str', '_name_optional': 'True',
'job': 'str', '_job_optional': 'True'
}
}"
A better solution, but I don't know if it will cause trouble for
Libvirt to parse the output.
"{'_type': 'type', '_name': 'NameInfo',
'data': { 'job': {'_value': 'str', '_recursive': 'True'},
'name': {'_value': 'str', '_recursive': 'True'}
},
'_recursive': 'False'
}"
When we describe a DataObject (dict/list/str, one schema, extened
schema, schema member, etc), so I we generally use a nested dictionary
to describe a DataObject, it will split the metadata with original
data two different dictionary level, it's convenient for parse of
Libvirt. Here I just use a dict member as an example, actually
it's more complex to parse all kinds of data objects.
> ...
> ;
>
> * Add a new type of qmp command, that returns a QString as a json literal.
> query-qmp-schema is defined as this type. (This wouldn't be much code, but
> may be abused in the future, I'm afraid. However we can review, limit its
> use to introspection only)
>
> * And return qmp_schema_table from query-qmp-shema, which will be copied to
> the wire.
>
> Feel free to disagree, it's not a perfect solution. But I really think we need
> to avoid duplicating "enum", "base", "type", "union", "discriminator", ...
In the past, we didn't consider to extend and add metadata by Python, so
Libvirt wasn't happy to just get a raw schema(not extended, no metadata).
But now, we already successfully to transfer this work to Python, and
we can adjust to make management to be happy for the metadata and
format.
The problem is that Libvirt should parse the output twice, the json
items are also json object string.
Eric, Is it acceptabled?
Example:
* as suggested by Fam to put the metadta with schema data in same
dict level
* process some special cases by nested dictionary
(eg: '*tls': 'bool' ==> 'tls': {'_value': 'bool', '_optional': 'True'} )
* return a strList to Libvirt, the content of string is json object,
that contains the metadata.
{
"return": [
"{'_type': 'enum', '_name': 'ErrorClass', 'data': ['GenericError', 'CommandNotFound', 'DeviceEncrypted', 'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap'], '_recursive': 'False'}",
"{'_type': 'command', '_name': 'add_client', 'data': {'tls': {'_value': 'bool', '_optional': 'True'}, 'skipauth': {'_value': 'bool', '_optional': 'True'}, 'protocol': 'str', 'fdname': 'str'}, '_recursive': 'False'}",
"{'_type': 'type', '_name': 'NameInfo', 'data': {'job': {'_value': 'str', '_optional': 'True'}, 'name': {'_value': 'str', '_optional': 'True'}}, '_recursive': 'False'}",
"{'returns': {'_type': 'type', '_recursive': 'False', 'data': {'job': {'_value': 'str', '_optional': 'True'}, 'name': {'_value': 'str', '_optional': 'True'}}, '_name': 'NameInfo'}, '_name': 'query-name', '_type': 'command', '_recursive': 'False'}",
"......",
"......",
"......"
]
}
> Fam
--
Amos.
10 years, 11 months
[libvirt] libvirt 1.2.1 vs. Xen 4.1.4
by Guido Günther
Hi,
a user of Debian's libvirt backport to wheezy using Xen reported libvirt
1.2.1 failing for him like:
info : libvirt version: 1.2.1
error : virIdentityGetSystem:173 : Unable to lookup SELinux process context: Invalid argument
error : xenHypervisorDoV2Sys:1011 : Unable to issue hypervisor ioctl 3166208: Permission denied
error : xenHypervisorDoV2Sys:1011 : Unable to issue hypervisor ioctl 3166208: Permission denied
error : xenHypervisorDoV2Sys:1011 : Unable to issue hypervisor ioctl 3166208: Permission denied
error : xenHypervisorDoV2Sys:1011 : Unable to issue hypervisor ioctl 3166208: Permission denied
error : xenHypervisorDoV2Sys:1011 : Unable to issue hypervisor ioctl 3166208: Permission denied
error : xend_req:302 : internal error: failed to parse Xend response return code
error : xend_req:302 : internal error: failed to parse Xend response return code
error : virNetSocketReadWire:1454 : End of file while reading data: Input/output error
It seems there weren't any significant changes in this code area
recently so I wonder what might be triggering this? Since I currently
don't have a xen test setup it'd be happy about any pointer. We don't
have libxl enabled.
https://bugzilla.redhat.com/show_bug.cgi?id=1055165
has a similar error message.
Cheers,
-- Guido
10 years, 11 months
[libvirt] [PATCH RFC 1/2] support compression when --memory-only option is specified
by Qiao Nuohan
--memory-only option is introduced without compression supported. Therefore,
this is a freature regression of virsh dump. This patch is used to add
"--compress" and "[--compression-format] <string>" to the command
"virsh dump --memory-only" and send dump-guest-memory command to qemu with dump
format specified to one of elf, kdump-zlib, kdump-lzo and kdump-snappy.
Signed-off-by: Qiao Nuohan <qiaonuohan(a)cn.fujitsu.com>
---
include/libvirt/libvirt.h.in | 18 +++++++++++++-----
src/libvirt.c | 15 +++++++++++++++
src/qemu/qemu_driver.c | 21 +++++++++++++++++----
src/qemu/qemu_monitor.c | 6 +++---
src/qemu/qemu_monitor.h | 3 ++-
src/qemu/qemu_monitor_json.c | 4 +++-
src/qemu/qemu_monitor_json.h | 3 ++-
tests/qemumonitorjsontest.c | 2 +-
tools/virsh-domain.c | 29 +++++++++++++++++++++++++++++
9 files changed, 85 insertions(+), 16 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a448411..cb8989e 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1165,11 +1165,19 @@ typedef virDomainMemoryStatStruct *virDomainMemoryStatPtr;
/* Domain core dump flags. */
typedef enum {
- VIR_DUMP_CRASH = (1 << 0), /* crash after dump */
- VIR_DUMP_LIVE = (1 << 1), /* live dump */
- VIR_DUMP_BYPASS_CACHE = (1 << 2), /* avoid file system cache pollution */
- VIR_DUMP_RESET = (1 << 3), /* reset domain after dump finishes */
- VIR_DUMP_MEMORY_ONLY = (1 << 4), /* use dump-guest-memory */
+ VIR_DUMP_CRASH = (1 << 0), /* crash after dump */
+ VIR_DUMP_LIVE = (1 << 1), /* live dump */
+ VIR_DUMP_BYPASS_CACHE = (1 << 2), /* avoid file system cache pollution */
+ VIR_DUMP_RESET = (1 << 3), /* reset domain after dump finishes */
+ VIR_DUMP_MEMORY_ONLY = (1 << 4), /* use dump-guest-memory */
+ VIR_DUMP_COMPRESS = (1 << 5), /* dump guest memory in
+ kdump-compressed format */
+ VIR_DUMP_COMPRESS_ZLIB = (1 << 6), /* kdump-compressed format, with
+ zlib-compressed */
+ VIR_DUMP_COMPRESS_LZO = (1 << 7), /* kdump-compressed format, with
+ lzo-compressed */
+ VIR_DUMP_COMPRESS_SNAPPY = (1 << 8), /* kdump-compressed format, with
+ snappy-compressed */
} virDomainCoreDumpFlags;
/* Domain migration flags. */
diff --git a/src/libvirt.c b/src/libvirt.c
index 666526e..318296e 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -2969,6 +2969,21 @@ virDomainCoreDump(virDomainPtr domain, const char *to,
unsigned int flags)
goto error;
}
+ if ((flags & VIR_DUMP_COMPRESS) && !(flags & VIR_DUMP_MEMORY_ONLY)) {
+ virReportInvalidArg(flags, "%s",
+ _("compress flag cannot be set without memory-only "
+ "flag"));
+ goto error;
+ }
+
+ if ((flags & (VIR_DUMP_COMPRESS_ZLIB | VIR_DUMP_COMPRESS_LZO |
+ VIR_DUMP_COMPRESS_SNAPPY)) && !(flags & VIR_DUMP_COMPRESS)) {
+ virReportInvalidArg(flags, "%s",
+ _("compression-format cannot be set without "
+ "compress flag"));
+ goto error;
+ }
+
if (conn->driver->domainCoreDump) {
int ret;
char *absolute_to;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index df4f5b5..c4e1aef 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3380,7 +3380,8 @@ cleanup:
}
static int qemuDumpToFd(virQEMUDriverPtr driver, virDomainObjPtr vm,
- int fd, enum qemuDomainAsyncJob asyncJob)
+ int fd, enum qemuDomainAsyncJob asyncJob,
+ const char* dump_format)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
int ret = -1;
@@ -3400,7 +3401,7 @@ static int qemuDumpToFd(virQEMUDriverPtr driver,
virDomainObjPtr vm,
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
return -1;
- ret = qemuMonitorDumpToFd(priv->mon, fd);
+ ret = qemuMonitorDumpToFd(priv->mon, fd, dump_format);
qemuDomainObjExitMonitor(driver, vm);
return ret;
@@ -3418,6 +3419,7 @@ doCoreDump(virQEMUDriverPtr driver,
virFileWrapperFdPtr wrapperFd = NULL;
int directFlag = 0;
unsigned int flags = VIR_FILE_WRAPPER_NON_BLOCKING;
+ const char *dump_format;
/* Create an empty file with appropriate ownership. */
if (dump_flags & VIR_DUMP_BYPASS_CACHE) {
@@ -3441,7 +3443,16 @@ doCoreDump(virQEMUDriverPtr driver,
goto cleanup;
if (dump_flags & VIR_DUMP_MEMORY_ONLY) {
- ret = qemuDumpToFd(driver, vm, fd, QEMU_ASYNC_JOB_DUMP);
+ if (dump_flags & VIR_DUMP_COMPRESS_ZLIB)
+ dump_format = "kdump-zlib";
+ else if (dump_flags & VIR_DUMP_COMPRESS_LZO)
+ dump_format = "kdump-lzo";
+ else if (dump_flags & VIR_DUMP_COMPRESS_SNAPPY)
+ dump_format = "kdump-snappy";
+ else
+ dump_format = "elf";
+ ret = qemuDumpToFd(driver, vm, fd, QEMU_ASYNC_JOB_DUMP,
+ dump_format);
} else {
ret = qemuMigrationToFile(driver, vm, fd, 0, path,
qemuCompressProgramName(compress), false,
@@ -3517,7 +3528,9 @@ static int qemuDomainCoreDump(virDomainPtr dom,
virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH |
VIR_DUMP_BYPASS_CACHE | VIR_DUMP_RESET |
- VIR_DUMP_MEMORY_ONLY, -1);
+ VIR_DUMP_MEMORY_ONLY | VIR_DUMP_COMPRESS |
+ VIR_DUMP_COMPRESS_ZLIB | VIR_DUMP_COMPRESS_LZO |
+ VIR_DUMP_COMPRESS_SNAPPY, -1);
if (!(vm = qemuDomObjFromDomain(dom)))
return -1;
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index a968901..c2c4a1e 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2338,10 +2338,10 @@ int qemuMonitorMigrateCancel(qemuMonitorPtr mon)
}
int
-qemuMonitorDumpToFd(qemuMonitorPtr mon, int fd)
+qemuMonitorDumpToFd(qemuMonitorPtr mon, int fd, const char *dump_format)
{
int ret;
- VIR_DEBUG("mon=%p fd=%d", mon, fd);
+ VIR_DEBUG("mon=%p fd=%d dump_format=%s", mon, fd, dump_format);
if (!mon) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
@@ -2361,7 +2361,7 @@ qemuMonitorDumpToFd(qemuMonitorPtr mon, int fd)
if (qemuMonitorSendFileHandle(mon, "dump", fd) < 0)
return -1;
- ret = qemuMonitorJSONDump(mon, "fd:dump");
+ ret = qemuMonitorJSONDump(mon, "fd:dump", dump_format);
if (ret < 0) {
if (qemuMonitorCloseFileHandle(mon, "dump") < 0)
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index eabf000..f2e5763 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -495,7 +495,8 @@ int qemuMonitorMigrateToUnix(qemuMonitorPtr mon,
int qemuMonitorMigrateCancel(qemuMonitorPtr mon);
int qemuMonitorDumpToFd(qemuMonitorPtr mon,
- int fd);
+ int fd,
+ const char *dump_format);
int qemuMonitorGraphicsRelocate(qemuMonitorPtr mon,
int type,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index ec3b958..a16ef44 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2636,7 +2636,8 @@ int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon)
int
qemuMonitorJSONDump(qemuMonitorPtr mon,
- const char *protocol)
+ const char *protocol,
+ const char *dump_format)
{
int ret;
virJSONValuePtr cmd = NULL;
@@ -2645,6 +2646,7 @@ qemuMonitorJSONDump(qemuMonitorPtr mon,
cmd = qemuMonitorJSONMakeCommand("dump-guest-memory",
"b:paging", false,
"s:protocol", protocol,
+ "s:format", dump_format,
NULL);
if (!cmd)
return -1;
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index a93c51e..7691356 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -148,7 +148,8 @@ int qemuMonitorJSONGetSpiceMigrationStatus(qemuMonitorPtr mon,
int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon);
int qemuMonitorJSONDump(qemuMonitorPtr mon,
- const char *protocol);
+ const char *protocol,
+ const char *dump_format);
int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon,
int type,
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index 2152e4a..256655a 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -1154,7 +1154,7 @@ GEN_TEST_FUNC(qemuMonitorJSONSetMigrationDowntime, 1)
GEN_TEST_FUNC(qemuMonitorJSONMigrate, QEMU_MONITOR_MIGRATE_BACKGROUND |
QEMU_MONITOR_MIGRATE_NON_SHARED_DISK |
QEMU_MONITOR_MIGRATE_NON_SHARED_INC, "tcp:localhost:12345")
-GEN_TEST_FUNC(qemuMonitorJSONDump, "dummy_protocol")
+GEN_TEST_FUNC(qemuMonitorJSONDump, "dummy_protocol", "dummy_dump_format")
GEN_TEST_FUNC(qemuMonitorJSONGraphicsRelocate, VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
"localhost", 12345, 12346, NULL)
GEN_TEST_FUNC(qemuMonitorJSONAddNetdev, "some_dummy_netdevstr")
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index b4ca4c3..652c7ec 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -4519,6 +4519,14 @@ static const vshCmdOptDef opts_dump[] = {
.type = VSH_OT_BOOL,
.help = N_("dump domain's memory only")
},
+ {.name = "compress",
+ .type = VSH_OT_BOOL,
+ .help = N_("dump domain's memory in kdump-compressed format")
+ },
+ {.name = "compression-format",
+ .type = VSH_OT_DATA,
+ .help = N_("specify the compression format of kdump-compressed format")
+ },
{.name = NULL}
};
@@ -4533,6 +4541,7 @@ doDump(void *opaque)
sigset_t sigmask, oldsigmask;
const char *name = NULL;
const char *to = NULL;
+ const char *compression_format = NULL;
unsigned int flags = 0;
sigemptyset(&sigmask);
@@ -4556,6 +4565,26 @@ doDump(void *opaque)
flags |= VIR_DUMP_RESET;
if (vshCommandOptBool(cmd, "memory-only"))
flags |= VIR_DUMP_MEMORY_ONLY;
+ if (vshCommandOptBool(cmd, "compress"))
+ flags |= VIR_DUMP_COMPRESS;
+
+ if (vshCommandOptString(cmd, "compression-format", &compression_format)) {
+ if (STREQ(compression_format, "zlib"))
+ flags |= VIR_DUMP_COMPRESS_ZLIB;
+ else if (STREQ(compression_format, "lzo"))
+ flags |= VIR_DUMP_COMPRESS_LZO;
+ else if (STREQ(compression_format, "snappy"))
+ flags |= VIR_DUMP_COMPRESS_SNAPPY;
+ else {
+ vshError(ctl, _("compression format %s is not supported, "
+ "expecting 'zlib', 'lzo' or 'snappy'."),
+ compression_format);
+ goto out;
+ }
+ } else {
+ if (flags & VIR_DUMP_COMPRESS)
+ flags |= VIR_DUMP_COMPRESS_ZLIB;
+ }
if (virDomainCoreDump(dom, to, flags) < 0) {
vshError(ctl, _("Failed to core dump domain %s to %s"), name, to);
--
1.8.3.1
10 years, 11 months
[libvirt] [PATCH RFC 0/2] support compression with dumping guest memory
by Qiao Nuohan
--memory-only option is introduced without compression supported. Therefore,
this is a freature regression of virsh dump. This patchset is used to add
compression support in libvirt side and please refer the following address to
see the qemu side, the lastest version of qemu side v7(ready for comment now).
http://lists.gnu.org/archive/html/qemu-devel/2014-01/msg03669.html
qiaonuohan (2):
support compression when --memory-only option is specified
support configuring the format of dumping memory in qemu.conf
include/libvirt/libvirt.h.in | 18 +++++++++----
src/libvirt.c | 15 +++++++++++
src/qemu/libvirtd_qemu.aug | 1 +
src/qemu/qemu.conf | 6 +++++
src/qemu/qemu_conf.c | 2 ++
src/qemu/qemu_conf.h | 1 +
src/qemu/qemu_driver.c | 52 +++++++++++++++++++++++++++++++++++---
src/qemu/qemu_monitor.c | 6 ++---
src/qemu/qemu_monitor.h | 3 ++-
src/qemu/qemu_monitor_json.c | 4 ++-
src/qemu/qemu_monitor_json.h | 3 ++-
src/qemu/test_libvirtd_qemu.aug.in | 1 +
tests/qemumonitorjsontest.c | 2 +-
tools/virsh-domain.c | 29 +++++++++++++++++++++
14 files changed, 127 insertions(+), 16 deletions(-)
--
1.8.3.1
10 years, 11 months