[libvirt] [PATCH] Use virDomainFindbyID and pass id instead of a pointer to lxcMontitorEvent.
by Thomas Hunger
This fixes a race condition when VIR_EVENT_HANDLE_HANGUP is triggered
during lxcDomainDestroyFlags: lxcMonitorEvent tries to acquire the
driver lock held by lxcDomainDestroyFlags and blocks. Meanwhile
lxcDomainDestroyFlags will free the "vm" structure and release the driver
lock. lxcMonitorEvent unblocks and operates on an invalid "vm" pointer.
By using virDomainFindbyID lxcMonitorEvent avoids using an invalid vm
pointer.
---
src/lxc/lxc_driver.c | 13 +++++++++----
1 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 3af8084..c55e164 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1523,12 +1523,17 @@ static void lxcMonitorEvent(int watch,
void *data)
{
lxc_driver_t *driver = lxc_driver;
- virDomainObjPtr vm = data;
+ int id = (int)data;
+ virDomainObjPtr vm = NULL;
virDomainEventPtr event = NULL;
lxcDomainObjPrivatePtr priv;
lxcDriverLock(driver);
- virDomainObjLock(vm);
+ vm = virDomainFindByID(&driver->domains, id);
+ if (vm == NULL) {
+ lxcDriverUnlock(driver);
+ goto cleanup;
+ }
lxcDriverUnlock(driver);
priv = vm->privateData;
@@ -1950,7 +1955,7 @@ static int lxcVmStart(virConnectPtr conn,
priv->monitor,
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP,
lxcMonitorEvent,
- vm, NULL)) < 0) {
+ (void*)vm->def->id, NULL)) < 0) {
goto error;
}
@@ -2513,7 +2518,7 @@ lxcReconnectVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
priv->monitor,
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP,
lxcMonitorEvent,
- vm, NULL)) < 0)
+ (void*)vm->def->id, NULL)) < 0)
goto error;
if (virSecurityManagerReserveLabel(driver->securityManager,
--
1.7.2.5
12 years, 9 months
[libvirt] Does libvirt check MCS labels during hot-add disk image ?
by Onkar N Mahajan
Libvirt doesn't care about security during hot add disk images. It even
accepts addition of disk images of other guest running on the host.
Steps followed to create this scenario :
Started two VMs with following security configurations:
vm1:
<seclabel type='dynamic' model='selinux' relabel='yes'>
<label>system_u:system_r:svirt_t:s0:c219,c564</label>
<imagelabel>system_u:object_r:svirt_image_t:s0:c219,c564</imagelabel>
</seclabel>
vm2 :
<seclabel type='dynamic' model='selinux' relabel='yes'>
<label>system_u:system_r:svirt_t:s0:c122,c658</label>
<imagelabel>system_u:object_r:svirt_image_t:s0:c122,c658</imagelabel>
</seclabel>
# virsh list --all
Id Name State
----------------------------------
28 vm1 running
29 vm2 running
# ls -lZ /var/lib/libvirt/images/
-rw-------. qemu qemu system_u:object_r:svirt_image_t:s0:c219,c564
vm1.img
-rw-------. qemu qemu system_u:object_r:svirt_image_t:s0:c122,c658
vm2.img
# ps auxZ | grep qemu-kvm | grep -v grep
system_u:system_r:svirt_t:s0:c219,c564 qemu 15744 47.2 5.8 2757852
472224 ? Sl 11:47 0:18 /usr/libexec/qemu-kvm -S -M rhel6.2.0
-enable-kvm -m 2048 -smp 4,sockets=4,cores=1,threads=1 -name vm1 -uuid
d3d3a3ee-4edf-a3d3-8dab-a77740266270 -nodefconfig -nodefaults -chardev
socket,id=charmonitor,path=/var/lib/libvirt/qemu/vm1.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -drive file=/var/lib/libvirt/images/vm1.img,if=none,id=drive-virtio-disk0,format=raw,cache=none -device virtio-blk-pci,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 -drive if=none,media=cdrom,id=drive-ide0-1-0,readonly=on,format=raw -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 -netdev tap,fd=26,id=hostnet0,vhost=on,vhostfd=27 -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:a1:29:45,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -usb -device usb-tablet,id=input0 -vnc 127.0.0.1:0 -vga cirrus -device intel-hda,id=sound0,bus=pci.0,addr=0x4 -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6
system_u:system_r:svirt_t:s0:c122,c658 qemu 15780 58.4 6.5 3063496
524048 ? Sl 11:47 0:20 /usr/libexec/qemu-kvm -S -M rhel6.2.0
-enable-kvm -m 2048 -smp 4,sockets=4,cores=1,threads=1 -name vm2 -uuid
b07607f8-2d03-cc1f-272b-22863667d1a4 -nodefconfig -nodefaults -chardev
socket,id=charmonitor,path=/var/lib/libvirt/qemu/vm2.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -drive file=/var/lib/libvirt/images/vm2.img,if=none,id=drive-virtio-disk0,format=raw,cache=none -device virtio-blk-pci,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 -drive if=none,media=cdrom,id=drive-ide0-1-0,readonly=on,format=raw -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 -netdev tap,fd=28,id=hostnet0,vhost=on,vhostfd=29 -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:e0:76:d1,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -usb -device usb-tablet,id=input0 -vnc 127.0.0.1:1 -vga cirrus -device intel-hda,id=sound0,bus=pci.0,addr=0x4 -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6
Now, try to add vm1's disk image into vm2 - this must not be allowed -
since for virtualized guest images. Only svirt_t processes with the
same MCS fields can read/write these images. i.e., for vm2 to access
vm1's disk image it's MCS label must be 's0:c660,c689'.
Hot addition of vm1's image i.e., /var/lib/libvirt/images/vm1.img is
successful ( which must not be allowed )
moreover , MCS label for vm1's image has changed to that of vm2
# ls -lZ /var/lib/libvirt/images/
-rw-------. qemu qemu system_u:object_r:svirt_image_t:s0:c122,c658
vm1.img
-rw-------. qemu qemu system_u:object_r:svirt_image_t:s0:c122,c658
vm2.img
Trying to read/write on vm1 will generate AVC messages
Seen following message in /var/log/audit/audit.log :
type=VIRT_RESOURCE msg=audit(1332310867.790:10312): user pid=5114 uid=0
auid=0 ses=3 subj=unconfined_u:system_r:virtd_t:s0-s0:c0.c1023
msg='virt=kvm resrc=disk reason=attach vm="vm2"
uuid=b07607f8-2d03-cc1f-272b-22863667d1a4 old-disk="?"
new-disk="/var/lib/libvirt/images/vm1.img":
exe=2F7573722F7362696E2F6C69627669727464202864656C6574656429 hostname=?
addr=? terminal=? res=success'
type=AVC msg=audit(1332310963.333:10313): avc: denied { write } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310963.333:10313): arch=c000003e syscall=18
success=no exit=-13 a0=9 a1=7fd3bc59d000 a2=1000 a3=10891b000 items=0
ppid=1 pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107
egid=107 sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310963.337:10314): avc: denied { read } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310963.337:10314): arch=c000003e syscall=295
success=no exit=-13 a0=9 a1=2d24368 a2=4 a3=88664000 items=0 ppid=1
pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107 egid=107
sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310963.338:10315): avc: denied { read } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310963.338:10315): arch=c000003e syscall=17
success=no exit=-13 a0=9 a1=7fd3bce4f000 a2=1000 a3=88664000 items=0
ppid=1 pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107
egid=107 sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310967.954:10316): avc: denied { read } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310967.954:10316): arch=c000003e syscall=295
success=no exit=-13 a0=9 a1=2d43768 a2=3 a3=1907c8000 items=0 ppid=1
pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107 egid=107
sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310967.955:10317): avc: denied { read } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310967.955:10317): arch=c000003e syscall=17
success=no exit=-13 a0=9 a1=7fd3bac95000 a2=1000 a3=1907c8000 items=0
ppid=1 pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107
egid=107 sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310968.594:10318): avc: denied { write } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310968.594:10318): arch=c000003e syscall=18
success=no exit=-13 a0=9 a1=7fd3bded9000 a2=1000 a3=2c3f000 items=0
ppid=1 pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107
egid=107 sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310968.594:10319): avc: denied { write } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310968.594:10319): arch=c000003e syscall=18
success=no exit=-13 a0=9 a1=7fd3b7947000 a2=1000 a3=9db2d000 items=0
ppid=1 pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107
egid=107 sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310968.594:10320): avc: denied { write } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310968.594:10320): arch=c000003e syscall=296
success=no exit=-13 a0=9 a1=2d6c0f8 a2=b a3=18851e000 items=0 ppid=1
pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107 egid=107
sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310968.598:10321): avc: denied { write } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310968.598:10321): arch=c000003e syscall=18
success=no exit=-13 a0=9 a1=7fd383b0f000 a2=1000 a3=18842e000 items=0
ppid=1 pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107
egid=107 sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
restricting vm1 read/write it's own image.
Changing seclabels with virsh/virt-manager is not supported so defined a
new XML with
<seclabel type='dynamic' model='selinux' relabel='no'>
<label>system_u:system_r:svirt_t:s0:c110,c401</label>
<imagelabel>system_u:object_r:svirt_image_t:s0:c110,c401</imagelabel>
</seclabel>
but when I try to define it , gives me error :
# virsh define vm3.xml
error: Failed to define domain from vm3.xml
error: unsupported configuration: dynamic label type must use resource
relabeling
looks like it's not possible to assign relabel='no' with dynamic
labelling.
libvirt/src/conf/domain_conf.c :
if (def->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
def->norelabel) {
virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
"%s", _("dynamic label type must use
resource relabeling"));
goto error;
}
--
Onkar N Mahajan
System Software Engineer,
IBM Linux Technology Center,
Bangalore,India
12 years, 9 months
[libvirt] [test-API PATCH 0/7] Multiple fixes and improvements series
by Peter Krempa
This is a set of more or less independent fixes and improvements to the
test API. I ran across these while trying to write a basic test case as
a "Hello world!" to the test-API.
Improvements are in fields of cross-distro compatibility, broken API's and
typos and usability.
Peter Krempa (7):
utils: Make ipget.sh more portable
lib: fix streamAPI class
domainAPI: Add wrapper method to work with domain's console
connections
repos/domain/create.py: Fix typo in path to python executable
utils: Allow suffixes in path to the main checkout folder
parser: Be more specific on mistakes in case files
domain/[start|destroy]: Add a optional noping flag to skip the ping
test
exception.py | 10 +++++++++
lib/domainAPI.py | 9 ++++++++
lib/streamAPI.py | 52 +++++++++++++++++++++++-----------------------
proxy.py | 4 +++
repos/domain/create.py | 2 +-
repos/domain/destroy.py | 50 +++++++++++++++++++++++++-------------------
repos/domain/start.py | 50 +++++++++++++++++++++-----------------------
utils/Python/utils.py | 2 +-
utils/ipget.sh | 4 +-
9 files changed, 105 insertions(+), 78 deletions(-)
--
1.7.3.4
12 years, 9 months
[libvirt] [PATCHv2] python: Avoid memory leaks on libvirt_virNodeGetCPUStats
by Alex Jia
Detected by valgrind. Leaks are introduced in commit 4955602.
* python/libvirt-override.c (libvirt_virNodeGetCPUStats): fix memory leaks
and improve codes return value.
For details, please see the following link:
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=770943
Signed-off-by: Alex Jia <ajia(a)redhat.com>
---
python/libvirt-override.c | 36 ++++++++++++++++++++++++++----------
1 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index 8ed9f73..22ee975 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -2503,7 +2503,9 @@ libvirt_virNodeGetCellsFreeMemory(PyObject *self ATTRIBUTE_UNUSED, PyObject *arg
static PyObject *
libvirt_virNodeGetCPUStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)
{
- PyObject *ret;
+ PyObject *ret = NULL;
+ PyObject *key = NULL;
+ PyObject *val = NULL;
PyObject *pyobj_conn;
virConnectPtr conn;
unsigned int flags;
@@ -2512,7 +2514,7 @@ libvirt_virNodeGetCPUStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)
virNodeCPUStatsPtr stats = NULL;
if (!PyArg_ParseTuple(args, (char *)"Oii:virNodeGetCPUStats", &pyobj_conn, &cpuNum, &flags))
- return(NULL);
+ return ret;
conn = (virConnectPtr)(PyvirConnect_Get(pyobj_conn));
LIBVIRT_BEGIN_ALLOW_THREADS;
@@ -2523,7 +2525,7 @@ libvirt_virNodeGetCPUStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)
if (nparams) {
if (VIR_ALLOC_N(stats, nparams) < 0)
- return VIR_PY_NONE;
+ return PyErr_NoMemory();
LIBVIRT_BEGIN_ALLOW_THREADS;
c_retval = virNodeGetCPUStats(conn, cpuNum, stats, &nparams, flags);
@@ -2533,18 +2535,32 @@ libvirt_virNodeGetCPUStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)
return VIR_PY_NONE;
}
}
- if (!(ret = PyDict_New())) {
- VIR_FREE(stats);
- return VIR_PY_NONE;
- }
+
+ if (!(ret = PyDict_New()))
+ goto error;
+
for (i = 0; i < nparams; i++) {
- PyDict_SetItem(ret,
- libvirt_constcharPtrWrap(stats[i].field),
- libvirt_ulonglongWrap(stats[i].value));
+ key = libvirt_constcharPtrWrap(stats[i].field);
+ val = libvirt_ulonglongWrap(stats[i].value);
+
+ if (!key || !val || PyDict_SetItem(ret, key, val) < 0) {
+ Py_DECREF(ret);
+ ret = NULL;
+ goto error;
+ }
+
+ Py_DECREF(key);
+ Py_DECREF(val);
}
VIR_FREE(stats);
return ret;
+
+error:
+ VIR_FREE(stats);
+ Py_XDECREF(key);
+ Py_XDECREF(val);
+ return ret;
}
static PyObject *
--
1.7.1
12 years, 9 months
[libvirt] [PATCH] build: drop a painfully long gnulib test
by Eric Blake
On machines with massive amounts of CPUs, the gnulib 'test-lock'
could take minutes, or even appear to deadlock, because of timing
interactions between multiple cores.
See https://bugzilla.redhat.com/show_bug.cgi?id=797284.
For precedence, note that iwhd has done the same:
https://lists.gnu.org/archive/html/bug-gnulib/2012-01/msg00311.html
We can re-enable things if gnulib ever analyzes and improves the
situation.
* bootstrap.conf (gnulib_tool_option_extras): Avoid lock-tests.
---
Personally, I haven't run into the problem on my 2-core laptop;
where do I sign up for one of the 2048-core machines in that BZ? :)
But since I haven't seen it, I can't push this under the trivial
rule, so I'll wait for a review.
bootstrap.conf | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/bootstrap.conf b/bootstrap.conf
index 03da267..c6f7fd9 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -174,6 +174,7 @@ gnulib_tool_option_extras="\
--with-tests\
--makefile-name=gnulib.mk\
--avoid=pt_chown\
+ --avoid=lock-tests\
"
local_gl_dir=gnulib/local
--
1.7.7.6
12 years, 9 months
[libvirt] [PATCH 0/5] Make migration more robust when client dies
by Jiri Denemark
Libvirt daemon was not completely ready to lose a connection to the client (may
even be source libvirtd) which is controling the migration. We might end up
with dangling migration jobs on both source and destination daemons. More
details about the scenarios this might happen can be found in patches 2/5 and
5/5 which fix the issue using infrastructure set up by the other patches in
this series.
Jiri Denemark (5):
qemu: Add support for domain cleanup callbacks
qemu: Avoid dangling migration-in job on shutoff domains
qemu: Add connection close callbacks
qemu: Make autodestroy utilize connection close callbacks
qemu: Avoid dangling migration-out job when client dies
src/qemu/qemu_conf.c | 172 +++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_conf.h | 30 +++++++-
src/qemu/qemu_domain.c | 75 +++++++++++++++++++-
src/qemu/qemu_domain.h | 17 +++++
src/qemu/qemu_driver.c | 10 ++-
src/qemu/qemu_migration.c | 88 +++++++++++++++++++++++
src/qemu/qemu_migration.h | 4 +
src/qemu/qemu_process.c | 109 +++++++----------------------
8 files changed, 413 insertions(+), 92 deletions(-)
--
1.7.8.5
12 years, 9 months
[libvirt] [PATCH] qemu: Use unlimited speed when migrating to file
by Jiri Denemark
This reverts commit 61f2b6ba5fdef0613d6351b99913b5ef468144ce and most of
commit d8916dc8e2f612ab3ce46f32c4bfeb0bd73f6007, which effectively
brings back commit ef1065cf5acad13767c054758cbe7f4e8af5d241 written by
Jim Fehlig:
The qemu migration speed default is 32MiB/s as defined in migration.c
/* Migration speed throttling */
static int64_t max_throttle = (32 << 20);
There's no need to throttle migration when targeting a file, so set
migration speed to unlimited prior to migration, and restore to libvirt
default value after migration.
Default units is MB for migrate_set_speed monitor command, so
(INT64_MAX / (1024 * 1024)) is used for unlimited migration speed.
This was reverted because migration to file could not be canceled and
even monitored since qemu were not processing any monitor commands until
the migration finished. This is now different as we make sure the
file descriptor we pass to qemu is able to properly report EAGAIN.
Recent qemu changes might have helped as well.
I tested managedsave with this patch in and indeed, it is 10x faster
while I can still monitor its progress.
---
src/qemu/qemu_domain.h | 7 +++++++
src/qemu/qemu_migration.c | 17 +++++++++++++++++
2 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index f8e943f..be9e34d 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -39,6 +39,13 @@
(1 << VIR_DOMAIN_VIRT_XEN))
# define QEMU_DOMAIN_DEFAULT_MIG_BANDWIDTH_MAX 32
+# if ULONG_MAX == 4294967295
+/* Qemu has a 64-bit limit, but we are limited by our historical choice of
+ * representing bandwidth in a long instead of a 64-bit int. */
+# define QEMU_DOMAIN_FILE_MIG_BANDWIDTH_MAX ULONG_MAX
+# else
+# define QEMU_DOMAIN_FILE_MIG_BANDWIDTH_MAX (INT64_MAX / (1024 * 1024))
+# endif
# define JOB_MASK(job) (1 << (job - 1))
# define DEFAULT_JOB_MASK \
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 81b2d5b..c0cf636 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2943,6 +2943,16 @@ qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm,
bool restoreLabel = false;
virCommandPtr cmd = NULL;
int pipeFD[2] = { -1, -1 };
+ unsigned long saveMigBandwidth = priv->migMaxBandwidth;
+
+ /* Increase migration bandwidth to unlimited since target is a file.
+ * Failure to change migration speed is not fatal. */
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
+ qemuMonitorSetMigrationSpeed(priv->mon,
+ QEMU_DOMAIN_FILE_MIG_BANDWIDTH_MAX);
+ priv->migMaxBandwidth = QEMU_DOMAIN_FILE_MIG_BANDWIDTH_MAX;
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ }
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD) &&
(!compressor || pipe(pipeFD) == 0)) {
@@ -3054,6 +3064,13 @@ qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm,
ret = 0;
cleanup:
+ /* Restore max migration bandwidth */
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
+ qemuMonitorSetMigrationSpeed(priv->mon, saveMigBandwidth);
+ priv->migMaxBandwidth = saveMigBandwidth;
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ }
+
VIR_FORCE_CLOSE(pipeFD[0]);
VIR_FORCE_CLOSE(pipeFD[1]);
virCommandFree(cmd);
--
1.7.8.5
12 years, 9 months
[libvirt] MCS labelling not working as expected
by Onkar N Mahajan
Started two VMs with following security configurations:
vm1:
<seclabel type='dynamic' model='selinux' relabel='yes'>
<label>system_u:system_r:svirt_t:s0:c219,c564</label>
<imagelabel>system_u:object_r:svirt_image_t:s0:c219,c564</imagelabel>
</seclabel>
vm2 :
<seclabel type='dynamic' model='selinux' relabel='yes'>
<label>system_u:system_r:svirt_t:s0:c122,c658</label>
<imagelabel>system_u:object_r:svirt_image_t:s0:c122,c658</imagelabel>
</seclabel>
# virsh list --all
Id Name State
----------------------------------
28 vm1 running
29 vm2 running
# ls -lZ /var/lib/libvirt/images/
-rw-------. qemu qemu system_u:object_r:svirt_image_t:s0:c219,c564
vm1.img
-rw-------. qemu qemu system_u:object_r:svirt_image_t:s0:c122,c658
vm2.img
# ps auxZ | grep qemu-kvm | grep -v grep
system_u:system_r:svirt_t:s0:c219,c564 qemu 15744 47.2 5.8 2757852
472224 ? Sl 11:47 0:18 /usr/libexec/qemu-kvm -S -M rhel6.2.0
-enable-kvm -m 2048 -smp 4,sockets=4,cores=1,threads=1 -name vm1 -uuid
d3d3a3ee-4edf-a3d3-8dab-a77740266270 -nodefconfig -nodefaults -chardev
socket,id=charmonitor,path=/var/lib/libvirt/qemu/vm1.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -drive file=/var/lib/libvirt/images/vm1.img,if=none,id=drive-virtio-disk0,format=raw,cache=none -device virtio-blk-pci,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 -drive if=none,media=cdrom,id=drive-ide0-1-0,readonly=on,format=raw -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 -netdev tap,fd=26,id=hostnet0,vhost=on,vhostfd=27 -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:a1:29:45,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -usb -device usb-tablet,id=input0 -vnc 127.0.0.1:0 -vga cirrus -device intel-hda,id=sound0,bus=pci.0,addr=0x4 -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6
system_u:system_r:svirt_t:s0:c122,c658 qemu 15780 58.4 6.5 3063496
524048 ? Sl 11:47 0:20 /usr/libexec/qemu-kvm -S -M rhel6.2.0
-enable-kvm -m 2048 -smp 4,sockets=4,cores=1,threads=1 -name vm2 -uuid
b07607f8-2d03-cc1f-272b-22863667d1a4 -nodefconfig -nodefaults -chardev
socket,id=charmonitor,path=/var/lib/libvirt/qemu/vm2.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -drive file=/var/lib/libvirt/images/vm2.img,if=none,id=drive-virtio-disk0,format=raw,cache=none -device virtio-blk-pci,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 -drive if=none,media=cdrom,id=drive-ide0-1-0,readonly=on,format=raw -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 -netdev tap,fd=28,id=hostnet0,vhost=on,vhostfd=29 -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:e0:76:d1,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -usb -device usb-tablet,id=input0 -vnc 127.0.0.1:1 -vga cirrus -device intel-hda,id=sound0,bus=pci.0,addr=0x4 -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6
Now, try to add vm1's disk image into vm2 - this must not be allowed -
since for virtualized guest images. Only svirt_t processes with the
same MCS fields can read/write these images. i.e., for vm2 to access
vm1's disk image it's MCS label must be 's0:c660,c689'.
Hot addition of vm1's image i.e., /var/lib/libvirt/images/vm1.img is
successful ( which must not be allowed )
moreover , MCS label for vm1's image has changed to that of vm2
# ls -lZ /var/lib/libvirt/images/
-rw-------. qemu qemu system_u:object_r:svirt_image_t:s0:c122,c658
vm1.img
-rw-------. qemu qemu system_u:object_r:svirt_image_t:s0:c122,c658
vm2.img
Trying to read/write on vm1 will generate AVC messages
Seen following message in /var/log/audit/audit.log :
type=VIRT_RESOURCE msg=audit(1332310867.790:10312): user pid=5114 uid=0
auid=0 ses=3 subj=unconfined_u:system_r:virtd_t:s0-s0:c0.c1023
msg='virt=kvm resrc=disk reason=attach vm="vm2"
uuid=b07607f8-2d03-cc1f-272b-22863667d1a4 old-disk="?"
new-disk="/var/lib/libvirt/images/vm1.img":
exe=2F7573722F7362696E2F6C69627669727464202864656C6574656429 hostname=?
addr=? terminal=? res=success'
type=AVC msg=audit(1332310963.333:10313): avc: denied { write } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310963.333:10313): arch=c000003e syscall=18
success=no exit=-13 a0=9 a1=7fd3bc59d000 a2=1000 a3=10891b000 items=0
ppid=1 pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107
egid=107 sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310963.337:10314): avc: denied { read } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310963.337:10314): arch=c000003e syscall=295
success=no exit=-13 a0=9 a1=2d24368 a2=4 a3=88664000 items=0 ppid=1
pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107 egid=107
sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310963.338:10315): avc: denied { read } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310963.338:10315): arch=c000003e syscall=17
success=no exit=-13 a0=9 a1=7fd3bce4f000 a2=1000 a3=88664000 items=0
ppid=1 pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107
egid=107 sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310967.954:10316): avc: denied { read } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310967.954:10316): arch=c000003e syscall=295
success=no exit=-13 a0=9 a1=2d43768 a2=3 a3=1907c8000 items=0 ppid=1
pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107 egid=107
sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310967.955:10317): avc: denied { read } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310967.955:10317): arch=c000003e syscall=17
success=no exit=-13 a0=9 a1=7fd3bac95000 a2=1000 a3=1907c8000 items=0
ppid=1 pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107
egid=107 sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310968.594:10318): avc: denied { write } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310968.594:10318): arch=c000003e syscall=18
success=no exit=-13 a0=9 a1=7fd3bded9000 a2=1000 a3=2c3f000 items=0
ppid=1 pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107
egid=107 sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310968.594:10319): avc: denied { write } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310968.594:10319): arch=c000003e syscall=18
success=no exit=-13 a0=9 a1=7fd3b7947000 a2=1000 a3=9db2d000 items=0
ppid=1 pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107
egid=107 sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310968.594:10320): avc: denied { write } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310968.594:10320): arch=c000003e syscall=296
success=no exit=-13 a0=9 a1=2d6c0f8 a2=b a3=18851e000 items=0 ppid=1
pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107 egid=107
sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
type=AVC msg=audit(1332310968.598:10321): avc: denied { write } for
pid=16241 comm="qemu-kvm" path="/var/lib/libvirt/images/vm1.img"
dev=sda1 ino=6431944 scontext=system_u:system_r:svirt_t:s0:c219,c564
tcontext=system_u:object_r:svirt_image_t:s0:c122,c658 tclass=file
type=SYSCALL msg=audit(1332310968.598:10321): arch=c000003e syscall=18
success=no exit=-13 a0=9 a1=7fd383b0f000 a2=1000 a3=18842e000 items=0
ppid=1 pid=16241 auid=0 uid=107 gid=107 euid=107 suid=107 fsuid=107
egid=107 sgid=107 fsgid=107 tty=(none) ses=3 comm="qemu-kvm"
exe="/usr/libexec/qemu-kvm" subj=system_u:system_r:svirt_t:s0:c219,c564
key=(null)
restricting vm1 read/write it's own image.
Changing seclabels with virsh/virt-manager is not supported so defined a
new XML with
<seclabel type='dynamic' model='selinux' relabel='no'>
<label>system_u:system_r:svirt_t:s0:c110,c401</label>
<imagelabel>system_u:object_r:svirt_image_t:s0:c110,c401</imagelabel>
</seclabel>
but when I try to define it , gives me error :
# virsh define vm3.xml
error: Failed to define domain from vm3.xml
error: unsupported configuration: dynamic label type must use resource
relabeling
looks like it's not possible to assign relabel='no' with dynamic
labelling.
libvirt/src/conf/domain_conf.c :
if (def->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
def->norelabel) {
virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
"%s", _("dynamic label type must use
resource relabeling"));
goto error;
}
--
Onkar N Mahajan
System Software Engineer,
IBM Linux Technology Center,
Bangalore,India
12 years, 9 months
[libvirt] [PATCHv4] python: Avoid memory leaks on libvirt_virNodeGetMemoryStats
by Alex Jia
Detected by valgrind. Leaks are introduced in commit 17c7795.
* python/libvirt-override.c (libvirt_virNodeGetMemoryStats): fix memory leaks
and improve codes return value.
For details, please see the following link:
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=770944
Signed-off-by: Alex Jia <ajia(a)redhat.com>
---
python/libvirt-override.c | 41 +++++++++++++++++++++++++++++++----------
1 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index 792cfa3..634e8bb 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -2550,7 +2550,9 @@ libvirt_virNodeGetCPUStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)
static PyObject *
libvirt_virNodeGetMemoryStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)
{
- PyObject *ret;
+ PyObject *ret = NULL;
+ PyObject *key = NULL;
+ PyObject *val = NULL;
PyObject *pyobj_conn;
virConnectPtr conn;
unsigned int flags;
@@ -2559,7 +2561,7 @@ libvirt_virNodeGetMemoryStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)
virNodeMemoryStatsPtr stats = NULL;
if (!PyArg_ParseTuple(args, (char *)"Oii:virNodeGetMemoryStats", &pyobj_conn, &cellNum, &flags))
- return(NULL);
+ return ret;
conn = (virConnectPtr)(PyvirConnect_Get(pyobj_conn));
LIBVIRT_BEGIN_ALLOW_THREADS;
@@ -2570,7 +2572,7 @@ libvirt_virNodeGetMemoryStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)
if (nparams) {
if (VIR_ALLOC_N(stats, nparams) < 0)
- return VIR_PY_NONE;
+ return PyErr_NoMemory();
LIBVIRT_BEGIN_ALLOW_THREADS;
c_retval = virNodeGetMemoryStats(conn, cellNum, stats, &nparams, flags);
@@ -2580,18 +2582,37 @@ libvirt_virNodeGetMemoryStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)
return VIR_PY_NONE;
}
}
- if (!(ret = PyDict_New())) {
- VIR_FREE(stats);
- return VIR_PY_NONE;
- }
+
+ if (!(ret = PyDict_New()))
+ goto error;
+
for (i = 0; i < nparams; i++) {
- PyDict_SetItem(ret,
- libvirt_constcharPtrWrap(stats[i].field),
- libvirt_ulonglongWrap(stats[i].value));
+ key = libvirt_constcharPtrWrap(stats[i].field);
+ val = libvirt_ulonglongWrap(stats[i].value);
+
+ if (!key || !val) {
+ ret = NULL;
+ goto error;
+ }
+
+ if (PyDict_SetItem(ret, key, val) < 0) {
+ Py_DECREF(ret);
+ ret = NULL;
+ goto error;
+ }
+
+ Py_DECREF(key);
+ Py_DECREF(val);
}
VIR_FREE(stats);
return ret;
+
+error:
+ VIR_FREE(stats);
+ Py_XDECREF(key);
+ Py_XDECREF(val);
+ return ret;
}
static PyObject *
--
1.7.1
12 years, 9 months
[libvirt] [PATCH v2] python: add virDomainGetCPUStats python binding API
by Guannan Ren
dom.getCPUStats(True, 0)
[{'cpu_time': 92913537401L, 'system_time': 5470000000L, 'user_time': 310000000L}]
dom.getCPUStats(False, 0)
[{'cpu_time': 39476858499L}, {'cpu_time': 10627048370L}, {'cpu_time': 21270945682L}, {'cpu_time': 21556420641L}]
*generator.py Add a new naming rule
*libvirt-override-api.xml The API function description
*libvirt-override.c Implement it.
---
python/generator.py | 5 +-
python/libvirt-override-api.xml | 10 +++
python/libvirt-override.c | 164 +++++++++++++++++++++++++++++++++++++++
3 files changed, 178 insertions(+), 1 deletions(-)
diff --git a/python/generator.py b/python/generator.py
index 98072f0..4f95cc9 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -423,7 +423,7 @@ skip_impl = (
'virDomainGetBlockIoTune',
'virDomainSetInterfaceParameters',
'virDomainGetInterfaceParameters',
- 'virDomainGetCPUStats', # not implemented now.
+ 'virDomainGetCPUStats',
'virDomainGetDiskErrors',
)
@@ -966,6 +966,9 @@ def nameFixup(name, classe, type, file):
elif name[0:19] == "virStorageVolLookup":
func = name[3:]
func = string.lower(func[0:1]) + func[1:]
+ elif name[0:20] == "virDomainGetCPUStats":
+ func = name[9:]
+ func = string.lower(func[0:1]) + func[1:]
elif name[0:12] == "virDomainGet":
func = name[12:]
func = string.lower(func[0:1]) + func[1:]
diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
index ab8f33a..c906cc3 100644
--- a/python/libvirt-override-api.xml
+++ b/python/libvirt-override-api.xml
@@ -149,6 +149,16 @@
<arg name='path' type='char *' info='the path for the block device'/>
<arg name='flags' type='int' info='flags (unused; pass 0)'/>
</function>
+ <function name='virDomainGetCPUStats' file='python'>
+ <info>Extracts CPU statistics for a running domain, On success it will return a list of data of dictionary type.
+ If boolean total is True, the first element of the list refers to CPU0 on the host, second element is CPU1, and so on.
+ The format of data struct is like [{cpu_time:xxx},{cpu_time:xxx}, ...]
+ If it is False, it returns total domain CPU statistics like [{cpu_time:xxx, user_time:xxx, system_time:xxx}]</info>
+ <return type='str *' info='returns a list of dictionary in case of success, None in case of error'/>
+ <arg name='domain' type='virDomainPtr' info='pointer to domain object'/>
+ <arg name='total' type='bool' info='on true, return total domain CPU statistics, false return per-cpu info'/>
+ <arg name='flags' type='int' info='flags (unused; pass 0)'/>
+ </function>
<function name='virDomainInterfaceStats' file='python'>
<info>Extracts interface device statistics for a domain</info>
<return type='virDomainInterfaceStats' info='a tuple of statistics'/>
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index 792cfa3..eb24c60 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -378,6 +378,169 @@ cleanup:
}
static PyObject *
+libvirt_virDomainGetCPUStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)
+{
+ virDomainPtr domain;
+ PyObject *pyobj_domain, *totalbool;
+ PyObject *ret = NULL;
+ PyObject *cpu, *total;
+ PyObject *error;
+ int i, i_retval;
+ int ncpus = -1;
+ int sumparams, nparams = -1;
+ unsigned int flags;
+ virTypedParameterPtr params, cpuparams;
+
+ if (!PyArg_ParseTuple(args, (char *)"OOi:virDomainGetNumaParameters",
+ &pyobj_domain, &totalbool, &flags))
+ return NULL;
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ if (!PyBool_Check(totalbool)) {
+ PyErr_Format(PyExc_TypeError,
+ "The \"total\" attribute must be bool");
+ return NULL;
+ }
+
+ if ((ret = PyList_New(0)) == NULL)
+ return NULL;
+
+ if (totalbool == Py_False) {
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ ncpus = virDomainGetCPUStats(domain, NULL, 0, 0, 0, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (ncpus < 0) {
+ error = VIR_PY_NONE;
+ goto failed;
+ }
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ nparams = virDomainGetCPUStats(domain, NULL, 0, 0, 1, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (nparams < 0) {
+ error = VIR_PY_NONE;
+ goto failed;
+ }
+
+ if (!nparams) {
+ if ((cpu = PyDict_New()) == NULL) {
+ error = NULL;
+ goto failed;
+ }
+
+ if (PyList_Append(ret, cpu) < 0) {
+ Py_DECREF(cpu);
+ error = NULL;
+ goto failed;
+ }
+
+ Py_DECREF(cpu);
+ return ret;
+ }
+ sumparams = nparams * ncpus;
+
+ if (VIR_ALLOC_N(params, sumparams) < 0) {
+ error = PyErr_NoMemory();
+ goto failed;
+ }
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetCPUStats(domain, params, nparams, 0, ncpus, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0) {
+ error = VIR_PY_NONE;
+ goto cleanup;
+ }
+
+ for (i = 0; i < ncpus; i++) {
+ if (params[i * nparams].type == 0)
+ continue;
+
+ cpuparams = ¶ms[i * nparams];
+ if ((cpu = getPyVirTypedParameter(cpuparams, nparams)) == NULL) {
+ error = NULL;
+ goto cleanup;
+ }
+ if (PyList_Append(ret, cpu) < 0) {
+ Py_DECREF(cpu);
+ error = NULL;
+ goto cleanup;
+ }
+ Py_DECREF(cpu);
+ }
+
+ virTypedParameterArrayClear(params, sumparams);
+ VIR_FREE(params);
+ return ret;
+ } else {
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ nparams = virDomainGetCPUStats(domain, NULL, 0, -1, 1, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (nparams < 0) {
+ error = VIR_PY_NONE;
+ goto failed;
+ }
+
+ if (!nparams) {
+ if ((total = PyDict_New()) == NULL) {
+ error = NULL;
+ goto failed;
+ }
+ if (PyList_Append(ret, total) < 0) {
+ Py_DECREF(total);
+ error = NULL;
+ goto failed;
+ }
+
+ Py_DECREF(total);
+ return ret;
+ }
+ sumparams = nparams;
+
+ if (VIR_ALLOC_N(params, nparams) < 0) {
+ error = PyErr_NoMemory();
+ goto failed;
+ }
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetCPUStats(domain, params, nparams, -1, 1, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0) {
+ error = VIR_PY_NONE;
+ goto cleanup;
+ }
+
+ if ((total = getPyVirTypedParameter(params, nparams)) == NULL) {
+ error = NULL;
+ goto cleanup;
+ }
+ if (PyList_Append(ret, total) < 0) {
+ Py_DECREF(total);
+ error = NULL;
+ goto cleanup;
+ }
+ Py_DECREF(total);
+
+ virTypedParameterArrayClear(params, sumparams);
+ VIR_FREE(params);
+ return ret;
+ }
+
+cleanup:
+ virTypedParameterArrayClear(params, sumparams);
+ VIR_FREE(params);
+
+failed:
+ Py_DECREF(ret);
+ return error;
+}
+
+static PyObject *
libvirt_virDomainInterfaceStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
virDomainPtr domain;
PyObject *pyobj_domain;
@@ -5366,6 +5529,7 @@ static PyMethodDef libvirtMethods[] = {
{(char *) "virNetworkGetAutostart", libvirt_virNetworkGetAutostart, METH_VARARGS, NULL},
{(char *) "virDomainBlockStats", libvirt_virDomainBlockStats, METH_VARARGS, NULL},
{(char *) "virDomainBlockStatsFlags", libvirt_virDomainBlockStatsFlags, METH_VARARGS, NULL},
+ {(char *) "virDomainGetCPUStats", libvirt_virDomainGetCPUStats, METH_VARARGS, NULL},
{(char *) "virDomainInterfaceStats", libvirt_virDomainInterfaceStats, METH_VARARGS, NULL},
{(char *) "virDomainMemoryStats", libvirt_virDomainMemoryStats, METH_VARARGS, NULL},
{(char *) "virNodeGetCellsFreeMemory", libvirt_virNodeGetCellsFreeMemory, METH_VARARGS, NULL},
--
1.7.7.5
12 years, 9 months