[libvirt] [PATCH] Fix a qemuDomainPCIAddressSetFree memory leak
by Chris Lalancette
qemuDomainPCIAddressSetFree was freeing up the hash
table for the pci addresses, but not freeing up the addr
structure. Looking over the callers of this function, it
seems like they expect it to also free up the structure,
so do that here.
Signed-off-by: Chris Lalancette <clalance(a)redhat.com>
---
src/qemu/qemu_conf.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index ed24916..5fa8c0a 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2110,7 +2110,7 @@ void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
return;
virHashFree(addrs->used, qemuDomainPCIAddressSetFreeEntry);
- addrs->used = NULL;
+ VIR_FREE(addrs);
}
--
1.6.6.1
14 years, 7 months
[libvirt] [PATCH] nwfilter: python bindings for nwfilter
by Stefan Berger
I have primarily followed the pattern of the 'secret' driver to provide
support for the missing python bindings for the network filter API.
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
---
python/generator.py | 35 ++++++++++-
python/libvirt-override-api.xml | 21 ++++++
python/libvirt-override.c | 124 ++++++++++++++++++++++++++++++++++++++++
python/typewrappers.c | 13 ++++
python/typewrappers.h | 9 ++
5 files changed, 198 insertions(+), 4 deletions(-)
Index: libvirt-acl/python/generator.py
===================================================================
--- libvirt-acl.orig/python/generator.py
+++ libvirt-acl/python/generator.py
@@ -175,7 +175,6 @@ skipped_types = {
'virConnectDomainEventIOErrorCallback': "No function types in python",
'virConnectDomainEventGraphicsCallback': "No function types in python",
'virEventAddHandleFunc': "No function types in python",
- 'virNWFilterPtr': "No function types in python",
}
#######################################################################
@@ -237,6 +236,11 @@ py_types = {
'virSecret *': ('O', "virSecret", "virSecretPtr", "virSecretPtr"),
'const virSecret *': ('O', "virSecret", "virSecretPtr", "virSecretPtr"),
+ 'virNWFilterPtr': ('O', "virNWFilter", "virNWFilterPtr", "virNWFilterPtr"),
+ 'const virNWFilterPtr': ('O', "virNWFilter", "virNWFilterPtr", "virNWFilterPtr"),
+ 'virNWFilter *': ('O', "virNWFilter", "virNWFilterPtr", "virNWFilterPtr"),
+ 'const virNWFilter *': ('O', "virNWFilter", "virNWFilterPtr", "virNWFilterPtr"),
+
'virStreamPtr': ('O', "virStream", "virStreamPtr", "virStreamPtr"),
'const virStreamPtr': ('O', "virStream", "virStreamPtr", "virStreamPtr"),
'virStream *': ('O', "virStream", "virStreamPtr", "virStreamPtr"),
@@ -308,6 +312,9 @@ skip_impl = (
'virSecretGetUUID',
'virSecretGetUUIDString',
'virSecretLookupByUUID',
+ 'virNWFilterGetUUID',
+ 'virNWFilterGetUUIDString',
+ 'virNWFilterLookupByUUID',
'virStreamRecv',
'virStreamSend',
'virStoragePoolGetUUID',
@@ -361,6 +368,7 @@ skip_function = (
"virNetworkRef",
"virNodeDeviceRef",
"virSecretRef",
+ "virNWFilterRef",
"virStoragePoolRef",
"virStorageVolRef",
@@ -371,6 +379,7 @@ skip_function = (
"virInterfaceGetConnect",
"virNetworkGetConnect",
"virSecretGetConnect",
+ "virNWFilterGetConnect",
"virStoragePoolGetConnect",
"virStorageVolGetConnect",
)
@@ -643,6 +652,8 @@ classes_type = {
"virNodeDevice *": ("._o", "virNodeDevice(self, _obj=%s)", "virNodeDevice"),
"virSecretPtr": ("._o", "virSecret(self, _obj=%s)", "virSecret"),
"virSecret *": ("._o", "virSecret(self, _obj=%s)", "virSecret"),
+ "virNWFilterPtr": ("._o", "virNWFilter(self, _obj=%s)", "virNWFilter"),
+ "virNWFilter *": ("._o", "virNWFilter(self, _obj=%s)", "virNWFilter"),
"virStreamPtr": ("._o", "virStream(self, _obj=%s)", "virStream"),
"virStream *": ("._o", "virStream(self, _obj=%s)", "virStream"),
"virConnectPtr": ("._o", "virConnect(_obj=%s)", "virConnect"),
@@ -657,7 +668,7 @@ converter_type = {
primary_classes = ["virDomain", "virNetwork", "virInterface",
"virStoragePool", "virStorageVol",
"virConnect", "virNodeDevice", "virSecret",
- "virStream", "virDomainSnapshot"]
+ "virNWFilter", "virStream", "virDomainSnapshot"]
classes_ancestor = {
}
@@ -669,6 +680,7 @@ classes_destructors = {
"virStorageVol": "virStorageVolFree",
"virNodeDevice" : "virNodeDeviceFree",
"virSecret": "virSecretFree",
+ "virNWFilter": "virNWFilterFree",
"virDomainSnapshot": "virDomainSnapshotFree",
# We hand-craft __del__ for this one
#"virStream": "virStreamFree",
@@ -691,6 +703,7 @@ functions_noexcept = {
'virNodeDeviceGetParent': True,
'virSecretGetUsageType': True,
'virSecretGetUsageID': True,
+ 'virNWFilterGetName': True,
}
reference_keepers = {
@@ -756,6 +769,12 @@ def nameFixup(name, classe, type, file):
elif name[0:15] == "virSecretLookup":
func = name[3:]
func = string.lower(func[0:1]) + func[1:]
+ elif name[0:17] == "virNWFilterDefine":
+ func = name[3:]
+ func = string.lower(func[0:3]) + func[3:]
+ elif name[0:17] == "virNWFilterLookup":
+ func = name[3:]
+ func = string.lower(func[0:3]) + func[3:]
elif name[0:20] == "virStoragePoolDefine":
func = name[3:]
func = string.lower(func[0:1]) + func[1:]
@@ -813,6 +832,12 @@ def nameFixup(name, classe, type, file):
elif name[0:9] == 'virSecret':
func = name[9:]
func = string.lower(func[0:1]) + func[1:]
+ elif name[0:14] == 'virNWFilterGet':
+ func = name[14:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:11] == 'virNWFilter':
+ func = name[11:]
+ func = string.lower(func[0:1]) + func[1:]
elif name[0:12] == 'virStreamNew':
func = "newStream"
elif name[0:9] == 'virStream':
@@ -1099,7 +1124,8 @@ def buildWrappers():
else:
classes.write("class %s:\n" % (classname))
if classname in [ "virDomain", "virNetwork", "virInterface", "virStoragePool",
- "virStorageVol", "virNodeDevice", "virSecret","virStream" ]:
+ "virStorageVol", "virNodeDevice", "virSecret","virStream",
+ "virNWFilter" ]:
classes.write(" def __init__(self, conn, _obj=None):\n")
else:
classes.write(" def __init__(self, _obj=None):\n")
@@ -1108,7 +1134,8 @@ def buildWrappers():
for ref in list:
classes.write(" self.%s = None\n" % ref[1])
if classname in [ "virDomain", "virNetwork", "virInterface",
- "virNodeDevice", "virSecret", "virStream" ]:
+ "virNodeDevice", "virSecret", "virStream",
+ "virNWFilter" ]:
classes.write(" self._conn = conn\n")
elif classname in [ "virStorageVol", "virStoragePool" ]:
classes.write(" self._conn = conn\n" + \
Index: libvirt-acl/python/typewrappers.c
===================================================================
--- libvirt-acl.orig/python/typewrappers.c
+++ libvirt-acl/python/typewrappers.c
@@ -215,6 +215,19 @@ libvirt_virSecretPtrWrap(virSecretPtr no
}
PyObject *
+libvirt_virNWFilterPtrWrap(virNWFilterPtr node)
+{
+ PyObject *ret;
+
+ if (node == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ ret = PyCObject_FromVoidPtrAndDesc(node, (char *) "virNWFilterPtr", NULL);
+ return (ret);
+}
+
+PyObject *
libvirt_virStreamPtrWrap(virStreamPtr node)
{
PyObject *ret;
Index: libvirt-acl/python/typewrappers.h
===================================================================
--- libvirt-acl.orig/python/typewrappers.h
+++ libvirt-acl/python/typewrappers.h
@@ -91,6 +91,14 @@ typedef struct {
virSecretPtr obj;
} PyvirSecret_Object;
+#define PyvirNWFilter_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyvirNWFilter_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ virNWFilterPtr obj;
+} PyvirNWFilter_Object;
+
#define PyvirStream_Get(v) (((v) == Py_None) ? NULL : \
(((PyvirStream_Object *)(v))->obj))
@@ -163,6 +171,7 @@ PyObject * libvirt_virFreeCallbackWrap(v
PyObject * libvirt_virVoidPtrWrap(void* node);
PyObject * libvirt_virNodeDevicePtrWrap(virNodeDevicePtr node);
PyObject * libvirt_virSecretPtrWrap(virSecretPtr node);
+PyObject * libvirt_virNWFilterPtrWrap(virNWFilterPtr node);
PyObject * libvirt_virStreamPtrWrap(virStreamPtr node);
PyObject * libvirt_virDomainSnapshotPtrWrap(virDomainSnapshotPtr node);
Index: libvirt-acl/python/libvirt-override.c
===================================================================
--- libvirt-acl.orig/python/libvirt-override.c
+++ libvirt-acl/python/libvirt-override.c
@@ -1957,6 +1957,126 @@ libvirt_virSecretSetValue(PyObject *self
}
static PyObject *
+libvirt_virNWFilterGetUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+ PyObject *py_retval;
+ unsigned char uuid[VIR_UUID_BUFLEN];
+ virNWFilterPtr nwfilter;
+ PyObject *pyobj_nwfilter;
+ int c_retval;
+
+ if (!PyArg_ParseTuple(args, (char *)"O:virNWFilterGetUUID", &pyobj_nwfilter))
+ return(NULL);
+ nwfilter = (virNWFilterPtr) PyvirNWFilter_Get(pyobj_nwfilter);
+
+ if (nwfilter == NULL)
+ return VIR_PY_NONE;
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ c_retval = virNWFilterGetUUID(nwfilter, &uuid[0]);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (c_retval < 0)
+ return VIR_PY_NONE;
+ py_retval = PyString_FromStringAndSize((char *) &uuid[0], VIR_UUID_BUFLEN);
+
+ return(py_retval);
+}
+
+static PyObject *
+libvirt_virNWFilterGetUUIDString(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args) {
+ PyObject *py_retval;
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virNWFilterPtr nwfilter;
+ PyObject *pyobj_nwfilter;
+ int c_retval;
+
+ if (!PyArg_ParseTuple(args, (char *)"O:virNWFilterGetUUIDString",
+ &pyobj_nwfilter))
+ return(NULL);
+ nwfilter = (virNWFilterPtr) PyvirNWFilter_Get(pyobj_nwfilter);
+
+ if (nwfilter == NULL)
+ return VIR_PY_NONE;
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ c_retval = virNWFilterGetUUIDString(nwfilter, &uuidstr[0]);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (c_retval < 0)
+ return VIR_PY_NONE;
+
+ py_retval = PyString_FromString((char *) &uuidstr[0]);
+ return(py_retval);
+}
+
+static PyObject *
+libvirt_virNWFilterLookupByUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+ PyObject *py_retval;
+ virNWFilterPtr c_retval;
+ virConnectPtr conn;
+ PyObject *pyobj_conn;
+ unsigned char * uuid;
+ int len;
+
+ if (!PyArg_ParseTuple(args, (char *)"Oz#:virNWFilterLookupByUUID", &pyobj_conn, &uuid, &len))
+ return(NULL);
+ conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+
+ if ((uuid == NULL) || (len != VIR_UUID_BUFLEN))
+ return VIR_PY_NONE;
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ c_retval = virNWFilterLookupByUUID(conn, uuid);
+ LIBVIRT_END_ALLOW_THREADS;
+ py_retval = libvirt_virNWFilterPtrWrap((virNWFilterPtr) c_retval);
+ return(py_retval);
+}
+
+
+static PyObject *
+libvirt_virConnectListNWFilters(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args) {
+ PyObject *py_retval;
+ char **uuids = NULL;
+ virConnectPtr conn;
+ int c_retval, i;
+ PyObject *pyobj_conn;
+
+ if (!PyArg_ParseTuple(args, (char *)"O:virConnectListNWFilters", &pyobj_conn))
+ return NULL;
+ conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ c_retval = virConnectNumOfNWFilters(conn);
+ LIBVIRT_END_ALLOW_THREADS;
+ if (c_retval < 0)
+ return VIR_PY_NONE;
+
+ if (c_retval) {
+ uuids = malloc(sizeof(*uuids) * c_retval);
+ if (!uuids)
+ return VIR_PY_NONE;
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ c_retval = virConnectListNWFilters(conn, uuids, c_retval);
+ LIBVIRT_END_ALLOW_THREADS;
+ if (c_retval < 0) {
+ free(uuids);
+ return VIR_PY_NONE;
+ }
+ }
+ py_retval = PyList_New(c_retval);
+
+ if (uuids) {
+ for (i = 0;i < c_retval;i++) {
+ PyList_SetItem(py_retval, i, libvirt_constcharPtrWrap(uuids[i]));
+ free(uuids[i]);
+ }
+ free(uuids);
+ }
+
+ return py_retval;
+}
+
+static PyObject *
libvirt_virConnectListInterfaces(PyObject *self ATTRIBUTE_UNUSED,
PyObject *args) {
PyObject *py_retval;
@@ -3316,6 +3436,10 @@ static PyMethodDef libvirtMethods[] = {
{(char *) "virConnectListSecrets", libvirt_virConnectListSecrets, METH_VARARGS, NULL},
{(char *) "virSecretGetValue", libvirt_virSecretGetValue, METH_VARARGS, NULL},
{(char *) "virSecretSetValue", libvirt_virSecretSetValue, METH_VARARGS, NULL},
+ {(char *) "virNWFilterGetUUID", libvirt_virNWFilterGetUUID, METH_VARARGS, NULL},
+ {(char *) "virNWFilterGetUUIDString", libvirt_virNWFilterGetUUIDString, METH_VARARGS, NULL},
+ {(char *) "virNWFilterLookupByUUID", libvirt_virNWFilterLookupByUUID, METH_VARARGS, NULL},
+ {(char *) "virConnectListNWFilters", libvirt_virConnectListNWFilters, METH_VARARGS, NULL},
{(char *) "virConnectListInterfaces", libvirt_virConnectListInterfaces, METH_VARARGS, NULL},
{(char *) "virConnectListDefinedInterfaces", libvirt_virConnectListDefinedInterfaces, METH_VARARGS, NULL},
{(char *) "virConnectBaselineCPU", libvirt_virConnectBaselineCPU, METH_VARARGS, NULL},
Index: libvirt-acl/python/libvirt-override-api.xml
===================================================================
--- libvirt-acl.orig/python/libvirt-override-api.xml
+++ libvirt-acl/python/libvirt-override-api.xml
@@ -226,6 +226,27 @@
<return type='char *' info='the UUID string or None in case of error'/>
<arg name='secret' type='virSecretPtr' info='a secret object'/>
</function>
+ <function name='virConnectListNWFilters' file='libvirt' module='libvirt'>
+ <info>List the defined network filters</info>
+ <arg name='conn' type='virConnectPtr' info='virConnect connection'/>
+ <return type='str *' info='the list of network filter IDs or None in case of error'/>
+ </function>
+ <function name='virNWFilterLookupByUUID' file='python'>
+ <info>Try to lookup a network filter on the given hypervisor based on its UUID.</info>
+ <return type='virNWFilterPtr' info='a new network filter object or NULL in case of failure'/>
+ <arg name='conn' type='virConnectPtr' info='pointer to the hypervisor connection'/>
+ <arg name='uuid' type='const unsigned char *' info='the UUID string for the secret, must be 16 bytes'/>
+ </function>
+ <function name='virNWFilterGetUUID' file='python'>
+ <info>Extract the UUID unique Identifier of a network filter.</info>
+ <return type='char *' info='the 16 bytes string or None in case of error'/>
+ <arg name='nwfilter' type='virNWFilterPtr' info='a network filter object'/>
+ </function>
+ <function name='virNWFilterGetUUIDString' file='python'>
+ <info>Fetch globally unique ID of the network filter as a string.</info>
+ <return type='char *' info='the UUID string or None in case of error'/>
+ <arg name='nwfilter' type='virNWFilterPtr' info='a network filter object'/>
+ </function>
<function name='virConnectListInterfaces' file='python'>
<info>list the running interfaces, stores the pointers to the names in @names</info>
<arg name='conn' type='virConnectPtr' info='pointer to the hypervisor connection'/>
14 years, 7 months
[libvirt] FW: Creating multiple network interfaces in libvirt Domain.
by Kumar L Srikanth-B22348
Hi All,
Can anybody please help me in the issue?
Regards,
Srikanth.
From: Kumar L Srikanth-B22348
Sent: Wednesday, April 28, 2010 4:47 PM
To: 'Daniel P. Berrange'
Subject: FW: Creating multiple network interfaces in libvirt Domain.
Also, can you please let me know, how can I create multiple interfaces
in the guest domain using Domain XML?
Regards,
Srikanth.
From: Kumar L Srikanth-B22348
Sent: Wednesday, April 28, 2010 2:26 PM
To: 'berrange(a)redhat.com'
Cc: 'libvir-list(a)redhat.com'
Subject: Creating multiple network interfaces in libvirt Domain.
Hi,
I want to create a Domain with two interfaces. I am using LXC hypervisor
in the libvirt.
My domain XML is shown below:
<domain type='lxc' id='1'>
<name>srikanth_vm2</name>
<memory>500000</memory>
<os>
<type>exe</type>
<init>/bin/sh</init>
</os>
<vcpu>1</vcpu>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/libexec/libvirt_lxc</emulator>
<filesystem type='mount'>
<source dir='/root/lxc/fedora1'/>
<target dir='/'/>
</filesystem>
<interface type='network'>
<source network='default'/>
</interface>
<interface type='network'>
<source network='default'/>
</interface>
<console type='pty' />
</devices>
</domain>
I am able to define the Domain. But, I am not able to start the Domain.
While starting the domain, I am getting the following error:
error: Failed to start domain srikanth_vm2
error: internal error Failed to create veth device pair: 512
Can you please let me know where I am going wrong?
Regards,
Srikanth.
14 years, 7 months
[libvirt] [PATCH] cygwin/mingw: Fix version script handling
by Matthias Bolte
Let configure detect ld instead of hardcoding /usr/bin/ld, because
MinGW may have ld in /bin.
Only use a .def file to export symbols on MinGW. Cygwin's ld supports
the normal .syms file used on Linux.
---
configure.ac | 11 ++++++++++-
1 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/configure.ac b/configure.ac
index 955a9e9..7121c3e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -73,9 +73,10 @@ AC_LIBTOOL_WIN32_DLL
AM_PROG_LIBTOOL
AM_PROG_CC_C_O
+AM_PROG_LD
VERSION_SCRIPT_FLAGS=-Wl,--version-script=
-`/usr/bin/ld --help 2>&1 | grep -- --version-script >/dev/null` || \
+`$LD --help 2>&1 | grep -- --version-script >/dev/null` || \
VERSION_SCRIPT_FLAGS="-Wl,-M -Wl,"
AC_SUBST(VERSION_SCRIPT_FLAGS)
@@ -1804,9 +1805,17 @@ case "$host" in
if test "x$enable_shared" = "xno"; then
WIN32_EXTRA_CFLAGS="-DLIBVIRT_STATIC"
fi
+esac
+case "$host" in
+ *-*-mingw* | *-*-msvc* )
# Also set the symbol file to .def, so src/Makefile generates libvirt.def
# from libvirt.syms and passes libvirt.def instead of libvirt.syms to the linker
LIBVIRT_SYMBOL_FILE=libvirt.def
+ # mingw's ld has the --version-script parameter, but it requires a .def file
+ # instead to work properly, therefore clear --version-script here
+ # cygwin's ld has the --version-script parameter too, but for some reason
+ # it's working there as expected
+ VERSION_SCRIPT_FLAGS=
;;
esac
AC_SUBST([CYGWIN_EXTRA_LDFLAGS])
--
1.6.3.3
14 years, 7 months
[libvirt] new NULL-dereference in qemu_driver.c
by Jim Meyering
I ran clang on the very latest and it spotted this problem:
>From qemu_driver.c, around line 11100,
else {
/* qemu is a little funny with running guests and the restoration
* of snapshots. If the snapshot was taken online,
* then after a "loadvm" monitor command, the VM is set running
* again. If the snapshot was taken offline, then after a "loadvm"
* monitor command the VM is left paused. Unpausing it leads to
* the memory state *before* the loadvm with the disk *after* the
* loadvm, which obviously is bound to corrupt something.
* Therefore we destroy the domain and set it to "off" in this case.
*/
if (virDomainObjIsActive(vm)) {
qemudShutdownVMDaemon(driver, vm);
event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
if (!vm->persistent) {
if (qemuDomainObjEndJob(vm) > 0)
virDomainRemoveInactive(&driver->domains, vm);
vm = NULL;
}
}
if (qemuDomainSnapshotSetActive(vm, driver->snapshotDir) < 0)
goto endjob;
}
vm->state = snap->def->state;
ret = 0;
endjob:
if (vm && qemuDomainObjEndJob(vm) == 0)
vm = NULL;
Note how "vm" is set to NULL.
Then, it can be dereferenced both via qemuDomainSnapshotSetActive
and via the vm->state = ... assignment.
14 years, 7 months
[libvirt] [PATCH TCK] Add a test for QCow2 files with a backing store
by Daniel P. Berrange
This test case verifies that it is possible to run QEMU guest
from a qcow2 file with a backing store pointing to a physical
disk. This verifies backing store handling with SELinux,
UID/GID changing code and CGroups ACLs
* scripts/qemu/150-disk-backingstore.t: New test case
* lib/Sys/Virt/TCK/StorageVolBuilder.pm: Allow volume backing
store to be set in XML
---
lib/Sys/Virt/TCK/StorageVolBuilder.pm | 14 +++++
scripts/qemu/150-disk-backingstore.t | 97 +++++++++++++++++++++++++++++++++
2 files changed, 111 insertions(+), 0 deletions(-)
create mode 100644 scripts/qemu/150-disk-backingstore.t
diff --git a/lib/Sys/Virt/TCK/StorageVolBuilder.pm b/lib/Sys/Virt/TCK/StorageVolBuilder.pm
index 00680ed..2772d51 100644
--- a/lib/Sys/Virt/TCK/StorageVolBuilder.pm
+++ b/lib/Sys/Virt/TCK/StorageVolBuilder.pm
@@ -68,6 +68,14 @@ sub secret {
return $self;
}
+sub backing_store {
+ my $self = shift;
+
+ $self->{backingStore} = shift;
+
+ return $self;
+}
+
sub as_xml {
my $self = shift;
@@ -95,6 +103,12 @@ sub as_xml {
$w->endTag("target");
}
+ if ($self->{backingStore}) {
+ $w->startTag("backingStore");
+ $w->dataElement("path", $self->{backingStore});
+ $w->endTag("backingStore");
+ }
+
$w->endTag("volume");
return $data;
diff --git a/scripts/qemu/150-disk-backingstore.t b/scripts/qemu/150-disk-backingstore.t
new file mode 100644
index 0000000..62d8faf
--- /dev/null
+++ b/scripts/qemu/150-disk-backingstore.t
@@ -0,0 +1,97 @@
+# -*- perl -*-
+#
+# Copyright (C) 2009-2010 Red Hat, Inc.
+#
+# This program is free software; You can redistribute it and/or modify
+# it under the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any
+# later version
+#
+# The file "LICENSE" distributed along with this file provides full
+# details of the terms and conditions
+#
+
+=pod
+
+=head1 NAME
+
+qemu/150-disk-backingstore.t - qcow2 image with a backing store on physical disk
+
+=head1 DESCRIPTION
+
+The test case validates that a guest can be booted from a
+qcow2 file with a backing store pointing to a physical disk.
+This verifies that SELinux labelling, uid/gid changes and
+cgroups ACL setup is working correctly with backing stores
+
+=cut
+
+use strict;
+use warnings;
+
+use Test::More tests => 8;
+
+use Sys::Virt::TCK;
+use Test::Exception;
+use File::Spec::Functions qw(catfile);
+
+my $tck = Sys::Virt::TCK->new();
+my $conn = eval { $tck->setup(); };
+BAIL_OUT "failed to setup test harness: $@" if $@;
+END { $tck->cleanup if $tck; }
+
+my $dev = $tck->get_host_block_device();
+
+SKIP: {
+ skip "no block device available", 8 unless $dev;
+ skip "Only relevant to QEMU driver", 8 unless $conn->get_type() eq "QEMU";
+
+ ok(-b $dev, "$dev is a block device");
+
+ my $dir = $tck->bucket_dir("150-disk-backingstore");
+ my $disk = catfile($dir, "demo.qcow2");
+
+ my $poolXML = Sys::Virt::TCK::StoragePoolBuilder->new()
+ ->source_dir($dir)->target($dir)->as_xml();
+
+ my $pool;
+
+ diag "Creating pool $poolXML";
+ lives_ok(sub { $pool = $conn->create_storage_pool($poolXML) }, "pool created");
+
+
+ my $volXML = Sys::Virt::TCK::StorageVolBuilder->new(name => "demo.qcow2")
+ ->capacity(1024*1024*1024)
+ ->format("qcow2")
+ ->backing_store($dev)
+ ->as_xml();
+
+ my $vol;
+
+ diag "Creating volume $volXML";
+ lives_ok(sub { $vol = $pool->create_volume($volXML) }, "volume created");
+
+ my $xml = $tck->generic_domain("tck")
+ ->disk(format => ["qemu", "qcow2"],
+ type => "file",
+ src => $disk,
+ dst => "hdb")
+ ->as_xml;
+
+ diag "Creating a transient guest with config $xml";
+ my $dom;
+ ok_domain(sub { $dom = $conn->create_domain($xml) }, "started transient domain config");
+
+ ok($dom->get_id() > 0, "running domain has an ID > 0");
+
+ diag "Trying another domain lookup by name";
+ my $dom1;
+ ok_domain(sub { $dom1 = $conn->get_domain_by_name("tck") }, "the running domain object");
+ ok($dom1->get_id() > 0, "running domain has an ID > 0");
+
+
+ diag "Destroying the running domain";
+ $dom->destroy();
+
+ ok_error(sub { $conn->get_domain_by_name("tck") }, "NO_DOMAIN error raised from missing domain", 42);
+}
--
1.6.5.2
14 years, 7 months
[libvirt] [PATCH] Fix detection of disk in IO events
by Daniel P. Berrange
When using -device syntax, the IO event will have a different
prefix, 'drive-' that needs to be skipped over before matching
against the libvirt disk alias
* src/qemu/qemu_driver.c: Skip QEMU_DRIVE_HOST_PREFIX in IO event
---
src/qemu/qemu_driver.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3e0a38a..9434e00 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -763,6 +763,9 @@ findDomainDiskByAlias(virDomainObjPtr vm,
{
int i;
+ if (STRPREFIX(alias, QEMU_DRIVE_HOST_PREFIX))
+ alias += strlen(QEMU_DRIVE_HOST_PREFIX);
+
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk;
--
1.6.6.1
14 years, 7 months