Re: [libvirt] [PATCH] tests: add missing files
于 2011年09月02日 22:44, Eric Blake 写道: Created by copying from qemuxml2argv-disk-drive-v2-wb.*, then s/writeback/directsync/. Hopefully this matches Osier's intentions. * tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-directsync.args: * tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-directsync.xml: Add missing files needed by 'make check'. --- Pushing under the build-breaker rule. Osier, if this conflicts with the files you have locally, then feel free to update the test to use the version you tested. It's same with what I created, thanks. .../qemuxml2argv-disk-drive-cache-directsync.args |5 +++ .../qemuxml2argv-disk-drive-cache-directsync.xml | 33 2 files changed, 38 insertions(+), 0 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-directsync.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-directsync.xml diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-directsync.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-directsync.args new file mode 100644 index 000..3e78726 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-directsync.args @@ -0,0 +1,5 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \ +-no-acpi -boot c -drive file=/dev/HostVG/QEMUGuest1,if=ide,bus=0,unit=0,\ +format=qcow2,cache=directsync -drive file=/dev/HostVG/QEMUGuest2,if=ide,\ +media=cdrom,bus=1,unit=0,format=raw -net none -serial none -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-directsync.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-directsync.xml new file mode 100644 index 000..17d7c1c --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-cache-directsync.xml @@ -0,0 +1,33 @@ +domain type='qemu' +nameQEMUGuest1/name +uuidc7a5fdbd-edaf-9455-926a-d65c16db1809/uuid +memory219136/memory +currentMemory219136/currentMemory +vcpu1/vcpu +os +type arch='i686' machine='pc'hvm/type +boot dev='hd'/ +/os +clock offset='utc'/ +on_poweroffdestroy/on_poweroff +on_rebootrestart/on_reboot +on_crashdestroy/on_crash +devices +emulator/usr/bin/qemu/emulator +disk type='block' device='disk' +driver name='qemu' type='qcow2' cache='directsync'/ +source dev='/dev/HostVG/QEMUGuest1'/ +target dev='hda' bus='ide'/ +address type='drive' controller='0' bus='0' unit='0'/ +/disk +disk type='block' device='cdrom' +driver name='qemu' type='raw'/ +source dev='/dev/HostVG/QEMUGuest2'/ +target dev='hdc' bus='ide'/ +readonly/ +address type='drive' controller='0' bus='1' unit='0'/ +/disk +controller type='ide' index='0'/ +memballoon model='virtio'/ +/devices +/domain -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Fix localtime handling for Xen-PV domains
On Mon, Aug 15, 2011 at 07:52:20PM +0200, Philipp Hahn wrote: At least Xen-3.4.3 translates the /vm/localtime SXPR value to /domain/platform/localtime and /domain/image/{linux,hvm}/localtime when the domain is defined. When reading back that information libvirt only handles HVM domains, but not PV domains: This results in libvirtd always returning clock offset=utc/ while Xend used (localtime 1). For PV domains use /domain/image/linux/localtime. Signed-off-by: Philipp Hahn h...@univention.de --- This is tracked at https://forge.univention.org/bugzilla/show_bug.cgi?id=22321 --- src/xenxs/xen_sxpr.c |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c index 1f5be5f..ff8326f 100644 --- a/src/xenxs/xen_sxpr.c +++ b/src/xenxs/xen_sxpr.c @@ -1195,6 +1195,9 @@ xenParseSxpr(const struct sexpr *root, def-clock.ntimers = 1; def-clock.timers[0] = timer; } +} else { /* !hvm */ +if (sexpr_int(root, domain/image/linux/localtime)) +def-clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME; } /* Current XenD allows localtime here, for PV and HVM */ Sounds reasonnable :-) ACK pushed, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] migration of vnlink VMs
On Tue, May 24, 2011 at 10:29:00PM +0200, Jérémie Tarot wrote: Hi, 2011/5/24 Daniel P. Berrange berra...@redhat.com ... And new bridging modes would be forward layer='link' mode='bridge-brctl|vepa|private|passthru|bridge-macvtap'/ VDE ? Openvswitch ? I would be very happy to push openvswitch and suggest to people to rely on it ... once it is accepted in the upstream kernel. Unfortunately that's still not the case, and history of hypervisors like openvz and xen really shows why this should be their #1 focus, instead of being put in the backburner TODO list as it seems [*] Daniel [*] I would love to be proved wrong on this ! -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/3] PIIX3 USB controller is on function 2
On Fri, Sep 02, 2011 at 07:43:31PM +0200, Marc-André Lureau wrote: Current code reserves slot 1 function 2 even if there is a user defined PIIX3 USB controller there. --- src/qemu/qemu_command.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 6ff1b2c..e4bdb57 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1181,7 +1181,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) * hardcoded slot=1, multifunction device */ for (function = 0; function QEMU_PCI_ADDRESS_LAST_FUNCTION; function++) { -if (function == 1 (reservedIDE || reservedUSB)) +if ((function == 1 reservedIDE) || +(function == 2 reservedUSB)) /* we have reserved this pci address */ continue; Yeah, I had to manually tweak that part on the rebase and of course got it wrong ! Thanks for the quick fix :-) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/3] Add a usb1 usb2 qemuxml2argv test
On Fri, Sep 02, 2011 at 07:43:33PM +0200, Marc-André Lureau wrote: --- tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.args | 15 tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.xml | 74 tests/qemuxml2argvtest.c |4 + 3 files changed, 93 insertions(+), 0 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.xml Okay that time this one applies and run fine, I commited the 3 patches from the series thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2] Source control for storage pool
On Sat, Sep 03, 2011 at 02:59:18AM +0800, Lei Li wrote: Fix bug #611823 storage driver should prohibit pools with duplicate underlying storage. Add API virStoragePoolSourceFindDuplicate() to do uniqueness check based on source location infomation for pool type. Okay I tweaked the subject and description a little bit Signed-off-by: Lei Li li...@linux.vnet.ibm.com --- src/conf/storage_conf.c | 80 ++ src/conf/storage_conf.h |5 +++ src/libvirt_private.syms |2 + src/storage/storage_driver.c |6 +++ 4 files changed, 93 insertions(+), 0 deletions(-) diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 8d14e87..1e7da69 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -1311,6 +1311,21 @@ virStoragePoolObjFindByName(virStoragePoolObjListPtr pools, return NULL; } +virStoragePoolObjPtr +virStoragePoolSourceFindDuplicateDevices(virStoragePoolObjPtr pool, + virStoragePoolDefPtr def) { +unsigned int i, j; + +for (i = 0; i pool-def-source.ndevice; i++) { +for (j = 0; j def-source.ndevice; j++) { +if (STREQ(pool-def-source.devices[i].path, def-source.devices[j].path)) +return pool; +} +} + +return NULL; +} + void virStoragePoolObjClearVols(virStoragePoolObjPtr pool) { @@ -1701,6 +1716,71 @@ cleanup: return ret; } +int virStoragePoolSourceFindDuplicate(virStoragePoolObjListPtr pools, + virStoragePoolDefPtr def) +{ +int i; +int ret = 1; +virStoragePoolObjPtr pool = NULL; +virStoragePoolObjPtr matchpool = NULL; + +/* Check the pool list for duplicate underlying storage */ +for (i = 0; i pools-count; i++) { +pool = pools-objs[i]; +if (def-type != pool-def-type) +continue; + +virStoragePoolObjLock(pool); + +switch (pool-def-type) { +case VIR_STORAGE_POOL_DIR: +if (STREQ(pool-def-target.path, def-target.path)) +matchpool = pool; +break; +case VIR_STORAGE_POOL_NETFS: +if ((STREQ(pool-def-source.dir, def-source.dir)) \ + (STREQ(pool-def-source.host.name, def-source.host.name))) +matchpool = pool; +break; +case VIR_STORAGE_POOL_SCSI: +if (STREQ(pool-def-source.adapter, def-source.adapter)) +matchpool = pool; +break; +case VIR_STORAGE_POOL_ISCSI: +{ +matchpool = virStoragePoolSourceFindDuplicateDevices(pool, def); +if (matchpool) { +if (STREQ(matchpool-def-source.host.name, def-source.host.name)) { +if ((matchpool-def-source.initiator.iqn) (def-source.initiator.iqn)) { +if (STREQ(matchpool-def-source.initiator.iqn, def-source.initiator.iqn)) +break; +matchpool = NULL; +} +break; +} +matchpool = NULL; +} +break; +} +case VIR_STORAGE_POOL_FS: +case VIR_STORAGE_POOL_LOGICAL: +case VIR_STORAGE_POOL_DISK: +matchpool = virStoragePoolSourceFindDuplicateDevices(pool, def); +break; +default: +break; +} +virStoragePoolObjUnlock(pool); +} + +if (matchpool) { +virStorageReportError(VIR_ERR_OPERATION_FAILED, + _(Storage source conflict with pool: '%s'), + matchpool-def-name); +ret = -1; +} +return ret; +} void virStoragePoolObjLock(virStoragePoolObjPtr obj) { diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h index 271441a..d115a15 100644 --- a/src/conf/storage_conf.h +++ b/src/conf/storage_conf.h @@ -335,6 +335,8 @@ virStoragePoolObjPtr virStoragePoolObjFindByUUID(virStoragePoolObjListPtr pools, const unsigned char *uuid); virStoragePoolObjPtr virStoragePoolObjFindByName(virStoragePoolObjListPtr pools, const char *name); +virStoragePoolObjPtr virStoragePoolSourceFindDuplicateDevices(virStoragePoolObjPtr pool, + virStoragePoolDefPtr def); virStorageVolDefPtr virStorageVolDefFindByKey(virStoragePoolObjPtr pool, const char *key); @@ -388,6 +390,9 @@ int virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools, virStoragePoolDefPtr def, unsigned int check_active); +int
[libvirt] [PATCH 0/8 v2] Report disk latency info
This patch series introduces a new API to report the disk latency related information, which is supported by upstream QEMU just a few days ago (commit c488c7f649, Thu Aug 25). Per previous dicussion on the ABI compatiblity, and API design principle, the new API is defined with style: int virDomainBlockStatsFlags (virDomainPtr dom, const char *path, virTypeParamsPtr params, int *nparams, unsigned int flags) V1 - V2: * Use virTypedParameter instead of creating a new struct for the new API. * Update comments for the API, (Eric's suggestion). [PATCH 1/8] latency: Define new public API and structure [PATCH 2/8] latency: Define the internal driver callback [PATCH 3/8] latency: Implemente the public API [PATCH 4/8] latency: Wire up the remote protocol [PATCH 5/8] latency: Update monitor functions for new latency fields [PATCH 6/8] latency: Implemente internal API for qemu driver [PATCH 7/8] latency: Expose the new API for Python binding [PATCH 8/8] latency: Update cmdBlkStats to use new API Regards, Osier -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 2/8] latency: Define the internal driver callback
--- src/driver.h |8 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index 21b2bd3..fc7a931 100644 --- a/src/driver.h +++ b/src/driver.h @@ -348,6 +348,13 @@ typedef int const char *path, struct _virDomainBlockStats *stats); typedef int +(*virDrvDomainBlockStatsFlags) +(virDomainPtr domain, + const char *path, + virTypedParameterPtr params, + int *nparams, + unsigned int flags); +typedef int (*virDrvDomainInterfaceStats) (virDomainPtr domain, const char *path, @@ -806,6 +813,7 @@ struct _virDriver { virDrvDomainMigratePerform domainMigratePerform; virDrvDomainMigrateFinish domainMigrateFinish; virDrvDomainBlockStats domainBlockStats; +virDrvDomainBlockStatsFlags domainBlockStatsFlags; virDrvDomainInterfaceStats domainInterfaceStats; virDrvDomainMemoryStats domainMemoryStats; virDrvDomainBlockPeek domainBlockPeek; -- 1.7.6 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 1/8] latency: Define new public API and structure
--- include/libvirt/libvirt.h.in | 84 ++ src/libvirt_public.syms |1 + 2 files changed, 85 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 8864865..735ea94 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -574,6 +574,85 @@ struct _virDomainBlockStats { */ typedef virDomainBlockStatsStruct *virDomainBlockStatsPtr; + +/** + * VIR_DOMAIN_BLOCK_STATS_FIELD_LENGTH: + * + * Macro providing the field length of virDomainBlockStatsFlagsStruct + */ +#define VIR_DOMAIN_BLOCK_STATS_FIELD_LENGTH 80 + +/** + * VIR_DOMAIN_BLOCK_STATS_READ_BYTES: + * + * Macro represents the total number of read bytes of the + * block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_READ_BYTES rd_bytes + +/** + * VIR_DOMAIN_BLOCK_STATS_READ_REQ: + * + * Macro represents the total read requests of the + * block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_READ_REQ rd_operations + +/** + * VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES: + * + * Macro represents the total time spend on cache reads in + * nano-seconds of the block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES rd_total_times + +/** + * VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES: + * + * Macro represents the total number of write bytes of the + * block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES wr_bytes + +/** + * VIR_DOMAIN_BLOCK_STATS_WRITE_REQ: + * + * Macro represents the total write requests of the + * block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_WRITE_REQ wr_operations + +/** + * VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES: + * + * Macro represents the total time spend on cache writes in + * nano-seconds of the block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES wr_total_times + +/** + * VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ: + * + * Macro represents the total flush requests of the + * block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ flush_operations + +/** + * VIR_DOMAIN_BLOCK_STATS_FLUSH_TOTAL_TIMES: + * + * Macro represents the total time spend on cache flushing in + * nano-seconds of the block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_FLUSH_TOTAL_TIMES flush_total_times + +/** + * VIR_DOMAIN_BLOCK_STATS_ERRS: + * + * In Xen this returns the mysterious 'oo_req' + */ +#define VIR_DOMAIN_BLOCK_STATS_ERRS errs + /** * virDomainInterfaceStats: * @@ -1178,6 +1257,11 @@ int virDomainBlockStats (virDomainPtr dom, const char *path, virDomainBlockStatsPtr stats, size_t size); +int virDomainBlockStatsFlags (virDomainPtr dom, + const char *path, + virTypedParameterPtr params, + int *nparams, + unsigned int flags); int virDomainInterfaceStats (virDomainPtr dom, const char *path, virDomainInterfaceStatsPtr stats, diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 169c3ee..dc5a80b 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -483,6 +483,7 @@ LIBVIRT_0.9.4 { LIBVIRT_0.9.5 { global: virDomainMigrateGetMaxSpeed; +virDomainBlockStatsFlags; } LIBVIRT_0.9.4; # define new API here using predicted next version number -- 1.7.6 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 5/8] latency: Update monitor functions for new latency fields
The mainly changes are: 1) Update qemuMonitorGetBlockStatsInfo and it's children (Text/JSON) functions to return the value of new latency fields. 2) Add new function qemuMonitorGetBlockStatsParamsNumber, which is to count how many parameters the underlying QEMU supports. 3) Update virDomainBlockStats in src/qemu/qemu_driver.c to be compatible with the changes by 1). --- src/qemu/qemu_driver.c |4 ++ src/qemu/qemu_monitor.c | 35 src/qemu/qemu_monitor.h |6 ++ src/qemu/qemu_monitor_json.c | 124 +- src/qemu/qemu_monitor_json.h |6 ++ src/qemu/qemu_monitor_text.c | 121 + src/qemu/qemu_monitor_text.h |6 ++ 7 files changed, 291 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7028d72..c5809d2 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7224,8 +7224,12 @@ qemudDomainBlockStats (virDomainPtr dom, disk-info.alias, stats-rd_req, stats-rd_bytes, + NULL, stats-wr_req, stats-wr_bytes, + NULL, + NULL, + NULL, stats-errs); qemuDomainObjExitMonitor(driver, vm); diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index db6107c..92631ae 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1201,8 +1201,12 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon, const char *devname, long long *rd_req, long long *rd_bytes, + long long *rd_total_times, long long *wr_req, long long *wr_bytes, + long long *wr_total_times, + long long *flush_req, + long long *flush_total_times, long long *errs) { int ret; @@ -1217,16 +1221,47 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon, if (mon-json) ret = qemuMonitorJSONGetBlockStatsInfo(mon, devname, rd_req, rd_bytes, + rd_total_times, wr_req, wr_bytes, + wr_total_times, + flush_req, + flush_total_times, errs); else ret = qemuMonitorTextGetBlockStatsInfo(mon, devname, rd_req, rd_bytes, + rd_total_times, wr_req, wr_bytes, + wr_total_times, + flush_req, + flush_total_times, errs); return ret; } +/* Return 0 and update @nparams with the number of block stats + * QEMU supports if success. Return -1 if failure. + */ +int qemuMonitorGetBlockStatsParamsNumber(qemuMonitorPtr mon, + int *nparams) +{ +int ret; +VIR_DEBUG(mon=%p nparams=%p, mon, nparams); + +if (!mon) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(monitor must not be NULL)); +return -1; +} + +if (mon-json) +ret = qemuMonitorJSONGetBlockStatsParamsNumber(mon, nparams); +else +ret = qemuMonitorTextGetBlockStatsParamsNumber(mon, nparams); + +return ret; +} + int qemuMonitorGetBlockExtent(qemuMonitorPtr mon, const char *devname, unsigned long long *extent) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index f241c9e..1b9d98d 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -212,9 +212,15 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon, const char *devname, long long *rd_req, long long *rd_bytes, + long long *rd_total_times, long long *wr_req, long long *wr_bytes, + long long *wr_total_times, + long
[libvirt] [PATCH 6/8] latency: Implemente internal API for qemu driver
--- src/qemu/qemu_driver.c | 189 1 files changed, 189 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c5809d2..a8b2b6d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7243,6 +7243,194 @@ cleanup: return ret; } +static int +qemudDomainBlockStatsFlags (virDomainPtr dom, +const char *path, +virTypedParameterPtr params, +int *nparams, +unsigned int flags) +{ +struct qemud_driver *driver = dom-conn-privateData; +int i, tmp, ret = -1; +virDomainObjPtr vm; +virDomainDiskDefPtr disk = NULL; +qemuDomainObjPrivatePtr priv; +long long rd_req, rd_bytes, wr_req, wr_bytes, rd_total_times; +long long wr_total_times, flush_req, flush_total_times, errs; + +virCheckFlags(0, -1); + +qemuDriverLock(driver); +vm = virDomainFindByUUID(driver-domains, dom-uuid); +qemuDriverUnlock(driver); +if (!vm) { +char uuidstr[VIR_UUID_STRING_BUFLEN]; +virUUIDFormat(dom-uuid, uuidstr); +qemuReportError(VIR_ERR_NO_DOMAIN, +_(no domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +if (!virDomainObjIsActive(vm)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, +%s, _(domain is not running)); +goto cleanup; +} + +if (*nparams != 0) { +for (i = 0 ; i vm-def-ndisks ; i++) { +if (STREQ(path, vm-def-disks[i]-dst)) { +disk = vm-def-disks[i]; +break; +} +} + +if (!disk) { +qemuReportError(VIR_ERR_INVALID_ARG, +_(invalid path: %s), path); +goto cleanup; +} + +if (!disk-info.alias) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _(missing disk device alias name for %s), disk-dst); + goto cleanup; +} +} + +priv = vm-privateData; +VIR_DEBUG(priv=%p, params=%p, flags=%x, priv, params, flags); + +if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) 0) +goto cleanup; + +qemuDomainObjEnterMonitor(driver, vm); +tmp = *nparams; +ret = qemuMonitorGetBlockStatsParamsNumber(priv-mon, nparams); + +if (tmp == 0) { +qemuDomainObjExitMonitor(driver, vm); +goto endjob; +} + +ret = qemuMonitorGetBlockStatsInfo(priv-mon, + disk-info.alias, + rd_req, + rd_bytes, + rd_total_times, + wr_req, + wr_bytes, + wr_total_times, + flush_req, + flush_total_times, + errs); + +qemuDomainObjExitMonitor(driver, vm); + +if (ret 0) +goto endjob; + +/* Field 'errs' is meaningless for QEMU, won't set it. */ +for (i = 0; i *nparams; i++) { +virTypedParameterPtr param = params[i]; + +switch (i) { +case 0: /* fill write_bytes here */ +if (virStrcpyStatic(param-field, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field write bytes too long for destination)); +goto cleanup; +} +param-type = VIR_TYPED_PARAM_LLONG; +param-value.l = wr_bytes; +break; + +case 1: /* fill wr_operations here */ +if (virStrcpyStatic(param-field, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field write requests too long for destination)); +goto cleanup; +} +param-type = VIR_TYPED_PARAM_LLONG; +param-value.l = wr_req; +break; + +case 2: /* fill read_bytes here */ +if (virStrcpyStatic(param-field, VIR_DOMAIN_BLOCK_STATS_READ_BYTES) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field read bytes too long for destination)); +goto cleanup; +} +param-type = VIR_TYPED_PARAM_LLONG; +param-value.l = rd_bytes; +break; + +case 3: /* fill rd_operations here */ +if (virStrcpyStatic(param-field, VIR_DOMAIN_BLOCK_STATS_READ_REQ) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field read requests too long for destination)); +goto cleanup; +}
[libvirt] [PATCH 3/8] latency: Implemente the public API
--- src/libvirt.c | 71 + 1 files changed, 71 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 4d80e2f..a921e4d 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -6442,6 +6442,77 @@ error: } /** + * virDomainBlockStatsFlags: + * @dom: pointer to domain object + * @path: path to the block device + * @params: pointer to block stats parameter object + * (return value) + * @nparams: pointer to number of block stats + * @flags: unused, always passes 0 + * + * This function is to get block stats parameters for block + * devices attached to the domain. + * + * The @path is the name of the block device. Get this + * by calling virDomainGetXMLDesc and finding the target dev='...' + * attribute within //domain/devices/disk. (For example, xvda). + * + * Domains may have more than one block device. To get stats for + * each you should make multiple calls to this function. + * + * The @params array will be filled with the value equal to the number of + * parameters suggested by @nparams. + * + * As the value of @nparams is dynamic, call the API setting @nparams to 0 and + * @params as NULL, the API returns the number of parameters supported by the + * HV by updating @nparams on SUCCESS. (Note that block device of different type + * might support different parameters numbers, so it might be necessary to compute + * @nparams for each block device type). The caller should then allocate @params + * array, i.e. (sizeof(@virTypedParameter) * @nparams) bytes and call the API + * again. See virDomainGetMemoryParameters for more details. + * + * Returns -1 in case of error, 0 in case of success. + */ +int virDomainBlockStatsFlags (virDomainPtr dom, + const char *path, + virTypedParameterPtr params, + int *nparams, + unsigned int flags) +{ +virConnectPtr conn; + +VIR_DOMAIN_DEBUG(dom, path=%s, params=%p, nparams=%d, flags=%x, + path, params, nparams ? *nparams : -1, flags); + +virResetLastError(); + +if (!VIR_IS_CONNECTED_DOMAIN (dom)) { +virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); +virDispatchError(NULL); +return -1; +} +if (!path || (nparams == NULL) || (*nparams 0)) { +virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__); +goto error; +} +conn = dom-conn; + +if (conn-driver-domainBlockStatsFlags) { +int ret; +ret = conn-driver-domainBlockStatsFlags(dom, path, params, nparams, flags); +if (ret 0) +goto error; +return ret; +} +virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: +virDispatchError(dom-conn); +return -1; +} + + +/** * virDomainInterfaceStats: * @dom: pointer to the domain object * @path: path to the interface -- 1.7.6 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 4/8] latency: Wire up the remote protocol
--- daemon/remote.c | 69 ++ src/remote/remote_driver.c | 64 ++ src/remote/remote_protocol.x | 19 +++- 3 files changed, 151 insertions(+), 1 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index d5ead81..38bbb10 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -933,6 +933,75 @@ cleanup: } static int +remoteDispatchDomainBlockStatsFlags(virNetServerPtr server ATTRIBUTE_UNUSED, +virNetServerClientPtr client ATTRIBUTE_UNUSED, +virNetMessageHeaderPtr hdr ATTRIBUTE_UNUSED, +virNetMessageErrorPtr rerr, +remote_domain_block_stats_flags_args *args, +remote_domain_block_stats_flags_ret *ret) +{ +virTypedParameterPtr params = NULL; +virDomainPtr dom = NULL; +int i; +const char *path = args-path; +int nparams = args-nparams; +unsigned int flags; +int rv = -1; +struct daemonClientPrivate *priv = +virNetServerClientGetPrivateData(client); + +if (!priv-conn) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open)); +goto cleanup; +} + +if (!(dom = get_nonnull_domain(priv-conn, args-dom))) +goto cleanup; +flags = args-flags; + +if (nparams REMOTE_DOMAIN_BLOCK_STATS_PARAMETERS_MAX) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(nparams too large)); +goto cleanup; +} +if (VIR_ALLOC_N(params, nparams) 0) { +virReportOOMError(); +goto cleanup; +} + +if (virDomainBlockStatsFlags(dom, path, params, nparams, flags) 0) +goto cleanup; + +/* In this case, we need to send back the number of parameters + * supported + */ +if (args-nparams == 0) { +ret-nparams = nparams; +goto success; +} + +/* Serialise the block stats. */ +if (remoteSerializeTypedParameters(params, nparams, + ret-params.params_val, + ret-params.params_len) 0) +goto cleanup; + +success: +rv = 0; + +cleanup: +if (rv 0) { +virNetMessageSaveError(rerr); +if (ret-params.params_val) { +for (i = 0; i nparams; i++) +VIR_FREE(ret-params.params_val[i].field); +VIR_FREE(ret-params.params_val); +} +} +VIR_FREE(params); +return rv; +} + +static int remoteDispatchDomainMemoryPeek(virNetServerPtr server ATTRIBUTE_UNUSED, virNetServerClientPtr client ATTRIBUTE_UNUSED, virNetMessageHeaderPtr hdr ATTRIBUTE_UNUSED, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 783c404..9d34b7e 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1361,6 +1361,69 @@ cleanup: } static int +remoteDomainBlockStatsFlags(virDomainPtr domain, +const char *path, +virTypedParameterPtr params, +int *nparams, +unsigned int flags) +{ +int rv = -1; +remote_domain_block_stats_flags_args args; +remote_domain_block_stats_flags_ret ret; +struct private_data *priv = domain-conn-privateData; + +remoteDriverLock(priv); + +make_nonnull_domain (args.dom, domain); +args.nparams = *nparams; +args.path = (char *) path; +args.flags = flags; + +memset (ret, 0, sizeof ret); +if (call (domain-conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_STATS_FLAGS, + (xdrproc_t) xdr_remote_domain_block_stats_flags_args, (char *) args, + (xdrproc_t) xdr_remote_domain_block_stats_flags_ret, (char *) ret) == -1) +goto done; + +/* Check the length of the returned list carefully. */ +if (ret.params.params_len REMOTE_DOMAIN_BLOCK_STATS_PARAMETERS_MAX || +ret.params.params_len *nparams) { +remoteError(VIR_ERR_RPC, %s, +_(remoteDomainBlockStatsFlags: + returned number of stats exceeds limit)); +goto cleanup; +} + +/* Handle the case when the caller does not know the number of stats + * and is asking for the number of stats supported + */ +if (*nparams == 0) { +*nparams = ret.nparams; +rv = 0; +goto cleanup; +} + +*nparams = ret.params.params_len; + +/* Deserialise the result. */ +if (remoteDeserializeTypedParameters(ret.params.params_val, + ret.params.params_len, + REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX, + params, + nparams) 0) +goto cleanup; + +rv = 0; + +cleanup: +xdr_free
[libvirt] [PATCH 7/8] latency: Expose the new API for Python binding
--- python/generator.py |1 + python/libvirt-override-api.xml |7 +++ python/libvirt-override.c | 85 +++ 3 files changed, 93 insertions(+), 0 deletions(-) diff --git a/python/generator.py b/python/generator.py index cc253cf..d17fb26 100755 --- a/python/generator.py +++ b/python/generator.py @@ -373,6 +373,7 @@ skip_impl = ( 'virNodeGetMemoryStats', 'virDomainGetBlockJobInfo', 'virDomainMigrateGetMaxSpeed', +'virDomainBlockStatsFlags', ) diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml index 1cf115c..3013e46 100644 --- a/python/libvirt-override-api.xml +++ b/python/libvirt-override-api.xml @@ -128,6 +128,13 @@ arg name='domain' type='virDomainPtr' info='a domain object'/ arg name='path' type='char *' info='the path for the block device'/ /function +function name='virDomainBlockStatsFlags' file='python' + infoExtracts block device statistics parameters of a running domain/info + return type='virTypedParameterPtr' info='None in case of error, returns a dictionary of params'/ + arg name='domain' type='virDomainPtr' info='pointer to domain object'/ + 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='virDomainInterfaceStats' file='python' infoExtracts 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 b020342..d65423d 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -100,6 +100,90 @@ libvirt_virDomainBlockStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { } static PyObject * +libvirt_virDomainBlockStatsFlags(PyObject *self ATTRIBUTE_UNUSED, + PyObject *args) { +virDomainPtr domain; +PyObject *pyobj_domain, *info; +int i_retval; +int nparams = 0, i; +unsigned int flags; +virTypedParameterPtr params; +const char *path; + +if (!PyArg_ParseTuple(args, (char *)Ozi:virDomainBlockStatsFlags, + pyobj_domain, path, flags)) +return(NULL); +domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + +LIBVIRT_BEGIN_ALLOW_THREADS; +i_retval = virDomainBlockStatsFlags(domain, path, NULL, nparams, flags); +LIBVIRT_END_ALLOW_THREADS; + +if (i_retval 0) +return VIR_PY_NONE; + +if ((params = malloc(sizeof(*params)*nparams)) == NULL) +return VIR_PY_NONE; + +LIBVIRT_BEGIN_ALLOW_THREADS; +i_retval = virDomainBlockStatsFlags(domain, path, params, nparams, flags); +LIBVIRT_END_ALLOW_THREADS; + +if (i_retval 0) { +free(params); +return VIR_PY_NONE; +} + +/* convert to a Python tuple of long objects */ +if ((info = PyDict_New()) == NULL) { +free(params); +return VIR_PY_NONE; +} + +for (i = 0 ; i nparams ; i++) { +PyObject *key, *val; + +switch (params[i].type) { +case VIR_TYPED_PARAM_INT: +val = PyInt_FromLong((long)params[i].value.i); +break; + +case VIR_TYPED_PARAM_UINT: +val = PyInt_FromLong((long)params[i].value.ui); +break; + +case VIR_TYPED_PARAM_LLONG: +val = PyLong_FromLongLong((long long)params[i].value.l); +break; + +case VIR_TYPED_PARAM_ULLONG: +val = PyLong_FromLongLong((long long)params[i].value.ul); +break; + +case VIR_TYPED_PARAM_DOUBLE: +val = PyFloat_FromDouble((double)params[i].value.d); +break; + +case VIR_TYPED_PARAM_BOOLEAN: +val = PyBool_FromLong((long)params[i].value.b); +break; + +default: +free(params); +Py_DECREF(info); +return VIR_PY_NONE; +} + +key = libvirt_constcharPtrWrap(params[i].field); +PyDict_SetItem(info, key, val); +} + +free(params); +return(info); +} + + +static PyObject * libvirt_virDomainInterfaceStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; @@ -4605,6 +4689,7 @@ static PyMethodDef libvirtMethods[] = { {(char *) virDomainGetAutostart, libvirt_virDomainGetAutostart, METH_VARARGS, NULL}, {(char *) virNetworkGetAutostart, libvirt_virNetworkGetAutostart, METH_VARARGS, NULL}, {(char *) virDomainBlockStats, libvirt_virDomainBlockStats, METH_VARARGS, NULL}, +{(char *) virDomainBlockStatsFlags, libvirt_virDomainBlockStatsFlags, METH_VARARGS, NULL}, {(char *) virDomainInterfaceStats, libvirt_virDomainInterfaceStats, METH_VARARGS, NULL}, {(char *) virDomainMemoryStats, libvirt_virDomainMemoryStats, METH_VARARGS, NULL}, {(char *)
[libvirt] [PATCH 8/8] latency: Update cmdBlkStats to use new API
The modified function fallbacks to use virDomainBlockStats if virDomainBlockStatsFlags is not supported by the hypervisor driver. If the new API is supported, it will be invoked instead of the old API. --- tools/virsh.c | 104 ++--- 1 files changed, 84 insertions(+), 20 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index c7240e5..ea41221 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1070,6 +1070,9 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) virDomainPtr dom; const char *name = NULL, *device = NULL; struct _virDomainBlockStats stats; +virTypedParameterPtr params = NULL; +int rc, nparams = 0; +bool ret = false; if (!vshConnectionUsability (ctl, ctl-conn)) return false; @@ -1077,34 +1080,95 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) if (!(dom = vshCommandOptDomain (ctl, cmd, name))) return false; -if (vshCommandOptString (cmd, device, device) = 0) { -virDomainFree(dom); -return false; -} +if (vshCommandOptString (cmd, device, device) = 0) +goto cleanup; -if (virDomainBlockStats (dom, device, stats, sizeof stats) == -1) { -vshError(ctl, _(Failed to get block stats %s %s), name, device); -virDomainFree(dom); -return false; -} +rc = virDomainBlockStatsFlags(dom, device, NULL, nparams, 0); -if (stats.rd_req = 0) -vshPrint (ctl, %s rd_req %lld\n, device, stats.rd_req); +/* It might fail when virDomainBlockStatsFlags is not + * supported on older libvirt, fallback to use virDomainBlockStats + * then. + */ +if (rc 0) { +if (last_error-code != VIR_ERR_NO_SUPPORT) { +virshReportError(ctl); +goto cleanup; +} else { +virFreeError(last_error); +last_error = NULL; -if (stats.rd_bytes = 0) -vshPrint (ctl, %s rd_bytes %lld\n, device, stats.rd_bytes); +if (virDomainBlockStats (dom, device, stats, + sizeof stats) == -1) { +vshError(ctl, _(Failed to get block stats %s %s), + name, device); +goto cleanup; +} + +if (stats.rd_req = 0) +vshPrint (ctl, %s rd_req %lld\n, device, stats.rd_req); -if (stats.wr_req = 0) -vshPrint (ctl, %s wr_req %lld\n, device, stats.wr_req); +if (stats.rd_bytes = 0) +vshPrint (ctl, %s rd_bytes %lld\n, device, stats.rd_bytes); -if (stats.wr_bytes = 0) -vshPrint (ctl, %s wr_bytes %lld\n, device, stats.wr_bytes); +if (stats.wr_req = 0) +vshPrint (ctl, %s wr_req %lld\n, device, stats.wr_req); -if (stats.errs = 0) -vshPrint (ctl, %s errs %lld\n, device, stats.errs); +if (stats.wr_bytes = 0) +vshPrint (ctl, %s wr_bytes %lld\n, device, stats.wr_bytes); +if (stats.errs = 0) +vshPrint (ctl, %s errs %lld\n, device, stats.errs); +} +} else { +params = vshMalloc(ctl, sizeof(*params) * nparams); +memset(params, 0, sizeof(*params) * nparams); + +if (virDomainBlockStatsFlags (dom, device, params, nparams, 0) 0) { +vshError(ctl, _(Failed to get block stats %s %s), name, device); +goto cleanup; +} + +int i; +/* XXX: The output sequence will be different. */ +for (i = 0; i nparams; i++) { +switch(params[i].type) { +case VIR_TYPED_PARAM_INT: +vshPrint (ctl, %s %s %d\n, device, + params[i].field, params[i].value.i); +break; +case VIR_TYPED_PARAM_UINT: +vshPrint (ctl, %s %s %u\n, device, + params[i].field, params[i].value.ui); +break; +case VIR_TYPED_PARAM_LLONG: +vshPrint (ctl, %s %s %lld\n, device, + params[i].field, params[i].value.l); +break; +case VIR_TYPED_PARAM_ULLONG: +vshPrint (ctl, %s %s %llu\n, device, + params[i].field, params[i].value.ul); +break; +case VIR_TYPED_PARAM_DOUBLE: +vshPrint (ctl, %s %s %f\n, device, + params[i].field, params[i].value.d); +break; +case VIR_TYPED_PARAM_BOOLEAN: +vshPrint (ctl, %s %s %s\n, device, + params[i].field, params[i].value.b ? _(yes) : _(no)); +break; +default: +vshError(ctl, _(unimplemented block statistics parameter type)); +} + +} +} + +ret = true; + +cleanup: +VIR_FREE(params); virDomainFree(dom); -return true; +return ret; } /* domifstat command -- 1.7.6
[libvirt] [PATCH RFC 0/2] XML: Improve XML parse error reporting
First patch modifies the error reporting function on parse errors of XML files. A new, more informative message is presented to the user, containing filename of the offending file, error description and context of the error in libxml2 style. Second patch changes default filenames used while parsing XML strings in memory to NULL, so that the error reporting function does not print bougus filename. src/conf/domain_conf.c- change domain.xml to NULL src/security/virt-aa-helper.c - change domain.xml to NULL src/util/xml.c- modify error reporting function Peter Krempa (2): XML: Improve XML parsing error messages XML: Suppress printing domain.xml for parse errors on XML strings src/conf/domain_conf.c|2 +- src/security/virt-aa-helper.c |2 +- src/util/xml.c| 88 +++-- 3 files changed, 78 insertions(+), 14 deletions(-) -- 1.7.3.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH RFC 1/2] XML: Improve XML parsing error messages
This patch modifies error handling function for the XML parser provided by libxml2. Originaly only a line number and error message were logged. With this new error handler function, the user is provided with a more complex description of the parsing error. Context of the error is printed in libXML2 style and filename of the file, that caused the error is printed. Example of an parse error: 13:41:36.262: 16032: error : catchXMLError:706 : /etc/libvirt/qemu/rh_bad.xml:58: Opening and ending tag mismatch: name line 2 and domain /domain -^ Context of the error gives the user hints that may help to quickly locate a corrupt xml file. fixes BZs: -- Bug 708735 - [RFE] Show column and line on XML parsing error https://bugzilla.redhat.com/show_bug.cgi?id=708735 Bug 726771 - libvirt does not specify problem file if persistent xml is invalid https://bugzilla.redhat.com/show_bug.cgi?id=726771 --- src/util/xml.c | 88 --- 1 files changed, 76 insertions(+), 12 deletions(-) diff --git a/src/util/xml.c b/src/util/xml.c index d301af6..b0942da 100644 --- a/src/util/xml.c +++ b/src/util/xml.c @@ -633,28 +633,92 @@ virXPathNodeSet(const char *xpath, * catchXMLError: * * Called from SAX on parsing errors in the XML. + * + * This version is heavily based on xmlParserPrintFileContextInternal from libxml2. */ static void catchXMLError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { -int domcode = VIR_FROM_XML; xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; -if (ctxt) { -if (ctxt-_private) +const xmlChar *cur, *base; +unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */ +int domcode = VIR_FROM_XML; + +virBuffer buf = VIR_BUFFER_INITIALIZER; +char *contextstr = NULL; +char *pointerstr = NULL; + + +/* conditions for error printing */ +if (!ctxt || +(virGetLastError() != NULL) || +ctxt-input == NULL || +ctxt-lastError.level != XML_ERR_FATAL || +ctxt-lastError.message == NULL) +return; + +if (ctxt-_private) domcode = ((struct virParserData *) ctxt-_private)-domcode; -if (virGetLastError() == NULL -ctxt-lastError.level == XML_ERR_FATAL -ctxt-lastError.message != NULL) { -virGenericReportError(domcode, VIR_ERR_XML_DETAIL, - _(at line %d: %s), - ctxt-lastError.line, - ctxt-lastError.message); -} + +cur = ctxt-input-cur; +base = ctxt-input-base; + +/* skip backwards over any end-of-lines */ +while ((cur base) ((*(cur) == '\n') || (*(cur) == '\r'))) { +cur--; } -} +/* search backwards for beginning-of-line (to max buff size) */ +while ((cur base) (*(cur) != '\n') (*(cur) != '\r')) +cur--; +if ((*(cur) == '\n') || (*(cur) == '\r')) cur++; + +/* calculate the error position in terms of the current position */ +col = ctxt-input-cur - cur; + +/* search forward for end-of-line (to max buff size) */ +/* copy selected text to our buffer */ +while ((*cur != 0) (*(cur) != '\n') (*(cur) != '\r')) { +virBufferAddChar(buf, *cur++); +} + +/* create blank line with problem pointer */ +contextstr = virBufferContentAndReset(buf); + +/* (leave buffer space for pointer + line terminator) */ +for (n = 0; (ncol) (contextstr[n] != 0); n++) { +if (contextstr[n] == '\t') +virBufferAddChar(buf, '\t'); +else +virBufferAddChar(buf, '-'); +} + +virBufferAddChar(buf, '^'); + +pointerstr = virBufferContentAndReset(buf); + +if (ctxt-lastError.file) { +virGenericReportError(domcode, VIR_ERR_XML_DETAIL, + _(%s:%d: %s%s\n%s), + ctxt-lastError.file, + ctxt-lastError.line, + ctxt-lastError.message, + contextstr, + pointerstr); +} else { + virGenericReportError(domcode, VIR_ERR_XML_DETAIL, + _(at line %d: %s%s\n%s), + ctxt-lastError.line, + ctxt-lastError.message, + contextstr, + pointerstr); +} + +VIR_FREE(contextstr); +VIR_FREE(pointerstr); +} /** * virXMLParseHelper: -- 1.7.3.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4] daemon: Create priority workers pool
This patch annotates APIs with low or high priority. In low set MUST be all APIs which might eventually access monitor (and thus block indefinitely). Other APIs may be marked as high priority. However, some must be (e.g. domainDestroy). For high priority calls (HPC), there are some high priority workers (HPW) created in the pool. HPW can execute only HPC, although normal worker can process any call regardless priority. Therefore, only those APIs which are guaranteed to end in reasonable small amount of time can be marked as HPC. The size of this HPC pool is static, because HPC are expected to end quickly, therefore jobs assigned to this pool will be served quickly. It can be configured in libvirtd.conf via prio_workers variable. Default is set to 5. To mark API with low or high priority, append priority:{low|high} to it's comment in src/remote/remote_protocol.x. This is similar to autogen|skipgen. If not marked, the generator assumes low as default. --- diff to v3: -make 'priority:low' as default which can be left out -rearrange some APIs to be HPC or LPC daemon/libvirtd.aug |1 + daemon/libvirtd.c |7 + daemon/libvirtd.conf |6 + src/qemu/qemu_driver.c|2 +- src/qemu/qemu_process.c |2 +- src/remote/qemu_protocol.x| 13 ++- src/remote/remote_protocol.x | 294 + src/rpc/gendispatch.pl| 20 +++- src/rpc/virnetserver.c| 60 + src/rpc/virnetserver.h|1 + src/rpc/virnetserverprogram.c | 11 ++ src/rpc/virnetserverprogram.h |4 + src/util/threadpool.c | 158 +++ src/util/threadpool.h |4 +- 14 files changed, 382 insertions(+), 201 deletions(-) diff --git a/daemon/libvirtd.aug b/daemon/libvirtd.aug index 3f47ebb..ce00db5 100644 --- a/daemon/libvirtd.aug +++ b/daemon/libvirtd.aug @@ -57,6 +57,7 @@ module Libvirtd = | int_entry max_clients | int_entry max_requests | int_entry max_client_requests +| int_entry prio_workers let logging_entry = int_entry log_level | str_entry log_filters diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 423c3d7..7b445a2 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -134,6 +134,8 @@ struct daemonConfig { int max_workers; int max_clients; +int prio_workers; + int max_requests; int max_client_requests; @@ -886,6 +888,8 @@ daemonConfigNew(bool privileged ATTRIBUTE_UNUSED) data-max_workers = 20; data-max_clients = 20; +data-prio_workers = 5; + data-max_requests = 20; data-max_client_requests = 5; @@ -1042,6 +1046,8 @@ daemonConfigLoad(struct daemonConfig *data, GET_CONF_INT (conf, filename, max_workers); GET_CONF_INT (conf, filename, max_clients); +GET_CONF_INT (conf, filename, prio_workers); + GET_CONF_INT (conf, filename, max_requests); GET_CONF_INT (conf, filename, max_client_requests); @@ -1430,6 +1436,7 @@ int main(int argc, char **argv) { config-auth_unix_ro == REMOTE_AUTH_POLKIT; if (!(srv = virNetServerNew(config-min_workers, config-max_workers, +config-prio_workers, config-max_clients, config-mdns_adv ? config-mdns_name : NULL, use_polkit_dbus, diff --git a/daemon/libvirtd.conf b/daemon/libvirtd.conf index 95e43dd..da3983e 100644 --- a/daemon/libvirtd.conf +++ b/daemon/libvirtd.conf @@ -257,6 +257,12 @@ #min_workers = 5 #max_workers = 20 + +# The number of priority workers. If all workers from above +# pool will stuck, some calls marked as high priority +# (notably domainDestroy) can be executed in this pool. +#prio_workers = 5 + # Total global limit on concurrent RPC calls. Should be # at least as large as max_workers. Beyond this, RPC requests # will be read into memory and queued. This directly impact diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f21122d..b26a0cb 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -656,7 +656,7 @@ qemudStartup(int privileged) { virHashForEach(qemu_driver-domains.objs, qemuDomainSnapshotLoad, qemu_driver-snapshotDir); -qemu_driver-workerPool = virThreadPoolNew(0, 1, processWatchdogEvent, qemu_driver); +qemu_driver-workerPool = virThreadPoolNew(0, 1, 0, processWatchdogEvent, qemu_driver); if (!qemu_driver-workerPool) goto error; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 58b4d36..878805a 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -576,7 +576,7 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, * deleted before handling watchdog event is finished. */
Re: [libvirt] [PATCHv4 00/51] another round of snapshot patches
On 09/02/2011 03:57 AM, Daniel Veillard wrote: On Thu, Sep 01, 2011 at 10:24:37PM -0600, Eric Blake wrote: I think I've addressed most findings from round 3 - by implementing 35, 36 ACK 37 ACK 38 ACK 39 ACK to new API flag 40 ACK 41 ACK 42 ACK 43 ACK 44 nice improvement, hopefully can't lead to regressions, and also end up cleaning up the code in a few places, ACK 45 useful for scripting, ACK 46 ACK 47 ACK 48 ACK 49 ACK, mechnical mostly 50 ACK 51 ACK All of these remaining patches are now pushed, all tied to BZ 638510. There's certainly more work that can be done for snapshot improvements, but I'm feeling pretty good about the current state of things for the purposes of making the 0.9.5 release candidate build. And while I won't be online much this week, I will definitely make it a priority to respond to any regression reports on the times that I am online. -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] conf: Assign newDef of active domain as persistent conf if it is NULL
于 2011年09月01日 21:44, Osier Yang 写道: Libvirt loads the domain conf from status XML if it's running when starting up. The problem is there is no record of the original conf. (dom-newDef is NULL here). So libvirt won't be able to restore the domain conf to original one when destroying/shutdown. E.g. 1) attach a device without --persistent 2) restart libvirtd 3) destroy domain 4) start domain One will see the the disk still exists. This patch is to fix the peoblem by assigning persistent domain conf to dom-newDef if it's NULL and the domain is running. --- src/conf/domain_conf.c |8 +++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 00212db..cbb99d3 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -10533,9 +10533,15 @@ static virDomainObjPtr virDomainLoadConfig(virCapsPtr caps, if ((dom = virDomainFindByUUID(doms, def-uuid))) { dom-autostart = autostart; +if (virDomainObjIsActive(dom) +!dom-newDef) { +virDomainObjAssignDef(dom, def, false); +} else { +virDomainDefFree(def); +} + VIR_FREE(configFile); VIR_FREE(autostartLink); -virDomainDefFree(def); return dom; } With my testing, this patch solve the problem well. Could someone review/ACK this? Thanks Osier -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 2/2] XML: Suppress printing domain.xml for parse errors on XML strings
Patch e81778d6184f1850a10eb661eb756b50421d5ac4 introduces printing file name on XML errors. This corrects the URL string to be NULL and therefore to print an error message not containing bogus filename domain.xml. NULL is a valid parameter for the file name value, as the only usage is for error handlers. Functions touching the value either in libxml2 or in libvirt check this parameter for NULL and behave according to it. --- src/conf/domain_conf.c|2 +- src/security/virt-aa-helper.c |2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index cce9955..06baaaf 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -7367,7 +7367,7 @@ virDomainDefParse(const char *xmlStr, xmlDocPtr xml; virDomainDefPtr def = NULL; -if ((xml = virXMLParse(filename, xmlStr, domain.xml))) { +if ((xml = virXMLParse(filename, xmlStr, NULL))) { def = virDomainDefParseNode(caps, xml, xmlDocGetRootElement(xml), expectedVirtTypes, flags); xmlFreeDoc(xml); diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index bb577d3..1de2f77 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -641,7 +641,7 @@ caps_mockup(vahControl * ctl, const char *xmlStr) xmlDocPtr xml = NULL; xmlXPathContextPtr ctxt = NULL; -if (!(xml = virXMLParseStringCtxt(xmlStr, domain.xml, ctxt))) { +if (!(xml = virXMLParseStringCtxt(xmlStr, NULL, ctxt))) { goto cleanup; } -- 1.7.3.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] redirdev: allows to specify device address
It is important to be able to attach USB redirected devices to a particular controller (one that supports USB2 for instance). Without this patch, only the default bus was used. redirdev bus='usb' type='spicevmc' address type='usb' bus='0' port='4'/ /redirdev --- docs/formatdomain.html.in | 19 +-- docs/schemas/domaincommon.rng |3 +++ src/conf/domain_conf.c | 14 ++ tests/qemuxml2argvdata/qemuxml2argv-usb-redir.args |2 +- tests/qemuxml2argvdata/qemuxml2argv-usb-redir.xml |1 + 5 files changed, 32 insertions(+), 7 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index b960381..399388f 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1417,14 +1417,21 @@ tunnel; codetype='tcp'/code or codetype='spicevmc'/code (which uses the usbredir channel of a a href=#elementsGraphicsSPICE graphics -device/a) are typical. Further sub-elements, such -as codelt;sourcegt;/code, may be required according to -the given type, although a codelt;targetgt;/code -sub-element is not required (since the consumer of the -character device is the hypervisor itself, rather than a -device visible in the guest)./dd +device/a) are typical./dd /dl +p + The redirdev element has an optional sub-element + codelt;addressgt;/code which can tie the device to a + particular controller. +/p +p + Further sub-elements, such as codelt;sourcegt;/code, may + be required according to the given type, although + a codelt;targetgt;/code sub-element is not required (since + the consumer of the character device is the hypervisor itself, + rather than a device visible in the guest). +/p h4a name=elementsSmartcardSmartcard devices/a/h4 diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 8e7fd63..02c3c7f 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1986,6 +1986,9 @@ ref name=qemucdevSrcTypeChoice/ /attribute ref name=qemucdevSrcDef/ + optional +ref name=address/ + /optional /element /define define name=hostdev diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index cce9955..706f445 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -5518,6 +5518,18 @@ virDomainRedirdevDefParseXML(const xmlNodePtr node, def-source.chr.data.spicevmc = VIR_DOMAIN_CHR_SPICEVMC_USBREDIR; } +if (virDomainDeviceInfoParseXML(node, def-info, flags) 0) +goto error; + +if (def-bus == VIR_DOMAIN_REDIRDEV_BUS_USB +def-info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE +def-info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) { +virDomainReportError(VIR_ERR_XML_ERROR, %s, + _(Invalid address for a USB device)); +goto error; +} + + cleanup: VIR_FREE(bus); VIR_FREE(type); @@ -10274,6 +10286,8 @@ virDomainRedirdevDefFormat(virBufferPtr buf, virBufferAsprintf(buf, redirdev bus='%s', bus); if (virDomainChrSourceDefFormat(buf, def-source.chr, false, flags) 0) return -1; +if (virDomainDeviceInfoFormat(buf, def-info, flags) 0) +return -1; virBufferAddLit(buf, /redirdev\n); return 0; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.args b/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.args index 4d4f30a..f6270d5 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.args @@ -6,5 +6,5 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -chardev socket,id=charredir0,host=localhost,port=4000 \ -device usb-redir,chardev=charredir0,id=redir0 \ -chardev spicevmc,id=charredir1,name=usbredir \ --device usb-redir,chardev=charredir1,id=redir1 \ +-device usb-redir,chardev=charredir1,id=redir1,bus=usb.0,port=4 \ -device virtio-balloon-pci,id=balloon0,bus=pci.0,multifunction=on,addr=0x3.0x0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.xml b/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.xml index c73e569..1dac3fb 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.xml @@ -34,6 +34,7 @@ protocol type='raw'/ /redirdev redirdev bus='usb' type='spicevmc' + address type='usb' bus='0' port='4'/ /redirdev memballoon model='virtio'/ /devices -- 1.7.6 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 1/5] link-state: util: Add equality comparision functions for structures
This patch adds functions to compare structures containing network device configuration for equality. They serve for the purpose of disallowing unsupported changes to live network devices. --- src/util/network.c | 62 src/util/network.h |5 2 files changed, 67 insertions(+), 0 deletions(-) diff --git a/src/util/network.c b/src/util/network.c index 6fcdab2..ee69557 100644 --- a/src/util/network.c +++ b/src/util/network.c @@ -842,6 +842,43 @@ error: return ret; } +bool +virVirtualPortProfileEqual(virVirtualPortProfileParamsPtr a, virVirtualPortProfileParamsPtr b) +{ +/* NULL resistant */ +if (!a !b) +return true; + +if (!a || !b) +return false; + +if (a-virtPortType != b-virtPortType) +return false; + +switch (a-virtPortType) { +case VIR_VIRTUALPORT_NONE: +break; + +case VIR_VIRTUALPORT_8021QBG: +if (a-u.virtPort8021Qbg.managerID != b-u.virtPort8021Qbg.managerID || +a-u.virtPort8021Qbg.typeID != b-u.virtPort8021Qbg.typeID || +a-u.virtPort8021Qbg.typeIDVersion != b-u.virtPort8021Qbg.typeIDVersion || +memcmp(a-u.virtPort8021Qbg.instanceID, b-u.virtPort8021Qbg.instanceID, VIR_UUID_BUFLEN) != 0) +return false; +break; + +case VIR_VIRTUALPORT_8021QBH: +if (STRNEQ(a-u.virtPort8021Qbh.profileID, b-u.virtPort8021Qbh.profileID)) +return false; +break; + +default: +break; +} + +return true; +} + void virVirtualPortProfileFormat(virBufferPtr buf, virVirtualPortProfileParamsPtr virtPort, @@ -1321,3 +1358,28 @@ cleanup: } return ret; } + +bool +virBandwidthEqual(virBandwidthPtr a, + virBandwidthPtr b) +{ +if (!a !b) +return true; + +if (!a || !b) +return false; + +/* in */ +if (a-in-average != b-in-average || +a-in-peak != b-in-peak || +a-in-burst != b-in-burst) +return false; + +/*out*/ +if (a-out-average != b-out-average || +a-out-peak != b-out-peak || +a-out-burst != b-out-burst) +return false; + +return true; +} diff --git a/src/util/network.h b/src/util/network.h index 6ceaa6d..4d195af 100644 --- a/src/util/network.h +++ b/src/util/network.h @@ -150,6 +150,8 @@ virVirtualPortProfileFormat(virBufferPtr buf, virVirtualPortProfileParamsPtr virtPort, const char *indent); +bool virVirtualPortProfileEqual(virVirtualPortProfileParamsPtr a, virVirtualPortProfileParamsPtr b); + virBandwidthPtr virBandwidthDefParseNode(xmlNodePtr node); void virBandwidthDefFree(virBandwidthPtr def); int virBandwidthDefFormat(virBufferPtr buf, @@ -160,4 +162,7 @@ int virBandwidthEnable(virBandwidthPtr bandwidth, const char *iface); int virBandwidthDisable(const char *iface, bool may_fail); int virBandwidthCopy(virBandwidthPtr *dest, const virBandwidthPtr src); +bool virBandwidthEqual(virBandwidthPtr a, virBandwidthPtr b); + + #endif /* __VIR_NETWORK_H__ */ -- 1.7.3.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v4] daemon: Create priority workers pool
On Mon, Sep 05, 2011 at 02:36:13PM +0200, Michal Privoznik wrote: This patch annotates APIs with low or high priority. In low set MUST be all APIs which might eventually access monitor (and thus block indefinitely). Other APIs may be marked as high priority. However, some must be (e.g. domainDestroy). For high priority calls (HPC), there are some high priority workers (HPW) created in the pool. HPW can execute only HPC, although normal worker can process any call regardless priority. Therefore, only those APIs which are guaranteed to end in reasonable small amount of time can be marked as HPC. The size of this HPC pool is static, because HPC are expected to end quickly, therefore jobs assigned to this pool will be served quickly. It can be configured in libvirtd.conf via prio_workers variable. Default is set to 5. To mark API with low or high priority, append priority:{low|high} to it's comment in src/remote/remote_protocol.x. This is similar to autogen|skipgen. If not marked, the generator assumes low as default. --- diff to v3: -make 'priority:low' as default which can be left out -rearrange some APIs to be HPC or LPC daemon/libvirtd.aug |1 + daemon/libvirtd.c |7 + daemon/libvirtd.conf |6 + src/qemu/qemu_driver.c|2 +- src/qemu/qemu_process.c |2 +- src/remote/qemu_protocol.x| 13 ++- src/remote/remote_protocol.x | 294 + src/rpc/gendispatch.pl| 20 +++- src/rpc/virnetserver.c| 60 + src/rpc/virnetserver.h|1 + src/rpc/virnetserverprogram.c | 11 ++ src/rpc/virnetserverprogram.h |4 + src/util/threadpool.c | 158 +++ src/util/threadpool.h |4 +- 14 files changed, 382 insertions(+), 201 deletions(-) diff --git a/daemon/libvirtd.aug b/daemon/libvirtd.aug index 3f47ebb..ce00db5 100644 --- a/daemon/libvirtd.aug +++ b/daemon/libvirtd.aug @@ -57,6 +57,7 @@ module Libvirtd = | int_entry max_clients | int_entry max_requests | int_entry max_client_requests +| int_entry prio_workers let logging_entry = int_entry log_level | str_entry log_filters diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 423c3d7..7b445a2 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -134,6 +134,8 @@ struct daemonConfig { int max_workers; int max_clients; +int prio_workers; + int max_requests; int max_client_requests; @@ -886,6 +888,8 @@ daemonConfigNew(bool privileged ATTRIBUTE_UNUSED) data-max_workers = 20; data-max_clients = 20; +data-prio_workers = 5; + data-max_requests = 20; data-max_client_requests = 5; @@ -1042,6 +1046,8 @@ daemonConfigLoad(struct daemonConfig *data, GET_CONF_INT (conf, filename, max_workers); GET_CONF_INT (conf, filename, max_clients); +GET_CONF_INT (conf, filename, prio_workers); + GET_CONF_INT (conf, filename, max_requests); GET_CONF_INT (conf, filename, max_client_requests); @@ -1430,6 +1436,7 @@ int main(int argc, char **argv) { config-auth_unix_ro == REMOTE_AUTH_POLKIT; if (!(srv = virNetServerNew(config-min_workers, config-max_workers, +config-prio_workers, config-max_clients, config-mdns_adv ? config-mdns_name : NULL, use_polkit_dbus, diff --git a/daemon/libvirtd.conf b/daemon/libvirtd.conf index 95e43dd..da3983e 100644 --- a/daemon/libvirtd.conf +++ b/daemon/libvirtd.conf @@ -257,6 +257,12 @@ #min_workers = 5 #max_workers = 20 + +# The number of priority workers. If all workers from above +# pool will stuck, some calls marked as high priority +# (notably domainDestroy) can be executed in this pool. +#prio_workers = 5 + # Total global limit on concurrent RPC calls. Should be # at least as large as max_workers. Beyond this, RPC requests # will be read into memory and queued. This directly impact diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f21122d..b26a0cb 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -656,7 +656,7 @@ qemudStartup(int privileged) { virHashForEach(qemu_driver-domains.objs, qemuDomainSnapshotLoad, qemu_driver-snapshotDir); -qemu_driver-workerPool = virThreadPoolNew(0, 1, processWatchdogEvent, qemu_driver); +qemu_driver-workerPool = virThreadPoolNew(0, 1, 0, processWatchdogEvent, qemu_driver); if (!qemu_driver-workerPool) goto error; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 58b4d36..878805a 100644 --- a/src/qemu/qemu_process.c +++
[libvirt] [PATCH v3 4/5] link-state: qemu: Add net intf modification to virUpdateDeviceFlags
This patch enables modifying network device configuration using the virUpdateDeviceFlags API method. Matching of devices is accomplished using MAC addresses. While updating live configuration of a running domain, the user is allowed only to change link state of the interface. Additional modifications may be added later. For now the code checks for unsupported changes and tereafer changes the link state, if applicable. When updating persistent configuration of guest's network interface the whole configuration (except for the MAC address) may be modified and is stored for the next startup. src/qemu/qemu_driver.c - Add dispatching of virUpdateDevice for network devices update (live/config) src/qemu/qemu_hotplug.c - add setting of initial link state on live device addition - add function to change network device configuration. By now it supports only changing of link state src/qemu/qemu_hotplug.h - Headers to above functions src/qemu/qemu_process.c - set link states before virtual machine start. Qemu does not support setting of this on the command line. --- src/qemu/qemu_driver.c | 24 +++ src/qemu/qemu_hotplug.c | 176 +++ src/qemu/qemu_hotplug.h |8 ++ src/qemu/qemu_process.c | 47 - 4 files changed, 254 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7028d72..648afae 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5474,6 +5474,9 @@ qemuDomainUpdateDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_GRAPHICS: ret = qemuDomainChangeGraphics(driver, vm, dev-data.graphics); break; +case VIR_DOMAIN_DEVICE_NET: +ret = qemuDomainChangeNet(driver, vm, dom, dev-data.net); +break; default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, _(device type '%s' cannot be updated), @@ -5608,6 +5611,7 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) { virDomainDiskDefPtr orig, disk; +virDomainNetDefPtr net; int pos; switch (dev-type) { @@ -5646,6 +5650,26 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef, } disk-src = NULL; break; + +case VIR_DOMAIN_DEVICE_NET: +net = dev-data.net; +if ((pos = virDomainNetIndexByMac(vmdef, net-mac)) 0) { +char macbuf[VIR_MAC_STRING_BUFLEN]; +virFormatMacAddr(net-mac, macbuf); +qemuReportError(VIR_ERR_INVALID_ARG, +_(mac %s doesn't exist), macbuf); +return -1; +} + +VIR_FREE(vmdef-nets[pos]); + +vmdef-nets[pos] = net; +dev-data.net = NULL; + +if (qemuDomainAssignPCIAddresses(vmdef) 0) +return -1; +break; + default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, _(persistent update of device is not supported)); diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 6ae834c..ad57b2f 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -751,6 +751,30 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, } qemuDomainObjExitMonitorWithDriver(driver, vm); +/* set link state */ +if (net-linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) { +if (!net-info.alias) { +qemuReportError(VIR_ERR_OPERATION_FAILED, +_(device alias not found: cannot set link state to down)); +} else { +qemuDomainObjEnterMonitorWithDriver(driver, vm); + +if (qemuCapsGet(priv-qemuCaps, QEMU_CAPS_NETDEV)) { +if (qemuMonitorSetLink(priv-mon, net-info.alias, VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) 0) { +qemuDomainObjExitMonitorWithDriver(driver, vm); +virDomainAuditNet(vm, NULL, net, attach, false); +goto try_remove; +} +} else { +qemuReportError(VIR_ERR_OPERATION_FAILED, +_(setting of link state not supported: Link is up)); +} + +qemuDomainObjExitMonitorWithDriver(driver, vm); +} +/* link set to down */ +} + virDomainAuditNet(vm, NULL, net, attach, true); ret = 0; @@ -1082,6 +1106,158 @@ error: return -1; } +static virDomainNetDefPtr qemuDomainFindNet(virDomainObjPtr vm, +virDomainNetDefPtr dev) +{ +int i; + +for (i = 0; i vm-def-nnets; i++) { +if (memcmp(vm-def-nets[i]-mac, dev-mac, VIR_MAC_BUFLEN) == 0) +return vm-def-nets[i]; +} + +return NULL; +} + +int
Re: [libvirt] [PATCH 2/2] XML: Suppress printing domain.xml for parse errors on XML strings
On 09/05/2011 05:02 PM, Eric Blake wrote: On 09/05/2011 06:33 AM, Peter Krempa wrote: Patch e81778d6184f1850a10eb661eb756b50421d5ac4 introduces printing file name on XML errors. This corrects the URL string to be NULL and therefore to print an error message not containing bogus filename domain.xml. NULL is a valid parameter for the file name value, as the only usage is for error handlers. Functions touching the value either in libxml2 or in libvirt check this parameter for NULL and behave according to it. --- src/conf/domain_conf.c|2 +- src/security/virt-aa-helper.c |2 +- 2 files changed, 2 insertions(+), 2 deletions(-) I still think a lot of the virXMLParseStringCtxt() calls in virsh.c need the same treatment. Uhm, yes. You're right. I forgot about that. I'll post another patch to this series. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 0/5] Virtual interface link state modification
This patchset adds the ability for libvirt users to control interface link state of the virtual network devices provided by hypervisors. Modification of the link state is accomplished by adding a new XML element link stateup or down to the domain XML. The corresponding network interface is thereafter initialised with the desired state. Live modification of the link state is achieved by calling virDomainUpdateDeviceFlags containing a modified interface configuration. Yet, users may modify only link state of an interface. This feature allows propagation of network topology changes to guests, testing scenarios in complex virtual networks, etc ... Future upgrade: - add support for VirtualBox Modifications to v2: - Rebase to curent HEAD Modifications to v1: - use virUpdateDeviceFlags instead of dedicated API - incorporate helpful comments by Eric Blake https://bugzilla.redhat.com/show_bug.cgi?id=643373 Peter Krempa (5): link-state: util: Add equality comparision functions for structures link-state: conf: Add element to XML for controling link state link-state: qemu: Add monitor handling for link state modification link-state: qemu: Add net intf modification to virUpdateDeviceFlags link-state: virsh: Add wrapper commands for changing link state docs/formatdomain.html.in| 21 +++ docs/schemas/network.rng | 11 ++ src/conf/domain_conf.c | 24 src/conf/domain_conf.h | 11 ++ src/qemu/qemu_driver.c | 24 src/qemu/qemu_hotplug.c | 176 ++ src/qemu/qemu_hotplug.h |8 ++ src/qemu/qemu_monitor.c | 19 +++ src/qemu/qemu_monitor.h |4 + src/qemu/qemu_monitor_json.c | 23 src/qemu/qemu_monitor_json.h |4 + src/qemu/qemu_monitor_text.c | 46 +++ src/qemu/qemu_monitor_text.h |4 + src/qemu/qemu_process.c | 47 +++- src/util/network.c | 62 + src/util/network.h |5 + tools/virsh.c| 286 ++ tools/virsh.pod | 11 ++ 18 files changed, 785 insertions(+), 1 deletions(-) -- 1.7.3.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/2] XML: Suppress printing domain.xml for parse errors on XML strings
On 09/05/2011 06:33 AM, Peter Krempa wrote: Patch e81778d6184f1850a10eb661eb756b50421d5ac4 introduces printing file name on XML errors. This corrects the URL string to be NULL and therefore to print an error message not containing bogus filename domain.xml. NULL is a valid parameter for the file name value, as the only usage is for error handlers. Functions touching the value either in libxml2 or in libvirt check this parameter for NULL and behave according to it. --- src/conf/domain_conf.c|2 +- src/security/virt-aa-helper.c |2 +- 2 files changed, 2 insertions(+), 2 deletions(-) I still think a lot of the virXMLParseStringCtxt() calls in virsh.c need the same treatment. -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2] virsh: Add more human-friendly output of domblkstat command
Users of virsh complain that output of the domblkstat command is not intuitive enough. This patch adds explanation of fields returned by this command to the help section for domblkstat and the man page of virsh. Also a switch --human is added for domblkstat that prints the fields with more descriptive texts. https://bugzilla.redhat.com/show_bug.cgi?id=731656 Changes to v1: -Rebased to current head --- tools/virsh.c | 52 +--- tools/virsh.pod | 11 ++- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index c7240e5..09337cb 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1054,13 +1054,21 @@ cleanup: */ static const vshCmdInfo info_domblkstat[] = { {help, N_(get device block stats for a domain)}, -{desc, N_(Get device block stats for a running domain.)}, +{desc, N_(Get device block stats for a running domain.\n\n +Explanation of fields:\n + rd_req - count of read requests\n + rd_bytes - count of read bytes\n + wr_req - count of write requests\n + wr_bytes - count of written bytes\n + errs - error count)}, {NULL,NULL} }; static const vshCmdOptDef opts_domblkstat[] = { {domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)}, {device, VSH_OT_DATA, VSH_OFLAG_REQ, N_(block device)}, +{human, VSH_OT_BOOL, 0, N_(print a more human readable output)}, + {NULL, 0, 0, NULL} }; @@ -1070,6 +1078,7 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) virDomainPtr dom; const char *name = NULL, *device = NULL; struct _virDomainBlockStats stats; +int humanReadable = vshCommandOptBool(cmd, human); if (!vshConnectionUsability (ctl, ctl-conn)) return false; @@ -1088,20 +1097,41 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) return false; } -if (stats.rd_req = 0) -vshPrint (ctl, %s rd_req %lld\n, device, stats.rd_req); +if (humanReadable) { +/* human friendly output */ +vshPrint(ctl, N_(Device: %s\n), device); + +if (stats.rd_req = 0) +vshPrint (ctl, N_(read request count: %lld\n), stats.rd_req); + +if (stats.rd_bytes = 0) +vshPrint (ctl, N_(number of read bytes:%lld\n), stats.rd_bytes); + +if (stats.wr_req = 0) +vshPrint (ctl, N_(write request count: %lld\n), stats.wr_req); -if (stats.rd_bytes = 0) -vshPrint (ctl, %s rd_bytes %lld\n, device, stats.rd_bytes); +if (stats.wr_bytes = 0) +vshPrint (ctl, N_(number of written bytes: %lld\n), stats.wr_bytes); -if (stats.wr_req = 0) -vshPrint (ctl, %s wr_req %lld\n, device, stats.wr_req); +if (stats.errs = 0) +vshPrint (ctl, N_(error count: %lld\n), stats.errs); +} else { +/* script friendly output */ +if (stats.rd_req = 0) +vshPrint (ctl, %s rd_req %lld\n, device, stats.rd_req); + +if (stats.rd_bytes = 0) +vshPrint (ctl, %s rd_bytes %lld\n, device, stats.rd_bytes); -if (stats.wr_bytes = 0) -vshPrint (ctl, %s wr_bytes %lld\n, device, stats.wr_bytes); +if (stats.wr_req = 0) +vshPrint (ctl, %s wr_req %lld\n, device, stats.wr_req); -if (stats.errs = 0) -vshPrint (ctl, %s errs %lld\n, device, stats.errs); +if (stats.wr_bytes = 0) +vshPrint (ctl, %s wr_bytes %lld\n, device, stats.wr_bytes); + +if (stats.errs = 0) +vshPrint (ctl, %s errs %lld\n, device, stats.errs); +} virDomainFree(dom); return true; diff --git a/tools/virsh.pod b/tools/virsh.pod index 30c0721..c333b2a 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -501,10 +501,19 @@ be lost once the guest stops running, but the snapshot contents still exist, and a new domain with the same name and UUID can restore the snapshot metadata with Bsnapshot-create. -=item Bdomblkstat Idomain Iblock-device +=item Bdomblkstat Idomain Iblock-device [I--human] Get device block stats for a running domain. +Use I--human for a more human readable output. + +BExplanation of fields: + rd_req - count of read requests + rd_bytes - count of read bytes + wr_req - count of write requests + wr_bytes - count of written bytes + errs - error count + =item Bdomifstat Idomain Iinterface-device Get network interface stats for a running domain. -- 1.7.3.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v4] daemon: Create priority workers pool
On 05.09.2011 17:00, Daniel Veillard wrote: On Mon, Sep 05, 2011 at 02:36:13PM +0200, Michal Privoznik wrote: This patch annotates APIs with low or high priority. In low set MUST be all APIs which might eventually access monitor (and thus block indefinitely). Other APIs may be marked as high priority. However, some must be (e.g. domainDestroy). For high priority calls (HPC), there are some high priority workers (HPW) created in the pool. HPW can execute only HPC, although normal worker can process any call regardless priority. Therefore, only those APIs which are guaranteed to end in reasonable small amount of time can be marked as HPC. The size of this HPC pool is static, because HPC are expected to end quickly, therefore jobs assigned to this pool will be served quickly. It can be configured in libvirtd.conf via prio_workers variable. Default is set to 5. To mark API with low or high priority, append priority:{low|high} to it's comment in src/remote/remote_protocol.x. This is similar to autogen|skipgen. If not marked, the generator assumes low as default. --- diff to v3: -make 'priority:low' as default which can be left out -rearrange some APIs to be HPC or LPC daemon/libvirtd.aug |1 + daemon/libvirtd.c |7 + daemon/libvirtd.conf |6 + src/qemu/qemu_driver.c|2 +- src/qemu/qemu_process.c |2 +- src/remote/qemu_protocol.x| 13 ++- src/remote/remote_protocol.x | 294 + src/rpc/gendispatch.pl| 20 +++- src/rpc/virnetserver.c| 60 + src/rpc/virnetserver.h|1 + src/rpc/virnetserverprogram.c | 11 ++ src/rpc/virnetserverprogram.h |4 + src/util/threadpool.c | 158 +++ src/util/threadpool.h |4 +- 14 files changed, 382 insertions(+), 201 deletions(-) diff --git a/daemon/libvirtd.aug b/daemon/libvirtd.aug index 3f47ebb..ce00db5 100644 --- a/daemon/libvirtd.aug +++ b/daemon/libvirtd.aug @@ -57,6 +57,7 @@ module Libvirtd = | int_entry max_clients | int_entry max_requests | int_entry max_client_requests +| int_entry prio_workers let logging_entry = int_entry log_level | str_entry log_filters diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 423c3d7..7b445a2 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -134,6 +134,8 @@ struct daemonConfig { int max_workers; int max_clients; +int prio_workers; + int max_requests; int max_client_requests; @@ -886,6 +888,8 @@ daemonConfigNew(bool privileged ATTRIBUTE_UNUSED) data-max_workers = 20; data-max_clients = 20; +data-prio_workers = 5; + data-max_requests = 20; data-max_client_requests = 5; @@ -1042,6 +1046,8 @@ daemonConfigLoad(struct daemonConfig *data, GET_CONF_INT (conf, filename, max_workers); GET_CONF_INT (conf, filename, max_clients); +GET_CONF_INT (conf, filename, prio_workers); + GET_CONF_INT (conf, filename, max_requests); GET_CONF_INT (conf, filename, max_client_requests); @@ -1430,6 +1436,7 @@ int main(int argc, char **argv) { config-auth_unix_ro == REMOTE_AUTH_POLKIT; if (!(srv = virNetServerNew(config-min_workers, config-max_workers, +config-prio_workers, config-max_clients, config-mdns_adv ? config-mdns_name : NULL, use_polkit_dbus, diff --git a/daemon/libvirtd.conf b/daemon/libvirtd.conf index 95e43dd..da3983e 100644 --- a/daemon/libvirtd.conf +++ b/daemon/libvirtd.conf @@ -257,6 +257,12 @@ #min_workers = 5 #max_workers = 20 + +# The number of priority workers. If all workers from above +# pool will stuck, some calls marked as high priority +# (notably domainDestroy) can be executed in this pool. +#prio_workers = 5 + # Total global limit on concurrent RPC calls. Should be # at least as large as max_workers. Beyond this, RPC requests # will be read into memory and queued. This directly impact diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f21122d..b26a0cb 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -656,7 +656,7 @@ qemudStartup(int privileged) { virHashForEach(qemu_driver-domains.objs, qemuDomainSnapshotLoad, qemu_driver-snapshotDir); -qemu_driver-workerPool = virThreadPoolNew(0, 1, processWatchdogEvent, qemu_driver); +qemu_driver-workerPool = virThreadPoolNew(0, 1, 0, processWatchdogEvent, qemu_driver); if (!qemu_driver-workerPool) goto error; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 58b4d36..878805a
[libvirt] [PATCH v3 2/5] link-state: conf: Add element to XML for controling link state
A new element is introduced to XML that allows to control state of virtual network interfaces in hypervisors. Live modification of the link state allows networking tools propagate topology changes to guest OS or testing of scenarios in complex (virtual) networks. This patch adds elements to XML grammars and parsing and generating code. docs/formatdomain.html.in - Documentation of new element docs/schemas/network.rng - Grammar for the new element src/conf/domain_conf.c - Parsing and generating code src/conf/domain_conf.h - Enum of available link states --- docs/formatdomain.html.in | 21 + docs/schemas/network.rng | 11 +++ src/conf/domain_conf.c| 24 src/conf/domain_conf.h| 11 +++ 4 files changed, 67 insertions(+), 0 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index b960381..53de6c8 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2092,6 +2092,27 @@ qemu-kvm -net nic,model=? /dev/null span class=sinceSince 0.9.4/span /p +h5a name=elementLinkModyfing virtual link state/a/h5 +pre + ... + lt;devicesgt; +lt;interface type='network'gt; + lt;source network='default'/gt; + lt;target dev='vnet0'/gt; + blt;link state='down'/gt;/b +lt;/interfacegt; + lt;devicesgt; + .../pre + +p + This element provides means of setting state of the virtual network link. + Possible values for attribute codestate/code are codeup/code and + codedown/code. If codedown/code is specified as the value, the interface + behaves as if it had the network cable disconnected. Default behavior if this + element is unspecified is to have the link state codeup/code. + span class=sinceSince 0.9.5/span +/p + h4a name=elementsInputInput devices/a/h4 p diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng index 1c44471..937e180 100644 --- a/docs/schemas/network.rng +++ b/docs/schemas/network.rng @@ -150,6 +150,17 @@ optional ref name=bandwidth/ /optional + optional + element name=link + attribute name=state + choice + valueup/value + valuedown/value + /choice + /attribute + empty/ + /element +/optional !-- ip element -- zeroOrMore diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index cce9955..75431fb 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -251,6 +251,11 @@ VIR_ENUM_IMPL(virDomainNetVirtioTxMode, VIR_DOMAIN_NET_VIRTIO_TX_MODE_LAST, iothread, timer) +VIR_ENUM_IMPL(virDomainNetInterfaceLinkState, VIR_DOMAIN_NET_INTERFACE_LINK_STATE_LAST, + default, + up, + down) + VIR_ENUM_IMPL(virDomainChrChannelTarget, VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST, guestfwd, @@ -2945,6 +2950,7 @@ virDomainNetDefParseXML(virCapsPtr caps, char *internal = NULL; char *devaddr = NULL; char *mode = NULL; +char *linkstate = NULL; virNWFilterHashTablePtr filterparams = NULL; virVirtualPortProfileParamsPtr virtPort = NULL; virDomainActualNetDefPtr actual = NULL; @@ -3021,6 +3027,9 @@ virDomainNetDefParseXML(virCapsPtr caps, /* An auto-generated target name, blank it out */ VIR_FREE(ifname); } +} else if ((linkstate == NULL) + xmlStrEqual(cur-name, BAD_CAST link)) { +linkstate = virXMLPropString(cur, state); } else if ((script == NULL) (def-type == VIR_DOMAIN_NET_TYPE_ETHERNET || def-type == VIR_DOMAIN_NET_TYPE_BRIDGE) @@ -3285,6 +3294,16 @@ virDomainNetDefParseXML(virCapsPtr caps, } } +def-linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DEFAULT; +if (linkstate != NULL) { +if ((def-linkstate = virDomainNetInterfaceLinkStateTypeFromString(linkstate)) = 0) { +virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _(unknown interface link state '%s'), + linkstate); +goto error; +} +} + if (filter != NULL) { switch (def-type) { case VIR_DOMAIN_NET_TYPE_ETHERNET: @@ -3332,6 +3351,7 @@ cleanup: VIR_FREE(internal); VIR_FREE(devaddr); VIR_FREE(mode); +VIR_FREE(linkstate); virNWFilterHashTableFree(filterparams); return def; @@ -9429,6 +9449,10 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferAddLit(buf, /tune\n); } +if (def-linkstate) +virBufferAsprintf(buf, link state='%s'/\n, + virDomainNetInterfaceLinkStateTypeToString(def-linkstate)); + if (virBandwidthDefFormat(buf,
[libvirt] [PATCH 3/2] virsh: Change domain.xml to NULL in XML parsing of strings
Clean up instances of domain.xml in context of parsing XML documents in memory to support new XML parse error reporting function. --- tools/virsh.c | 10 +- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index c7240e5..1b11f79 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -8616,7 +8616,7 @@ makeCloneXML(const char *origxml, const char *newname) { xmlChar *newxml = NULL; int size; -doc = virXMLParseStringCtxt(origxml, domain.xml, ctxt); +doc = virXMLParseStringCtxt(origxml, NULL, ctxt); if (!doc) goto cleanup; @@ -10407,7 +10407,7 @@ cmdVNCDisplay(vshControl *ctl, const vshCmd *cmd) if (!doc) goto cleanup; -xml = virXMLParseStringCtxt(doc, domain.xml, ctxt); +xml = virXMLParseStringCtxt(doc, NULL, ctxt); VIR_FREE(doc); if (!xml) goto cleanup; @@ -10475,7 +10475,7 @@ cmdTTYConsole(vshControl *ctl, const vshCmd *cmd) if (!doc) goto cleanup; -xml = virXMLParseStringCtxt(doc, domain.xml, ctxt); +xml = virXMLParseStringCtxt(doc, NULL, ctxt); VIR_FREE(doc); if (!xml) goto cleanup; @@ -10862,7 +10862,7 @@ cmdDetachInterface(vshControl *ctl, const vshCmd *cmd) if (!doc) goto cleanup; -xml = virXMLParseStringCtxt(doc, domain.xml, ctxt); +xml = virXMLParseStringCtxt(doc, NULL, ctxt); VIR_FREE(doc); if (!xml) { vshError(ctl, %s, _(Failed to get interface information)); @@ -11329,7 +11329,7 @@ cmdDetachDisk(vshControl *ctl, const vshCmd *cmd) if (!doc) goto cleanup; -xml = virXMLParseStringCtxt(doc, domain.xml, ctxt); +xml = virXMLParseStringCtxt(doc, NULL, ctxt); VIR_FREE(doc); if (!xml) { vshError(ctl, %s, _(Failed to get disk information)); -- 1.7.3.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 3/5] link-state: qemu: Add monitor handling for link state modification
This patch adds handlers for modification of guest's interface link state. Both HMP and QMP commands are supported, but as the link state functionality is from the beginning supported in QMP the HMP code will probably never be used. src/qemu/qemu_monitor.c- Add command dispatcher src/qemu/qemu_monitor.h- Add headar for command src/qemu/qemu_monitor_json.c - Add QMP command handling src/qemu/qemu_monitor_json.h - Add header for command src/qemu/qemu_monitor_text.c - Add HMP command handling src/qemu/qemu_monitor_text.h - Add header for command --- src/qemu/qemu_monitor.c | 19 + src/qemu/qemu_monitor.h |4 +++ src/qemu/qemu_monitor_json.c | 23 + src/qemu/qemu_monitor_json.h |4 +++ src/qemu/qemu_monitor_text.c | 46 ++ src/qemu/qemu_monitor_text.h |4 +++ 6 files changed, 100 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index db6107c..5738116 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1135,6 +1135,25 @@ int qemuMonitorGetCPUInfo(qemuMonitorPtr mon, return ret; } +int qemuMonitorSetLink(qemuMonitorPtr mon, + const char *name, + enum virDomainNetInterfaceLinkState state) +{ +int ret; +VIR_DEBUG(mon=%p, name=%p:%s, state=%u, mon, name, name, state); + +if (!mon || !name) { +qemuReportError(VIR_ERR_INVALID_ARG, +_(monitor || name must not be NULL)); +return -1; +} + +if (mon-json) +ret = qemuMonitorJSONSetLink(mon, name, state); +else +ret = qemuMonitorTextSetLink(mon, name, state); +return ret; +} int qemuMonitorGetVirtType(qemuMonitorPtr mon, int *virtType) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index f241c9e..cd46608 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -145,6 +145,10 @@ void qemuMonitorUnlock(qemuMonitorPtr mon); int qemuMonitorRef(qemuMonitorPtr mon); int qemuMonitorUnref(qemuMonitorPtr mon) ATTRIBUTE_RETURN_CHECK; +int qemuMonitorSetLink(qemuMonitorPtr mon, + const char *name, + enum virDomainNetInterfaceLinkState state) ; + /* These APIs are for use by the internal Text/JSON monitor impl code only */ char *qemuMonitorNextCommandID(qemuMonitorPtr mon); int qemuMonitorSend(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 4ceb536..c502b72 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -955,6 +955,29 @@ int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon) return ret; } +int qemuMonitorJSONSetLink(qemuMonitorPtr mon, + const char *name, + enum virDomainNetInterfaceLinkState state) +{ + +int ret; +virJSONValuePtr reply = NULL; +virJSONValuePtr cmd = qemuMonitorJSONMakeCommand(set_link, + s:name, name, + b:up, state != VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN, + NULL); + +if (!cmd) +return -1; + +if ((ret = qemuMonitorJSONCommand(mon, cmd, reply)) == 0) +ret = qemuMonitorJSONCheckError(cmd, reply); + +virJSONValueFree(cmd); +virJSONValueFree(reply); + +return ret; +} int qemuMonitorJSONSystemReset(qemuMonitorPtr mon) { diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 9512793..2611b07 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -231,4 +231,8 @@ int qemuMonitorJSONBlockJob(qemuMonitorPtr mon, virDomainBlockJobInfoPtr info, int mode); +int qemuMonitorJSONSetLink(qemuMonitorPtr mon, + const char *name, + enum virDomainNetInterfaceLinkState state); + #endif /* QEMU_MONITOR_JSON_H */ diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 854ee7f..0fdc223 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -433,6 +433,52 @@ int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon) { return 0; } +int qemuMonitorTextSetLink(qemuMonitorPtr mon, const char *name, enum virDomainNetInterfaceLinkState state) { +char *info = NULL; +char *cmd = NULL; +const char *st_str = NULL; + +/* determine state */ +if (state == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) +st_str = off; +else +st_str = on; + +if (virAsprintf(cmd, set_link %s %s, name, st_str) 0) { +virReportOOMError(); +goto error; +} +if (qemuMonitorHMPCommand(mon, cmd, info) 0) { +qemuReportError(VIR_ERR_OPERATION_FAILED, +
[libvirt] [PATCH v3 5/5] link-state: virsh: Add wrapper commands for changing link state
Two new commands are added to virsh that wrap usage of virDomainUpdateDeviceFlags for changing link state of domain's network interfaces. These wrappers extract network devices's xml configuration and modify the link state for easy manipulation from user's perspective. * domif-setlink - set link state of a domains virtual network interface * domif-getlink - get link state tools/virsh.c - Add functionality to virsh tools/virsh.pod - Manpage documentation --- tools/virsh.c | 286 +++ tools/virsh.pod | 11 ++ 2 files changed, 297 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index c7240e5..dff048a 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1173,6 +1173,290 @@ cmdDomIfstat (vshControl *ctl, const vshCmd *cmd) return true; } +/* domif-setlink command + */ +static const vshCmdInfo info_domif_setlink[] = { +{help, N_(set link state of a virtual interface)}, +{desc, N_(Set link state of a domain's virtual interface. This command wraps usage of update-device command.)}, +{NULL,NULL} +}; + +static const vshCmdOptDef opts_domif_setlink[] = { +{domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)}, +{interface, VSH_OT_DATA, VSH_OFLAG_REQ, N_(interface device (MAC Address))}, +{state, VSH_OT_DATA, VSH_OFLAG_REQ, N_(new state of the device)}, +{persistent, VSH_OT_BOOL, 0, N_(persist interface state)}, +{NULL, 0, 0, NULL} +}; + +static bool +cmdDomIfSetLink (vshControl *ctl, const vshCmd *cmd) +{ + +virDomainPtr dom; +const char *interface; +const char *state; +const char *mac; +const char *desc; +bool persistent; +bool ret = false; +unsigned int flags = 0; +int i; + +xmlDocPtr xml = NULL; +xmlXPathContextPtr ctxt = NULL; +xmlXPathObjectPtr obj = NULL; +xmlNodePtr cur = NULL; +xmlBufferPtr xml_buf = NULL; + + +if (!vshConnectionUsability(ctl, ctl-conn)) +return false; + +if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) +return false; + +if (vshCommandOptString(cmd, interface, interface) = 0) +goto cleanup; + +if (vshCommandOptString(cmd, state, state) = 0) +goto cleanup; + +persistent = vshCommandOptBool(cmd, persistent); + +if (STRNEQ(state, up) STRNEQ(state, down)) { +vshError(ctl, _(invalid link state '%s'), state); +goto cleanup; +} + +/* get persistent or live description of network device */ +desc = virDomainGetXMLDesc(dom, persistent?VIR_DOMAIN_XML_INACTIVE:0); +if (desc == NULL) { +vshError(ctl, _(Failed to get domain description xml)); +goto cleanup; +} + +if (persistent) +flags = VIR_DOMAIN_AFFECT_CONFIG; +else +flags = VIR_DOMAIN_AFFECT_LIVE; + +if (virDomainIsActive(dom) == 0) +flags = VIR_DOMAIN_AFFECT_CONFIG; + +/* extract current network device description */ +xml = virXMLParseStringCtxt(desc, domain configuration, ctxt); +VIR_FREE(desc); +if (!xml) { +vshError(ctl, _(Failed to parse domain description xml)); +goto cleanup; +} + +obj = xmlXPathEval(BAD_CAST /domain/devices/interface, ctxt); +if (obj == NULL || obj-type != XPATH_NODESET || +obj-nodesetval == NULL || obj-nodesetval-nodeNr == 0) { +vshError(ctl, _(Failed to extract interface information or no interfaces found)); +goto cleanup; +} + +/* find interface with matching mac addr */ +for (i = 0; i obj-nodesetval-nodeNr; i++) { +cur = obj-nodesetval-nodeTab[i]-children; + +while (cur) { +if (cur-type == XML_ELEMENT_NODE +xmlStrEqual(cur-name, BAD_CAST mac)) { +mac = virXMLPropString(cur, address); + +if (STRCASEEQ(mac, interface)) { +VIR_FREE(mac); +goto hit; +} +VIR_FREE(mac); +} +cur = cur-next; +} +} + +vshError(ctl, _(interface with address '%s' not found), interface); +goto cleanup; + +hit: +/* find and modify/add link state node */ +/* try to find link element */ +cur = obj-nodesetval-nodeTab[i]-children; + +while (cur) { +if (cur-type == XML_ELEMENT_NODE +xmlStrEqual(cur-name, BAD_CAST link)) { +/* found, just modify the property */ +xmlSetProp(cur, BAD_CAST state, BAD_CAST state); + +break; +} +cur = cur-next; +} + +if (!cur) { +/* element link not found, add one */ +cur = xmlNewChild(obj-nodesetval-nodeTab[i], + NULL, + BAD_CAST link, + NULL); +if (!cur) +goto cleanup; + +if (xmlNewProp(cur, BAD_CAST state, BAD_CAST state) == NULL) +goto cleanup; +} + +xml_buf = xmlBufferCreate(); +if
[libvirt] [PATCH] Don't treat pci_system_init failure as fatal if no PCI bus is present
Xen PV domU's have no PCI bus. node_device_udev.c calls pci_system_init which looks for /sys/bus/pci. If it does not find /sys/bus/pci (which it won't in a Xen PV domU) it returns unsuccesfully (ENOENT), which libvirt considers fatal. This makes libvirt unusable in this environment, even though there are plenty of valid virtualisation options that work there (LXC, UML, and QEmu spring to mind) https://bugzilla.redhat.com/show_bug.cgi?id=709471 Signed-off-by: Soren Hansen so...@linux2go.dk --- src/node_device/node_device_udev.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index badf241..08ef856 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -1620,7 +1620,7 @@ static int udevDeviceMonitorStartup(int privileged) /* Ignore failure as non-root; udev is not as helpful in that * situation, but a non-privileged user won't benefit much * from udev in the first place. */ -if (privileged || errno != EACCES) { +if (errno != ENOENT (privileged || errno != EACCES)) { char ebuf[256]; VIR_ERROR(_(Failed to initialize libpciaccess: %s), virStrerror(pciret, ebuf, sizeof ebuf)); -- 1.7.5.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [test-API][PATCH 2/2] Modify migration.py to support testing with tcp and tls
On 09/02/2011 03:23 PM, Guannan Ren wrote: --- repos/domain/migrate.py |7 +-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/repos/domain/migrate.py b/repos/domain/migrate.py index 3f80bd0..6b86188 100644 --- a/repos/domain/migrate.py +++ b/repos/domain/migrate.py @@ -1,6 +1,8 @@ #!/usr/bin/env python this script is for migration testing domain:migrate + transport + tcp|tls|ssh target_machine 10.66.5.5 username @@ -105,7 +107,7 @@ def env_clean(src, dst, srcdom, dstdom, target_machine, guestname, logger): def check_params(params): check out the arguments requried for migration logger = params['logger'] -keys = ['target_machine', 'username', 'password', 'guestname', 'flags'] +keys = ['transport', 'target_machine', 'username', 'password', 'guestname', 'flags'] for key in keys: if key not in params: logger.error(Argument %s is required % key) @@ -194,6 +196,7 @@ def migrate(params): if params_check_result: return 1 +transport = params['transport'] target_machine = params['target_machine'] username = params['username'] password = params['password'] @@ -243,7 +246,7 @@ def migrate(params): commands.getstatusoutput(ssh-add) srcuri = qemu:///system -dsturi = qemu+ssh://%s/system % target_machine +dsturi = qemu+%s://%s/system % (transport, target_machine) # Connect to local hypervisor connection URI util = utils.Utils() ACK. - nzhang -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [test-API][PATCH 1/2] Remove cases/migrate.conf testcases and create a set of migration testcases
On 09/02/2011 03:23 PM, Guannan Ren wrote: *cases/migrate.conf remove it. *cases/migration/* create a new set of migraion testcases with tcp, tls and sasl combination It's huge, so I send the header of commit here. --- cases/migrate.conf | 97 cases/migration/ssh_persistent_paused_no_dst.conf | 459 +++ .../migration/ssh_persistent_paused_with_dst.conf | 459 +++ cases/migration/ssh_persistent_running_no_dst.conf | 435 ++ .../migration/ssh_persistent_running_with_dst.conf | 435 ++ cases/migration/ssh_transient_paused_no_dst.conf | 403 + cases/migration/ssh_transient_paused_with_dst.conf | 403 + cases/migration/ssh_transient_running_no_dst.conf | 388 .../migration/ssh_transient_running_with_dst.conf | 382 cases/migration/tcp_persistent_paused_no_dst.conf | 471 .../migration/tcp_persistent_paused_with_dst.conf | 471 cases/migration/tcp_persistent_running_no_dst.conf | 447 +++ .../migration/tcp_persistent_running_with_dst.conf | 447 +++ .../tcp_sasl_persistent_paused_no_dst.conf | 167 +++ .../tcp_sasl_persistent_paused_with_dst.conf | 168 +++ .../tcp_sasl_persistent_running_no_dst.conf| 159 +++ .../tcp_sasl_persistent_running_with_dst.conf | 159 +++ .../tcp_sasl_transient_paused_no_dst.conf | 151 +++ .../tcp_sasl_transient_paused_with_dst.conf| 151 +++ .../tcp_sasl_transient_running_no_dst.conf | 143 ++ .../tcp_sasl_transient_running_with_dst.conf | 143 ++ cases/migration/tcp_transient_paused_no_dst.conf | 415 + cases/migration/tcp_transient_paused_with_dst.conf | 415 + cases/migration/tcp_transient_running_no_dst.conf | 400 + .../migration/tcp_transient_running_with_dst.conf | 394 cases/migration/tls_persistent_paused_no_dst.conf | 471 .../migration/tls_persistent_paused_with_dst.conf | 471 cases/migration/tls_persistent_running_no_dst.conf | 447 +++ .../migration/tls_persistent_running_with_dst.conf | 447 +++ .../tls_sasl_persistent_paused_no_dst.conf | 167 +++ .../tls_sasl_persistent_paused_with_dst.conf | 167 +++ .../tls_sasl_persistent_running_no_dst.conf| 159 +++ .../tls_sasl_persistent_running_with_dst.conf | 159 +++ .../tls_sasl_transient_paused_no_dst.conf | 151 +++ .../tls_sasl_transient_paused_with_dst.conf| 151 +++ .../tls_sasl_transient_running_no_dst.conf | 143 ++ .../tls_sasl_transient_running_with_dst.conf | 143 ++ cases/migration/tls_transient_paused_no_dst.conf | 415 + cases/migration/tls_transient_paused_with_dst.conf | 415 + cases/migration/tls_transient_running_no_dst.conf | 400 + .../migration/tls_transient_running_with_dst.conf | 394 41 files changed, 12765 insertions(+), 97 deletions(-) delete mode 100644 cases/migrate.conf create mode 100644 cases/migration/ssh_persistent_paused_no_dst.conf create mode 100644 cases/migration/ssh_persistent_paused_with_dst.conf create mode 100644 cases/migration/ssh_persistent_running_no_dst.conf create mode 100644 cases/migration/ssh_persistent_running_with_dst.conf create mode 100644 cases/migration/ssh_transient_paused_no_dst.conf create mode 100644 cases/migration/ssh_transient_paused_with_dst.conf create mode 100644 cases/migration/ssh_transient_running_no_dst.conf create mode 100644 cases/migration/ssh_transient_running_with_dst.conf create mode 100644 cases/migration/tcp_persistent_paused_no_dst.conf create mode 100644 cases/migration/tcp_persistent_paused_with_dst.conf create mode 100644 cases/migration/tcp_persistent_running_no_dst.conf create mode 100644 cases/migration/tcp_persistent_running_with_dst.conf create mode 100644 cases/migration/tcp_sasl_persistent_paused_no_dst.conf create mode 100644 cases/migration/tcp_sasl_persistent_paused_with_dst.conf create mode 100644 cases/migration/tcp_sasl_persistent_running_no_dst.conf create mode 100644 cases/migration/tcp_sasl_persistent_running_with_dst.conf create mode 100644 cases/migration/tcp_sasl_transient_paused_no_dst.conf create mode 100644 cases/migration/tcp_sasl_transient_paused_with_dst.conf create mode 100644 cases/migration/tcp_sasl_transient_running_no_dst.conf create mode 100644 cases/migration/tcp_sasl_transient_running_with_dst.conf create mode 100644 cases/migration/tcp_transient_paused_no_dst.conf create mode 100644
Re: [libvirt] [PATCH 1/8] latency: Define new public API and structure
On Mon, Sep 05, 2011 at 04:38:28PM +0800, Osier Yang wrote: --- include/libvirt/libvirt.h.in | 84 ++ src/libvirt_public.syms |1 + 2 files changed, 85 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 8864865..735ea94 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -574,6 +574,85 @@ struct _virDomainBlockStats { */ typedef virDomainBlockStatsStruct *virDomainBlockStatsPtr; + +/** + * VIR_DOMAIN_BLOCK_STATS_FIELD_LENGTH: + * + * Macro providing the field length of virDomainBlockStatsFlagsStruct + */ +#define VIR_DOMAIN_BLOCK_STATS_FIELD_LENGTH 80 + +/** + * VIR_DOMAIN_BLOCK_STATS_READ_BYTES: + * + * Macro represents the total number of read bytes of the + * block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_READ_BYTES rd_bytes + +/** + * VIR_DOMAIN_BLOCK_STATS_READ_REQ: + * + * Macro represents the total read requests of the + * block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_READ_REQ rd_operations + +/** + * VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES: + * + * Macro represents the total time spend on cache reads in + * nano-seconds of the block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES rd_total_times + +/** + * VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES: + * + * Macro represents the total number of write bytes of the + * block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES wr_bytes + +/** + * VIR_DOMAIN_BLOCK_STATS_WRITE_REQ: + * + * Macro represents the total write requests of the + * block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_WRITE_REQ wr_operations + +/** + * VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES: + * + * Macro represents the total time spend on cache writes in + * nano-seconds of the block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES wr_total_times + +/** + * VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ: + * + * Macro represents the total flush requests of the + * block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ flush_operations + +/** + * VIR_DOMAIN_BLOCK_STATS_FLUSH_TOTAL_TIMES: + * + * Macro represents the total time spend on cache flushing in + * nano-seconds of the block device. + */ +#define VIR_DOMAIN_BLOCK_STATS_FLUSH_TOTAL_TIMES flush_total_times + +/** + * VIR_DOMAIN_BLOCK_STATS_ERRS: + * + * In Xen this returns the mysterious 'oo_req' + */ +#define VIR_DOMAIN_BLOCK_STATS_ERRS errs + /** * virDomainInterfaceStats: * @@ -1178,6 +1257,11 @@ int virDomainBlockStats (virDomainPtr dom, const char *path, virDomainBlockStatsPtr stats, size_t size); +int virDomainBlockStatsFlags (virDomainPtr dom, + const char *path, + virTypedParameterPtr params, + int *nparams, + unsigned int flags); int virDomainInterfaceStats (virDomainPtr dom, const char *path, virDomainInterfaceStatsPtr stats, diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 169c3ee..dc5a80b 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -483,6 +483,7 @@ LIBVIRT_0.9.4 { LIBVIRT_0.9.5 { global: virDomainMigrateGetMaxSpeed; +virDomainBlockStatsFlags; } LIBVIRT_0.9.4; # define new API here using predicted next version number -- 1.7.6 ACK now, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/8] latency: Define the internal driver callback
On Mon, Sep 05, 2011 at 04:38:29PM +0800, Osier Yang wrote: --- src/driver.h |8 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index 21b2bd3..fc7a931 100644 --- a/src/driver.h +++ b/src/driver.h @@ -348,6 +348,13 @@ typedef int const char *path, struct _virDomainBlockStats *stats); typedef int +(*virDrvDomainBlockStatsFlags) +(virDomainPtr domain, + const char *path, + virTypedParameterPtr params, + int *nparams, + unsigned int flags); +typedef int (*virDrvDomainInterfaceStats) (virDomainPtr domain, const char *path, @@ -806,6 +813,7 @@ struct _virDriver { virDrvDomainMigratePerform domainMigratePerform; virDrvDomainMigrateFinishdomainMigrateFinish; virDrvDomainBlockStats domainBlockStats; +virDrvDomainBlockStatsFlags domainBlockStatsFlags; virDrvDomainInterfaceStats domainInterfaceStats; virDrvDomainMemoryStats domainMemoryStats; virDrvDomainBlockPeekdomainBlockPeek; ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/2] make remote_exec_pexpect return the output of command
On 09/01/2011 10:19 AM, Guannan Ren wrote: *utils/Python/utils.py return 0,child.before intead *repos/remoteAccess/tcp_setup.py repos/remoteAccess/tls_setup.py switch over to use new remote_exec_pexpect() --- repos/remoteAccess/tcp_setup.py | 18 +- repos/remoteAccess/tls_setup.py | 20 ++-- utils/Python/utils.py |4 ++-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/repos/remoteAccess/tcp_setup.py b/repos/remoteAccess/tcp_setup.py index 8f88810..b3877f7 100644 --- a/repos/remoteAccess/tcp_setup.py +++ b/repos/remoteAccess/tcp_setup.py @@ -56,7 +56,7 @@ def sasl_user_add(target_machine, username, password, util, logger): execute saslpasswd2 to add sasl user logger.info(add sasl user on server side) saslpasswd2_add = echo %s | %s -a libvirt %s % (password, SASLPASSWD2, username) -ret = util.remote_exec_pexpect(target_machine, username, +ret, output = util.remote_exec_pexpect(target_machine, username, password, saslpasswd2_add) if ret: logger.error(failed to add sasl user) @@ -70,7 +70,7 @@ def tcp_libvirtd_set(target_machine, username, password, logger.info(setting libvirtd.conf on libvirt server) # open libvirtd --listen option listen_open_cmd = echo 'LIBVIRTD_ARGS=\--listen\' %s % SYSCONFIG_LIBVIRTD -ret = util.remote_exec_pexpect(target_machine, username, +ret, output = util.remote_exec_pexpect(target_machine, username, password, listen_open_cmd) if ret: logger.error(failed to uncomment --listen in %s % SYSCONFIG_LIBVIRTD) @@ -79,7 +79,7 @@ def tcp_libvirtd_set(target_machine, username, password, # set listen_tls logger.info(set listen_tls to 0 in %s % LIBVIRTD_CONF) listen_tls_disable = echo \listen_tls = 0\ %s % LIBVIRTD_CONF -ret = util.remote_exec_pexpect(target_machine, username, +ret, output = util.remote_exec_pexpect(target_machine, username, password, listen_tls_disable) if ret: logger.error(failed to set listen_tls to 0 in %s % LIBVIRTD_CONF) @@ -89,7 +89,7 @@ def tcp_libvirtd_set(target_machine, username, password, if listen_tcp == 'enable': logger.info(enable listen_tcp = 1 in %s % LIBVIRTD_CONF) listen_tcp_set = echo 'listen_tcp = 1' %s % LIBVIRTD_CONF -ret = util.remote_exec_pexpect(target_machine, username, +ret, output = util.remote_exec_pexpect(target_machine, username, password, listen_tcp_set) if ret: logger.error(failed to set listen_tcp in %s % LIBVIRTD_CONF) @@ -98,7 +98,7 @@ def tcp_libvirtd_set(target_machine, username, password, # set auth_tcp logger.info(set auth_tcp to \%s\ in %s % (auth_tcp, LIBVIRTD_CONF)) auth_tcp_set = echo 'auth_tcp = \%s\' %s % (auth_tcp, LIBVIRTD_CONF) -ret = util.remote_exec_pexpect(target_machine, username, +ret, output = util.remote_exec_pexpect(target_machine, username, password, auth_tcp_set) if ret: logger.error(failed to set auth_tcp in %s % LIBVIRTD_CONF) @@ -107,7 +107,7 @@ def tcp_libvirtd_set(target_machine, username, password, # restart remote libvirtd service libvirtd_restart_cmd = service libvirtd restart logger.info(libvirtd restart) -ret = util.remote_exec_pexpect(target_machine, username, +ret, output = util.remote_exec_pexpect(target_machine, username, password, libvirtd_restart_cmd) if ret: logger.error(failed to restart libvirtd service) @@ -225,18 +225,18 @@ def tcp_setup_clean(params): if auth_tcp == 'sasl': saslpasswd2_delete = %s -a libvirt -d %s % (SASLPASSWD2, username) -ret = util.remote_exec_pexpect(target_machine, username, +ret, output = util.remote_exec_pexpect(target_machine, username, password, saslpasswd2_delete) if ret: logger.error(failed to delete sasl user) libvirtd_conf_retore = sed -i -n '/^[ #]/p' %s % LIBVIRTD_CONF -ret = util.remote_exec_pexpect(target_machine, username, +ret, output = util.remote_exec_pexpect(target_machine, username, password, libvirtd_conf_retore) if ret: logger.error(failed to restore %s % LIBVIRTD_CONF) sysconfig_libvirtd_restore = sed -i -n '/^[ #]/p' %s % SYSCONFIG_LIBVIRTD -ret = util.remote_exec_pexpect(target_machine, username, +ret, output = util.remote_exec_pexpect(target_machine, username, password, sysconfig_libvirtd_restore) if ret: logger.error(failed to restore %s % SYSCONFIG_LIBVIRTD) diff --git a/repos/remoteAccess/tls_setup.py
Re: [libvirt] [PATCH 3/8] latency: Implemente the public API
On Mon, Sep 05, 2011 at 04:38:30PM +0800, Osier Yang wrote: --- src/libvirt.c | 71 + 1 files changed, 71 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 4d80e2f..a921e4d 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -6442,6 +6442,77 @@ error: } /** + * virDomainBlockStatsFlags: + * @dom: pointer to domain object + * @path: path to the block device + * @params: pointer to block stats parameter object objects (plural) + * (return value) + * @nparams: pointer to number of block stats need to describe the behaviour of allocation, i.e. who allocate, and what happens if the caller doesn't allocate enough parameters + * @flags: unused, always passes 0 + * + * This function is to get block stats parameters for block + * devices attached to the domain. + * + * The @path is the name of the block device. Get this + * by calling virDomainGetXMLDesc and finding the target dev='...' + * attribute within //domain/devices/disk. (For example, xvda). + * + * Domains may have more than one block device. To get stats for + * each you should make multiple calls to this function. + * + * The @params array will be filled with the value equal to the number of + * parameters suggested by @nparams. still unclear if it is too much or too many + * As the value of @nparams is dynamic, call the API setting @nparams to 0 and + * @params as NULL, the API returns the number of parameters supported by the + * HV by updating @nparams on SUCCESS. (Note that block device of different type + * might support different parameters numbers, so it might be necessary to compute + * @nparams for each block device type). The caller should then allocate @params + * array, i.e. (sizeof(@virTypedParameter) * @nparams) bytes and call the API + * again. See virDomainGetMemoryParameters for more details. tend to disagree, we should document the behaviour here, not reference another function docuemntation, copy as needed + * Returns -1 in case of error, 0 in case of success. + */ +int virDomainBlockStatsFlags (virDomainPtr dom, + const char *path, + virTypedParameterPtr params, + int *nparams, + unsigned int flags) +{ +virConnectPtr conn; + +VIR_DOMAIN_DEBUG(dom, path=%s, params=%p, nparams=%d, flags=%x, + path, params, nparams ? *nparams : -1, flags); + +virResetLastError(); + +if (!VIR_IS_CONNECTED_DOMAIN (dom)) { +virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); +virDispatchError(NULL); +return -1; +} +if (!path || (nparams == NULL) || (*nparams 0)) { okay we accept param == NULL here, +virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__); +goto error; +} +conn = dom-conn; + +if (conn-driver-domainBlockStatsFlags) { +int ret; +ret = conn-driver-domainBlockStatsFlags(dom, path, params, nparams, flags); +if (ret 0) +goto error; +return ret; +} +virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: +virDispatchError(dom-conn); +return -1; +} + + +/** * virDomainInterfaceStats: * @dom: pointer to the domain object * @path: path to the interface ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/2] Add new testcase for cpu topology testing
On 09/01/2011 10:19 AM, Guannan Ren wrote: *repos/domain/cpu_topology.py --- repos/domain/cpu_topology.py | 248 ++ 1 files changed, 248 insertions(+), 0 deletions(-) create mode 100644 repos/domain/cpu_topology.py diff --git a/repos/domain/cpu_topology.py b/repos/domain/cpu_topology.py new file mode 100644 index 000..7202559 --- /dev/null +++ b/repos/domain/cpu_topology.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python + To test guest cpu topology +domain:cpu_topology +guestname +xxx +username +root +password +xx +sockets +2 +cores +1 +threads +2 + + +__author__ = 'Guannan Ren: g...@redhat.com' +__date__ = 'Tue Aug 30, 2011' +__version__ = '0.1.0' +__credits__ = 'Copyright (C) 2011 Red Hat, Inc.' +__all__ = [] + +import os +import re +import sys +import time +from xml.dom import minidom + +def append_path(path): +Append root path of package +if path in sys.path: +pass +else: +sys.path.append(path) + +pwd = os.getcwd() +result = re.search('(.*)libvirt-test-API', pwd) +append_path(result.group(0)) + +from lib import connectAPI +from lib import domainAPI +from utils.Python import utils +from exception import LibvirtAPI + +def check_params(params): +check out the arguments requried for testing +logger = params['logger'] +keys = ['guestname', 'username', 'password', +'sockets', 'cores', 'threads'] +for key in keys: +if key not in params: +logger.error(Argument %s is required % key) +return 1 +return 0 + +def check_domain_running(domobj, guestname, logger): +check if the domain exists, may or may not be active +defined_guest_names = domobj.get_defined_list() + +if guestname not in defined_guest_names: +logger.error(%s doesn't exist or still in running % guestname) +return 1 +else: +return 0 + +def add_cpu_xml(domobj, guestname, sockets, cores, threads, logger): +edit domain xml description and insertcpu element + +guestxml = domobj.get_xml_desc(guestname) +logger.debug('''original guest %s xml :\n%s''' %(guestname, guestxml)) + +doc = minidom.parseString(guestxml) +cpu = doc.createElement('cpu') +topology = doc.createElement('topology') +topology.setAttribute('sockets', sockets) +topology.setAttribute('cores', cores) +topology.setAttribute('threads', threads) +cpu.appendChild(topology) + +vcpuval = int(sockets) * int(cores) * int(threads) +newvcpu = doc.createElement('vcpu') +newvcpuval = doc.createTextNode(str(vcpuval)) +newvcpu.appendChild(newvcpuval) +oldvcpu = doc.getElementsByTagName('vcpu')[0] + +domain = doc.getElementsByTagName('domain')[0] +domain.appendChild(cpu) +domain.replaceChild(newvcpu, oldvcpu) + +return doc.toxml() + +def guest_undefine(domobj, guestname, logger): +undefine original guest +try: +logger.info(undefine guest) +domobj.undefine(guestname) +logger.info(undefine the domain is successful) +except LibvirtAPI, e: +logger.error(API error message: %s, error code is %s % \ + (e.response()['message'], e.response()['code'])) +logger.error(fail to undefine domain) +return 1 + +return 0 + +def guest_define(domobj, domxml, logger): +define new guest xml +try: +logger.info(define guest) +domobj.define(domxml) +logger.info(success to define new domain xml description) +except LibvirtAPI, e: +logger.error(API error message: %s, error code is %s % \ + (e.response()['message'], e.response()['code'])) +logger.error(fail to define domain) +return 1 + +return 0 + +def guest_start(domobj, guestname, util, logger): +start guest +timeout = 600 +ip = '' +mac = util.get_dom_mac_addr(guestname) + +try: +logger.info(start guest) +domobj.start(guestname) +except LibvirtAPI, e: +logger.error(API error message: %s, error code is %s % \ + (e.response()['message'], e.response()['code'])) +logger.error(fail to start domain) +return 1 + +while timeout: +time.sleep(10) +timeout -= 10 + +ip = util.mac_to_ip(mac, 180) + +if not ip: +logger.info(str(timeout) + s left) +else: +logger.info(vm %s power on successfully % guestname) +logger.info(the ip address of vm %s is %s % (guestname, ip)) +break + +if timeout= 0: +logger.info(fail to power on vm %s % guestname) +return 1, ip + +return 0, ip + +def cpu_topology_check(ip, username, password, + sockets, cores, threads, util, logger): +login the guest, run lscpu command to check the result +lscpu =
Re: [libvirt] [PATCH 6/8] latency: Implemente internal API for qemu driver
On Mon, Sep 05, 2011 at 04:38:33PM +0800, Osier Yang wrote: --- src/qemu/qemu_driver.c | 189 1 files changed, 189 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c5809d2..a8b2b6d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7243,6 +7243,194 @@ cleanup: return ret; } +static int +qemudDomainBlockStatsFlags (virDomainPtr dom, +const char *path, +virTypedParameterPtr params, +int *nparams, +unsigned int flags) +{ +struct qemud_driver *driver = dom-conn-privateData; +int i, tmp, ret = -1; +virDomainObjPtr vm; +virDomainDiskDefPtr disk = NULL; +qemuDomainObjPrivatePtr priv; +long long rd_req, rd_bytes, wr_req, wr_bytes, rd_total_times; +long long wr_total_times, flush_req, flush_total_times, errs; + +virCheckFlags(0, -1); + +qemuDriverLock(driver); +vm = virDomainFindByUUID(driver-domains, dom-uuid); +qemuDriverUnlock(driver); +if (!vm) { +char uuidstr[VIR_UUID_STRING_BUFLEN]; +virUUIDFormat(dom-uuid, uuidstr); +qemuReportError(VIR_ERR_NO_DOMAIN, +_(no domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +if (!virDomainObjIsActive(vm)) { +qemuReportError(VIR_ERR_OPERATION_INVALID, +%s, _(domain is not running)); +goto cleanup; +} + +if (*nparams != 0) { +for (i = 0 ; i vm-def-ndisks ; i++) { +if (STREQ(path, vm-def-disks[i]-dst)) { +disk = vm-def-disks[i]; +break; +} +} + +if (!disk) { +qemuReportError(VIR_ERR_INVALID_ARG, +_(invalid path: %s), path); +goto cleanup; +} + +if (!disk-info.alias) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _(missing disk device alias name for %s), disk-dst); + goto cleanup; +} +} + +priv = vm-privateData; +VIR_DEBUG(priv=%p, params=%p, flags=%x, priv, params, flags); + +if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) 0) +goto cleanup; + +qemuDomainObjEnterMonitor(driver, vm); +tmp = *nparams; +ret = qemuMonitorGetBlockStatsParamsNumber(priv-mon, nparams); + +if (tmp == 0) { +qemuDomainObjExitMonitor(driver, vm); +goto endjob; +} + +ret = qemuMonitorGetBlockStatsInfo(priv-mon, + disk-info.alias, + rd_req, + rd_bytes, + rd_total_times, + wr_req, + wr_bytes, + wr_total_times, + flush_req, + flush_total_times, + errs); + +qemuDomainObjExitMonitor(driver, vm); + +if (ret 0) +goto endjob; + +/* Field 'errs' is meaningless for QEMU, won't set it. */ +for (i = 0; i *nparams; i++) { +virTypedParameterPtr param = params[i]; + +switch (i) { +case 0: /* fill write_bytes here */ +if (virStrcpyStatic(param-field, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field write bytes too long for destination)); +goto cleanup; +} +param-type = VIR_TYPED_PARAM_LLONG; +param-value.l = wr_bytes; +break; + +case 1: /* fill wr_operations here */ +if (virStrcpyStatic(param-field, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field write requests too long for destination)); +goto cleanup; +} +param-type = VIR_TYPED_PARAM_LLONG; +param-value.l = wr_req; +break; + +case 2: /* fill read_bytes here */ +if (virStrcpyStatic(param-field, VIR_DOMAIN_BLOCK_STATS_READ_BYTES) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field read bytes too long for destination)); +goto cleanup; +} +param-type = VIR_TYPED_PARAM_LLONG; +param-value.l = rd_bytes; +break; + +case 3: /* fill rd_operations here */ +if (virStrcpyStatic(param-field,
Re: [libvirt] [PATCH 5/8] latency: Update monitor functions for new latency fields
On Mon, Sep 05, 2011 at 04:38:32PM +0800, Osier Yang wrote: The mainly changes are: 1) Update qemuMonitorGetBlockStatsInfo and it's children (Text/JSON) functions to return the value of new latency fields. 2) Add new function qemuMonitorGetBlockStatsParamsNumber, which is to count how many parameters the underlying QEMU supports. 3) Update virDomainBlockStats in src/qemu/qemu_driver.c to be compatible with the changes by 1). --- src/qemu/qemu_driver.c |4 ++ src/qemu/qemu_monitor.c | 35 src/qemu/qemu_monitor.h |6 ++ src/qemu/qemu_monitor_json.c | 124 +- src/qemu/qemu_monitor_json.h |6 ++ src/qemu/qemu_monitor_text.c | 121 + src/qemu/qemu_monitor_text.h |6 ++ 7 files changed, 291 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7028d72..c5809d2 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7224,8 +7224,12 @@ qemudDomainBlockStats (virDomainPtr dom, disk-info.alias, stats-rd_req, stats-rd_bytes, + NULL, stats-wr_req, stats-wr_bytes, + NULL, + NULL, + NULL, stats-errs); qemuDomainObjExitMonitor(driver, vm); diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index db6107c..92631ae 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1201,8 +1201,12 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon, const char *devname, long long *rd_req, long long *rd_bytes, + long long *rd_total_times, long long *wr_req, long long *wr_bytes, + long long *wr_total_times, + long long *flush_req, + long long *flush_total_times, long long *errs) { int ret; @@ -1217,16 +1221,47 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon, if (mon-json) ret = qemuMonitorJSONGetBlockStatsInfo(mon, devname, rd_req, rd_bytes, + rd_total_times, wr_req, wr_bytes, + wr_total_times, + flush_req, + flush_total_times, errs); else ret = qemuMonitorTextGetBlockStatsInfo(mon, devname, rd_req, rd_bytes, + rd_total_times, wr_req, wr_bytes, + wr_total_times, + flush_req, + flush_total_times, errs); return ret; } +/* Return 0 and update @nparams with the number of block stats + * QEMU supports if success. Return -1 if failure. + */ +int qemuMonitorGetBlockStatsParamsNumber(qemuMonitorPtr mon, + int *nparams) +{ +int ret; +VIR_DEBUG(mon=%p nparams=%p, mon, nparams); + +if (!mon) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(monitor must not be NULL)); +return -1; +} + +if (mon-json) +ret = qemuMonitorJSONGetBlockStatsParamsNumber(mon, nparams); +else +ret = qemuMonitorTextGetBlockStatsParamsNumber(mon, nparams); + +return ret; +} + int qemuMonitorGetBlockExtent(qemuMonitorPtr mon, const char *devname, unsigned long long *extent) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index f241c9e..1b9d98d 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -212,9 +212,15 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon, const char *devname, long long *rd_req, long long *rd_bytes, + long long *rd_total_times, long
Re: [libvirt] [PATCH 4/8] latency: Wire up the remote protocol
On Mon, Sep 05, 2011 at 04:38:31PM +0800, Osier Yang wrote: --- daemon/remote.c | 69 ++ src/remote/remote_driver.c | 64 ++ src/remote/remote_protocol.x | 19 +++- 3 files changed, 151 insertions(+), 1 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index d5ead81..38bbb10 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -933,6 +933,75 @@ cleanup: } static int +remoteDispatchDomainBlockStatsFlags(virNetServerPtr server ATTRIBUTE_UNUSED, +virNetServerClientPtr client ATTRIBUTE_UNUSED, +virNetMessageHeaderPtr hdr ATTRIBUTE_UNUSED, +virNetMessageErrorPtr rerr, +remote_domain_block_stats_flags_args *args, +remote_domain_block_stats_flags_ret *ret) +{ +virTypedParameterPtr params = NULL; +virDomainPtr dom = NULL; +int i; +const char *path = args-path; +int nparams = args-nparams; +unsigned int flags; +int rv = -1; +struct daemonClientPrivate *priv = +virNetServerClientGetPrivateData(client); + +if (!priv-conn) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open)); +goto cleanup; +} + +if (!(dom = get_nonnull_domain(priv-conn, args-dom))) +goto cleanup; +flags = args-flags; + +if (nparams REMOTE_DOMAIN_BLOCK_STATS_PARAMETERS_MAX) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(nparams too large)); +goto cleanup; +} +if (VIR_ALLOC_N(params, nparams) 0) { +virReportOOMError(); +goto cleanup; +} + +if (virDomainBlockStatsFlags(dom, path, params, nparams, flags) 0) +goto cleanup; + +/* In this case, we need to send back the number of parameters + * supported + */ +if (args-nparams == 0) { +ret-nparams = nparams; +goto success; +} + +/* Serialise the block stats. */ +if (remoteSerializeTypedParameters(params, nparams, + ret-params.params_val, + ret-params.params_len) 0) +goto cleanup; + +success: +rv = 0; + +cleanup: +if (rv 0) { +virNetMessageSaveError(rerr); +if (ret-params.params_val) { +for (i = 0; i nparams; i++) +VIR_FREE(ret-params.params_val[i].field); +VIR_FREE(ret-params.params_val); +} +} +VIR_FREE(params); +return rv; +} + +static int remoteDispatchDomainMemoryPeek(virNetServerPtr server ATTRIBUTE_UNUSED, virNetServerClientPtr client ATTRIBUTE_UNUSED, virNetMessageHeaderPtr hdr ATTRIBUTE_UNUSED, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 783c404..9d34b7e 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1361,6 +1361,69 @@ cleanup: } static int +remoteDomainBlockStatsFlags(virDomainPtr domain, +const char *path, +virTypedParameterPtr params, +int *nparams, +unsigned int flags) +{ +int rv = -1; +remote_domain_block_stats_flags_args args; +remote_domain_block_stats_flags_ret ret; +struct private_data *priv = domain-conn-privateData; + +remoteDriverLock(priv); + +make_nonnull_domain (args.dom, domain); +args.nparams = *nparams; +args.path = (char *) path; +args.flags = flags; + +memset (ret, 0, sizeof ret); +if (call (domain-conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_STATS_FLAGS, + (xdrproc_t) xdr_remote_domain_block_stats_flags_args, (char *) args, + (xdrproc_t) xdr_remote_domain_block_stats_flags_ret, (char *) ret) == -1) +goto done; + +/* Check the length of the returned list carefully. */ +if (ret.params.params_len REMOTE_DOMAIN_BLOCK_STATS_PARAMETERS_MAX || +ret.params.params_len *nparams) { +remoteError(VIR_ERR_RPC, %s, +_(remoteDomainBlockStatsFlags: + returned number of stats exceeds limit)); +goto cleanup; +} + +/* Handle the case when the caller does not know the number of stats + * and is asking for the number of stats supported + */ +if (*nparams == 0) { +*nparams = ret.nparams; +rv = 0; +goto cleanup; +} + +*nparams = ret.params.params_len; + +/* Deserialise the result. */ +if (remoteDeserializeTypedParameters(ret.params.params_val, + ret.params.params_len, +
Re: [libvirt] [PATCH 8/8] latency: Update cmdBlkStats to use new API
On Mon, Sep 05, 2011 at 04:38:35PM +0800, Osier Yang wrote: The modified function fallbacks to use virDomainBlockStats if virDomainBlockStatsFlags is not supported by the hypervisor driver. If the new API is supported, it will be invoked instead of the old API. --- tools/virsh.c | 104 ++--- 1 files changed, 84 insertions(+), 20 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index c7240e5..ea41221 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1070,6 +1070,9 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) virDomainPtr dom; const char *name = NULL, *device = NULL; struct _virDomainBlockStats stats; +virTypedParameterPtr params = NULL; +int rc, nparams = 0; +bool ret = false; if (!vshConnectionUsability (ctl, ctl-conn)) return false; @@ -1077,34 +1080,95 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) if (!(dom = vshCommandOptDomain (ctl, cmd, name))) return false; -if (vshCommandOptString (cmd, device, device) = 0) { -virDomainFree(dom); -return false; -} +if (vshCommandOptString (cmd, device, device) = 0) +goto cleanup; -if (virDomainBlockStats (dom, device, stats, sizeof stats) == -1) { -vshError(ctl, _(Failed to get block stats %s %s), name, device); -virDomainFree(dom); -return false; -} +rc = virDomainBlockStatsFlags(dom, device, NULL, nparams, 0); -if (stats.rd_req = 0) -vshPrint (ctl, %s rd_req %lld\n, device, stats.rd_req); +/* It might fail when virDomainBlockStatsFlags is not + * supported on older libvirt, fallback to use virDomainBlockStats + * then. + */ +if (rc 0) { +if (last_error-code != VIR_ERR_NO_SUPPORT) { +virshReportError(ctl); +goto cleanup; +} else { +virFreeError(last_error); +last_error = NULL; -if (stats.rd_bytes = 0) -vshPrint (ctl, %s rd_bytes %lld\n, device, stats.rd_bytes); +if (virDomainBlockStats (dom, device, stats, + sizeof stats) == -1) { +vshError(ctl, _(Failed to get block stats %s %s), + name, device); +goto cleanup; +} + +if (stats.rd_req = 0) +vshPrint (ctl, %s rd_req %lld\n, device, stats.rd_req); -if (stats.wr_req = 0) -vshPrint (ctl, %s wr_req %lld\n, device, stats.wr_req); +if (stats.rd_bytes = 0) +vshPrint (ctl, %s rd_bytes %lld\n, device, stats.rd_bytes); -if (stats.wr_bytes = 0) -vshPrint (ctl, %s wr_bytes %lld\n, device, stats.wr_bytes); +if (stats.wr_req = 0) +vshPrint (ctl, %s wr_req %lld\n, device, stats.wr_req); -if (stats.errs = 0) -vshPrint (ctl, %s errs %lld\n, device, stats.errs); +if (stats.wr_bytes = 0) +vshPrint (ctl, %s wr_bytes %lld\n, device, stats.wr_bytes); +if (stats.errs = 0) +vshPrint (ctl, %s errs %lld\n, device, stats.errs); +} +} else { +params = vshMalloc(ctl, sizeof(*params) * nparams); +memset(params, 0, sizeof(*params) * nparams); + +if (virDomainBlockStatsFlags (dom, device, params, nparams, 0) 0) { +vshError(ctl, _(Failed to get block stats %s %s), name, device); +goto cleanup; +} + +int i; +/* XXX: The output sequence will be different. */ +for (i = 0; i nparams; i++) { +switch(params[i].type) { +case VIR_TYPED_PARAM_INT: +vshPrint (ctl, %s %s %d\n, device, + params[i].field, params[i].value.i); +break; +case VIR_TYPED_PARAM_UINT: +vshPrint (ctl, %s %s %u\n, device, + params[i].field, params[i].value.ui); +break; +case VIR_TYPED_PARAM_LLONG: +vshPrint (ctl, %s %s %lld\n, device, + params[i].field, params[i].value.l); +break; +case VIR_TYPED_PARAM_ULLONG: +vshPrint (ctl, %s %s %llu\n, device, + params[i].field, params[i].value.ul); +break; +case VIR_TYPED_PARAM_DOUBLE: +vshPrint (ctl, %s %s %f\n, device, + params[i].field, params[i].value.d); +break; +case VIR_TYPED_PARAM_BOOLEAN: +vshPrint (ctl, %s %s %s\n, device, + params[i].field, params[i].value.b ? _(yes) : _(no)); +break; +default: +vshError(ctl, _(unimplemented block statistics parameter
Re: [libvirt] [PATCH 7/8] latency: Expose the new API for Python binding
On Mon, Sep 05, 2011 at 04:38:34PM +0800, Osier Yang wrote: --- python/generator.py |1 + python/libvirt-override-api.xml |7 +++ python/libvirt-override.c | 85 +++ 3 files changed, 93 insertions(+), 0 deletions(-) diff --git a/python/generator.py b/python/generator.py index cc253cf..d17fb26 100755 --- a/python/generator.py +++ b/python/generator.py @@ -373,6 +373,7 @@ skip_impl = ( 'virNodeGetMemoryStats', 'virDomainGetBlockJobInfo', 'virDomainMigrateGetMaxSpeed', +'virDomainBlockStatsFlags', ) diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml index 1cf115c..3013e46 100644 --- a/python/libvirt-override-api.xml +++ b/python/libvirt-override-api.xml @@ -128,6 +128,13 @@ arg name='domain' type='virDomainPtr' info='a domain object'/ arg name='path' type='char *' info='the path for the block device'/ /function +function name='virDomainBlockStatsFlags' file='python' + infoExtracts block device statistics parameters of a running domain/info + return type='virTypedParameterPtr' info='None in case of error, returns a dictionary of params'/ + arg name='domain' type='virDomainPtr' info='pointer to domain object'/ + 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='virDomainInterfaceStats' file='python' infoExtracts 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 b020342..d65423d 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -100,6 +100,90 @@ libvirt_virDomainBlockStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { } static PyObject * +libvirt_virDomainBlockStatsFlags(PyObject *self ATTRIBUTE_UNUSED, + PyObject *args) { +virDomainPtr domain; +PyObject *pyobj_domain, *info; +int i_retval; +int nparams = 0, i; +unsigned int flags; +virTypedParameterPtr params; +const char *path; + +if (!PyArg_ParseTuple(args, (char *)Ozi:virDomainBlockStatsFlags, + pyobj_domain, path, flags)) +return(NULL); +domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + +LIBVIRT_BEGIN_ALLOW_THREADS; +i_retval = virDomainBlockStatsFlags(domain, path, NULL, nparams, flags); +LIBVIRT_END_ALLOW_THREADS; + +if (i_retval 0) +return VIR_PY_NONE; + +if ((params = malloc(sizeof(*params)*nparams)) == NULL) +return VIR_PY_NONE; + +LIBVIRT_BEGIN_ALLOW_THREADS; +i_retval = virDomainBlockStatsFlags(domain, path, params, nparams, flags); +LIBVIRT_END_ALLOW_THREADS; + +if (i_retval 0) { +free(params); +return VIR_PY_NONE; +} + +/* convert to a Python tuple of long objects */ +if ((info = PyDict_New()) == NULL) { +free(params); +return VIR_PY_NONE; +} + +for (i = 0 ; i nparams ; i++) { +PyObject *key, *val; + +switch (params[i].type) { +case VIR_TYPED_PARAM_INT: +val = PyInt_FromLong((long)params[i].value.i); +break; + +case VIR_TYPED_PARAM_UINT: +val = PyInt_FromLong((long)params[i].value.ui); +break; + +case VIR_TYPED_PARAM_LLONG: +val = PyLong_FromLongLong((long long)params[i].value.l); +break; + +case VIR_TYPED_PARAM_ULLONG: +val = PyLong_FromLongLong((long long)params[i].value.ul); +break; + +case VIR_TYPED_PARAM_DOUBLE: +val = PyFloat_FromDouble((double)params[i].value.d); +break; + +case VIR_TYPED_PARAM_BOOLEAN: +val = PyBool_FromLong((long)params[i].value.b); +break; + +default: +free(params); +Py_DECREF(info); +return VIR_PY_NONE; +} + +key = libvirt_constcharPtrWrap(params[i].field); +PyDict_SetItem(info, key, val); +} + +free(params); +return(info); +} + + +static PyObject * libvirt_virDomainInterfaceStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; @@ -4605,6 +4689,7 @@ static PyMethodDef libvirtMethods[] = { {(char *) virDomainGetAutostart, libvirt_virDomainGetAutostart, METH_VARARGS, NULL}, {(char *) virNetworkGetAutostart, libvirt_virNetworkGetAutostart, METH_VARARGS, NULL}, {(char *) virDomainBlockStats, libvirt_virDomainBlockStats, METH_VARARGS, NULL}, +{(char *) virDomainBlockStatsFlags, libvirt_virDomainBlockStatsFlags, METH_VARARGS, NULL}, {(char
Re: [libvirt] [PATCH 8/8] latency: Update cmdBlkStats to use new API
于 2011年09月06日 11:59, Daniel Veillard 写道: On Mon, Sep 05, 2011 at 04:38:35PM +0800, Osier Yang wrote: The modified function fallbacks to use virDomainBlockStats if virDomainBlockStatsFlags is not supported by the hypervisor driver. If the new API is supported, it will be invoked instead of the old API. --- tools/virsh.c | 104 ++--- 1 files changed, 84 insertions(+), 20 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index c7240e5..ea41221 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1070,6 +1070,9 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) virDomainPtr dom; const char *name = NULL, *device = NULL; struct _virDomainBlockStats stats; +virTypedParameterPtr params = NULL; +int rc, nparams = 0; +bool ret = false; if (!vshConnectionUsability (ctl, ctl-conn)) return false; @@ -1077,34 +1080,95 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) if (!(dom = vshCommandOptDomain (ctl, cmd,name))) return false; -if (vshCommandOptString (cmd, device,device)= 0) { -virDomainFree(dom); -return false; -} +if (vshCommandOptString (cmd, device,device)= 0) +goto cleanup; -if (virDomainBlockStats (dom, device,stats, sizeof stats) == -1) { -vshError(ctl, _(Failed to get block stats %s %s), name, device); -virDomainFree(dom); -return false; -} +rc = virDomainBlockStatsFlags(dom, device, NULL,nparams, 0); -if (stats.rd_req= 0) -vshPrint (ctl, %s rd_req %lld\n, device, stats.rd_req); +/* It might fail when virDomainBlockStatsFlags is not + * supported on older libvirt, fallback to use virDomainBlockStats + * then. + */ +if (rc 0) { +if (last_error-code != VIR_ERR_NO_SUPPORT) { +virshReportError(ctl); +goto cleanup; +} else { +virFreeError(last_error); +last_error = NULL; -if (stats.rd_bytes= 0) -vshPrint (ctl, %s rd_bytes %lld\n, device, stats.rd_bytes); +if (virDomainBlockStats (dom, device,stats, + sizeof stats) == -1) { +vshError(ctl, _(Failed to get block stats %s %s), + name, device); +goto cleanup; +} + +if (stats.rd_req= 0) +vshPrint (ctl, %s rd_req %lld\n, device, stats.rd_req); -if (stats.wr_req= 0) -vshPrint (ctl, %s wr_req %lld\n, device, stats.wr_req); +if (stats.rd_bytes= 0) +vshPrint (ctl, %s rd_bytes %lld\n, device, stats.rd_bytes); -if (stats.wr_bytes= 0) -vshPrint (ctl, %s wr_bytes %lld\n, device, stats.wr_bytes); +if (stats.wr_req= 0) +vshPrint (ctl, %s wr_req %lld\n, device, stats.wr_req); -if (stats.errs= 0) -vshPrint (ctl, %s errs %lld\n, device, stats.errs); +if (stats.wr_bytes= 0) +vshPrint (ctl, %s wr_bytes %lld\n, device, stats.wr_bytes); +if (stats.errs= 0) +vshPrint (ctl, %s errs %lld\n, device, stats.errs); +} +} else { +params = vshMalloc(ctl, sizeof(*params) * nparams); +memset(params, 0, sizeof(*params) * nparams); + +if (virDomainBlockStatsFlags (dom, device, params,nparams, 0) 0) { +vshError(ctl, _(Failed to get block stats %s %s), name, device); +goto cleanup; +} + +int i; +/* XXX: The output sequence will be different. */ +for (i = 0; i nparams; i++) { +switch(params[i].type) { +case VIR_TYPED_PARAM_INT: +vshPrint (ctl, %s %s %d\n, device, + params[i].field, params[i].value.i); +break; +case VIR_TYPED_PARAM_UINT: +vshPrint (ctl, %s %s %u\n, device, + params[i].field, params[i].value.ui); +break; +case VIR_TYPED_PARAM_LLONG: +vshPrint (ctl, %s %s %lld\n, device, + params[i].field, params[i].value.l); +break; +case VIR_TYPED_PARAM_ULLONG: +vshPrint (ctl, %s %s %llu\n, device, + params[i].field, params[i].value.ul); +break; +case VIR_TYPED_PARAM_DOUBLE: +vshPrint (ctl, %s %s %f\n, device, + params[i].field, params[i].value.d); +break; +case VIR_TYPED_PARAM_BOOLEAN: +vshPrint (ctl, %s %s %s\n, device, + params[i].field, params[i].value.b ? _(yes) : _(no)); +break; +default: +vshError(ctl, _(unimplemented block statistics parameter type)); +} + +} +} + +ret = true; + +cleanup: +VIR_FREE(params);